An adapter connects one coding agent to the companion. Everything specific to that agent lives in its folder here. The core never names an agent; it reaches it only through the contract in src/core/adapter.ts.
Start from the adapter closer to yours:
| Claude Code | Codex | Pi | |
|---|---|---|---|
| Requests reach it through | an MCP channel (channel-server.ts) |
its app server (app-server.ts) |
the companion's extension (extension.ts) |
| Observed through | hooks, or its transcript | hooks and its transcript | the same extension, posting to /hook |
- Launch the agent's own command unchanged, adding only what the companion needs: hooks that run the relay (
hook-command.ts), and a way in for requests (launch.ts). Refuse arguments that would hide the agent from the companion (arguments.ts). - Observe every event, from a hook or the transcript, as an
Observation: a shared kind, the agent's own name for the event, the whole event as JSON, and the turn state after it. Refuse another session's events (observer.ts, built onagent-observer.ts;transcript-tail.tsfollows a transcript file). - Filter what reaches GPT Live with one table of rows (
context.ts). A row removes an event or keys, or truncates keys to a number of characters, cut from the middle. Its paths step through lists, and its conditions can name nested fields. The core already omits base64 data and the echo of a voice request, and notes any record still over about 1,200 tokens: that note shows where a row is missing. Leave out the agent's own housekeeping text that restates or predicts the conversation, such as compaction summaries, recaps and suggested next prompts: GPT Live has taken the operator's words in it for the operator speaking. - Deliver a spoken request into the running agent, mid-turn when it can, and report whether it was sent. Never resend (
delivery.ts). Recognize the request when the agent shows it back as a prompt (receivedRequest). If the agent treats the way in as external input, say through its prompt hook that a delivered request is the operator's own speech (vouch; Claude needs this). - Describe the agent for prompts and the page: its names, the event that ends a turn, whether a running turn can take a request (
profile.ts). - Register the
AgentDefinition, withdoctorand help text, inindex.ts, and add it tosrc/adapters/index.ts.fdc <agent>,fdc doctor,fdc --help, the voice prompts and the page pick it up from there.
Then copy the adapter's tests and use the agent through fdc for real: see CONTRIBUTING.md. The design rules behind all this are in PRINCIPLES.md.