Claude Code + OpenRouter: the setup that keeps your Max/Pro subscription intact
·Published 11 August 2026
Prefer to read? The full walkthrough is below.
Every guide in this category tells you the same thing. Cancel your subscription, here's how to run Claude Code for free.
This one does the opposite. You keep the subscription, and you add other models next to it.
That matters because the official setup, followed literally, takes away things you're already paying for. Not obviously, and not with an error message.
Warning: this is for the Claude Code CLI, the one you run in a
terminal. It will not work in the Claude Code desktop app. The whole approach
depends on setting environment variables inline for a single claude
invocation, and the desktop app doesn't launch from your shell, so there's
nowhere to put them.
Just have Claude Code set it up
If you'd rather not hand-edit your shell config, paste this into a Claude Code session and it'll walk you through it. It asks which models you want before it writes anything.
# Goal
Set me up to run third-party models through OpenRouter inside Claude Code, **without breaking my existing Claude subscription**.
# Hard requirements (do not deviate)
- Do **not** export `ANTHROPIC_BASE_URL`, `ANTHROPIC_AUTH_TOKEN` or `ANTHROPIC_API_KEY` globally in my shell profile. Set them per-invocation only.
- Do **not** run `/logout`, and do not touch my cached Anthropic credentials.
- Do **not** add an `env` block to any `.claude/settings.local.json`.
- My plain `claude` command must keep working exactly as it does now.
# Steps
1. **Ask me which models I want commands for.** Suggest a few options with their current OpenRouter prices and what each is good at. Wait for my answer.
2. **Ask where my OpenRouter API key lives** (an env var, or a file path I give you). Never print the key back to me.
3. **Check whether any model I picked needs an OpenRouter preset** to route around a provider that rejects Claude Code's tool schemas. If so, give me the exact steps to create that preset in the OpenRouter dashboard on *my* account, then use the resulting `model@preset/name` slug. Presets are per-account, so I cannot reuse someone else's.
4. **Write one shared shell function** that sets the variables inline for a single invocation, plus one short wrapper per model I picked. Override `ANTHROPIC_DEFAULT_OPUS_MODEL`, `ANTHROPIC_DEFAULT_SONNET_MODEL`, `ANTHROPIC_DEFAULT_HAIKU_MODEL` and `CLAUDE_CODE_SUBAGENT_MODEL` too, so background calls and subagents don't silently bill Anthropic models through OpenRouter.
5. **Default each session to no MCP servers**, with a flag to turn them back on. The tool schemas are most of the request payload, and claude.ai-hosted connectors don't work on OpenRouter auth anyway.
6. **Show me the diff before writing it.** Then tell me exactly what to run to reload my shell and test one model end to end.The rest of this guide explains what that prompt is doing and why each constraint is in there. Worth reading before you run it on a machine you care about.
What the official instructions actually do
OpenRouter's Claude Code guide asks you to do two things.
- Export
ANTHROPIC_BASE_URL,ANTHROPIC_AUTH_TOKENand an explicitly emptyANTHROPIC_API_KEYin your shell profile. - Run
/logoutto clear the cached Anthropic login.
Both are global. On a machine with a Claude subscription, a shell-wide
ANTHROPIC_AUTH_TOKEN silently hides /schedule, because cloud Routines need
subscription auth. It stops claude.ai connectors loading at all, so Calendar,
Drive, Slack, Notion and any claude.ai-hosted MCP server go quiet. And it can
route your Claude Code usage to API billing instead of your subscription.
Warning: /logout is not per-session. It deletes the one cached login. On
macOS that's a single Keychain entry called Claude Code-credentials. Follow
the docs literally and every Claude Code session on the machine becomes an
OpenRouter session.
None of that announces itself. You notice weeks later, when a slash command has quietly stopped existing.
The fix: set the variables per process
Claude Code reads ANTHROPIC_BASE_URL and ANTHROPIC_AUTH_TOKEN from the
environment of its own process. Set them inline for a single invocation and
nothing else on the machine ever sees them. No exports, no /logout, no config
changes.
The practical form is a shell function rather than exports, so nothing leaks into your normal sessions.
_openrouter_claude() {
local model="$1"; shift
# MCP servers OFF by default. See the note below.
local mcp_args=(--strict-mcp-config --mcp-config '{"mcpServers":{}}')
if [ "$1" = "--mcp" ]; then
mcp_args=()
shift
fi
local key="$OPENROUTER_API_KEY"
if [ -z "$key" ]; then
echo "No OPENROUTER_API_KEY set" >&2
return 1
fi
ANTHROPIC_BASE_URL="https://openrouter.ai/api" \
ANTHROPIC_AUTH_TOKEN="$key" \
ANTHROPIC_API_KEY="" \
ANTHROPIC_DEFAULT_OPUS_MODEL="$model" \
ANTHROPIC_DEFAULT_SONNET_MODEL="$model" \
ANTHROPIC_DEFAULT_HAIKU_MODEL="$model" \
CLAUDE_CODE_SUBAGENT_MODEL="$model" \
claude --model "$model" "${mcp_args[@]}" "$@"
}
kimi() { _openrouter_claude "moonshotai/kimi-k3@preset/kimi-cc" "$@" }
glm() { _openrouter_claude "z-ai/glm-5.2" "$@" }Drop that in your ~/.zshrc, put your OpenRouter key in OPENROUTER_API_KEY,
and you get two new commands. claude still means your subscription. kimi
means Kimi K3 on OpenRouter credits. They can run at the same time in different
terminals without touching each other.
Warning: @preset/kimi-cc is a preset on my OpenRouter account, and
presets are per-account. Copy that line as-is and it will fail for you. You
need to create your own preset first, which takes a minute in the OpenRouter
dashboard under Presets. The next section explains what it's for and what to
put in it. The glm line has no preset, so that one works as written.
The @preset/... suffix is load-bearing, and the reason is worth understanding
before you copy anything.
Why the Haiku and subagent overrides are there
Claude Code spawns background Haiku-class calls and subagents. Without those four model overrides, they'd call Anthropic models through OpenRouter, quietly burning OpenRouter credits on requests your subscription would otherwise have covered.
The mental model
The Claude Code harness is the CLI, not the model. The CLI on your machine
assembles everything into one request. System prompt, CLAUDE.md, skills, tool
definitions, MCP servers, hooks, permissions. Then it sends that request to
whatever endpoint ANTHROPIC_BASE_URL points at, and the model is just the
brain answering it.
Swap the endpoint and the entire scaffold stays identical. That's the whole trick.
OpenRouter's side of it is what they call the Anthropic Skin.
https://openrouter.ai/api speaks the native Anthropic Messages protocol, so
you don't need a local proxy. That description comes from OpenRouter's own
documentation rather than anything I tested.
What carries over, and what you lose
Carries over, identically:
- All your skills and slash commands
- Global CLAUDE.md and project AGENTS.md rules
- Every built-in tool. Bash, Edit, Read, Agent and the rest
- Locally-configured MCP servers
- Hooks, permission modes, the whole harness
Lost, in that session only:
- claude.ai-hosted connectors, meaning anything authenticated through the subscription
/scheduleand cloud Routines- Behavioural reliability. The prompts and tool schemas are tuned for Claude. OpenRouter's own documentation warns that Claude Code "may not work correctly with other providers". Expect clumsier tool calls and weaker rule-following.
Warning: keep anything touching email, money or external systems in real Claude sessions. That reliability gap isn't theoretical.
Turn MCP servers off by default
The wrapper passes --strict-mcp-config --mcp-config '{"mcpServers":{}}', for a
reason that only became obvious after the first OpenRouter bill.
MCP tool schemas were about 540KB of a roughly 600KB request payload. The claude.ai-hosted connectors don't work on OpenRouter auth anyway, so you're paying to send schemas for tools that can't run. Measured effect of turning them off: 201 tools down to 28 core tools, roughly 150k input tokens down to roughly 38k per fresh request. That cut the per-request cost by about 75%.
Pass --mcp as the first argument when you do want them, so kimi --mcp.
Note: /mcp inside a session can only manage servers that were configured
at launch. It can't add servers to a strict-empty session, so re-enabling
means restarting with --mcp.
The 400 error, and why a preset fixes it
The first real run failed with API Error: 400 Provider returned error, both
headless and interactively. The debugging arc is worth knowing, because the root
cause isn't what it looks like.
A hand-built minimal Messages request to OpenRouter worked fine, so the key, the endpoint and the model were all correct. Bisecting Claude Code's features passed too. Thinking, tools, cache control, beta headers, streaming, all fine individually.
Capturing Claude Code's exact request and replaying it verbatim produced inconsistent results. Sometimes fine, sometimes a 400, with the real error finally visible.
Invalid request: tools.function.parameters is not a valid moonshot flavored JSON schemaThe root cause was provider roulette. Seven providers serve Kimi K3 on OpenRouter, and OpenRouter load-balances between them per request. Moonshot's own first-party API rejects some of Claude Code's tool schemas. The other hosts accept them. So every request was a dice roll.
Claude Code can't send OpenRouter's provider routing field. But OpenRouter
presets embed routing config in the model slug itself, and the slug is what
the environment variables control. Creating a preset called kimi-cc that
ignores the moonshotai provider, then referencing
moonshotai/kimi-k3@preset/kimi-cc, made the full Claude Code payload succeed
first attempt.
To do that on your own account: OpenRouter dashboard, Presets, new preset,
model moonshotai/kimi-k3, and a provider config that ignores moonshotai.
Name it whatever you like and use your own name in the slug. The point of
presets is that you can edit the routing there later without touching your
shell config at all.
The irony is worth sitting with. The provider failover OpenRouter sells as a reliability feature was the exact thing making Claude Code unreliable.
Presets also answer the data-privacy question
There's a circulating warning that Kimi sends your data to Chinese servers under Chinese jurisdiction. The distinction that matters is between the consumer chat app and the open-weight model served by third parties. These are open weights, so the jurisdiction risk attaches to whose servers run them, not to the model itself.
The usual advice is to pass a per-request provider block with
data_collection: "deny" and zdr: true. That advice doesn't work here, for
the same reason the 400 fix needed a preset. Claude Code can't send a
provider field. Pasting that JSON changes nothing.
Presets can carry it instead.
| Preset | Stored provider config | Effect |
|---|---|---|
kimi-cc | ignore: [moonshotai], data_collection: deny, zdr: true | Never touches Moonshot's own API, never a data-collecting host, zero-retention endpoints only |
glm-safe | data_collection: deny, zdr: true | Keeps requests off Z.AI, Alibaba, Baidu, SiliconFlow, StreamLake and other data-collecting hosts |
GLM was the real exposure, not Kimi. Kimi was already clean by accident,
because kimi-cc skipped Moonshot for schema reasons. GLM had no preset at all,
and its 33-endpoint pool includes Z.AI itself, Alibaba, Baidu, SiliconFlow,
StreamLake and Chutes. So every request was a fresh dice roll onto potentially
Chinese infrastructure, with no way to see which host served it.
Note: routing controls make third-party models safe for non-sensitive work. They're not a licence to widen what you send. Data classification beats model choice, so customer data, database rows and financial figures stay in first-party sessions regardless of routing.
What it costs
Prices per million tokens, pulled live from OpenRouter on 30 July 2026, with the Claude figures from Anthropic's published price card.
| Model | Billed via | Input | Output | Cached input |
|---|---|---|---|---|
| GLM-5.2 | OpenRouter credits | $0.97 | $3.04 | $0.18 |
| Kimi K3 | OpenRouter credits | $3.00 | $15.00 | $0.30 |
| Claude Sonnet 5 | Anthropic API | $3.00 | $15.00 | ~0.1× input |
| Claude Opus 5 | Anthropic API | $5.00 | $25.00 | ~0.1× input |
Two things people get wrong here.
Kimi K3 costs exactly Sonnet 5 list price. The cheap-challenger framing only holds for GLM-5.2, which is roughly three times cheaper than both.
Claude Code's /usage display overstates third-party costs by about 5×. It
flags that costs may be inaccurate for unknown models, and prices them at Opus 5
rates. A GLM session displaying $1.06 really cost about $0.21. Treat /usage as
a token counter in these sessions. The OpenRouter activity dashboard is the
actual bill.
Is the quality actually there?
From the Vals AI SWE-bench Verified leaderboard, an independent eval firm running every model on the same harness, as of 31 July 2026.
| Model | SWE-bench Verified |
|---|---|
| Claude Opus 5 | 97.0% |
| Kimi K3 | 93.4% |
| Claude Opus 4.8 | 88.6% |
| GLM-5.2 | 82.8% |
| Claude Sonnet 5 | 79.6% |
One benchmark, one leaderboard, and scores move. But the shape is clear enough. Kimi K3 at Sonnet list price scores near Opus 5. GLM-5.2 matches Anthropic's frontier model from roughly seven months earlier, at a fifth of the price.
There's a detail buried in that table I find genuinely interesting. Vals lists Opus 4.8 twice, at 88.6% on their default harness and 85.8% inside Claude Code. Same model, three points apart. The harness moves the score.
When you'd still follow the official approach
If you have no Claude subscription to protect, the global export is simpler and none of the warnings above apply to you. The per-process version exists specifically to keep a subscription intact alongside.
One more deviation worth naming. Skip the .claude/settings.local.json
alternative too. A project-level env block overrides auth for every session in
that repo, which is the same trap as the shell export, just scoped to a project
instead of a machine.
The honest version
The harness swap works perfectly. The third-party model ecosystem underneath is the wild west. Schema dialects, capacity roulette, per-provider quirks. Kimi K3 spent its launch evening returning 429s from every provider at once, because only seven serve it and all of them were saturated.
So you're not getting Claude Code for free. You're getting the option to point the best coding harness available at whichever model suits the job, while keeping the subscription that makes the default case reliable.
Tagged: claude-code, openrouter