pi-subagent-bridge
v0.4.0
Published
Codex plugin for running isolated Pi coding-agent subprocesses through MCP.
Readme
Pi Subagent Bridge
Codex plugin marketplace repo that exposes a bundled MCP stdio server for managing Pi coding-agent subprocesses.
Status: v0.4.0. Linux and macOS are supported; Windows has not yet been tested. Node.js 22+, Python 3, Git, Codex, and the
piCLI are required.
What It Provides
pi_list_models: searches Pi's structured RPC model catalog. Passqueryfor focused selection such asgpt 5.5 reasoning; the server does not scrape terminal-formatted output.pi_run: preferred one-call delegation API. It starts Pi, waits internally, and returns structured result and workspace metadata.pi_doctor: checks the Pi executable, bridge state, allowed roots, and git availability.pi_start: starts onepi --mode rpcsubprocess per run and returns a stablerun_idimmediately. Passsession_idto continue a previous Pi session. By default, git-backed workspaces run in an isolatedgit worktree.pi_wait: waits for a run to reachcompleted,failed,stopped, ortimed_out, plus any Pisession_idand compact workspace change references. Whentimeout_msis provided, it may instead return a non-terminal heartbeat withprogress.elapsed_msandprogress.tool_calls_count; callpi_waitagain with the samerun_idto continue waiting.pi_get_run_status: returns a bounded activity snapshot for deciding whether and how to steer a run.pi_get_run_events: returns a sanitized cursor-based event feed when the status snapshot is insufficient.pi_steer: injects a follow-up instruction into arunningPi session. Its acknowledgement confirms RPC acceptance; inspect subsequent status/events or the final result to verify that the agent acted on it.pi_stop: sends Pi's RPC abort command, waits for the grace period, then terminates the child process group if needed.pi_recent_tool_calls: returns timestamped, ordered, sanitizedtool_execution_startaudit entries only.pi_get_run: diagnostic state for recovery and debugging, including any Pisession_id.pi_read_result: reads an already completed result after an interrupted wait connection, including any Pisession_id.pi_apply_changes: conflict-checks and applies a completed isolated run's patch to the coordinator checkout. Passdry_run: trueto perform only the checks.pi_discard_workspace: removes a completed run's isolated worktree and branch.
Execution Profiles
pi_run and pi_start accept an optional agent profile. Profiles supply Pi's
tools, workspace mode, and role instructions at the bridge layer, so task text
should describe the desired outcome without restating the role:
explore: inspect and map relevant code, data flow, conventions, and risks. It runs in the current workspace withread,grep,find, andlsonly.review: independently audit correctness, regressions, security, and missing verification. It has the same read-only tools and reports findings by severity.implement: make and verify scoped changes with read/write tools in an isolated git worktree.
The selected profile overrides a caller-supplied workspace_mode. Explore and
Review are read-only at the Pi tool layer; they are not an operating-system
sandbox for untrusted repositories or tool implementations.
Session Continuation
pi_start accepts an optional session_id. When omitted, Pi creates a normal persistent session. The bridge captures session ids from Pi RPC responses/events and returns them from pi_wait, pi_read_result, and pi_get_run. Pass that value as session_id on a later pi_start to continue the same Pi conversation.
Workspace Isolation
pi_start accepts workspace_mode:
auto(default): create an isolated snapshot worktree containing current tracked and untracked coordinator state. Pi's returned patch contains only changes made after that snapshot.snapshot: require the snapshot behavior used byautofor git workspaces.clean_head: create the isolated worktree from cleanHEAD, excluding uncommitted coordinator state.worktree: require git worktree isolation and fail ifworking_directoryis not in a git repo.direct: run inworking_directory.
Worktree results do not inline full diffs into MCP responses. Instead, pi_start, pi_wait, pi_get_run, and pi_read_result return compact workspace metadata with paths and commands:
agent_working_directory: where Pi actually ran.branch,base_commit,target_commit, andworktree_path.changed_files,untracked_files, andhas_changes.status_path,patch_path, andmetadata_pathunder.pi-bridge/in the worktree.status_command,diff_command,apply_command, andmerge_command.
This lets the coordinator inspect changes with normal git commands, or apply the generated patch, without loading every changed line into the context window. In auto and snapshot modes, the worktree receives a private snapshot commit containing eligible coordinator changes; returned patches and diff_command show only the agent's changes after that snapshot.
Installation For Users
Install the package globally. Its install hook registers the bundled marketplace and installs the Codex plugin:
npm install --global pi-subagent-bridgeIf npm cannot run install scripts, finish setup explicitly with pi-subagent-bridge install. For a project-local package, use npx pi-subagent-bridge install.
Confirm that pi is on your PATH, then start a new Codex thread so the bundled skill and MCP tools are loaded. Ask Codex to run pi_doctor to verify the installation.
The installer reports the Pi executable it selected. If Pi is missing, install it with npm install --global @earendil-works/pi-coding-agent or set PI_EXECUTABLE, then rerun pi-subagent-bridge install.
To update, install the latest npm release:
npm install --global pi-subagent-bridge@latestDo not install from ~/.codex/plugins/cache; that directory is a local installed copy generated by Codex. The shareable package is this repository's marketplace layout:
.agents/plugins/marketplace.jsonplugins/pi-subagent-bridge/.codex-plugin/plugin.jsonplugins/pi-subagent-bridge/.mcp.jsonplugins/pi-subagent-bridge/skills/plugins/pi-subagent-bridge/server/
The root .codex-plugin, .mcp.json, skills/, and server/ directories mirror the plugin for local development.
Development Setup
cd server
npm install
npm run buildFor marketplace installation testing, build the nested plugin server too:
cd plugins/pi-subagent-bridge/server
npm install
npm run buildThe root server and skill directories are canonical. After building, synchronize the installable plugin bundle with:
node scripts/sync-plugin.mjs
node scripts/sync-plugin.mjs --checkConfiguration
Environment variables:
PI_EXECUTABLE: optional Pi executable override. By default the bridge detectspionPATHand in common user-local install locations, then uses its absolute path. When Pi is found outside the inheritedPATH, its bin directory is placed first for Pi so#!/usr/bin/env nodelaunchers use the matching Node runtime.PI_RPC_ARGS: override Pi RPC args. Default:--mode rpc.PI_RPC_SESSION_ID_FLAG: flag used whenpi_start.session_idis provided. Default:--session-id.PI_RPC_NO_SESSION_FLAG: optional flag to append for starts withoutsession_id. Leave unset for persistent Pi sessions; set to--no-sessionto force ephemeral sessions.PI_RPC_MODEL_LIST_METHOD: defaultget_available_models.PI_RPC_START_METHOD: defaultprompt.PI_RPC_STEER_METHOD: RPC method used for steering. Defaults toPI_RPC_START_METHOD.PI_RPC_ABORT_METHOD: defaultabort.PI_ALLOWED_ROOTS: path-delimited roots allowed forworking_directory. Default: the current user's home directory.PI_BRIDGE_WORKTREE_ROOT_NAME: repo-local directory name for isolated git worktrees. Default:.pi-subagent-runs.PI_BRIDGE_DATA_DIR: SQLite state directory. Default:$XDG_STATE_HOME/pi-subagent-bridge, then$HOME/.local/state/pi-subagent-bridge, with the OS temporary directory as a fallback.PI_CODING_AGENT_DIRandPI_CODING_AGENT_SESSION_DIR: optional Pi state overrides. When the agent directory is unset, the bridge reuses an existing$HOME/.pi/agent(or the process account's home) so Pi authentication, providers, and models match the user's CLI; otherwise it falls back toPI_BRIDGE_DATA_DIR/pi-agent. Sessions default toPI_BRIDGE_DATA_DIR/pi-agent/sessionsand remain separate from interactive Pi sessions.PI_BRIDGE_MAX_RUNTIME_MS: default1800000.PI_BRIDGE_STOP_GRACE_MS: default5000.PI_BRIDGE_MAX_TOOL_CALLS: default1000.PI_BRIDGE_MAX_RUNS: default200.PI_BRIDGE_MAX_CONCURRENT_RUNS: default4; additional starts fail withRUN_CONCURRENCY_LIMIT.PI_BRIDGE_KILL_GRACE_MS: delay between terminalSIGTERMand fallbackSIGKILL. Default:500.PI_BRIDGE_MODEL_CACHE_TTL_MS: model catalog cache TTL. Default:60000.PI_RPC_REQUEST_TIMEOUT_MS: timeout for an individual RPC request. Default:120000.PI_RPC_IGNORE_NON_JSON_NOISE: set to1to ignore non-JSON stdout lines instead of failing the run.PI_BRIDGE_MAX_SNAPSHOT_FILE_BYTES: maximum copied untracked-file size. Default:10485760;.env*and common private-key files are always skipped.
The bridge preserves the environment that found Pi when launching it, so a Pi
launcher using #!/usr/bin/env node can select its compatible bundled Node.js
runtime. pi_doctor reports the resolved Node.js and Pi executable paths.
PI_BRIDGE_REDACT_FINAL_ANSWERS: set to1to redact likely secrets before persisting final answers. Returned live answers are unchanged.PI_BRIDGE_AUTO_DISCARD_AFTER_APPLY: set to1to remove a worktree after its patch applies successfully.
Development
cd server
npm run format
npm run format:check
npm run typecheck
npm testTests use server/test/fixtures/fake-pi.py, a deterministic JSONL executable that mimics Pi RPC behavior.
Before opening a pull request, also validate that the checked-in installable bundle matches the development source:
node scripts/sync-plugin.mjs --check
node scripts/validate-plugin.mjsSecurity Notes
- MCP protocol responses are written only to stdout. Operational logs are structured JSON lines on stderr.
- Working directories are restricted to configured allowed roots, reject
..traversal segments, and are checked through canonical paths to prevent symlink escapes. - Tool-call audit storage records only
tool_execution_startmetadata. It never persists tool results, output chunks, ortool_execution_endresult content. - Arguments are redacted for likely credentials, tokens, passwords, authorization headers, and common API-key patterns before persistence.
- Completed model responses are persisted only as final answers for interrupted-wait recovery.
- Final answers may contain secrets. Enable
PI_BRIDGE_REDACT_FINAL_ANSWERS=1when recovery fidelity is less important than minimizing persisted secret risk. - Report suspected vulnerabilities privately as described in SECURITY.md.
License
MIT. See LICENSE.
Troubleshooting
- If
pi_list_modelsfails, confirm your Pi RPC model-list method matchesPI_RPC_MODEL_LIST_METHOD. - If
pi_startfails immediately, verifyPI_EXECUTABLE,PI_RPC_ARGS, andPI_ALLOWED_ROOTS. - If a run times out, raise
PI_BRIDGE_MAX_RUNTIME_MSor inspectpi_get_run. - If cancellation seems slow, lower
PI_BRIDGE_STOP_GRACE_MS; the server escalates only after the grace period.
