Claude Code is the provider.
The official Claude CLI, with your login, in opencode. Claude keeps its own tools, MCP servers and skills, opencode runs everything that touches your machine, and your login stays in the Claude Code CLI.
{
"plugin": ["@khalilgharbaoui/opencode-claude-code-plugin"]
}Add to opencode.json, then relaunch. Requires claude installed and logged in.
- opencodeyourun the suite. which test files cover the proxy broker?
- claude{"type":"system","subtype":"init", … "mcp_servers":[{"name":"opencode_proxy","status":"connected"}]}
- claude{"type":"assistant", … {"type":"tool_use","name":"Grep","input":{"pattern":"queuePendingProxyCall"}}} · ran inside Claude Code
- claude{"type":"assistant", … {"type":"tool_use","name":"mcp__opencode_proxy__bash","input":{"command":"npm test"}}}
- opencodepermissionrun npm test?
- opencodeyouallow once
- opencodebashran here, under opencode's own permissions and audit log · 1,083 tests
- claude{"type":"assistant", … {"type":"text","text":"test-broker.ts and test-proxy-task.ts: per-tool deadlines, the guard, stall warnings, fan-out, late results."}}
- claude{"type":"result","subtype":"success","is_error":false}
- opencodeyoudoes this plugin ever touch my Claude login?
- claude{"type":"assistant", … {"type":"tool_use","name":"Read","input":{"file_path":"docs/introduction.md"}}} · ran inside Claude Code, not through the proxy
- claude{"type":"user", … {"type":"tool_result","tool_use_id":"toolu_01…","content":"# Introduction …"}}
- opencodereaddocs/introduction.md · ran by Claude Code, shown here as it completes
- claude{"type":"assistant", … {"type":"text","text":"No. The plugin never reads, stores or replays an OAuth token of its own …"}}
- claude{"type":"result","subtype":"success","is_error":false}
- opencodeyoutighten the deadline guard in the broker and run the suite
- claude{"type":"assistant", … {"type":"tool_use","name":"mcp__opencode_proxy__edit","input":{"filePath":"src/proxy-broker.ts", …}}}
- opencodeyou/btw why a guard instead of a longer deadline? · typed while the turn is still running
- claude{"type":"control_response","response":{"response":{"response":"A fixed deadline would count the operator's time on a permission prompt …"}}}
Project numbers
- 85GitHub starsapi.github.com
- 8,268npm downloads, last 30 daysapi.npmjs.org
- 25,212npm downloads since 2026-04-25api.npmjs.org
- 1,083tests in the suitenpm test, this build
- 109tagged releasesapi.github.com
- 16contributorsapi.github.com
- 25forksapi.github.com
- 18Claude models registeredsrc/models.ts
Read at build time from the GitHub REST API and api.npmjs.org; nothing is requested from your browser. Rebuilt daily. This build: .
01how it works
Two processes. One of them is the official client.
opencode spawns the real claude binary headless and talks to it over stream-json. The tools that touch your machine come back to opencode over a loopback MCP server the plugin runs in-process. Nothing in between holds a credential.
process 1opencode
Your terminal. Its permission prompts, its audit log, its MCP servers, its skills. The tools that touch your machine run here: bash, edit, write, webfetch,task.
in-processthe plugin
- One
claudechild per conversation, keyed on cwd, model, tool scope and session. opencode_proxy: an MCP server on loopback. Bearer token, written into a0600--mcp-config, never logged.- One provider per account, each with its own
CLAUDE_CONFIG_DIR. - Reads no credential. There is nothing here to lift.
- your prompt, as stream-json on stdin
- frames on stdout: text, thinking, tool_use, result
- a proxied tool call over loopback HTTP, held open until it ends
- its result, once opencode has run it
process 2claude --print
The official client, headless. It authenticates itself, talks to Anthropic itself, and bills as its own login bills.
- Its own tools stay its own:
Read,Grep,Glob,WebSearch. - Your opencode MCP servers, bridged in through
--mcp-config. - Your opencode skills, staged for its
Skilltool with--plugin-dir. - Your login, which the plugin never reads.
Anthropic. A subscription, an API key, Bedrock or Vertex: whatever the CLI holds. The plugin never talks to it.
How a turn worksHow a proxied call endsScratch files and security
02what it does
One claude process per conversation, with opencode in charge of the machine.
The plugin streams the CLI's output into opencode as it arrives, routes the tools that touch your files and shell back to opencode, and keeps the conversation's own claude process alive between turns so the model keeps its context.
01auth
Your CLI's login, untouched
The official claude binary authenticates: a subscription login, an API key, Bedrock or Vertex. The plugin never reads, stores or replays a token, so there is nothing here to lift.
Which login bills what02tools
opencode runs the tools
Bash, Edit, Write, WebFetch and Task are proxied by default. Claude calls an in-process MCP tool and opencode executes it, behind its own permission prompts and audit log.
"proxyTools": ["Bash", "Edit", "Write", "WebFetch", "Task"]Read more03claude
Claude's own tools, MCP servers and skills
Read, Grep, Glob and WebSearch run inside Claude Code. opencode's MCP servers are bridged into the spawn, and opencode's skills can be staged for Claude's native Skill tool.
Read more04accounts
Several accounts, with failover
Declare accounts once and each becomes its own provider with its own CLAUDE_CONFIG_DIR. When one runs out of usage mid-task, opencode's question form offers the others. Nothing moves until you pick.
"accounts": ["personal", "work"]Read more05subagents
Your account, their model
An agent file can pin forceModel, reasoningEffort and cacheTtl while inheriting the caller's account. task_batch dispatches several subagents at once, because the CLI serialises MCP calls.
forceModel: claude-haiku-4-5Read more06hosts
One package, opencode 1.x and 2.x
The default export carries both entrypoints and the same config works on both majors. opencode 2's tool vocabulary (shell, subagent) is translated per model, never process-wide.
Read more07skill
Ships the skill that configures it
Ask Claude to set it up. The package bundles a claude-code-plugin skill that knows every option, env var, model id and troubleshooting rule, staged into Claude Code on every spawn and kept in step with the code by tests.
use the claude-code-plugin skill to add a work accountRead more08doctor
A health report safe to paste
/claude-code-doctor reports versions, live processes, pending calls and what the CLI skipped. Its bundle form redacts by allowlist: nothing survives unless the plugin can name it, so a bug report never carries a prompt or a key.
/claude-code-doctor bundleRead more09cache
Forks keep the cache warm
forkSessions forks the Claude session instead of replaying the transcript. Measured on a fork's first turn: 814 prompt-cache writes against 22,355, 27x fewer, and the parent untouched.
"forkSessions": trueRead more
Also in the box: /btw side questions on the live process, a read-only permission preset, 18 registered models with reasoning variants and fast mode, background subagents with status and cancel, and a fallback model chain.
03why the CLI and not the API
The three objections, answered with what is measured.
- Just use the API.
The API is pay as you go on a Platform key. This plugin inherits whatever the claude CLI already holds, so a subscription login runs on the plan's usage limits, and an API key, Bedrock or Vertex login bills exactly as that CLI would. The CLI reports which one is in effect on every session (apiKeySource), and the plugin warns when a stray ANTHROPIC_API_KEY would move the bill.
Billing: what a turn draws from- Is this allowed? How is it billed?
The official client does the authenticating, and driving claude is what claude is for. Proxy and token-reuse plugins lift the OAuth session out of the client, which Anthropic disallowed for third-party use in February 2026; this plugin cannot do that, structurally. Headless --print usage on a subscription draws from the plan's ordinary limits, per Anthropic's own page, which the docs link and date rather than paraphrase.
How this compares, with every claim sourced- A CLI wrapper must be flaky.
It is engineered like a transport, not a shell-out. An abort sends the CLI an interrupt. A proxied call ends on an event, never on a clock. Two watchdogs cover a child that is alive but wedged, and a child that dies without a result is an error, never a silent stop. The suite is 1,083 tests, a dozen of whose files drive a fake CLI through real turns, and every rule in AGENTS.md cites the measurement that produced it.
Internals: how a turn works
04quickstart
Three steps. The second one is a single line.
-
Install and log in the Claude Code CLI. The plugin drives an existing
claude; it does not bundle one.Terminal window claude --version # e.g. 2.1.284 (Claude Code)claude auth status # which account you are signed in asclaude auth login # only if you are not signed in yet -
Add the package to opencode’s global config. That spec is the whole install: opencode resolves and caches plugin packages itself, so do not
npm installit.~/.config/opencode/opencode.json {"plugin": ["@khalilgharbaoui/opencode-claude-code-plugin"]} -
Quit opencode fully and relaunch. Plugins load once, at process start. The model picker now has a Claude Code (Default) provider with entries such as
Claude Sonnet 5.5 (2×)andClaude Opus 5 (5×); the suffix is each model’s list price relative to Haiku.
Something missing from the picker? Troubleshooting is keyed on the first thing you see, and /claude-code-doctor in any session prints what the plugin thinks is happening without calling a model.
05built from measurements
Every rule was learned from a measurement, and says so.
The project's engineering file does not contain opinions. Each rule names the probe, the version and the number that produced it, and the test that keeps it true.
1,083tests, across 63 files
A dozen of those files drive a fake claude through a real turn: the stream parser, the proxy broker, the watchdogs, abort, respawn, account failover and the model fallback chain are exercised end to end, not mocked at the edge. Two runtime dependencies in total.
measuredevery rule in AGENTS.md cites the evidence that produced it
A finish's usage is context occupancy to opencode, so its input side is the turn's LAST real API call, never result.usage, which sums every call: a 14-call turn at 180K real context reported 2,050,806 cache read and opencode auto-compacted.
27×fewer prompt-cache writes on a forked claude session than on the replay it replaces: 814 against 22,355, one measured thread (h #g187)
Read the rulebook16contributors, with authorship preserved
- @khalilgharbaouimaintainer: built and runs the plugin, reviews and credits every contribution
- @unixfoxthe first version, March 2026, and the idea it still runs on
- @broskeestask_batch, the skill bridge, the usage fix that stopped early auto-compaction
- @jknlsnper-tool proxy timeouts, subagent dispatch steering, the question proxy
- @galvaniper-session working directory for opencode serve
- @willmcginnisauthentication on the proxy MCP endpoint
- @acastro2the opencode 2 tool-result name fix
- @bangnh1opencode 2's MCP config layout and Code Mode proxying
06how this compares
Three ways to reach Claude from opencode. They are not interchangeable.
Where a cell names what another project does, the full comparison page quotes that project's own README.
opencode’s native anthropic provider |
This plugin | Proxy and token-reuse plugins | |
|---|---|---|---|
| Authentication | An Anthropic Platform API key in opencode’s auth store. | Whatever the official claude CLI holds: a subscription login, an API key, Bedrock or Vertex. No token is read, stored or replayed. |
The Claude OAuth session, lifted out of the official client and refreshed by the plugin itself. |
| What is billed | Pay as you go on the key’s Platform account. | Whatever the CLI’s own login bills: plan usage limits on a subscription, pay as you go on a key. The CLI’s apiKeySource says which, on every session. |
The subscription the reused session belongs to. |
| Terms of service | The ordinary API route. Nothing unusual about it. | Sanctioned: the official client does the authenticating, and driving claude is what claude is for. |
Disallowed. Anthropic disallowed reusing subscription authentication for third-party Claude use in February 2026, and each of those projects carries its own disclaimer. |
| Who runs Bash, Edit, Write | opencode, behind its permission prompts. | opencode, behind its permission prompts: those tools are proxied by default. Read, Grep and Glob run inside Claude Code. | opencode. |
| Claude Code’s tools, MCP servers, skills | Not involved: opencode’s own tools only. | Claude’s built-ins run in Claude Code, opencode’s MCP servers are bridged in, opencode’s skills can be staged for Claude’s Skill tool. | Not involved: the model call is an ordinary API call. |
| What it costs you | Baseline. | A claude child per conversation (about 250 MB idle) under a cap of 16, a local keyword title instead of a model-written one, and Claude Code’s own compaction happening behind opencode’s back. |
One more moving part between you and Anthropic, plus the account risk in the terms row. |
The full comparison has nine rows, names the projects in the third column, and links the policy sources with the date they were last read.
07add it
One line in opencode.json.
{ "plugin": ["@khalilgharbaoui/opencode-claude-code-plugin"]}08the work, and the ask
Built in the open, one measurement at a time.
These are the numbers behind the plugin, read from the repository and the registries when this page was built. People support effort they can see.
- 201days since the first commit, 2026-03-16git log, this build
- 458commitsgit rev-list, this build
- 109tagged releasesapi.github.com
- 55merged pull requestsapi.github.com
- 1,083tests in the suitenpm test, this build
- 27,200lines of test code, in 63 filestest-*.ts, this build
- 16contributors, authorship preservedapi.github.com
- 25,212npm downloads since 2026-04-25api.npmjs.org
Free, MIT, and built in the open since 2026-03-16. Every rule in its engineering file names the measurement that produced it. If the plugin saves you time, buy its maintainer a coffee, or leave a star so the next person finds it.
Free and MIT-licensed, made by @khalilgharbaoui. If the plugin saves you time, you can buy its maintainer a coffee.
