返回指南
Integration·2026年7月26日·9 min read

Claude Code Router — route Claude Code to any model, or skip the router entirely

Most people reaching for claude-code-router only want Claude Code somewhere cheaper — and that is a base-URL swap, not an install. Here is when the router actually earns its place, the exact variables for both routes, and an honest list of what a gateway breaks.

Most people searching for Claude Code Router want one of two different things: route Claude Code across several model providers, or just run Claude Code somewhere cheaper than Anthropic's list price. Only the first needs the router. Claude Code reads ANTHROPIC_BASE_URL natively, so the second is three environment variables and no extra software at all.

This guide covers both paths, with the exact variable names, the credential trap that produces a silent 401, and an honest list of what stops working behind any gateway.

Which one do you actually need?

What you wantUse
Run Claude in Claude Code, cheaperBase URL swap — no install
A different model per task (plan / code / background)Either — ANTHROPIC_DEFAULT_* vars, or the router
Mix several providers behind one Claude Codeclaude-code-router
Drive Claude Code with non-Claude modelsclaude-code-router

The router is a local proxy: one more process to run, configure and keep current. It earns that cost when you genuinely need multi-provider routing. It does not earn it when a base URL would have done.

Option A — the base URL swap (no install)

Kunavo serves the native Anthropic Messages API at /v1/messages, which is the endpoint Claude Code calls. Point it there:

~/.zshrc
export ANTHROPIC_BASE_URL=https://api.kunavo.com
export ANTHROPIC_AUTH_TOKEN=sk-kn-...              # create at kunavo.com/app/keys
export ANTHROPIC_MODEL=claude-sonnet-4-6           # exact slug — see the table below
export ANTHROPIC_DEFAULT_HAIKU_MODEL=claude-haiku-4-5   # background tasks

ANTHROPIC_BASE_URL is the origin only — Claude Code appends /v1/messages itself, so don't include a path. Get the key from the dashboard after signing up and topping up $5; it's shown once.

Which credential variable — and why it matters

Claude Code sends the two credential variables in different HTTP headers, and a key in the header the server doesn't read fails with 401:

VariableHeader sentOn Kunavo
ANTHROPIC_AUTH_TOKENAuthorization: BearerRecommended — works everywhere
ANTHROPIC_API_KEYx-api-keyWorks for chat; breaks model discovery

Prefer ANTHROPIC_AUTH_TOKEN for two concrete reasons. First, ANTHROPIC_API_KEY needs a one-time approval in an interactive session, and a key you declined once is ignored afterwards with no prompt — a confusing failure where the variable is plainly set and plainly unused. Second, Claude Code's gateway model discovery sends only the bearer token when ANTHROPIC_AUTH_TOKEN is set, and falls back to x-api-key otherwise — and Kunavo's /v1/models endpoint reads the bearer header only. With ANTHROPIC_API_KEY, discovery fails silently.

Make it stick

Shell exports only apply to that terminal and anything launched from it — an editor opened from the dock won't see them, and neither will background agents. Put the values in a settings file to cover everything:

~/.claude/settings.json
{
  "env": {
    "ANTHROPIC_BASE_URL": "https://api.kunavo.com",
    "ANTHROPIC_AUTH_TOKEN": "sk-kn-...",
    "ANTHROPIC_MODEL": "claude-sonnet-4-6",
    "ANTHROPIC_DEFAULT_HAIKU_MODEL": "claude-haiku-4-5"
  }
}

Use ~/.claude/settings.json for all projects. Never put a key in a project's .claude/settings.json — that file gets committed.

Verify before you trust it

Test the endpoint directly first, so a failure points at the configuration rather than at Claude Code:

verify.sh
curl -X POST "$ANTHROPIC_BASE_URL/v1/messages" \
  -H "Authorization: Bearer $ANTHROPIC_AUTH_TOKEN" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{"model":"claude-sonnet-4-6","max_tokens":1,"messages":[{"role":"user","content":"."}]}'

# A response starting with {"id":"msg_ means the URL and key both work.
# 401 -> the key is in the wrong header; see "Which credential variable" below.

Then start claude from the same shell and run /status. An Anthropic base URL line showing api.kunavo.com and an Auth token line naming your variable confirm both halves are live.

Pick the model explicitly

Kunavo resolves model slugs by exact match and does not alias date-suffixed names, so claude-sonnet-4-5-20250929 returns 404 where claude-sonnet-4-6 succeeds. Always set ANTHROPIC_MODEL rather than relying on the built-in default:

RoleSlugInput / output per 1M
Everyday coding (default)claude-sonnet-4-6$1.20 / $6.00
Near-Opus coding qualityclaude-sonnet-5$2.10 / $10.50
Hardest refactors, plan modeclaude-opus-5$2.00 / $10.00
Background tasks, quick asksclaude-haiku-4-5$0.40 / $2.00

The alias variables give you per-task routing without any router at all: ANTHROPIC_DEFAULT_OPUS_MODEL backs the opus alias and plan mode, ANTHROPIC_DEFAULT_SONNET_MODEL backs sonnet, and ANTHROPIC_DEFAULT_HAIKU_MODEL backs haiku plus Claude Code's background work — the summaries and titles that quietly accumulate cost. Pointing that one at claude-haiku-4-5 is the single highest-value line in the config. (ANTHROPIC_SMALL_FAST_MODEL is the deprecated spelling of the same setting.)

Optional: show every model in the picker

Set CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1 (Claude Code v2.1.129+) and Claude Code queries GET /v1/models at startup, adding what it finds to the /model picker labelled From gateway. Kunavo serves that endpoint, so every enabled Claude model shows up and /model becomes a live menu instead of a list you maintain by hand. This is the path that requires ANTHROPIC_AUTH_TOKEN — see above.

Option B — claude-code-router with Kunavo as a provider

If you do want the router — for multi-provider fan-out, or to put non-Claude models behind Claude Code's interface — Kunavo slots in as an OpenAI-compatible provider. The router talks to providers over /v1/chat/completions:

~/.claude-code-router/config.json
{
  "Providers": [
    {
      "name": "kunavo",
      "api_base_url": "https://api.kunavo.com/v1/chat/completions",
      "api_key": "sk-kn-...",
      "models": ["claude-sonnet-4-6", "claude-opus-5", "claude-haiku-4-5"]
    }
  ],
  "Router": {
    "default":     "kunavo,claude-sonnet-4-6",
    "background":  "kunavo,claude-haiku-4-5",
    "think":       "kunavo,claude-opus-5",
    "longContext": "kunavo,claude-sonnet-4-6"
  }
}

Then run ccr code instead of claude. The Router block is where the router earns its keep: distinct models for default, background, thinking and long-context work, switchable without touching your shell. Field names have moved between router versions — check yours against the config schema it ships with if a key is rejected.

Note the tradeoff: this path uses the OpenAI-compatible surface, so cache_control is translated rather than passed through. The base-URL route in Option A uses the native Messages API, where prompt caching reaches the model untouched and cached input bills at 10% of the input rate (how it works). On an agent loop that resends a stable prefix every step, that is the largest single saving available — which is a real argument for Option A beyond simply being less to install.

What a coding session costs

Claude Code resends the system prompt, conversation and fresh file context on every step, so the per-token rate compounds quickly. At Kunavo rates on claude-sonnet-4-6:

UnitTokens (in / out)KunavoAnthropic list
One agentic step25,000 / 1,200$0.037$0.093
A 20-step task~500k / ~24k~$0.74~$1.86
A heavy day (5 tasks)~$3.72~$9.30

That is roughly 60% off on the mainline model, before prompt caching. Full rates are in the Claude API pricing guide, and the cost calculator takes your own token counts.

What still works — and what doesn't

Pointing Claude Code at any gateway changes a few things. The list is short and worth knowing before you commit:

FeatureBehind a gateway
Coding, tools, subagents, MCP, hooksUnaffected
Prompt cachingWorks — native Messages API route
Your claude.ai subscriptionNot used; billed per token to the key instead
Remote ControlUnavailable — needs a claude.ai identity
Voice dictationUnavailable — same reason
/context token countsEstimated locally (see below)

On that last row: token counting is the one endpoint Anthropic's own gateway specification marks optional, and Claude Code estimates context usage locally when it is absent. Kunavo does not serve /v1/messages/count_tokens today, so your /context figure is an estimate rather than an exact count. Nothing degrades beyond that number — auto-compaction and the session itself are unaffected.

Troubleshooting

SymptomCause and fix
401 on every requestKey is in the header the server doesn't read. Switch between ANTHROPIC_AUTH_TOKEN and ANTHROPIC_API_KEY and retry the curl above.
Claude Code asks you to log in, but curl worksA reachable base URL is not a credential. Set ANTHROPIC_AUTH_TOKEN somewhere read before first-run setup: a shell export or ~/.claude/settings.json.
ANTHROPIC_API_KEY set but ignored, no promptThe one-time approval was declined earlier. Enable it under /configUse custom API key, or switch to ANTHROPIC_AUTH_TOKEN.
404 naming the modelExact-slug matching — drop any date suffix and use a slug from the table above.
400 naming thinking or adaptiveClaude Code requests adaptive reasoning on 4.6+ models. On Opus 4.6 and Sonnet 4.6, CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING=1 works around it.
/fast says fast mode is disabledThe availability check calls api.anthropic.com directly and doesn't follow your base URL. Set CLAUDE_CODE_SKIP_FAST_MODE_ORG_CHECK=1.
Models missing from the pickerEnable CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1 with ANTHROPIC_AUTH_TOKEN set, or name them via the ANTHROPIC_DEFAULT_*_MODEL variables.

Error-by-error fixes for the API itself are in the invalid API key and rate limit troubleshooting pages.

FAQ

Do I need claude-code-router at all?

Only for multi-provider routing or non-Claude models. To run Claude on a cheaper endpoint, the base-URL swap in Option A does the same job with nothing to install and keeps native prompt caching.

Can I use my Claude Pro or Max subscription instead?

No. Chat subscriptions don't include API access, and setting a gateway credential deliberately parks your claude.ai login — the subscription's limits stop applying and usage bills per token to the key instead. See is Claude Code free for the full breakdown.

Does this work with the VS Code extension?

Yes, but the extension checks credentials before launching, so set them in VS Code's own claudeCode.environmentVariables setting rather than only in ~/.claude/settings.json.

What about Cursor, Kilo Code or Cline?

Those use an OpenAI-compatible provider field instead of environment variables — base URL https://api.kunavo.com/v1, same key. See the Kilo Code, Cline and Roo Code guide.