ACP wrapper for the Pi coding agent (mirrors @agentclientprotocol/claude-agent-acp pattern)
- TypeScript 91.2%
- JavaScript 8.8%
|
All checks were successful
CI / build (push) Successful in 30s
Mirrors the @agentclientprotocol/claude-agent-acp pattern: one process
per ACP session, each spawning `pi --mode rpc` and translating frames
between ACP (JSON-RPC 2.0) and Pi's bare-JSON RPC.
What's wired:
- ACP initialize/newSession/prompt/cancel/setSessionModel
- Pi message_update (text + thinking) → agent_message_chunk / agent_thought_chunk
- Pi tool_execution_* → tool_call / tool_call_update
- ACP cancel → Pi abort; stopReason derived from Pi's done/error reason
- Prompt content blocks flattened to Pi's {message, images?} shape
What's not (yet):
- session/request_permission round-trips (Pi is auto-approve for now)
- loadSession (capability advertised false)
- extension UI dialogs surfaced through ACP
|
||
|---|---|---|
| .forgejo/workflows | ||
| src | ||
| .gitignore | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
pi-agent-acp
Agent Client Protocol wrapper for the Pi
coding agent. Speaks ACP on its
stdio, spawns pi --mode rpc per session, translates between the two.
Mirrors the shape of @agentclientprotocol/claude-agent-acp
and @zed-industries/codex-acp.
Usage
# inside a container or environment with `pi` on PATH:
pi-agent-acp [--pi-binary /path/to/pi] [--provider anthropic] [--model claude-sonnet-4-20250514]
The wrapper is a one-process-per-session bridge:
ACP client (Zed / OpenClaw acpx)
│ ACP / JSON-RPC 2.0 over stdio
▼
pi-agent-acp
│ Pi RPC (JSONL over stdio)
▼
pi --mode rpc
Mapping
| ACP | Pi RPC |
|---|---|
initialize |
(no-op; advertise capabilities) |
session/new |
spawn pi --mode rpc |
session/prompt |
prompt |
session/cancel |
abort |
agent_message_chunk update |
message_update with text_delta |
agent_thought_chunk update |
message_update with thinking_delta |
tool_call / tool_call_update |
tool_execution_* |
stopReason: "end_turn" |
done.reason = "stop" |
stopReason: "cancelled" |
error.reason = "aborted" |
Status
Experimental — first cut. Things that intentionally aren't wired up yet:
- ACP
session/request_permissioncallbacks (Pi handles permissions internally via its approval modes; we run Pi in auto-approve and never ask the ACP client to confirm tool calls). loadSession(the loadSession capability is advertised asfalse).- ACP audio / embedded-context content blocks.
- Surfacing Pi
extension_ui_requestdialogs back through ACP — they're currently logged and silently auto-resolved by Pi's defaults.
Layout
src/
├── lib.ts public exports
├── cli.ts bin entry — wires stdio to AgentSideConnection
├── acp-agent.ts implements ACP `Agent`, one PiRpcClient per session
├── pi-rpc-client.ts LF-framed JSONL client for `pi --mode rpc`
└── translate.ts pure event → ACP update mapping