Skip to content

feat(claude-code-cli): add the pi:interactive native target - #213

Merged
goldmedal merged 3 commits into
mainfrom
feat/pi-interactive-target
Oct 6, 2026
Merged

goldmedal merged 3 commits into
mainfrom
feat/pi-interactive-target

Conversation

@goldmedal

Copy link
Copy Markdown
Collaborator

Why

GenBI wants a vendor-neutral native session runtime for API-key vendors (anything other than Claude Code and Codex). The pi coding agent (earendil-works/pi) fits that role, but it ships no permission system: it executes every tool call with the account's OS permissions. A Warble target for pi therefore has one job — author a launch contract that leaves the session nothing but the host-owned MCP server, and refuse every shape it cannot keep inside that contract.

What

A fifth native target, pi:interactive, folded into the warble binary next to codex:interactive.

  • warble dispatch ir.json --target pi:interactive --purpose analysis --native-scope scope.json --native-mcp mcp.json --pi-model <provider>/<model-id> --out <cwd> emits:
    • .warble/pi/SYSTEM.md — the authored system prompt (brief + analysis prompt fragment + scope/safety instructions + the shared persistence/presentation/dashboard instructions), handed to pi through --system-prompt, which replaces its default prompt;
    • .warble/pi/agent/settings.json and .warble/pi/agent/mcp.json — the server-owned pi agent directory (PI_CODING_AGENT_DIR). Project trust is refused, telemetry is off, pi's own retries are off, and the MCP credential is referenced through ${WARBLE_MCP_CONNECTION_CREDENTIAL} so the file never carries it (same posture as Codex's bearer_token_env_var);
    • RUN.md, .warble/interactive-launch.json (v4, or v5 with --native-host) and .warble/interactive-ownership.json.
  • The launch spec's argv starts an RPC session with every pi discovery mechanism switched off by name and an explicit --tools mcp__genbi_session__… allowlist. --no-tools is deliberately not used: it also drops MCP tools. The spec's new pi object carries the one-shot JSON-mode argv (prompt positional after --), the first prompt for the RPC prompt command, the agent directory, the required environment, and the minimum pi version (1.0.4, the first release whose --tools keeps MCP tools when named).
  • Capability profile: analytical capabilities are realized through the host MCP server; mutation, approval, repository-read and setup/enrichment capabilities fail loudly; divergent step tiers degrade to the single session model unless a --native-host plan runs the steps.
  • Wall-hits, each named: any purpose other than analysis, a missing --native-mcp, a missing or malformed --pi-model, --provider fragments, scope entry, component composition without a host, and any component whose shape no host MCP tool serves.

No existing target's output changes; claude-code:* and codex:interactive launch specs are byte-identical to before (the only shared-code change threads an optional pi input through the launch-spec renderer).

Verification

Gate Result
cargo fmt --all --check PASS
cargo clippy --workspace --all-targets --locked -- -D warnings PASS
cargo build --workspace --locked PASS
cargo test --workspace --locked PASS (see summary below)
RUSTDOCFLAGS=-D warnings cargo doc --workspace --no-deps PASS
cli/tests/pi_interactive_dispatch.rs (8 tests) PASS
cargo build --release -p warble-cli + just install-ts lint-ts test-ts build-ts PASS
just install-codex-ts lint-codex-ts test-codex-ts build-codex-ts PASS
just install-bird-eval lint-bird-eval test-bird-eval build-bird-eval PASS
just publish-check PASS
actionlint not run locally (no workflow file is touched)

What I did not exercise:

  • No pi process is started by these tests or by Warble; the argv/env contract was measured against pi 1.0.4 separately (closed launch, --tools allowlist semantics, env-var interpolation in mcp.json, RPC lifecycle). A comma-separated --tools list with several exact names was not part of that measurement; only a single exact name and a mcp__* glob were.
  • The --native-host (v5) path for pi is covered by the shared host validation and plan writing, not by a pi-specific live test.
  • The TypeScript back-ends are untouched.

🤖 Generated with Claude Code

goldmedal and others added 3 commits October 6, 2026 13:47
A native session runtime is needed for API-key vendors other than Claude
and Codex, and the pi coding agent fits that role. pi ships no permission
system of its own, so this target's whole job is the launch contract: an
argv that disables every pi tool except the host-owned MCP server's, a
server-owned agent directory the target writes itself, an authored system
prompt, and loud wall-hits for every shape the contract cannot keep.

The target realizes `--purpose analysis` only, requires `--native-mcp` and
a `--pi-model <provider>/<model-id>`, rejects `--provider` fragments and
scope entry, and degrades divergent step tiers to the single session model
unless a host plan runs the steps. The MCP credential is referenced through
its environment variable in `mcp.json`, never written. Existing targets'
launch specs are unchanged; the renderer only gains an optional pi input.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…dash-leading model ids out of its argv

Review of the pi target found two gaps between what the code enforced and
what it claimed. `NativeHost::prepare` only knew the Claude and Codex
vendors, so `--native-host` with `pi:interactive` was refused as a
wall-hit while the docs and the capability profile said a host plan
restores exact step tiers; the vendor table now has a `pi` arm, with the
same no-scope-entry rule as Codex, and the v5 composed-session test
covers pi. `PiModel::parse` accepted a provider or model id starting with
`-`, which would have put an option-shaped value in a flag position of
the closed argv; both now fail validation.

Tests also cover a changed model being refused on repeat dispatch and the
dashboard-only tool allowlist.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ost-plan targets

`docs/site/docs/reference/direct-session.md` is generated from
`docs/spec/direct-session.md`; the previous commit edited the generated
page directly, so the docs-site workflow's generated-content check failed.
The change now lives in the source the generator reads.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@goldmedal
goldmedal merged commit 26aceda into main Oct 6, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant