claude-code-router
- title
- claude-code-router
- type
- toolbox
- summary
- Request-layer router that puts Claude Code on other model providers, with per-task routing slots
- tags
- typescript, claude-code, llm, api-gateway
- language
- TypeScript
- license
- MIT
- created
- 2026-05-13
- updated
- 2026-09-13
Claude Code Router (ccr) is a request-layer router that sits between Claude Code and one or more model providers. The Claude Code binary is unchanged; ccr intercepts API calls, applies a routing table, transforms requests/responses per provider, and forwards. Anthropic's UX, anyone else's model.
What it does
- Multi-provider β OpenRouter, DeepSeek, Gemini, Ollama, Volcengine, SiliconFlow, ModelScope, DashScope, AIHubMix, plus arbitrary OpenAI-compatible endpoints.
- Routing rules β
default,background,think,longContext,image,webSearchslots each map to aprovider,modelpair, so different request types go to different models. - Transformers β per-provider request/response munging (the
openrouter,deepseek,gemini,enhancetool,maxtoken,reasoning,toolusetransformers ship in-box; new ones can be plugged in). - Dynamic switching β
/modelslash command from inside Claude Code rewrites the default route on the fly, andccr modeldoes the same from a separate terminal. - CLI β
ccr code,ccr model,ccr status,ccr logs,ccr restart. - GitHub Actions integration β non-interactive mode (
NON_INTERACTIVE_MODE: true) setsCI=true,FORCE_COLOR=0, fixes stdin handling so Claude Code can run in a workflow. - Env-var interpolation β
"$OPENAI_API_KEY"/"${GEMINI_API_KEY}"inconfig.jsonso secrets stay out of the file. - Plugin system β drop a TypeScript file into the transformer directory, ccr loads it on restart.
How it works
config.json (at ~/.claude-code-router/config.json) declares providers and a router. Each provider has name, api_base_url, api_key, models, and optional transformer. The Router section picks defaults:
{
"Providers": [
{
"name": "deepseek",
"api_base_url": "https://api.deepseek.com/chat/completions",
"api_key": "$DEEPSEEK_API_KEY",
"models": ["deepseek-chat", "deepseek-reasoner"],
"transformer": {
"use": ["deepseek"],
"deepseek-chat": { "use": ["tooluse"] }
}
},
{
"name": "ollama",
"api_base_url": "http://localhost:11434/v1/chat/completions",
"api_key": "ollama",
"models": ["qwen2.5-coder:latest"]
}
],
"Router": {
"default": "deepseek,deepseek-chat",
"background": "ollama,qwen2.5-coder:latest",
"think": "deepseek,deepseek-reasoner"
}
}
Two log surfaces: pino-formatted server logs at ~/.claude-code-router/logs/ccr-*.log (HTTP / API events) and a separate claude-code-router.log for routing decisions and business-logic events. APIKEY adds a shared-secret check in the Authorization / x-api-key header; if unset, HOST is forced to 127.0.0.1 so an unauthenticated daemon can never bind to the network.
Install
npm install -g @anthropic-ai/claude-code
npm install -g @musistudio/claude-code-router
Then point Claude Code at ccr (the project's docs walk through the env vars).
Where it fits
CCR is the request-layer counterpart to cc-mirror β same goal (Claude Code on non-Anthropic models), different mechanism. CC-Mirror clones the install per provider; ccr keeps one install and routes at request time. Both ship a ccrouter integration so cc-mirror variants can use ccr as their backend. cursor-bridge is the opposite end of the same family: no configuration, no daemon, one backend, and a process that lives and dies with the terminal.
Conceptually it's an llm-api-routing-layer β same shape as Vercel AI Gateway, Helicone, LiteLLM β except the upstream client is Claude Code specifically, and the transformers know about Claude Code's tool-call format. The 33k-star count makes it the most-adopted Claude-Code-shaped LLM gateway.
Limitations
- Configuration is text-edited JSON β the surface is big and easy to mis-shape.
- Tool-use fidelity across providers is uneven; transformers paper over the worst gaps but model-specific quirks remain.
- Routing costs the prompt cache. KV state is model-specific and does not travel, so a
/modelswitch or a slot that sendsthinkrequests elsewhere re-prefills the whole session at uncached prices β see prompt-caching-in-agents. portal-shunt-token-routing routes by task instead: bulk reads go out as separate calls, so the main session's cache stays intact. - A single ccr instance is single-tenant by default β the
APIKEYmechanism is a minimum, not full multi-tenant auth. - Sponsored by Z.ai (the GLM-CODING-PLAN promo banner sits at the top of the README); their interest in keeping ccr useful is structural, not contractual.
Repo: https://github.com/musistudio/claude-code-router (MIT, 33.8k stars).