pi-acp-provider1.2.1
Pi agent provider extension that delegates execution to any Agent Client Protocol (ACP) agent, such as GitHub Copilot CLI or Gemini CLI.
Untested on omp
This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.
Reports 0
No reports yet.
Readme
pi-acp-provider
A Pi provider extension that drives any Agent Client Protocol (ACP) agent, such as GitHub Copilot CLI, Gemini CLI, or any other command that speaks ACP over stdio.
┌────────────────────────────────────────────────────────┐
│ Pi TUI │
│ (Input bar, Stream Renderer, Status line) │
└───────────────────────────▲────────────────────────────┘
│ Pi AssistantMessageEventStream
┌───────────────────────────▼────────────────────────────┐
│ ACP Provider Extension │
│ streamSimple() → ACP client (NDJSON RPC) │
└───────────────────────────┼────────────────────────────┘
│ stdio (stdin / stdout), one process per agent
┌───────────────────────────▼────────────────────────────┐
│ ACP agent (e.g. `copilot --acp`, `gemini …`) │
│ (Autonomous agent, file tools, bash, LSP) │
└────────────────────────────────────────────────────────┘
Instead of Pi running its own LLM tool loop, the ACP agent does the work, the same way Zed uses ACP agents: it plans, edits files, runs commands, and streams progress back. Pi's own tools are bypassed. The agent runs everything itself in the session working directory.
Install
pi install npm:pi-acp-provider
Or from git: pi install git:github.com/R-Dson/pi-acp-provider.
To try it for one session without installing: pi -e npm:pi-acp-provider.
Configuration
Declare agents under acp.agents in ~/.pi/agent/settings.json (or
$PI_CODING_AGENT_DIR/settings.json). Each key becomes a model:
/model acp/<key>.
{
"acp": {
"autoApproveTools": true,
"agents": {
"copilot": { "name": "GitHub Copilot", "command": "copilot", "args": ["--acp"] },
"gemini": { "name": "Gemini", "command": "gemini", "args": ["--experimental-acp"] }
}
}
}
The commands above are examples. Check each agent's documentation for the flag that starts its ACP mode. With no agents configured, Pi shows a warning at startup and the provider has no models.
Models and thinking level
Models are discovered automatically. When Pi refreshes its model list (at
interactive startup and whenever /model opens), each agent is started and an
ACP session is opened to read the models it offers. They show up as
acp/<key>/<model id>, e.g. /model acp/copilot/gpt-5. acp/<key> keeps the
agent's own default. The list is saved, so pi -p and offline startups use the
last one found.
Both the ACP configOptions model selector and the older models /
session/set_model API are supported. If the agent exposes a thought_level
option, Pi's thinking level (shift+tab, --thinking) is applied to it; levels
the agent doesn't offer are hidden. Discovery never triggers authMethod
sign-in; that waits for the first prompt.
Agent slash commands
Each agent registers a Pi command named after its key. /<key> <command>
runs a slash command the agent advertises over ACP (available_commands_update),
e.g. /copilot context or /copilot session info for Copilot CLI. Arguments
autocomplete from the agent's current list. /<key> alone lists the commands.
Running one switches to that agent if another model is active, then sends
/<command> as the prompt, which is how ACP agents expect commands.
Per-agent keys:
| Key | Required | Meaning |
|---|---|---|
command |
yes | Executable, spawned in the session cwd. |
args |
no | Arguments, e.g. the agent's ACP flag. Default []. |
name |
no | Display name in the model picker and messages. Default: the key. |
env |
no | Extra environment variables for the agent process. |
authMethod |
no | ACP authenticate method id to use when the agent reports auth_required (see Auth below). |
Global keys:
| Key | Env override | Default | Meaning |
|---|---|---|---|
autoApproveTools |
ACP_AUTO_APPROVE |
true |
When false, each permission request opens a select dialog (TUI/RPC) or is denied (print/JSON mode). |
handshakeTimeoutMs |
30000 |
Milliseconds to wait for initialize, session/new, and model or thinking-level changes. |
|
ACP_DEBUG=1 |
off | Wire diagnostics on stderr. |
Behavior
- Lifecycle: each agent's process spawns lazily on its first prompt,
stays alive across prompts, and is killed on session shutdown (
/new,/resume, quit, reload). Each agent runs in its own process group, so the whole tree (including tool subprocesses) is killed. Parent signal hooks, shared by all agents, cover exits without a session shutdown. A crashed agent is respawned with a fresh session on the next prompt. - Session mapping: one ACP session per Pi session per agent. Each Pi model turn sends only the new user message, because the agent keeps conversation history on its side. Image attachments are noted but not forwarded.
- Streaming: ACP v1
session/updatenotifications.agent_thought_chunkmaps to Pi thinking blocks andagent_message_chunkto text blocks. Tool calls render as⚙️ Executing [title]...and, on completion,✓ title: <first line of output>(or✗on failure), including calls reported already finished. Other update kinds (plans, mode changes) are ignored. - Abort: Pi's abort signal (Ctrl+C) sends
session/canceland finalizes the message as aborted immediately. It answers any open permission prompt withcancelledand leaves the session usable. The next prompt waits (up to 5 s) for the agent to confirm the cancellation, so late updates can't leak into it. - Permissions:
session/request_permissionis auto-approved by default (allow_once, neverallow_always). SetautoApproveTools: falseto get an interactive select dialog that names the asking agent. - Auth: when an agent answers
session/newwith ACPauth_required(code -32000), the provider callsauthenticatewith the agent's configuredauthMethodand retries once. Without one, the error lists the auth methods the agent advertised ininitialize, so you can sign in with the agent's own CLI or pick a method. A missing command reports a not-found hint naming the agent. The provider registers as ambient-auth so/modelselection never blocks. - Usage: ACP does not report per-turn token usage, so the provider records zeros.
Known limitations
- No image input (prompts are sent as text only).
/resumeand/forkstart a fresh ACP session. Prior Pi history is not replayed to the agent, and switching models mid-conversation does not carry history across agents.- No ACP client capabilities (
fs,terminal) are offered, so agents use their own file and terminal tools. Other agent→client requests get method-not-found. - Of Pi's stream hooks,
onPayloadandonProviderStreamEventare honored.onResponseis HTTP-specific and not called.
Development
npm run typecheck # strict tsc, no emit
npm test # node:test suite against a scripted fake ACP agent
The fake agent (test/fake-agent.mjs) speaks ACP v1 wire shapes and covers
streaming, permissions (string request ids), cancellation, crashes, auth
(auth_required plus authenticate), refusals, and split NDJSON frames. No
real agent or network is needed.
Layout
src/acp.ts: ACP v1 / JSON-RPC wire types and boundary parserssrc/acp-client.ts: child process, NDJSON transport, handshake, sessions, authsrc/provider.ts: the PiProvider(agents and their discovered models), model and thinking-level selection, and event translationsrc/config.ts: settings and env resolutionsrc/index.ts: extension factory (pi.registerProvider, lifecycle wiring)