How to run Claude Code on OpenRouter and DeepSeek: the ANTHROPIC_BASE_URL guide

How to run Claude Code on OpenRouter with alternative models like DeepSeek: the ANTHROPIC_BASE_URL guide

👁22views

Set the `ANTHROPIC_BASE_URL` environment variable to the OpenRouter endpoint `https://openrouter.ai/api/v1` before launching Claude Code, and ensure your `ANTHROPIC_API_KEY` contains a valid OpenRouter API key. This directs all Claude Code API calls through OpenRouter instead of Anthropic. The variable controls the request destination, not the model selection, which you must configure separately using the ` model` flag with a model name like `deepseek/deepseek coder`.

CloudScale AI SEO: Article Summary
  • 1.
    What it is
    This ANTHROPIC_BASE_URL guide explains how to run Claude Code on OpenRouter and DeepSeek by changing the request endpoint without changing the model, and provides exact scripts to set it up.
  • 2.
    Why it matters
    Precise ANTHROPIC_BASE_URL configuration prevents silent tool call failures and enables cost tiering by routing subagents to cheaper models on OpenRouter or DeepSeek.
  • 3.
    Key takeaway
    ANTHROPIC_BASE_URL changes only the request endpoint, not the model, and a cached claude.ai login can override your environment variable settings.
~7 min read
🎧 Listen to this article

1. Why this is worth being precise about

Claude Code’s model can be changed through an environment variable, and that variable can point at a gateway such as OpenRouter rather than at Anthropic’s own API. This is how people run Claude Code against DeepSeek, GLM, or any other backend a gateway serves. The question comes up often, and the mechanism behind it gets conflated just as often. The environment variable in question is ANTHROPIC_BASE_URL, and it is worth being precise about what it does and does not control, because getting this wrong is how people end up with a session that authenticates fine and then fails silently on tool calls halfway through a task.

2. What the variable actually controls

ANTHROPIC_BASE_URL changes where Claude Code sends its requests. It does not change which model answers them. Those are two separate decisions, and Claude Code treats them as such:

  • Where the request goes: ANTHROPIC_BASE_URL, plus a credential in either ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY.
  • Which model answers: ANTHROPIC_MODEL for the session, or ANTHROPIC_DEFAULT_SONNET_MODEL, ANTHROPIC_DEFAULT_OPUS_MODEL, and ANTHROPIC_DEFAULT_HAIKU_MODEL for what the built in aliases resolve to.

Once you point ANTHROPIC_BASE_URL somewhere other than Anthropic’s own API, that endpoint decides what a given model name actually resolves to. Claude Code keeps speaking its native Anthropic Messages protocol regardless of where the request lands. This matters because a provider that only speaks an OpenAI style format will accept the connection and then fail in ways that look like a Claude Code bug but are actually a protocol mismatch.

OpenRouter is the cleanest example of doing this properly. It exposes an endpoint at https://openrouter.ai/api that speaks the Anthropic Messages protocol natively, what OpenRouter calls its Anthropic Skin. Claude Code sends the same request shape it always sends, OpenRouter maps the model name and forwards it to whichever provider actually serves it, and extended thinking and native tool use pass through the round trip intact. No local proxy is required for this path specifically, which is not true of every provider that advertises Claude Code compatibility.

DeepSeek takes the same approach from the other direction. Rather than sitting behind a routing layer, it exposes its own Anthropic compatible endpoint directly, so Claude Code can talk to it without OpenRouter or any translation proxy in between. The shape of the trick is identical in both cases:

                     Claude Code
                          |
                 Anthropic Messages
                          |
                ANTHROPIC_BASE_URL
                          |
           +--------------+--------------+
           |                             |
      OpenRouter                     DeepSeek
  openrouter.ai/api        api.deepseek.com/anthropic
           |                             |
      model routing                 DeepSeek V4
           |
    +------+-------+
  Claude  DeepSeek  etc.

Claude Code is the agent harness. Anthropic Messages is the protocol it speaks. ANTHROPIC_BASE_URL chooses the endpoint that receives that protocol. The endpoint, whether a multi provider router or a single vendor’s own compatible API, decides which model ultimately answers.

3. Script one: point Claude Code at OpenRouter

This is the minimal setup for routing through OpenRouter rather than Anthropic’s own billing. Save it as a shell function so you can switch it on deliberately rather than leaving it set permanently in your profile.

cat > claude-via-openrouter.sh << 'EOF'
#!/usr/bin/env bash
# claude-via-openrouter.sh
# Routes this shell's Claude Code sessions through OpenRouter's
# Anthropic compatible endpoint instead of Anthropic's own API.

set -euo pipefail

if [ -z "${OPENROUTER_API_KEY:-}" ]; then
  echo "Set OPENROUTER_API_KEY first, e.g. export OPENROUTER_API_KEY=sk-or-..." >&2
  exit 1
fi

export ANTHROPIC_BASE_URL="https://openrouter.ai/api"
export ANTHROPIC_AUTH_TOKEN="$OPENROUTER_API_KEY"
export ANTHROPIC_API_KEY=""

echo "Claude Code will now route through OpenRouter for this shell."
echo "Run 'claude', then '/status' to confirm the base URL and auth source."
EOF
chmod +x claude-via-openrouter.sh

Source it rather than executing it in a subshell, so the exports land in your current session:

source ./claude-via-openrouter.sh

If you were previously logged in with a claude.ai account in this terminal, run /logout inside Claude Code once before relaunching. A cached first party login can override the environment variables and produce confusing model not found errors that have nothing to do with your OpenRouter setup.

Confirm the switch took effect:

/status

You should see Anthropic base URL: https://openrouter.ai/api and Auth token: ANTHROPIC_AUTH_TOKEN on the Status tab. If either line is missing, the exports did not reach the process, most commonly because you ran the script in a subshell instead of sourcing it.

4. Script two: point Claude Code directly at DeepSeek

DeepSeek publishes its own Anthropic compatible endpoint at api.deepseek.com/anthropic, so this path skips OpenRouter entirely. DeepSeek’s own Claude Code integration guide maps the three model tiers to two of its own models: requests aimed at Opus resolve to deepseek-v4-pro, while Sonnet and Haiku both resolve to deepseek-v4-flash unless you override the mapping yourself.

cat > claude-via-deepseek.sh << 'EOF'
#!/usr/bin/env bash
# claude-via-deepseek.sh
# Routes this shell's Claude Code sessions through DeepSeek's own
# Anthropic compatible endpoint instead of Anthropic's own API.

set -euo pipefail

if [ -z "${DEEPSEEK_API_KEY:-}" ]; then
  echo "Set DEEPSEEK_API_KEY first, e.g. export DEEPSEEK_API_KEY=sk-..." >&2
  exit 1
fi

export ANTHROPIC_BASE_URL="https://api.deepseek.com/anthropic"
export ANTHROPIC_AUTH_TOKEN="$DEEPSEEK_API_KEY"
unset ANTHROPIC_API_KEY

export ANTHROPIC_MODEL="deepseek-v4-pro[1m]"
export ANTHROPIC_DEFAULT_OPUS_MODEL="deepseek-v4-pro[1m]"
export ANTHROPIC_DEFAULT_SONNET_MODEL="deepseek-v4-pro[1m]"
export ANTHROPIC_DEFAULT_HAIKU_MODEL="deepseek-v4-flash"
export CLAUDE_CODE_SUBAGENT_MODEL="deepseek-v4-flash"
export CLAUDE_CODE_EFFORT_LEVEL="max"

echo "Claude Code will now route through DeepSeek for this shell."
echo "Run 'claude', then '/status' to confirm the base URL and auth source."
EOF
chmod +x claude-via-deepseek.sh

Source it the same way as the OpenRouter script:

source ./claude-via-deepseek.sh

The [1m] suffix requests the larger context window on the model that supports it, and CLAUDE_CODE_SUBAGENT_MODEL pins subagents to the cheaper flash tier rather than letting them inherit the pro model by default. Run /logout first if this terminal has a cached claude.ai login, for the same reason noted in the OpenRouter setup.

5. Script three: tier your models by task cost

Claude Code lets you keep the main session on a stronger model while assigning a cheaper model to subagents, through CLAUDE_CODE_SUBAGENT_MODEL. That makes delegated investigation, codebase exploration, and other fan out work a natural place to reduce inference cost, without needing a gateway at all.

cat > claude-tiered-models.sh << 'EOF'
#!/usr/bin/env bash
# claude-tiered-models.sh
# Keeps the main session on a strong model while assigning
# a cheaper model to subagents.

set -euo pipefail

# Main session: your default provider and model resolution, unchanged.
unset ANTHROPIC_BASE_URL
unset ANTHROPIC_AUTH_TOKEN

# Subagents inherit the session model by default. Override that here
# so delegated investigation and fan out work runs on a cheaper model.
export CLAUDE_CODE_SUBAGENT_MODEL="haiku"

echo "Main session model: default alias resolution."
echo "Subagent model pinned to: $CLAUDE_CODE_SUBAGENT_MODEL"
echo "Adjust with claude --model <alias> at launch, or /model inside a session."
EOF
chmod +x claude-tiered-models.sh

If you want the cheap tier to run through OpenRouter or DeepSeek specifically while your main session stays on Anthropic’s own API directly, combine this script with whichever gateway script applies, and set the gateway variables only inside a settings file scoped to sessions that should use it, rather than exporting them globally. A blanket ANTHROPIC_BASE_URL export affects every Claude surface launched from that shell, including your main session.

6. Making the routing decision deliberate rather than accidental

I would not put either of these in a shell profile that loads by default. A settings file scoped to the project or the session gives you the same effect with a paper trail, and it reaches background agents that a shell export does not reliably reach.

{
  "env": {
    "ANTHROPIC_BASE_URL": "https://openrouter.ai/api",
    "ANTHROPIC_AUTH_TOKEN": "sk-or-your-key",
    "CLAUDE_CODE_SUBAGENT_MODEL": "haiku"
  }
}

Place that in .claude/settings.local.json for a project you want on a specific routing policy, and keep it out of version control since it carries a credential. If your team runs this at scale rather than per developer, the same pattern belongs in an organisation LLM gateway configuration rather than in individual settings files, which gives you spend limits and an audit log that a personal OpenRouter key does not.

7. What you give up when you route away from Anthropic’s own API

Three things stop working the moment ANTHROPIC_BASE_URL points anywhere other than Anthropic, and none of them announce themselves clearly when they fail:

  1. Remote Control and voice dictation both depend on a claude.ai identity and are disabled while a gateway credential variable is active, regardless of which gateway it is.
  2. Reliable tool use is not guaranteed on every backend. Claude Code is an agentic harness built around a specific model’s behaviour with tool calls, file edits, and multi step plans. OpenRouter’s own guidance is explicit that this integration is only fully guaranteed against Anthropic’s first party models; a cheaper model behind the same endpoint may answer prompts well and still mishandle the tool calling patterns Claude Code relies on for editing your codebase safely.
  3. Fast mode’s availability check goes straight to api.anthropic.com regardless of your base URL setting, so it can report itself unavailable even when your actual inference requests are working fine through the gateway.

None of this is a reason to avoid routing away from Anthropic’s own API. It is a reason to test it on work you can afford to redo before you trust it with a refactor you cannot easily check by eye. The engineering discipline I would apply here is the same one I have carried since my algorithmic trading days: speed and correctness are not a tradeoff you get to choose one side of. A cheap model that quietly mangles a tool call on a production codebase has not saved you money, it has deferred the cost to the debugging session that follows.