External agents (ACP)
Chimera can hand a coding turn to an agent it did not write — Claude Code, Gemini CLI, or any adapter that speaks the Agent Client Protocol. The transcript, the verifier, the checkpoint and the revert stay Chimera's; the work is somebody else's.
Why
Chimera's claim is not that its loop is the only good loop. It is the governance around a loop: the taint ledger, the write region, the snapshot before a turn, the verdict after it, the receipt that says what actually happened. Those apply to any worker. Refusing to drive a worker you already trust would mean insisting on the least interesting half of the product.
What is guaranteed, and what is not
Read this part before the setup, because it is the part that decides whether this feature is right for you.
An ACP agent declares which of the client's capabilities it will use, and Chimera offers
fs/read_text_file and fs/write_text_file. Offering is not enforcing. The agents worth driving
have file and shell tools of their own: Claude Code writes through the Claude Agent SDK, and it is
under no obligation to ask us first.
So, concretely:
| Chimera's own loop | External agent | |
|---|---|---|
| Write region refuses a write outside it | Always | Only for writes routed through us |
| Shell runs in the configured sandbox | Always | The agent runs commands its own way |
| Taint ledger arms the dangerous-tool gate | Always | Only for tools we mediate |
| Workspace snapshot before the turn | Yes | Yes |
| One-click revert of the whole turn | Yes | Yes |
| Every permission granted appears on the receipt | n/a | Yes |
The last three rows are the real guarantee, and they are what the posture line on the Code screen
promises when an external agent is selected. It stops saying "edits inside /project, runs no
commands" — that sentence describes tools Chimera owns — and says instead that a copy was taken and
the turn can be undone. A screen that kept the stronger sentence would be making a promise the turn
cannot keep.
Chimera also declines the ACP terminal capability. A terminal we hosted would be a second execution path beside the sandbox with none of its rules.
Setup
Nothing to configure for the agents Chimera knows:
npm i -g @agentclientprotocol/claude-agent-acp # Claude Code, needs Node 22+
npm i -g @google/gemini-cli # Gemini CLI (its ACP mode is experimental upstream)
Then check what this machine can actually run:
chimera doctor
external_agents reports each one with available: true/false and, when false, the line that fixes
it. Availability is resolved on the machine the sidecar runs on — which for a packaged desktop build
is a machine assembled by CI that nobody looked at, so "it should be there" is not evidence.
The desktop app shows a Worker row above the composer listing whatever doctor found. When
nothing runnable is installed the row does not appear at all; doctor is where "you do not have this
yet, here is how" belongs.
Credentials
Every child process Chimera spawns gets an environment with API_KEY / TOKEN / SECRET variables
stripped, so a shell command cannot echo a provider key. An ACP agent is a program whose entire job
needs one, so each agent declares the variables it needs by name and only those are put back:
- Claude Code:
ANTHROPIC_API_KEY,ANTHROPIC_AUTH_TOKEN,ANTHROPIC_BASE_URL,CLAUDE_CONFIG_DIR - Gemini CLI:
GEMINI_API_KEY,GOOGLE_API_KEY,GOOGLE_APPLICATION_CREDENTIALS
Passing the whole environment would be easier and would hand every future adapter every key on the machine.
A custom adapter
Codex and others reach ACP through third-party adapters this project has not run. Rather than list an unverified command — which turns "we did not check" into "supported" — point Chimera at the one you have:
// POST /api/code/turn
{
"message": "fix the failing test",
"provider": "custom",
"provider_command": "npx -y some-acp-adapter --flag"
}
The command is split shell-style and run without a shell, so a stray pipe is an argument rather
than a second command. On Windows, an argument containing cmd.exe syntax (& | < > ^ %) reaching a
.cmd launcher is refused rather than escaped: quoting rules differ per launcher and a wrong guess
runs your machine instead of a program on it.
How it works
- One child process per conversation, not per turn. A
session/promptis one message in a context the agent is keeping; a fresh process each time would make every turn turn one. - At most four live at once, and one untouched for an hour is closed. Each is a process holding a model connection.
- The process is started in its own group and killed as a tree — a coding agent is a launcher, and
killing only the process we hold would leave the workers running and the workspace locked. An
atexitreaper covers the app being quit mid-turn. - The agent's
session/updatenotifications are translated into the same events the native loop emits, so the screen needs no second implementation. Reasoning chunks are dropped rather than folded into the answer; adiffcontent block becomes the unified patch the transcript renders. - Numbers the native loop owns and this one cannot report —
steps,context_peak_tokens— arrive asnullrather than0. Zero would read as "it did nothing".
Limits
- Permission prompts are answered
allow_onceand recorded on the receipt. Gating a prompt the agent did not have to ask is theatre; the honest version is to grant, record, and rely on the checkpoint that also covers the writes which never asked. - Fusion, roles, memory recall and the repo map are Chimera's own loop. An external turn reports
fused: falseand no memory usage because none of it happened. - Gemini's ACP mode is flagged experimental upstream and its behaviour may change between releases.