Skip to content

korbitdev/open-p

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

39 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

open-p

A local agent CLI compatibility layer for running prompt-driven turns through supported backend CLIs.

openp wraps one prompt turn through a selected backend and returns the result through a stable openp JSON interface.

Prerequisites

  • Node.js >= 20
  • tmux (used internally by the Claude backend PTY runner; brew install tmux on macOS, apt install tmux on Debian/Ubuntu)
  • At least one backend CLI installed:
Backend Required CLI Install
Claude claude Claude Code CLI
Codex codex Codex CLI
Kiro kiro-cli Kiro CLI

Install

git clone https://github.com/sky1core/open-p.git
cd open-p
npm install
npm run build
npm link
openp --version

Quick Start

openp claude "hello"
openp codex "hello"
openp kiro "hello"

The first positional argument selects the backend. There is no default backend.

Pipe from stdin:

echo "summarize this" | openp claude

Output Formats

Flag stdout
--output-format text Answer text only
--output-format json Single JSON result object
--output-format stream-json JSONL records ending with openp.form: "result"

Default is text.

JSON Output

JSON-family outputs use openp as the top-level public object. Use openp.form, openp.scope, and openp.output to read the result.

openp claude --output-format json "hello"
{
  "openp": {
    "form": "result",
    "output": {
      "answer": ["hello"],
      "reasoning": [],
      "toolCall": [],
      "toolResult": []
    },
    "sessionId": "...",
    "metadata": { "..." }
  }
}

Result openp.output contains aggregate arrays for answer, reasoning, toolCall, and toolResult.

Streaming

By default, stream-json output emits only the terminal result record. Use --streaming to receive active-turn streaming events as the backend works:

openp claude --output-format stream-json --streaming "hello"

Streaming records use openp.form: "streaming" with a strict oneOf openp.output:

{"openp": {"form": "streaming", "output": {"answer": "hel"}}}
{"openp": {"form": "streaming", "output": {"answer": "hello"}}}
{"openp": {"form": "result", "output": {"answer": ["hello"], "reasoning": [], "toolCall": [], "toolResult": []}}}

Streaming answer and reasoning values are cumulative snapshots, not deltas. Tool streaming records contain complete objects.

Claude Backend Notes

The Claude backend runs through a PTY-backed interactive Claude Code session and reads Claude's local session log for structured turn data. It does not use Claude print mode.

To keep one openp invocation mapped to one synchronous prompt turn, the Claude backend disables background/monitor workflows and blocking interactive question tools at launch.

Backend Instances

The Claude backend supports configured instances: derived backend ids that run Claude Code with a separate configuration directory (CLAUDE_CONFIG_DIR). Each instance keeps its own Claude Code login, settings, and session logs, so you can keep independent Claude Code profiles side by side.

Define instances in ${XDG_CONFIG_HOME:-~/.config}/open-p/instances.yaml:

instances:
  claude-alt:
    backend: claude
    configDir: ~/.claude-alt

Then select the instance like any backend:

openp claude-alt "prompt"

Notes:

  • configDir is required and must be absolute or ~/-prefixed. Run claude once with that CLAUDE_CONFIG_DIR to log the profile in before using it through openp.
  • Instance ids must not collide with built-in backend ids.
  • Sessions are bound to the instance that created them; resuming a session through a different backend or instance id fails.
  • The base claude backend always uses the default Claude Code configuration directory; it does not read an ambient CLAUDE_CONFIG_DIR.
  • An instance reads user-scope skills, subagents, and settings.json (hooks, permissions) only from its own configDir; they are not inherited from the default ~/.claude profile. Replicate them in the instance directory (copy, or symlink the skills/agents directories) if you want the same behavior.
  • Give the instance configDir its own CLAUDE.md. Without one, a workspace under $HOME makes Claude Code pick up the default ~/.claude/CLAUDE.md as a project file, and any external @ import it declares raises a per-workspace "Allow external CLAUDE.md file imports?" approval prompt that an unattended run cannot answer. A CLAUDE.md in the instance configDir loads the same imports as user scope and skips that prompt.

Sessions

First-turn session ids are generated by openp or the backend. To resume a session, capture the session id from JSON output and pass it with --resume:

openp codex --output-format json "first prompt"
# read openp.sessionId from the output
openp codex --resume <session-id> "follow-up"

Text output does not include session ids.

Timeout and Interrupt

No default timeout. Set one explicitly:

openp claude --timeout 60 "prompt"

--timeout 0 disables it. Ctrl-C sends graceful interruption; repeated Ctrl-C escalates.

Options

Option Purpose
--resume <session-id> Resume a previous session
--timeout <seconds> Per-turn wall-clock timeout
--input-format <fmt> text or stream-json
--output-format <fmt> text, json, or stream-json
--model <model> Backend model selection
--effort <level> Reasoning effort where supported
--tools <tools> Tool allowlist where supported
--json-schema <json> Structured output schema where supported
--streaming Active-turn streaming opt-in
--dangerously-skip-permissions Trust backend tool execution
--debug-log Write diagnostics to the open-p state log
--verbose Include diagnostic markers in output

Options may appear before or after the backend name. Only the options listed above are the public openp interface.

Backend-native flags that are not listed above fail closed instead of being ignored or passed through. This includes Claude print-mode and raw Claude configuration flags such as -p, --print, --include-partial-messages, --brief, --permission-mode, --allowedTools, --allowed-tools, --disallowedTools, --disallowed-tools, --mcp-config, --settings, --setting-sources, and --add-dir.

Use --tools for the public tool-policy selector and --dangerously-skip-permissions for the public trusted-tool intent. The selected backend may still reject a public option when it does not support that feature.

Stream-JSON Input

For programmatic use, send structured input on stdin:

printf '{"type":"user","message":{"content":"hello"}}\n' \
  | openp claude --input-format stream-json --output-format stream-json

Diagnostics

--debug-log writes to:

${XDG_STATE_HOME:-~/.local/state}/open-p/workspaces/<workspace-hash>/logs/debug.jsonl

Debug logs may contain session ids, prompts, response previews, and error context.

--verbose adds diagnostic markers to output. In text mode, a marker line is appended after the answer. In JSON modes, warnings appear under openp.metadata.warnings.

License

MIT

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • TypeScript 94.4%
  • JavaScript 5.6%