Skip to content

Roadmap

  1. Port ClaudeAdapter exactly. ✅ Done.
  2. Add a second adapter, and extract the common contract from it.
  3. Settle AbstractAdapter after that.

ActiveRecord also started with MySQL alone.

Provider differences — codex’s threadId, and whatever the others turn out to spell differently — only become visible when the second adapter is attached. A common contract designed from Claude alone is a guess dressed as an abstraction.

AbstractAdapter is therefore kept deliberately small while only one subclass exists:

abstract class AbstractAdapter {
abstract get command(): string;
abstract buildArgv(options: SpawnOptions): string[];
abstract spawn(options: SpawnOptions): ChildProcess;
abstract parseLine(line: string): AbstractEvent | null;
abstract reportedMode(event: AbstractEvent): PermissionMode | null;
}

A contract drawn from a single implementation is a guess; the shape that survives two is the one worth committing to.

The largest competing plugin, jetbrains-cc-gui (★5,315), attached six adapters under ai-bridge/channels/ — claude, codex, grok, kimi, opencode, pi — with no common contract between them.

  • Claude’s send: sessionId + disableThinking + agentPrompt
  • Codex’s send: threadId + baseUrl + apiKey + serviceTier

The same send, with different parameters, and command lists that do not match either — Claude has seven, Codex three. The caller has to know who it is talking to before it can build a payload. That is not integration; it is separate storage in one cupboard.

The cause is structural: export async function handleClaudeCommand(command, args, stdinData) — functions scattered across modules, dispatched by a large switch, with state passed along as arguments. This is the concrete counter-example the design principles aim at, and the evidence that a function-module approach leads to a failed abstraction.

A provider is not finished when it spawns. The bar is the one the first consumer sets: every call site in Swttch that drives a CLI must be replaceable. Where Claude is concerned that list is complete and verified — much of it on real Windows in CI.

Which is why the second adapter is the interesting one. It has to reach the same bar through the same interface, and every place it cannot is a place the contract was wrong.

These five are listed in the sidebar rather than hidden, because the roadmap is the point rather than an omission to apologise for.

Provider Status
Claude Shipped, verified against the real CLI
Codex Planned — the one that forces the contract
Grok Planned
Kimi Planned
OpenCode Planned
pi Planned

Zed’s ACP has been built into JetBrains IDEs since December 2025 and supports 25+ agents. But ACP presumes a human sitting in an editor to approve things, and it does not standardise the process-execution problem — finding the executable, Windows, WSL. Its adopters carry those unsolved: Zed #56176 (ACP server fails to launch under WSL), Kiro’s documentation makes “hardcode an absolute path” the official answer, and JetBrains AI Assistant does not support WSL at all.

So ACP is not a competitor. As headless-cli demonstrated, it can be absorbed as one more adapter.

1.0 is when every call site through which a plugin drives a CLI is replaceable — the transcription table in Why ActiveCLI is that checklist, and it is how “done” is defined rather than by a feature count.

There was no new protocol to design. The work was placing what already ran into classes, according to the principles — and doing that against the real CLI caught three defects that script mocks had hidden: starting new sessions with --resume, wrapping the permission response one envelope short, and discarding stderr so nothing could be diagnosed.