Multi-provider model router for Claude Code. Route different models to different LLM providers — use Anthropic for Opus, OpenAI for Sonnet, DeepSeek for Haiku, or any combination you want.
CC-Router acts as a local proxy that speaks the Anthropic Messages API on the front end and translates requests to the correct provider on the back end. Claude Code talks to CC-Router as if it were the Anthropic API; CC-Router routes each request based on the model name.
Claude Code
│
│ ANTHROPIC_BASE_URL=http://127.0.0.1:8787
▼
┌─────────────┐ route: *opus* ┌──────────────┐
│ CC-Router │ ──────────────────► │ Anthropic │
│ (proxy) │ │ API │
│ │ route: *sonnet* ├──────────────┤
│ │ ──────────────────► │ OpenAI │
│ │ │ API │
│ │ route: *haiku* ├──────────────┤
│ │ ──────────────────► │ DeepSeek │
└─────────────┘ │ API │
└──────────────┘
- Claude Code sends a request to
http://127.0.0.1:8787/v1/messages - CC-Router matches the model name against your route rules
- The request is forwarded to the matched provider (with format conversion if needed)
- The response is translated back to Anthropic format and returned to Claude Code
npm install -g @ssbun/cc-routerOr run without installing:
npx @ssbun/cc-router --helpRequires Node.js 20+.
cc-router setupThe interactive wizard walks you through adding providers one by one:
- Choose provider type (
anthropic-compatibleoropenai-compatible) - Enter provider name, base URL, and API key
- Add models to the provider
- Configure routes (map model patterns to providers)
- Set server host and port
Config is saved to ~/.cc-router/config.yaml.
cc-router startOr run as a background daemon:
cc-router start --daemonThe server prints the environment variables you need to set.
Add the printed exports to your shell (e.g., ~/.zshrc or ~/.bashrc):
export ANTHROPIC_BASE_URL="http://127.0.0.1:8787"
export ANTHROPIC_AUTH_TOKEN="<generated-token>"
export ANTHROPIC_DEFAULT_OPUS_MODEL="glm-5.1"
export ANTHROPIC_DEFAULT_SONNET_MODEL="deepseek-v4-pro"
export ANTHROPIC_DEFAULT_HAIKU_MODEL="deepseek-v4-flash"Or configure Claude Code interactively:
cc-router claudeThis opens an interactive wizard that manages all of ~/.claude/settings.json — cc-router env vars, feature flags, preferences, and more. Includes a token-efficient preset and j/k vim navigation. The legacy inject command is deprecated.
Print exports manually anytime:
cc-router envclaudeClaude Code now routes through CC-Router. Opus requests go to Anthropic, Sonnet requests go to OpenAI, Haiku requests go to DeepSeek — all transparent.
CC-Router includes a built-in web dashboard for monitoring requests in real time. Open it at:
http://127.0.0.1:8787/dashboard
- Live request stream — real-time feed of all proxied requests via SSE
- Request details — click any request to inspect full request/response payloads
- Structured view — toggle between raw JSON and parsed chat timeline (messages, tool calls, thinking blocks)
- Markdown preview — render message content as markdown
- Usage stats — request count, token usage, error rate, latency percentiles
- Provider & route info — sidebar with provider status, active routes, top models
- Config & models viewer — inspect your routing config and built-in model database
Request records are stored in SQLite at ~/.cc-router/metrics.db. History survives server restarts. Use the "Clear History" button in the dashboard to wipe stored data.
For full request/response payload capture:
cc-router start --log-level traceTrace mode stores complete request and response bodies, enabling detailed inspection of messages, tools, and thinking blocks in the dashboard.
Config lives at ~/.cc-router/config.yaml. Edit it directly or use the CLI:
cc-router config edit # Open in $EDITOR
cc-router config show # Print current config
cc-router config path # Print config file pathserver:
host: "127.0.0.1"
port: 8787
auth_token: ""
providers:
anthropic:
type: "anthropic-compatible"
api_key: "${ANTHROPIC_API_KEY}"
base_url: "https://api.anthropic.com"
models:
- id: "claude-opus-4-20250514"
max_input_tokens: 1000000
- id: "claude-sonnet-4-20250514"
max_input_tokens: 1000000
- id: "claude-haiku-4-20251001"
max_input_tokens: 200000
openai:
type: "openai-compatible"
api_key: "${OPENAI_API_KEY}"
base_url: "https://api.openai.com/v1"
models:
- "gpt-4o"
- "o3-mini"
deepseek:
type: "openai-compatible"
api_key: "${DEEPSEEK_API_KEY}"
base_url: "https://api.deepseek.com/v1"
models:
- id: "deepseek-chat"
max_input_tokens: 1000000
routes:
- match: "*opus*"
provider: "anthropic"
model: "claude-opus-4-20250514"
- match: "*sonnet*"
provider: "openai"
model: "gpt-4o"
- match: "*haiku*"
provider: "deepseek"
model: "deepseek-chat"
- match: "*"
provider: "anthropic"Use ${VAR_NAME} syntax in config values. CC-Router interpolates them at load time:
api_key: "${ANTHROPIC_API_KEY}"If the variable is not set, the literal ${VAR_NAME} is kept and a warning is logged.
| Type | Description | API Format |
|---|---|---|
anthropic-compatible |
Anthropic or Anthropic-compatible API | Anthropic Messages |
openai-compatible |
OpenAI or OpenAI-compatible API | Converted to/from OpenAI Chat Completions |
Each provider has an optional models array. Models can be simple strings or objects with max_input_tokens and max_tokens:
providers:
openai:
type: "openai-compatible"
api_key: "${OPENAI_API_KEY}"
base_url: "https://api.openai.com/v1"
models:
- "gpt-4o" # simple string
- id: "o3-mini" # with token limits
max_input_tokens: 200000
max_tokens: 16000Context window resolution priority: provider config → built-in database → tier inference. The built-in database covers 15+ models (GLM + DeepSeek).
Query the database:
cc-router models # list all known models in table format
cc-router models glm-5.1 # show details for a specific modelRoutes use picomatch glob patterns:
| Pattern | Matches |
|---|---|
*opus* |
Any model containing "opus" |
*sonnet* |
Any model containing "sonnet" |
*haiku* |
Any model containing "haiku" |
claude-* |
Models starting with "claude-" |
* |
Everything (catch-all) |
Routes are evaluated top to bottom. First match wins. The optional model field overrides the model name sent to the provider.
Add extra headers per provider (useful for gateways and proxies):
providers:
gateway:
type: "anthropic-compatible"
api_key: "${API_KEY}"
base_url: "https://my-gateway.example.com"
models:
- "claude-sonnet-4-20250514"
headers:
X-Custom-Auth: "Bearer ${GATEWAY_TOKEN}"cc-router start [-p <port>] [-d] [--log-level <level>] Start the server
cc-router stop Stop the daemon
cc-router restart [-p <port>] Restart the daemon
cc-router status Show server status
cc-router list List providers and routes
cc-router env Print export statements
cc-router setup Interactive setup wizard
cc-router claude [--dry-run] [--no-backup] Configure Claude Code settings
cc-router dashboard Open web dashboard in browser
cc-router models [<id>] Query built-in model database
cc-router config show Print current config
cc-router config path Print config file path
cc-router config edit Open config in $EDITOR
cc-router route list List routes
cc-router route add Add a new route
cc-router route edit Edit an existing route
cc-router route remove Remove a route
cc-router route reorder Change route priority
cc-router chat [-m <model>] [--no-stream] Test chat with a provider
cc-router start --log-level trace # full request/response payloads
cc-router start --log-level debug # request summaries
cc-router start --log-level info # default
cc-router start --verbose # shorthand for --log-level debugManage routing rules without editing the config file directly:
# List current routes with priority order
cc-router route list
# Add a new route (interactive)
cc-router route add
# Edit an existing route's match pattern, provider, or model
cc-router route edit
# Remove a route
cc-router route remove
# Reorder routes (priority matters — first match wins)
cc-router route reorderTest your provider connections directly from the terminal:
cc-router chat -m claude-sonnet-4-20250514
cc-router chat -m gpt-4o --no-streamSupports streaming by default. Type /exit to quit, /clear to reset history.
Claude Code lets you set per-tier model overrides via environment variables:
| Variable | Controls |
|---|---|
ANTHROPIC_DEFAULT_OPUS_MODEL |
Which model Claude Code uses for "Opus" |
ANTHROPIC_DEFAULT_SONNET_MODEL |
Which model Claude Code uses for "Sonnet" |
ANTHROPIC_DEFAULT_HAIKU_MODEL |
Which model Claude Code uses for "Haiku" |
CC-Router's env command detects your route config and prints the correct exports. Example: if your route maps *sonnet* to OpenAI's gpt-4o, cc-router env prints:
export ANTHROPIC_DEFAULT_SONNET_MODEL="gpt-4o"Claude Code then sends requests with model gpt-4o. CC-Router matches *sonnet* (or *), routes to OpenAI, and converts the response back.
- Streaming and non-streaming responses
- Tool use (function calling) with format conversion between Anthropic and OpenAI
- Multi-turn conversations
- Image inputs
- Thinking/extended thinking blocks
- CORS support
- Request authentication via auth token
- Daemon mode with PID management
- Environment variable interpolation in config
- Built-in web dashboard with real-time monitoring
- SQLite-backed request history persistence
MIT