DeepSeek in Claude Code: The Complete Setup Guide

Same terminal. Same keybindings, same slash commands, same workflow you've built your week around. Nothing about the cockpit changes — but open the hood and the engine is different. The model answering underneath is now DeepSeek V4, running on your own API budget instead of an Anthropic plan.

That's the whole pitch of the DeepSeek Claude Code pairing, and it's less invasive than it sounds. No proxy layer, no forked client, no wrapper scripts. DeepSeek publishes an endpoint that speaks Claude's native protocol, so you redirect Claude Code with a handful of environment variables and keep every habit intact. This guide walks the full path — install, configure, verify, and fix — with the official recipe up front and the community-tested reality behind it. I've run this pairing as my daily driver since spring; the notes below are what I wish I'd had on day one.

How the DeepSeek Claude Code Connection Works

Think of a travel adapter. Your appliance doesn't change, the wall socket doesn't change — the adapter translates between them. DeepSeek runs an Anthropic-compatible API at https://api.deepseek.com/anthropic, built precisely so tools in the Claude ecosystem can plug in without modification. Claude Code reads one variable, ANTHROPIC_BASE_URL, and once it points at DeepSeek, every request changes course.

Two details make the pairing sturdier than it looks.

First, Claude Code itself doesn't validate model names when a custom base URL is set. Model strings pass straight through to the provider, which is why you can write deepseek-v4-pro[1m] in a slot that officially expects a Claude name — the client shrugs and forwards it.

Second, DeepSeek's server side catches whatever slips through. Names starting with claude-opus map to deepseek-v4-pro; names starting with claude-sonnet or claude-haiku map to deepseek-v4-flash. Anything unrecognized falls back to v4-flash rather than erroring out. So even a half-configured setup tends to work — it just quietly runs the lighter model everywhere.

Equally important is what the swap doesn't touch. Your CLAUDE.md project instructions, slash commands, permission rules, MCP servers, hooks, subagent definitions — all of that lives in the client and rides along untouched. The server only ever sees model requests and returns model responses. When people report that a model "ignores CLAUDE.md," that's the model's obedience, not the file failing to load; the instruction still arrives with every request.

Before You Start: API Key and Prerequisites

Three things to have ready:

  • A DeepSeek API key. Create one at the DeepSeek Platform — it starts with sk-. Billing is pay-as-you-go per token, so top up a few dollars of credit before the first session; requests fail on an empty balance.
  • Node.js 18 or newer, if you install via npm. Windows users also want Git for Windows installed (it provides the bash environment Claude Code leans on).
  • Key hygiene decided. The key grants account-level spending power. Keep it out of git repositories — an env file in .gitignore or your secret manager is the right home.

Step 1 — Install Claude Code

Two official installers exist, and either works:

# Native installer (Anthropic's current recommendation, macOS/Linux/WSL)
curl -fsSL https://claude.ai/install.sh | bash

# npm package (the path shown in DeepSeek's docs, needs Node.js 18+)
npm install -g @anthropic-ai/claude-code

Verify with claude --version — a version number means the binary is on your PATH.

One warning worth planting now: keep exactly one installation. If the native binary and an old npm copy both exist, your shell may resolve the stale one and you'll chase phantom bugs later. If npm is slow on your network, temporarily pointing the registry at a mirror and switching back after install is a well-trodden fix.

Step 2 — Point Claude Code at DeepSeek

Here's the core of the DeepSeek Claude Code setup, and you have three ways to do it. All three end in the same place; they differ in how long the change survives and who else can read it.

Method 1: Environment Variables

The official integration guide gives a nine-variable recipe. Linux and macOS:

export ANTHROPIC_BASE_URL=https://api.deepseek.com/anthropic
export ANTHROPIC_AUTH_TOKEN=<your DeepSeek 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
export CLAUDE_CODE_AUTO_COMPACT_WINDOW=786432

Windows PowerShell users set the same values with $env: assignments — for example $env:ANTHROPIC_BASE_URL="https://api.deepseek.com/anthropic" — in the window that will launch the tool.

What each line actually does:

VariableRole
ANTHROPIC_BASE_URLThe redirect. All requests go to DeepSeek's compatible endpoint
ANTHROPIC_AUTH_TOKENYour sk- key, sent as the auth token
ANTHROPIC_MODELThe model for the main conversation
ANTHROPIC_DEFAULT_OPUS_MODELWhat the "opus" slot resolves to
ANTHROPIC_DEFAULT_SONNET_MODELWhat the "sonnet" slot resolves to
ANTHROPIC_DEFAULT_HAIKU_MODELWhat the lightweight "haiku" slot resolves to
CLAUDE_CODE_SUBAGENT_MODELModel for background subagents
CLAUDE_CODE_EFFORT_LEVELReasoning effort; the recipe pins max
CLAUDE_CODE_AUTO_COMPACT_WINDOWAuto-compaction threshold in tokens (786,432 ≈ 768K)

Exports live for one terminal session. For daily use, append them to ~/.bashrc or ~/.zshrc (or your PowerShell profile) and source once — the classic "why did it forget my settings" question is just session scope doing its job — I asked it twice in my first week before the habit stuck.

Method 2: The settings.json File

DeepSeek's own integration repository recommends a config file instead: ~/.claude/settings.json on Linux and macOS, C:\Users\<you>\.claude\settings.json on Windows. Create it if it doesn't exist:

{
  "env": {
    "ANTHROPIC_BASE_URL": "https://api.deepseek.com/anthropic",
    "ANTHROPIC_AUTH_TOKEN": "<your DeepSeek API Key>",
    "ANTHROPIC_MODEL": "deepseek-v4-pro[1m]",
    "ANTHROPIC_DEFAULT_OPUS_MODEL": "deepseek-v4-pro[1m]",
    "ANTHROPIC_DEFAULT_SONNET_MODEL": "deepseek-v4-pro[1m]",
    "ANTHROPIC_DEFAULT_HAIKU_MODEL": "deepseek-v4-flash[1m]",
    "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
    "CLAUDE_CODE_EFFORT_LEVEL": "max"
  }
}

Why prefer a file? Every surface of Claude Code reads it — the CLI and the VS Code extension alike — so the configuration travels with the tool, not with one shell. It also keeps your dotfiles clean.

Honest footnote: the two official sources don't publish identical variable sets. The API docs include the subagent and auto-compact variables; the repository adds CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC and skips the other two. Both are official, neither is wrong — merging them (file plus the two extra env lines) is what many setups settle on.

Method 3: CC Switch

If you rotate backends — DeepSeek today, another provider tomorrow — a GUI switcher beats hand-editing JSON. CC Switch is an open-source desktop tool (52,000+ GitHub stars) that manages multiple providers for Claude Code and similar CLIs: pick DeepSeek from its preset list, paste your key, add the model ID deepseek-v4-pro[1m], hit enable, and click "test" to fire a sample request. Under the hood it writes the same settings.json from Method 2 — it's a friendly editor, not a different mechanism.

Quick decision rule: trying it out for an afternoon → Method 1; committing for daily work → Method 2; juggling several providers → Method 3.

Step 3 — Verify the Connection

Three gauges, from cheapest to most definitive.

The oil light: launch the tool in your project and run /status. A correct setup shows three lines — Base URL: https://api.deepseek.com/anthropic, the model you pinned, and Small fast model: deepseek-v4-flash.

The self-check: claude doctor inspects the installation itself — PATH problems, broken tools, version oddities. Run it whenever the command starts but behaves strangely.

The multimeter: test the endpoint directly, bypassing the client entirely:

curl -X POST https://api.deepseek.com/anthropic/v1/messages \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <your key>" \
  -d '{"model":"deepseek-v4-flash","max_tokens":10,"messages":[{"role":"user","content":"test"}]}'

A JSON response means key, endpoint, and network are all fine; an auth error means the problem is upstream of Claude Code.

One expectation to set: seeing both v4-pro and v4-flash usage in your DeepSeek console is correct, not a misconfiguration — background subagents intentionally run on Flash. When in doubt, trust the model ID in the provider's usage log over anything the terminal displays.

The [1m] Suffix and the Context Window

That bracketed suffix in deepseek-v4-pro[1m] isn't decoration. In Claude Code's model naming — per its own configuration docs[1m] selects the one-million-token context window, the long-session variant of a model. The official DeepSeek recipe pins it on every main slot, and pairs it with an auto-compact threshold of 786,432 tokens: roughly 768K, leaving headroom inside the 1M window for compaction to happen before you fall off the edge.

What about the bare name, without the suffix? Here the community disagrees. One camp reports the plain deepseek-v4-pro defaults to a smaller window unless you append [1m]; another insists both models serve 1M through the official API regardless. Neither claim is officially documented, so the practical move is boring and safe: copy the official recipe exactly, brackets included, and don't freelance model strings.

Long-window reality check, from developers who push it: a 400K-token codebase analysis ran with latency surprisingly close to native, but coherence past the ~500K mark draws drift reports. The million-token window is real; treating it as uniformly sharp across its entire span is optimistic.

When does the suffix actually earn its keep? The cases where it visibly pays off are the ones Claude Code creates naturally: whole-monorepo questions ("where does this function get called?"), marathon refactors that accumulate tool output for hours, and long sessions you keep resuming instead of restarting. For a typical feature branch that stays under a hundred thousand tokens, the standard window would never be missed — which is also why the recipe's split (big window on the main session, fast model on subagents) makes economic sense.

Which Model Answers Which Call

Claude Code runs a small duty roster. The main conversation holds one model; background subagents — file searches, quick summaries, agent teams — hold another; and the opus/sonnet/haiku aliases are slots that resolve to whatever you pin. Your variables are the roster sheet:

Claude Code slotOfficial DeepSeek recipe
Main session (opus/sonnet tier)deepseek-v4-pro[1m]
Lightweight calls (haiku tier)deepseek-v4-flash
Subagentsdeepseek-v4-flash
Unmapped names (server fallback)deepseek-v4-flash

Why split at all? Money and speed. A developer who ran this stack for a week found Flash handled roughly 80% of daily work — refactors, stacktrace triage, new functions — at single-digit-second latency, saving Pro for genuinely hard planning. An analysis of real sessions estimated that most of the savings come from the haiku-tier routing alone: every small internal call lands on Flash's bargain pricing instead of the flagship's.

Two more behaviors worth knowing. Reasoning effort — CLAUDE_CODE_EFFORT_LEVEL — controls how hard the model thinks per step, and the recipe pins it to max (community reports suggest agent traffic gets max effort automatically anyway). And Web Search works natively: when a question needs fresh information, the model invokes the search tool through DeepSeek's API, at the cost of some extra tokens to summarize what it found.

If you use the Claude Desktop app instead of the terminal, the same server-side mapping applies — its developer mode accepts a custom base URL and key, and the name translation does the rest. (The full model lineup behind these names is covered in What is DeepSeek?.)

What the Compatibility Layer Actually Supports

The adapter metaphor holds down to the request fields. DeepSeek's Anthropic-format endpoint publishes a compatibility matrix, and knowing the shape of it explains most "why does X behave differently" moments:

Request fieldStatus on DeepSeek's endpoint
temperature (0.0–2.0), top_p, stop_sequences, stream, system, max_tokensFully supported
Tool definitions, tool_choice, tool resultsFully supported
thinkingSupported — budget_tokens is ignored
Image input (base64, URL, file)Supported
top_kIgnored
cache_control (prompt caching markers)Ignored
Document blocks, code execution results, MCP tool blocksNot supported

Two rows matter day to day. The thinking row means reasoning depth flows through the effort setting rather than a token budget — consistent with the effort variable sitting in the official recipe. The cache row means Anthropic-style cache markers are no-ops; DeepSeek applies its own input cache-hit discounts on the billing side instead of asking you to annotate cache breakpoints. Everything Claude Code itself sends by default lands in the supported columns, which is why the integration feels native rather than shimmed.

Troubleshooting: One Table for the Common Failures

Every failure mode below has tripped someone up publicly. Scan the symptom, apply the fix:

SymptomLikely causeFix
claude: command not foundBinary not on PATH, or duplicate installsReopen the shell; which -a claude and npm -g ls @anthropic-ai/claude-code to find strays; keep one
Login prompt keeps appearingLaunching shell didn't load the variablesConfirm env in the exact shell that starts it; the ~/.claude.json hasCompletedOnboarding trick is a community fallback
"Not logged in" inside WSLWSL resolved the Windows copy of the binaryCheck PATH; make sure the Linux-side install is the one running
401 on first requestWrong key, or empty account balanceRe-paste the sk- key; top up credit
403Base URL never got pointed at DeepSeekVerify ANTHROPIC_BASE_URL spelling
404Model string typoCopy deepseek-v4-pro[1m] character for character — brackets included
Flash usage where you expected ProSubagents are supposed to use FlashCheck the request role in the provider log before declaring a bug
Can't save settings in vim (E212)~/.claude owned by wrong usermkdir -p ~/.claude && chown -R $USER ~/.claude && chmod -R 755 ~/.claude
npm install crawls or diesRegistry unreachable on your networkSwitch to a mirror for the install, switch back after

Three of these deserve a beat more. The PATH conflict is the sneakiest — two binaries, the wrong one winning, symptoms that look like anything but an installation issue. The curl test is your cleanest binary search: it isolates key-and-endpoint from client-and-config in one command. And the 404 case is almost always invisible characters or a dropped bracket in the model name, which is why the recipe is worth pasting rather than retyping.

What to Expect: The Honest Trade-offs

What does the swap actually feel like? The numbers people have published are consistent in shape.

Cost: a well-known developer burned about $1 per hour of intense agentic usage on v4-pro. A security researcher logged a full working day — 412 tool calls across expert-level web challenges and a real Android app — for $6.84. Against Anthropic's flagship output pricing at launch time, v4-pro's per-token rate ran roughly seven times cheaper, and blind benchmark watchers found the two within 0.2 points on SWE-bench Verified. (Those figures are from the April–May 2026 window; check the current price page before doing your own math.)

Capability: the fair summary from several weeks of community use is "80–85% of the Claude experience at around a tenth of the price." Flash-speed work feels nearly identical. Hard planning on Pro holds up well.

The rough edges are real too. One long-running user's list: it sometimes ignores directives from CLAUDE.md, needs repeated reminders to honor memory notes and encoding rules, and made unsupervised changes that git had to rescue. "Cheap, but you have to watch it" was the verdict — one my own git reflog can confirm. Two habits defuse most of this: swap one model slot at a time so regressions have an obvious suspect, and keep the terminal within eyeshot for anything that edits files unsupervised.

Who should think twice? Anyone whose sessions genuinely exceed half a million tokens and need tight coherence end to end — that's the regime where the drift reports cluster, and where the flagship Claude models still hold a real edge. For everyone else — feature work, refactors, code review, the daily grind — the trade keeps coming out ahead.

One under-appreciated upside: pay-per-token billing makes cost visible per turn. The six-thousand-token CLAUDE.md and three MCP servers you forgot about become line items, and configs get cleaned up fast.

FAQ

Do I need an Anthropic account or API key for this?No. The route uses ANTHROPIC_BASE_URL plus your DeepSeek key in ANTHROPIC_AUTH_TOKEN. Nothing authenticates against Anthropic. If a login flow appears, the launching shell didn't load your variables.

Is it free?No — DeepSeek's API is pay-as-you-go, billed per token with cache-hit discounts on input. Balances are cheap to feed, but an empty account refuses requests. New-account bonus credit has been reported; don't count on it.

Does Web Search work?Yes, natively. When the model decides a question needs fresh sources, it calls the search tool through DeepSeek's API. Summarizing results costs additional tokens, so heavy search sessions show up on the bill.

How do I switch back to official Claude models?Remove the overrides — unset the variables (or delete the env block from settings.json) and log in normally. With CC Switch, it's one click in the provider list.

Which model should handle daily coding?Follow the official split: v4-pro for the main session and hard problems, Flash for the lightweight tier and subagents. Community testing says Flash alone covers about 80% of day-to-day requests; if you're tuning prompts for either model, the techniques in our DeepSeek prompt guide carry over directly.

Does this work in the VS Code extension?Yes. The extension reads the same ~/.claude/settings.json, which is exactly why the file method beats shell exports for anything permanent.

The whole migration is three moves: grab a key from the platform, paste the official nine-variable recipe into your shell or settings file, and confirm with /status that the base URL took. After that, it's the same cockpit you know: same commands, same reflexes, a different engine under the hood, and a fuel gauge you can actually afford to watch.