@geohar/pi-acp
ACP adapter for pi coding agent (fork), with a bundled pi extension for subagent→plan
Package details
Install @geohar/pi-acp from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@geohar/pi-acp- Package
@geohar/pi-acp- Version
0.3.1- Published
- Aug 31, 2026
- Downloads
- 1,289/mo · 249/wk
- Author
- georgeharker
- License
- MIT
- Types
- extension
- Size
- 433.1 KB
- Dependencies
- 2 dependencies · 0 peers
Pi manifest JSON
{
"extensions": [
"./src/pi-extension.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-acp
ACP (Agent Client Protocol) adapter for pi coding agent (fka shitty coding agent).
pi-acp communicates ACP JSON-RPC 2.0 over stdio to an ACP client (e.g. Zed editor) and spawns pi --mode rpc, bridging requests/events between the two.
Status
This is an MVP-style adapter intended to be useful today and easy to iterate on. Some ACP features may be not implemented or are not supported (see Limitations). Development is centered around Zed editor support, other clients may have varying levels of compatibility.
Expect some minor breaking changes.
Differences from upstream
This is a fork of svkozak/pi-acp, published to npm as
@geohar/pi-acp (upstream is unscoped pi-acp).
Why a fork. It exists to carry capabilities upstream doesn't have — chiefly surfacing the
pi-subagents fleet as ACP tasks, auto-configuring MCP
for pi, multi-root workspaces, and moving toward ACP v2 — and to iterate on them independently. It's
an independent fork published under the @geohar scope so it can be installed and depended on
directly; it does not track upstream on a schedule, and there's no commitment to contribute these
changes back (they may or may not be upstreamed later). If you want the original, use
svkozak/pi-acp.
On top of upstream it adds:
- Subagents as ACP tasks — a bundled pi extension bridges the
pi-subagents fleet into the ACP
planchannel, so each subagent shows up as a task. See Subagents as tasks. - MCP auto-configuration — ACP
mcpServersare translated into a generated<cwd>/.pi/mcp.jsonfor pi-mcp-adapter to load. See MCP servers. - Multi-root workspaces — additional workspace roots on
session/new/session/load(sessionCapabilities.additionalDirectories), communicated to pi via--append-system-prompt. - v2-oriented session capabilities — advertises
session/resume,session/close, andmcpCapabilities.http(steps toward ACP v2 parity; seedocs/v2-parity-and-mcp-plan.md). PI_ACP_DATA_DIR— env override for the adapter's own data directory (see Environment variables).
Features
- Streams assistant output as ACP
agent_message_chunk - Maps pi tool execution to ACP
tool_call/tool_call_update- Tool call locations are surfaced when available for ACP clients that support opening the referenced file/context
- Relative file paths from pi are resolved against the session cwd before being emitted as ACP tool locations, which enables follow-along features in clients like Zed
- For
edit,pi-acpattempts to infer a 1-based line number from a uniqueoldTextmatch in the pre-edit file snapshot and includes it in the emitted tool location when possible - For
edit,pi-acpsnapshots the file before the tool runs and emits an ACP structured diff (oldText/newText) on completion when possible
- Session persistence
- pi stores its own sessions in
~/.pi/agent/sessions/... pi-acpstores a small mapping file at~/.pi/pi-acp/session-map.jsonsosession/loadcan reattach to a previous pi session file
- pi stores its own sessions in
- Multi-workspace support (
sessionCapabilities.additionalDirectories)- ACP clients can pass additional workspace roots on
session/new/session/load(e.g. Zed multi-root workspaces) cwdstays the primary working directory; the additional roots are communicated to pi via--append-system-prompt, since pi has no native multi-root workspace concept
- ACP clients can pass additional workspace roots on
- Slash commands
- Loads file-based slash commands compatible with pi’s conventions
- Adds a small set of built-in commands for headless/editor usage
- Supports skill commands (if enabled in pi settings, they appear as
/skill:skill-namein the ACP client)
- Skills are loaded by pi directly and are available in ACP sessions
- (Zed)
pi-acpemits “startup info” block into the session (pi version, context, skills, prompts, extensions - similar topiin the terminal). You can disable it by settingquietStartup: truein pi settings (~/.pi/agent/settings.jsonor<project>/.pi/settings.json). WhenquietStartupis enabled,pi-acpwill still emit a 'New version available' message if the installed pi version is outdated. - (Zed) Session history is supported in Zed starting with
v0.225.0. Session loading / history maps to pi's session files. Sessions can be resumed both inpiand in the ACP client.
Prerequisites
Make sure pi is installed
npm install -g @earendil-works/pi-coding-agent
- Node.js 22+
piv0.80.4+ installed and available on yourPATH(the adapter runs thepiexecutable)- Configure
piseparately for your model providers/API keys
Install
Add pi-acp to your ACP client, e.g. Zed
Using ACP Registry in Zed or other clients that support it
In Zed launch the registry with zed: acp registry command and select pi ACP adapter from the list. This will automatically add the agent server configuration to your settings.json and keep it up to date:
"agent_servers": {
"pi-acp": {
"type": "registry",
},
}
Using with npx (no global install needed, always loads the latest version)
Add the following to your Zed settings.json:
"agent_servers": {
"pi": {
"type": "custom",
"command": "npx",
"args": ["-y", "@geohar/pi-acp"],
"env": {}
}
}
Global install
npm install -g @geohar/pi-acp
"agent_servers": {
"pi": {
"type": "custom",
"command": "pi-acp",
"args": [],
"env": {}
}
}
From source
npm install
npm run build
Point your ACP client to the built dist/index.js:
"agent_servers": {
"pi": {
"type": "custom",
"command": "node",
"args": ["/path/to/pi-acp/dist/index.js"],
"env": {}
}
}
Settings (pi-acp.json)
pi-acp reads its own settings from pi-acp.json in the pi agent's extensions/ directory — i.e. <PI_CODING_AGENT_DIR>/extensions/pi-acp.json (default ~/.pi/agent/extensions/pi-acp.json), alongside other extensions' settings. This is a dedicated pi-acp file; it is not merged into pi's own settings.json. A default file is written on first run if one does not already exist, and an existing file is never overwritten. For backward compatibility the pre-0.2.2 location — <PI_CODING_AGENT_DIR>/pi-acp.json (agent root) — is still read as a fallback when no file exists in extensions/.
Options:
embeddedContext(boolean, defaulttrue) — advertises ACPpromptCapabilities.embeddedContextto the client. Whenfalse, compliant ACP clients should avoid sending embeddedresourceblocks; if they send them anyway,pi-acpstill degrades gracefully by converting them into plain-text prompt context.rpcTimeoutMs(number, default120000) — per-request timeout for pi RPC calls. Generous so legitimately slow commands (e.g. compaction) finish.debug(boolean, defaultfalse) — emit adapter debug logging to stderr.piCommand(string, optional) — override the pi executable name/path. Absent = platform default (pi, orpi.cmdon Windows).dataDir(string, optional) — override pi-acp's own data directory. Absent =~/.pi/pi-acp. This controls where the session-map file and any future adapter-owned data is stored; it is separate fromPI_CODING_AGENT_DIR, which rehomes pi's own agent directory (and henceextensions/pi-acp.json).
The default file written on first run contains:
{
"embeddedContext": true,
"rpcTimeoutMs": 120000,
"debug": false
}
Slash commands
pi-acp supports slash commands:
1) File-based commands (aka prompts)
Loaded from:
- User commands:
~/.pi/agent/prompts/**/*.md - Project commands:
<cwd>/.pi/prompts/**/*.md
2) Built-in commands
/compact [instructions...]– run pi compaction (optionally with custom instructions)/autocompact on|off|toggle– toggle automatic compaction/export– export the current session to HTML in the sessioncwd/session– show session stats (tokens/messages/cost/session file)/name <name>– set session display name/queue all|one-at-a-time– set pi queue mode (unstable feature)/changelog– print the installed pi changelog (best-effort)/steering- maps topiSteering Mode, get/set/follow-up- pats topiFollow-up Mode, get/set
Other built-in commands:
/model- not implemented (use the model selector UI in Zed)/thinking- maps to 'mode' selector in Zed/clear- not implemented (use ACP client 'new' command)
3) Skill commands
- Skill commands can be enabled in pi settings and will appear in the slash command list in ACP client as
/skill:skill-name.
Note: Slash commands provided by pi extensions are not currently supported.
Subagents as tasks
pi itself emits no ACP plans, so the ACP plan (task-list) channel is unused. When you use the
pi-subagents extension, pi-acp can surface the running
subagent fleet as an ACP plan — each subagent becomes a task with pending / in_progress /
completed status.
Because pi's RPC mode does not forward pi's in-process event bus (subagents:*), the bridging is
done by a pi extension. The pi-acp package doubles as that extension (src/pi-extension.ts,
declared under pi.extensions): loaded inside pi, it subscribes to the bus and, for each change,
persists a CustomEntry via pi.appendEntry("acp:subagents", <record>). Appending emits an
entry_appended event, which pi forwards over RPC (unlike the bus itself); the adapter decodes it
into a plan update. CustomEntry (not CustomMessageEntry) is used deliberately so the fleet
state is recorded without entering the model's context. entry_appended forwards while a turn is
active (subagents run inside turns), so plan updates track the fleet during a prompt.
No configuration — it just works once the two packages are installed:
pi install npm:@tintinweb/pi-subagents
pi install npm:@geohar/pi-acp # loads the pi.extensions entry (the bridge)
The adapter marks the pi process it spawns with PI_ACP=1, which activates the bundled extension
there; the extension stays inert in a normal terminal pi session (no marker), so it has no effect
outside the adapter.
ACP PlanEntryStatus has no failed value, so a failed subagent is shown as completed with a
(failed) annotation.
Authentication (ACP Registry support)
This agent supports Terminal Auth for the ACP Registry. In Zed, this will show an Authenticate banner that launches pi in a terminal. Launch pi in a terminal for interactive login/setup:
pi-acp --terminal-login
Your ACP client can also invoke this automatically based on the agent's advertised authMethods.
Development
npm install
npm run dev # run from src via tsx
npm run build
npm run lint
npm run test
Project layout:
src/acp/*– ACP server + translation layersrc/pi-rpc/*– pi subprocess wrapper (RPC protocol)
Limitations
- No ACP filesystem delegation (
fs/*) and no ACP terminal delegation (terminal/*). pi reads/writes and executes locally. - No ACP permission gating (
session/request_permission): pi executes tools locally and does not surface pre-execution tool intents over RPC, so the adapter cannot gate them yet.
MCP servers
MCP servers passed by the ACP client (session/new, session/load, session/resume) are translated
into a session-scoped temp file and handed to pi-mcp-adapter
via pi --mode rpc --mcp-config <tempfile>. stdio and http servers are supported; sse/acp servers
cannot be expressed and are skipped with a notice. The temp file is removed when the session closes.
Install pi-mcp-adapter in your pi packages for the servers to actually load — the adapter emits a
startup notice when it is missing.
The temp file may hold secrets the client sent literally (an Authorization header value, or stdio
env values), so it is written in an owner-only (0700) temp dir with 0600 permissions. To keep a
bearer token off disk entirely, express it as $env:VAR (via the policy's auth.bearerTokenEnv, or a
$env:-valued header from the client) — pi-mcp-adapter resolves $env: at connect, so only the
placeholder is written.
pi-acp deliberately does not write <cwd>/.pi/mcp.json. That path is pi's own highest-precedence
project config namespace (settings, prompts, trust, mcp): writing there overrode the user's global
MCP config, persisted past the session, and leaked into unrelated (even non-ACP) pi sessions launched
from the same directory. --mcp-config overrides only pi-mcp-adapter's pi-global source, never pi's
config dir, so all of pi's own MCP config (global and project) still flows through. A stale
<cwd>/.pi/mcp.json left by an older pi-acp version (marked _generatedBy: pi-acp) is cleaned up
automatically.
MCP generation policy
By default pi-acp generates every ACP-provided server into the temp overlay (additive — it never
overrides your own config). To control which servers it generates — same semantics pi uses for
subagent tool/extension inheritance — create ~/.pi/pi-acp/mcp-policy.json (under PI_ACP_DATA_DIR):
{
"generate": "*",
"exclude": ["mcp-combiner"],
"auth": {
"some-http-server": { "bearerTokenEnv": "MY_TOKEN", "headers": { "X-Extra": "v" } }
}
}
generate— which servers pi-acp may write:true/"*"/omitted = all (default) ·["a","b"]= only those ·false= none. Servers not generated are left to your own (lower-precedence) config.exclude— denylist (wins overgenerate): never generate these. Use it for a server you configure globally with its own auth (e.g. a bearer-auth'd combiner) so pi-acp doesn't override it.auth— for a server pi-acp does generate, writeAuthorization: Bearer $env:<VAR>(+ extra headers). pi-mcp-adapter interpolates$env:at connect, so the token is never written to disk.
Names are case-insensitive. Note the ACP MCP shape has no dedicated auth field, so bearer auth can
only travel as an HTTP header — either provided by the client in the server's headers, or added via
this policy's auth.
- Additional workspace roots are not a hard filesystem boundary: pi can operate outside them. They are communicated to the model (workspace awareness), not enforced as a sandbox.
- Assistant streaming is currently sent as
agent_message_chunk(no separate thought stream). - Queue is implemented client-side and should work like pi's
one-at-a-time ACP clients don't yet suport session history, but ACP sessions frompi-acpcan be/resumed in pi directly
License
MIT (see LICENSE).