@tian.zuo/pi-devin-acp
Use Devin (devin acp) models inside the pi coding agent over the Agent Client Protocol, with pi as the UI.
Package details
Install @tian.zuo/pi-devin-acp from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@tian.zuo/pi-devin-acp- Package
@tian.zuo/pi-devin-acp- Version
0.3.4- Published
- Sep 19, 2026
- Downloads
- 323/mo · 323/wk
- Author
- tian.zuo
- License
- MIT
- Types
- extension
- Size
- 281.5 KB
- Dependencies
- 5 dependencies · 4 peers
Pi manifest JSON
{
"extensions": [
"./index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@tian.zuo/pi-devin-acp
Use Devin models inside pi by driving the Devin CLI as an ACP (Agent Client Protocol) server.
pi -e ./extensions/pi-devin-acp.ts --model devin/swe-2
Devin runs its own agent loop server-side — this extension keeps that loop intact and surfaces it in pi: streamed text and thinking, tool cards, usage, permissions, modes, and persistent sessions.
Requirements
devinCLI ≥3000.10.0onPATH(orDEVIN_BINARY=/path/to/devin)- Authenticated once via
devin auth login(orWINDSURF_API_KEY)
Models
Run devin models list to see the catalog. The extension registers one pi
model per Devin model family/variant and resolves pi's thinking suffix to a
concrete Devin row:
| pi model | resolves to (examples) |
|---|---|
devin/adaptive |
Devin's auto model selection |
devin/swe-2 |
swe-2-medium (default) |
devin/swe-2:max |
swe-2-max |
devin/claude-opus-5:high |
claude-opus-5-high |
devin/claude-opus-5-fast:low |
claude-opus-5-low-fast |
devin/gpt-5.4:off |
gpt-5-4-none |
devin/gpt-5.4-fast:high |
gpt-5-4-high-priority |
devin/claude-sonnet-4.6:high |
claude-sonnet-4-6-thinking |
Requested thinking levels resolve to the highest available Devin variant at or
below that level (e.g. :xhigh on a family without xhigh picks high).
Model discovery runs devin models list, caches the parsed catalog in
~/.pi/devin-acp/models.json, and falls back to a bundled snapshot when the CLI is
unavailable.
Commands
/devin— current session, model, mode, and turn stats/devin reset— drop the Devin session binding (next turn starts fresh)/devin sessions— list Devin sessions; attach or delete one/devin-tasks— list Devin operations still in flight (slow execs, detached background shells) in a /ps-style overlay:enteropens a read-only detail view (invocation info + live streamed output with tabs and scrolling),xasks Devin to stop a background shell,ddrops a stale entry (it reappears on the op's next update if it is genuinely still running)/devin-usage— account quota plus session usage: daily/weekly quota windows with reset times and the extra-usage balance (the sameGetUserStatusdata Devin CLI's/usageshows), then the ACP-reported session view — context-window bar, cumulative tokens/cost (credits/ACUs when billed), and last-turn stats. While a Devin model is selected the footer status line also shows the compact quota (devin 100% day 81% wk, remaining percents, refreshed on session start, model select, and turns with a 60s cache)/devin mode [ask|plan|accept-edits|bypass]— get/set Devin's permission mode/devin yolo [on|off]— persistently pin Devin tobypassmode (~/.pi/devin-acp/settings.json); while on,/devin modestays bypass and any permission request that still arrives is auto-approved/devin models— re-discover models and re-register the picker/devin login— trigger Devin's browser authentication/devin doctor— binary, auth, catalog, and runtime diagnostics/devin-<sub>— the hyphenated aliases (/devin-sessions,/devin-reset,/devin-models,/devin-mode,/devin-yolo,/devin-login,/devin-doctor) run the matching/devin <sub>command inline/devin-<name>— run Devin's own slash commands and skills-as-commands (e.g./devin-compact). Only exists while a Devin model is selected; forwards/<name> argsinto the ACP session/compactunder a Devin model runs Devin's compaction instead — every pi compaction pass is vetoed (session_before_compact), and a manual/compact [instructions]is forwarded into the ACP session. Auto triggers (the context threshold, overflow recovery) are vetoed silently: Devin compacts itself internally and reports it viacompaction_update./skill:<name>under a Devin model runs Devin's same-named skill-command; pi's own skill never expands.
How it works
- One
devin acpchild process (stdio NDJSON/JSON-RPC) hosts ACP sessions. - Each pi session branch binds to one Devin session id; the binding persists in
pi's session file (
pi-devin-acp-session-stateentries) so reloading pi resumes the same Devin session viasession/load. - Streamed
session/updatenotifications become pi thinking/text blocks, tool-card placeholders, and usage. Billable tokens and estimated cost are delta-billed: each pi assistant message of a turn (replay segment or terminal) persists only the share not already billed, so pi's footer fills live while the session log still sums to the authoritative turn total.usage.totalTokensseparately reports Devin's context occupancy (usage_update.usedscaled into the model window) rather than the billed sums, so pi's context gauge and auto-compaction threshold see the real fill level — summed internal requests would otherwise read as a bogus context overflow. Pi also treatsinput + cacheReadas a single request's prompt size: when aggregated billing exceeds the model window, the excess is stored incacheWriteas a synthetic overflow bucket (including uncached input if necessary). Token totals are preserved; costs are calculated before this adaptation from the original token classes, so the synthetic counters must not be used to recalculate costs./devin-usageshows live usage; failed or aborted streams record their latest observed turn usage, and successful summaries record their own usage. - Devin tool calls appear as display-only
devintool calls; pi "executes" them by replaying the recorded Devin result, then re-enters the provider. session/request_permissionprompts through pi's select UI and reportsagent:input_required(plus the legacyherdr:blockedalias) on pi's event bus while it waits, so integrations such as Herdr can flag the session as blocked. Headless runs deny by default; setPI_DEVIN_HEADLESS_PERMISSION=allowto auto-allow.- Pi-side compaction is vetoed for Devin models (
session_before_compact). Devin compacts its context server-side on its own — only a manual/compactis routed to Devin's/compact. Branch-summary prompts still run in disposable ACP sessions, synced to the selected model, so they never pollute the real Devin session's history. - Switching between Devin models keeps the live session — the new model is
applied via
session/set_config_option. Switching to or from another provider re-bootstraps the next turn from pi's transcript. - A message that arrives while a Devin turn is still running (steering text, a
/devin-tasksshell stop) becomes the next prompt in the same session: the ACP channel takes one prompt at a time, so the in-flight turn is cancelled and the new prompt is issued once Devin acknowledges the cancel. - Long-running Devin operations (foreground
sleep-style execs, shells detached to the background via_meta["cognition.ai/background"]) are tracked as live ops: a status-bar widget showsdevin: N running — …while any are in flight, and/devin-taskslists them. A backgrounded shell that outlives its turn replays as a neutral note (with its shell id) instead of a failure card; it drops off the list when itsterminal_exitarrives. In the picker,xasks Devin to stop a background shell andddrops an entry that was stranded without a terminal update (a genuinely running op re-adds itself on its next update). A cancelled prompt sweeps its in-turn ops automatically after a short grace window (swept ids are tombstoned against late updates); detached background shells stay listed until theirterminal_exit. Closing the runtime (/new,/quit,/reload) kills detached background shells together with thedevin acpchild — their process groups are signalled before the child dies, so nothing is orphaned. - Backend reconnects surface in the same status-bar widget: devin reports
_cognition.ai/connection_retry(attempt,maxAttempts,isStreamRetry) per attempt while a prompt waits on the stream, and pi showsdevin: connection failed (attempt N/M), retrying…— orconnection lostfor mid-stream drops — until updates resume, the turn settles, or the state goes stale.
Environment variables
| Variable | Purpose |
|---|---|
DEVIN_BINARY |
Path to the devin binary (default: PATH) |
PI_DEVIN_DEBUG=1 |
Log devin-acp stderr lines to pi's stderr |
PI_DEVIN_HEADLESS_PERMISSION |
allow auto-approves prompts without a UI |
DEVIN_MODEL |
Devin-side default model for new sessions |
Notes and limits
- Devin ACP does not implement
session/resume,session/fork, orsession/close— the extension usessession/load/session/newonly. - Empty Devin sessions are not persisted server-side; the binding falls back to
session/newif a stored session is gone. - MCP servers cannot be attached through ACP (
mcpCapabilitiesaccepts stdio only, unused here); Devin's own MCP config applies. - Devin's slash commands and skills-as-commands arrive via
available_commands_update(counted in/devinstatus);/devin-<name>is intercepted and forwards/<name> argsto Devin, which runs it server-side. before_provider_requestfires for devin turns with the ACP prompt request ({ sessionId, prompt }); returning an object with a replacementpromptswaps the outgoing content blocks.after_provider_responsenever fires: it reports an HTTP status and headers, and ACP over stdio has neither.
Development
pnpm run check # typecheck (tsc --noEmit)
pnpm test # unit tests + a live ACP round-trip (skipped without devin)