Summary
Add an OpenCode Go upstream so Claude Code can use an OpenCode Go subscription ($5 first month, then $10/mo) through this proxy’s existing Anthropic-compatible surface.
Unlike Codex/Kimi/Grok/Cursor, OpenCode Go is API-key auth only — there is no OAuth login flow. The value CCP adds is per-model wire routing + translation, not credential management UX.
How this fits the project
claude-code-proxy already does:
credentials → local Anthropic Messages API → provider-specific upstream
Claude Code talks Anthropic; the proxy authenticates upstream and translates. OpenCode Go should be another provider on that path.
The main reason it belongs in CCP (vs. asking users to run a second proxy) is that OpenCode Go splits models across two wire protocols on one subscription. Claude Code only has one ANTHROPIC_BASE_URL and cannot pick the upstream API per model itself.
Motivation
OpenCode Go docs expose 14 curated open coding models via API, but they are not all on the same endpoint:
| Models |
Upstream endpoint |
Wire format |
| GLM-5.2, GLM-5.1, Kimi K2.7 Code, Kimi K2.6, DeepSeek V4 Pro/Flash, MiMo-V2.5, MiMo-V2.5-Pro |
https://opencode.ai/zen/go/v1/chat/completions |
OpenAI-compatible |
| MiniMax M3/M2.7/M2.5, Qwen3.7 Max, Qwen3.7 Plus, Qwen3.6 Plus |
https://opencode.ai/zen/go/v1/messages |
Anthropic-compatible |
Claude Code always sends Anthropic POST /v1/messages. Without a smart proxy:
- Pointing at
…/messages breaks half the catalog (GLM, Kimi, DeepSeek, MiMo).
- Pointing at
…/chat/completions breaks the other half (MiniMax, Qwen).
- Community proxies (
ocgo, oc-go-cc, opencode-proxy-for-claude-code, etc.) each re-implement routing + translation.
CCP already solves this class of problem for Codex (Responses), Kimi (OpenAI chat), Grok (Responses), and Cursor (Connect). OpenCode Go is the same pattern with a per-model endpoint split.
Note: Go endpoint assignments differ from OpenCode Zen for some models (e.g. MiniMax is chat/completions on Zen but messages on Go). Routing must follow the Go table, not Zen’s.
Authentication (API key — not OAuth)
Per OpenCode Go docs:
- Sign in to OpenCode Zen, subscribe to Go, copy your workspace API key from opencode.ai/auth
- In OpenCode itself:
/connect → OpenCode Go → paste key (stored in ~/.local/share/opencode/auth.json via opencode auth login)
There is no browser/device OAuth for Go. The key is a static bearer token until rotated in the Zen console.
What CCP should do (and not do)
Do not mirror codex auth login / grok auth device for OpenCode Go — that implies an OAuth flow that does not exist.
Do follow the same pattern community proxies use:
| Source |
Variable / config |
Notes |
| Env (preferred) |
OPENCODE_API_KEY or CCP_OPENCODE_API_KEY |
Same key OpenCode integrations expect (ACP docs) |
config.json |
opencode.apiKey |
Env wins over file (CCP precedence) |
| Optional convenience |
Read OpenCode’s ~/.local/share/opencode/auth.json |
Only if user already connected via OpenCode TUI; don’t require OpenCode install |
Inbound vs outbound credentials (important):
- Claude Code → CCP:
ANTHROPIC_AUTH_TOKEN / ANTHROPIC_API_KEY can be dummy (unused, sk-test) — CCP does not validate these for upstream
- CCP → OpenCode: real
Authorization: Bearer <OPENCODE_API_KEY>
Proxy should fail fast when an OpenCode Go model is requested but no API key is configured (clear error: set OPENCODE_API_KEY or opencode.apiKey in config).
Optional CLI (not auth login):
claude-code-proxy opencode status # key present? source (env/config/opencode-auth.json)?
No logout needed — unset env or remove config key.
Go vs Zen billing on one key
The same Zen workspace API key can access pay-as-you-go Zen models (zen/v1/*) and Go subscription models (zen/go/v1/*). They are different upstream bases and billing pools. v1 scope: Go endpoint only (zen/go/v1); Zen PAYG is a separate follow-up.
Proposed routing UX
Route via ANTHROPIC_MODEL with explicit Go model IDs, e.g.:
kimi-k2.7-code, kimi-k2.6
glm-5.2, glm-5.1
deepseek-v4-pro, deepseek-v4-flash
mimo-v2.5, mimo-v2.5-pro
minimax-m3, minimax-m2.7, minimax-m2.5
qwen3.7-max, qwen3.7-plus, qwen3.6-plus
Proxy behavior:
- Accept Anthropic Messages / streaming (+
count_tokens) from Claude Code
- Resolve model →
chat/completions or messages upstream path under zen/go/v1
- Translate Anthropic ↔ OpenAI where needed; passthrough or light adapt for
messages models
- Inject
Authorization: Bearer <api_key> on upstream calls
- Reject unknown model IDs with HTTP 400 listing supported Go models
Catalog metadata: GET https://opencode.ai/zen/go/v1/models
Claude Code env example
OPENCODE_API_KEY=sk-... \
ANTHROPIC_BASE_URL=http://localhost:18765 \
ANTHROPIC_AUTH_TOKEN=unused \
ANTHROPIC_MODEL=kimi-k2.7-code \
ANTHROPIC_SMALL_FAST_MODEL=mimo-v2.5 \
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 \
CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK=1 \
claude
Or persist the key in ~/.config/claude-code-proxy/config.json:
{
"opencode": {
"apiKey": "sk-...",
"baseUrl": "https://opencode.ai/zen/go/v1"
}
}
ANTHROPIC_SMALL_FAST_MODEL should map to a cheap Go model — Claude Code emits background haiku-style requests that would 400 without it.
Optional follow-ups (out of scope for v1?)
Implementation sketch
src/providers/opencode/
credentials.rs # env > config.json > optional opencode auth.json
client.rs # HTTP to zen/go/v1/* with Bearer
model.rs # allowlist + EndpointKind { Messages, ChatCompletions }
translate/ # reuse Kimi OpenAI path; thinner path for messages models
Registry: opencode provider; provider_for_model("kimi-k2.7-code") → opencode (distinct from existing kimi.com Kimi Code OAuth provider).
Config/env:
CCP_OPENCODE_API_KEY / OPENCODE_API_KEY
CCP_OPENCODE_BASE_URL default https://opencode.ai/zen/go/v1
No ProviderGroup auth subcommands unless we add a minimal opencode status later.
Prior art / references
Notes / caveats
- Usage limits: dollar-based ($12 / 5h, $30 / week, $60 / month); surface upstream 429/limit errors clearly
- One Go subscriber per workspace (OpenCode billing)
- Model catalog may change
- Skills / rules: Claude Code vs OpenCode harness mismatch — this FR is wire routing only
- Reasoning / tool round-trips: per-model validation (Kimi/DeepSeek reasoning replay, strip thinking for non-reasoning models)
- ocgo limitation: some community proxies only hit
chat/completions — CCP should implement both Go endpoint families
Related issues
Happy to help test or send a PR.
Summary
Add an OpenCode Go upstream so Claude Code can use an OpenCode Go subscription ($5 first month, then $10/mo) through this proxy’s existing Anthropic-compatible surface.
Unlike Codex/Kimi/Grok/Cursor, OpenCode Go is API-key auth only — there is no OAuth login flow. The value CCP adds is per-model wire routing + translation, not credential management UX.
How this fits the project
claude-code-proxyalready does:credentials → local Anthropic Messages API → provider-specific upstream
Claude Code talks Anthropic; the proxy authenticates upstream and translates. OpenCode Go should be another provider on that path.
The main reason it belongs in CCP (vs. asking users to run a second proxy) is that OpenCode Go splits models across two wire protocols on one subscription. Claude Code only has one
ANTHROPIC_BASE_URLand cannot pick the upstream API per model itself.Motivation
OpenCode Go docs expose 14 curated open coding models via API, but they are not all on the same endpoint:
https://opencode.ai/zen/go/v1/chat/completionshttps://opencode.ai/zen/go/v1/messagesClaude Code always sends Anthropic
POST /v1/messages. Without a smart proxy:…/messagesbreaks half the catalog (GLM, Kimi, DeepSeek, MiMo).…/chat/completionsbreaks the other half (MiniMax, Qwen).ocgo,oc-go-cc,opencode-proxy-for-claude-code, etc.) each re-implement routing + translation.CCP already solves this class of problem for Codex (Responses), Kimi (OpenAI chat), Grok (Responses), and Cursor (Connect). OpenCode Go is the same pattern with a per-model endpoint split.
Note: Go endpoint assignments differ from OpenCode Zen for some models (e.g. MiniMax is
chat/completionson Zen butmessageson Go). Routing must follow the Go table, not Zen’s.Authentication (API key — not OAuth)
Per OpenCode Go docs:
/connect→ OpenCode Go → paste key (stored in~/.local/share/opencode/auth.jsonviaopencode auth login)There is no browser/device OAuth for Go. The key is a static bearer token until rotated in the Zen console.
What CCP should do (and not do)
Do not mirror
codex auth login/grok auth devicefor OpenCode Go — that implies an OAuth flow that does not exist.Do follow the same pattern community proxies use:
OPENCODE_API_KEYorCCP_OPENCODE_API_KEYconfig.jsonopencode.apiKey~/.local/share/opencode/auth.jsonInbound vs outbound credentials (important):
ANTHROPIC_AUTH_TOKEN/ANTHROPIC_API_KEYcan be dummy (unused,sk-test) — CCP does not validate these for upstreamAuthorization: Bearer <OPENCODE_API_KEY>Proxy should fail fast when an OpenCode Go model is requested but no API key is configured (clear error: set
OPENCODE_API_KEYoropencode.apiKeyin config).Optional CLI (not auth login):
claude-code-proxy opencode status # key present? source (env/config/opencode-auth.json)?No
logoutneeded — unset env or remove config key.Go vs Zen billing on one key
The same Zen workspace API key can access pay-as-you-go Zen models (
zen/v1/*) and Go subscription models (zen/go/v1/*). They are different upstream bases and billing pools. v1 scope: Go endpoint only (zen/go/v1); Zen PAYG is a separate follow-up.Proposed routing UX
Route via
ANTHROPIC_MODELwith explicit Go model IDs, e.g.:kimi-k2.7-code,kimi-k2.6glm-5.2,glm-5.1deepseek-v4-pro,deepseek-v4-flashmimo-v2.5,mimo-v2.5-prominimax-m3,minimax-m2.7,minimax-m2.5qwen3.7-max,qwen3.7-plus,qwen3.6-plusProxy behavior:
count_tokens) from Claude Codechat/completionsormessagesupstream path underzen/go/v1messagesmodelsAuthorization: Bearer <api_key>on upstream callsCatalog metadata:
GET https://opencode.ai/zen/go/v1/modelsClaude Code env example
Or persist the key in
~/.config/claude-code-proxy/config.json:{ "opencode": { "apiKey": "sk-...", "baseUrl": "https://opencode.ai/zen/go/v1" } }ANTHROPIC_SMALL_FAST_MODELshould map to a cheap Go model — Claude Code emits background haiku-style requests that would 400 without it.Optional follow-ups (out of scope for v1?)
aliasProvider: "opencode"— see Route Anthropic-style aliases (haiku/sonnet/opus/claude-*) to Codex when Kimi isn't used #12go-auto/ task-based model selection (community proxies only)zen/v1/*with same API keyauth.jsonautomaticallyImplementation sketch
Registry:
opencodeprovider;provider_for_model("kimi-k2.7-code")→ opencode (distinct from existing kimi.com Kimi Code OAuth provider).Config/env:
CCP_OPENCODE_API_KEY/OPENCODE_API_KEYCCP_OPENCODE_BASE_URLdefaulthttps://opencode.ai/zen/go/v1No
ProviderGroupauth subcommands unless we add a minimalopencode statuslater.Prior art / references
opencode auth loginstores API keys inauth.json(OpenCode app, not CCP OAuth)OCGO_API_KEY+setup), srthorat/opencode-proxy-for-claude-code (OPENCODE_API_KEYin.env)Notes / caveats
chat/completions— CCP should implement both Go endpoint familiesRelated issues
aliasProvider)Happy to help test or send a PR.