Add a new CLI to cc-multi-cli-plugin
cc-multi-cli-plugin is a multi-plugin marketplace with four built-in CLIs: Codex, Cursor, Antigravity, and OpenCode. Adding a new CLI beyond these means two things:
- A new adapter in the
multihub —plugins/multi/scripts/lib/adapters/<cli>.mjs— that conforms to the adapter contract and is registered inlib/adapters/registry.mjs, plus a dispatch branch inlib/commands/task.mjs. - A new thin plugin —
plugins/<cli>/with command files + aplugin.json, registered in the rootmarketplace.json— that forwards/<cli>:<role>into the hub viamulti:<cli>-<role>subagents.
The adapter interface is transport-agnostic. The companion consumes only the five-method adapter object defined in plugins/multi/scripts/lib/adapters/CONTRACT.md (name, isAvailable, isAuthenticated, invoke, cancel, plus optional getSession). How the adapter talks to the CLI — headless print mode, spawn-and-read-files, app-server HTTP, or (legacy) ACP — is your choice, driven by what the CLI actually exposes. Read CONTRACT.md first; it's the source of truth for the result shape.
There is no buildPrompt() function and no slash-command-prefix layer (an older design that's gone). A role's read/write behavior is expressed as CLI flags/sandbox inside the adapter; a role's prompt framing lives in its subagent .md. Don't reintroduce a buildPrompt.
Step 0 — Research the CLI first
Before writing any code, pull everything you need so you don't guess or ask the user later:
- Install status and binary name — is the user's machine set up? What's the exact command (
agent?qwen?aider?opencode?). - A drivable headless transport — see Prerequisites below. This is the make-or-break question.
- Exact model identifiers the CLI accepts (or
autoif offered). A wrong model string causes a 400/exit-1 at runtime. - Modes / permission flags — read-only vs write, an
ask/planmode, a--force/--yoloauto-approve flag, a sandbox setting. These are what you'll map roles onto inside the adapter. - Runtime flags — output format (
--output-format json?), resume/session, background — what does--helpactually list? - Authentication mechanism — env var, OAuth keyring, device code, API key header.
- Known quirks (Windows shell requirements, PATH issues, empty-stdout-when-piped bugs, version-specific behavior).
Pick sources proportional to the question. Start cheap and authoritative; escalate only if unclear.
First: search for an existing Claude Code (or other) integration of this CLI
Before anything else, search exa for an existing implementation. The community has wired up many CLIs already — finding one collapses days of trial-and-error into "read their adapter, adapt to our marketplace structure."
Useful queries (try in order, stop when you find a working example):
<cli-name> claude code plugin
<cli-name> headless print mode json output
<cli-name> agent SDK / programmatic API
<cli-name> claude-code marketplace
<cli-name> @anthropic-ai claude
A reference implementation reveals things probes don't:
- Spawn quirks — does the CLI need
shell: trueon Windows? A specific env var to init? Does it want the prompt on stdin vs as an arg? - Output completeness — does its
-pmode actually print the answer, or (likeagy) write nothing to stdout when piped? What's the JSON envelope shape? - Auth flow specifics — env vars, token paths, OAuth dance details.
- Model ID conventions — version suffixes, deprecated aliases. (The Gemini family's
-previewsuffix trap — which Antigravity surfaces — is the canonical example.)
If you find one:
- Read its full implementation. Note any "this CLI is weird about X" comments.
- Note pre-flight config it requires (env, config-file entries, auth setup).
- Cite the source (NOTICE attribution + a comment in the new adapter).
- Adapt — don't blindly copy. Our marketplace structure differs; the principles transfer, the file paths don't.
If you don't find one (or it's stale), proceed with the verification ladder below. Looking is cheap.
Verification sources, in order of cost/authority
<cli> --help,<cli> models,<cli> about,<cli> --list-models— fastest, no network, authoritative for "what does this binary accept right now."- Vendor docs via context7 —
resolve-library-id→query-docs. Good for canonical names and deprecation context. - exa web search — for changelogs, forum posts, obscure flags context7 doesn't have.
- CLI source on GitHub — config constants. Slowest; use only when 1–3 disagree or come up empty.
- Prompt the CLI itself (
<cli> -p "List the exact model strings this CLI accepts.") — only when no listing subcommand exists and docs are empty. Costs credits.
Hard rules:
- Never ask one CLI about another CLI's features. A CLI is a source only for itself.
- Preview-suffix trap: many CLIs qualify unstable IDs with
-preview/-beta/-exp. Don't hardcode the unsuffixed variant — it 404s at runtime. - Resolving disagreements: CLI wins for "does it work right now"; docs win for "should I use this."
- Record the source you used inline so the user can catch a bad citation.
- Read the existing adapters in
plugins/multi/scripts/lib/adapters/— they're your worked examples (see the transport table at the end).
Proceed without asking the user to confirm facts you can verify yourself.
Prerequisites — confirm the CLI can be driven headlessly
Check in this order. The first match that fits the CLI is your transport; the earlier ones are simpler.
1. Headless print mode with structured output (the common path)
Most modern agent CLIs have a non-interactive mode: -p/--print with --output-format json (single result object) or --output-format stream-json (NDJSON events + a final result). The prompt goes in as an arg or on stdin. This is how Cursor is driven by default (agent -p; it also has an opt-in ACP path — see path 4), and it's the path most new CLIs will use. If <cli> --help shows a print/headless mode with JSON output, go to "Headless integration" below — cursor.mjs is your template.
2. The CLI runs headlessly but writes nothing usable to stdout
Some CLIs run a prompt but don't print the answer to stdout when piped (a known class of bug — e.g. Antigravity's agy, gemini-cli#27466). If the CLI persists results somewhere on disk (a transcript/log/session file), you can still drive it: spawn it, learn the artifact location, and read the answer back. This is how Antigravity is driven — antigravity.mjs is your template. More work than path 1, but the same five-method adapter interface.
3. App-server / HTTP transport (ASP)
Some CLIs expose a long-lived server (HTTP + SSE, JSON-RPC over a socket) you connect to and stream turns from. This is how Codex is driven (codex --app-server behind a broker daemon) — codex.mjs + lib/app-server.mjs are your template. Reuse this only if the CLI genuinely requires it.
4. ACP (Agent Client Protocol) — live, opt-in
ACP is a cross-vendor stdio JSON-RPC standard (newline-delimited JSON-RPC 2.0). The plugin has a maintained, SDK-based ACP client at lib/acp/client.mjs (built on the official @agentclientprotocol/sdk), and Cursor and OpenCode both ship ACP adapters behind the MULTI_TRANSPORT_CURSOR / MULTI_TRANSPORT_OPENCODE env flags (default headless, opt-in acp). ACP buys in-protocol model selection (session/set_config_option), session modes for read-only (session/set_mode → ask/plan), and a real session/cancel. Take this path when a CLI's ACP mode is genuinely better than its headless mode, OR when you want those structured controls. See "ACP integration" at the end — lib/acp/client.mjs + lib/acp/resolve.mjs and the dual-transport pattern in cursor.mjs/opencode.mjs are your templat