Skip to content

Repository files navigation

opencode-claude — Claude Code in OpenCode, subscription OAuth, Agent SDK

npm version npm downloads MIT license linux, macos, windows latest release

Claude Code inside OpenCode — Pro/Max subscription OAuth,
Agent SDK harness, effort variants, tools, images, and compact.

Install · Authenticate · Why this plugin · Architecture · Changelog


Run Claude Code from your Claude Pro/Max subscription inside OpenCode: Fable, Opus, Sonnet, Haiku — with thinking effort lowmax, streaming, OpenCode tool calls that park and resume, MCP, image/PDF attachments, and auto-compact.

Uses the same Agent SDK + claude CLI stack as the OpenChamber Claude harness. Plugin shape mirrors @otto-assistant/opencode-cursor.

Install

claude-code is not a built-in OpenCode provider. Install the plugin first, or opencode auth login --provider claude-code fails with Unknown provider "claude-code".

# global (recommended)
opencode plugin @otto-assistant/opencode-claude -g

# or project-local (writes .opencode/opencode.json)
opencode plugin @otto-assistant/opencode-claude

Optional provider naming (also seeded when the plugin loads):

{
  "$schema": "https://opencode.ai/config.json",
  "plugin": ["@otto-assistant/opencode-claude"],
  "provider": {
    "claude-code": { "name": "Claude Code" }
  }
}

Or build from source:

git clone https://github.com/otto-assistant/opencode-claude.git
cd opencode-claude
bun install && bun run build
opencode plugin file://$PWD

Authenticate

Requires the plugin to be installed (see above).

# Option A — sync from Claude Code CLI (recommended)
claude auth login
opencode auth login --provider claude-code
# pick "Use Claude Code CLI login"

# Option B — browser OAuth (Pro/Max)
opencode auth login --provider claude-code
# pick "Login with Claude Pro/Max"

Then start OpenCode, pick provider claude-code, choose a model, and set the effort variant (low / medium / high / xhigh / max) when you want deeper thinking.

opencode run "Summarise this repository in five bullets." --model claude-code/sonnet

Why this plugin

Agent SDK harness Runs Claude through @anthropic-ai/claude-agent-sdk + the local claude CLI — same stack as OpenChamber.
Subscription auth Claude Pro/Max OAuth (CLI sync or browser). API keys are stripped from the child env so billing stays on the subscription.
Effort / thinking Native OpenCode variants lowmax map to Claude --effort + adaptive thinking.
Agent-grade tools OpenCode tools bridge as in-process MCP; calls park and resume instead of deadlocking or inventing output.
Attachments Images and PDFs from OpenCode reach Claude (data URLs + remote URLs).
Auto-compact Long sessions compact like Claude Code; boundary events are surfaced in the stream.
Session resume Sticky foreign Claude session IDs so follow-ups continue the same Agent SDK turn.
History transfer When no Claude session can be resumed (first claude-code turn of a chat, model switch mid-conversation, pruned transcript), the full prior conversation is serialized into the prompt — Claude never starts blind.
Rate-limit counter Subscription limit state is tracked with its reset time; GET /v1/rate-limit answers "when are limits back", and doomed turns fail fast with 429 + Retry-After.

Architecture

OpenCode
  └─ /v1/chat/completions
       └─ Bun.serve proxy (ephemeral port; published via auth loader)
            └─ Claude Agent SDK query()
                 └─ claude CLI (subscription OAuth)

Model catalog: aliases fable / opus / sonnet / haiku plus pinned ids. Effort selection is encoded in x-opencode-claude-effort so the proxy passes the exact effort (+ adaptive thinking) into the Agent SDK.

Rate-limit counter

The proxy records Agent SDK rate_limit_event telemetry and hard session-limit errors (including the parsed reset time) to ~/.local/share/opencode-claude/rate-limit.json.

  • GET /v1/rate-limit{ limited, status, rateLimitType, utilization, resetsAt, resetsAtISO, resetInSeconds, message, updatedAt } — poll this for a "limits reset in …" countdown. utilization is only present when the latest SDK event reported it — it is never carried over from an earlier limit window, so a freshly reset window never shows a stale percentage.
  • GET /health includes a compact rateLimit summary.
  • While a confirmed hard limit is active, new chat turns return HTTP 429 with Retry-After + x-claude-rate-limit-reset headers and an error.type = "rate_limit_error" body (title/summary meta requests are never gated). The block lifts automatically at reset time; the next turn then resumes the same Claude session (sticky session store is untouched).
  • OPENCODE_CLAUDE_RATE_LIMIT_FAST_FAIL=0 disables the 429 gate (turns are attempted and error normally).

Requirements

  • OpenCode
  • Claude Code CLI on PATH
  • Claude Pro/Max subscription (or CLI OAuth credentials)
  • Bun (plugin runtime) · Node.js ≥ 18

Development

bun install
bun run build
bun run test

Debug logging: OPENCODE_CLAUDE_DEBUG=1.

Optional knobs:

  • OPENCODE_CLAUDE_PROXY_PORT — optional pinned proxy port (default: ephemeral / OS-assigned; live URL is published to OpenCode via config + auth loader)
  • OPENCODE_CLAUDE_CWD — working directory passed to the Agent SDK
  • CLAUDE_CODE_OAUTH_TOKEN — inject a subscription token (CI / headless)
  • OPENCODE_CLAUDE_RATE_LIMIT_FAST_FAIL0 disables the 429 rate-limit gate
  • OPENCODE_CLAUDE_RATE_LIMIT_STORE — override the rate-limit store path (tests)
  • OPENCODE_CLAUDE_HISTORY_MAX_CHARS — budget for transferred conversation history when a Claude session cannot be resumed (default 400000; newest messages are kept, 0 disables transfer)

Release

Publish via GitHub Actions → Actions → Release → Run workflow:

Input Purpose
version Explicit semver (0.6.0). Empty → use bump
bump minor (default) / patch / major
dry_run Skip npm publish; create a draft GitHub release

Requires repo secrets: NPM_TOKEN, optional DISCORD_WEBHOOK_URL.

Local pin refresh after a release:

./scripts/update-plugin.sh --dry-run
./scripts/update-plugin.sh

License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages