DeepSeek Everywhere: Wiring a Cheap Cloud Brain Into Claude Code and a Local Agent Stack

Posted
July 11, 2026
By
Jacob Lloyd β€” written with AI assistance, post-project
Read time
8 min read

In plain terms: A guide to plugging DeepSeek β€” a very cheap cloud AI service β€” into your existing AI tools instead of paying for pricier options. It shows three ready-to-copy setups, including one that keeps your secret access key safely hidden. You get capable AI assistance for fractions of a cent per message.

DeepSeek now backs three different things in my house: the brains of my agent stack, the Claude Code CLI, and the cloud rung of a fallback ladder. Total wiring effort was some JSON, a few environment variables, and one systemd escaping bug that ate an evening.

tl;dr

  • What it is: DeepSeek's paid cloud API as the brain behind a multi-agent home stack and as a drop-in backend for the Claude Code CLI β€” not another "run it on your own GPU" guide.
  • What it costs: fractions of a cent per message on the cheap tier. No subscription, just an API key.
  • What you need: a DeepSeek API key, anything that speaks OpenAI-style chat completions, and systemd if you want the Claude Code trick.
  • What you end up with: three copy-pasteable configs, a cloud-vs-local decision list, and a secret-handling trick that keeps the key out of ps, systemctl show, and your logs.

What you end up with

Before the how-to, the shape of the thing. I run OpenClaw, an agent gateway, with eight named agents behind a chat UI, plus the Claude Code CLI those agents spawn for real coding work. DeepSeek backs both.

PatternWhat it doesCost
1. Agent brainDeepSeek as a provider in the gateway config; any agent can pick it as primary or fallback$0.14–$0.87 / million tokens
2. Claude Code backendA systemd drop-in re-points the CLI at DeepSeek's Anthropic-compatible endpoint, no reinstallsame per-token pricing
3. Fallback ladderA decision list for when a job goes to DeepSeek vs a local model$0 when it stays local

The one line that makes all of it possible: DeepSeek ships an Anthropic-compatible endpoint at https://api.deepseek.com/anthropic. Anything built to talk to Claude β€” the Claude Code CLI included β€” can be pointed at it with nothing but environment variables. No wrapper script, no fork.

Pattern 1: DeepSeek as an agent brain

One provider block in the gateway config. Real thing, key redacted:

"deepseek": {
  "baseUrl": "https://api.deepseek.com/v1",
  "api": "openai-completions",
  "apiKey": "CHANGE_ME",
  "timeoutSeconds": 450,
  "models": [
    {
      "id": "deepseek-v4-pro",
      "name": "deepseek-v4-pro",
      "reasoning": true,
      "input": ["text"],
      "cost": { "input": 0.435, "output": 0.87,
                "cacheRead": 0.003625, "cacheWrite": 0.435 },
      "contextWindow": 1000000,
      "maxTokens": 384000
    },
    {
      "id": "deepseek-v4-flash",
      "name": "deepseek-v4-flash",
      "reasoning": true,
      "input": ["text"],
      "cost": { "input": 0.14, "output": 0.28,
                "cacheRead": 0.0028, "cacheWrite": 0.14 },
      "contextWindow": 1000000,
      "maxTokens": 384000
    }
  ]
}

Each agent then picks a primary model and a fallback chain:

"model": {
  "primary": "deepseek/deepseek-v4-flash",
  "fallbacks": ["deepseek/deepseek-v4-pro", "vllm/google/gemma-4-31b"]
}

Here's what happens when a message comes in on that routing:

My actual roster. Most agents lead with DeepSeek and fall back to local; Doxy runs the inverse on purpose:

AgentPrimaryFallbacks
Bits (main chat)DeepSeek flashDeepSeek pro β†’ local gemma-4-31b
BrainsDeepSeek prolocal gemma-4-31b
FlashDeepSeek flashDeepSeek pro β†’ local
Hermes (deploy agent)DeepSeek proDeepSeek flash β†’ local
Alpha (family-safe)DeepSeek flashDeepSeek pro β†’ local
Doxy (local workhorse)local 120BDeepSeek flash (inverse β€” local leads)
betalocalDeepSeek flash β†’ DeepSeek pro
Charley (vision)local gemma-31bDeepSeek pro β†’ DeepSeek flash

Charley matters here: these DeepSeek entries are text-only ("input": ["text"]), so image work stays local no matter what the chain says. Aliases (ds-flash, ds-brain) let me swap models mid-conversation instead of editing config.

Two settings will bite you if you skip them:

  • "reasoning": true is mandatory for reasoning models. They stream reasoning_content before the actual answer; with the flag off, the gateway hears silence, decides the model stalled, and kills the turn around 390 seconds in. Ask me how I know.
  • Raise timeoutSeconds. The default request timeout was 120 seconds; long reasoning runs blow past that and "fail" at random. 450 fixed it here, and provider settings hot-reload β€” no gateway restart.

Pattern 2: Claude Code CLI on DeepSeek

The Claude Code CLI reads ANTHROPIC_BASE_URL, ANTHROPIC_MODEL, and ANTHROPIC_AUTH_TOKEN/ANTHROPIC_API_KEY from its environment, and DeepSeek's /anthropic endpoint speaks the same wire format Claude does. So rerouting the CLI is just changing the environment the gateway hands each Claude Code subprocess it spawns β€” the CLI stays a stock install.

The file is a systemd user drop-in. Mine is generated by a small GTK app I built that flips between four modes (Local LM Studio / DeepSeek / Anthropic Cloud / Off), but it's short enough to write by hand:

# ~/.config/systemd/user/openclaw-gateway.service.d/60-subagent-routing.conf
[Service]
# Routes Claude Code CLI sub-processes to DeepSeek's Anthropic-compatible
# endpoint. The key is NOT copied here: $$DEEPSEEK_API_KEY is systemd's escape
# for a literal $DEEPSEEK_API_KEY, which bash expands at runtime from the
# gateway EnvironmentFile -- the secret never enters the unit or the argv.
Environment="ANTHROPIC_BASE_URL=https://api.deepseek.com/anthropic"
Environment="ANTHROPIC_MODEL=deepseek-v4-pro"
ExecStart=
ExecStart=/usr/bin/bash -c 'export ANTHROPIC_AUTH_TOKEN="$$DEEPSEEK_API_KEY"; export ANTHROPIC_API_KEY="$$DEEPSEEK_API_KEY"; exec node /path/to/openclaw/dist/index.js gateway --port 18789'

The key itself lives in exactly one place: the service's EnvironmentFile (~/.openclaw/gateway.systemd.env, chmod 600), which just contains DEEPSEEK_API_KEY=CHANGE_ME.

The $$ gotcha (the whole reason this post exists)

My first attempt used a single $. It did not go well. Inside a unit file, $VAR gets expanded by systemd itself at spawn time, which bakes the key straight into the command line β€” visible in ps, in /proc/<pid>/cmdline, and in systemctl show. Not exactly where you want a secret sitting.

$$VAR is systemd's escape for a literal $VAR: systemd passes the string through untouched and bash expands it at runtime, from the environment the EnvironmentFile already populated. Net effect: the secret exists in one chmod-600 file and nowhere else β€” it never appears in the unit file, in systemctl show, or in any argv. A poor-man's secrets manager built out of systemd and bash, and it works.

More gotchas from actually running this:

  • Set both auth vars. Different CLI versions read ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY; setting only one is a coin flip.
  • Pin ANTHROPIC_MODEL, or the CLI's usual sonnet/opus aliases get sent to DeepSeek's endpoint and 404.
  • The drop-in shadows any real Anthropic key. One environment owns the whole CLI β€” I found out when it silently broke my "route to real Claude" aliases.
  • Blank ExecStart= first β€” the empty line before the override β€” or systemd appends your command instead of replacing the original.
  • Package updates can orphan the wrapper. It hard-codes the launch command, so an update that changes the real ExecStart means regenerating the drop-in. My generator reads the canonical command from the unit's FragmentPath and refuses to wrap anything already containing $$DEEPSEEK_API_KEY.
  • Then reload: systemctl --user daemon-reload && systemctl --user restart <service>.

To prove the whole path end to end, skip the CLI and curl it:

curl https://api.deepseek.com/anthropic/v1/messages \
  -H "x-api-key: $DEEPSEEK_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{"model":"deepseek-v4-pro","max_tokens":16,"messages":[{"role":"user","content":"ping"}]}'

A "type":"message" response back means the whole Anthropic-compat path genuinely works.

Pattern 3: when to actually use DeepSeek vs local

Having both doesn't mean every job goes to the cloud. Per million tokens, with Claude's list prices for scale (Opus $5/$25, Sonnet $3/$15, Haiku $1/$5):

OptionInputOutputNotes
DeepSeek flash$0.14$0.28cache read $0.0028 β€” chat-agent duty costs pennies a day
DeepSeek pro$0.435$0.87the "thinking" tier, still 7–17x cheaper than Sonnet
Local (same box)$0$0electricity only

Speed was the bigger surprise. Local 100B-class models forced me to raise turn timeouts to 20–30 minutes, and two agents sharing one GPU box stall each other. DeepSeek answers in seconds; the 450-second ceiling only ever mattered for worst-case reasoning runs. Context is the other gap β€” a 1M-token window against roughly 128k for the local models β€” so long agentic sessions and big-codebase coding jobs default to DeepSeek. Vision goes the opposite way: my DeepSeek entries are text-only, so "look at this picture" stays on a local vision model.

The privacy rule of thumb I actually use: don't send the cloud anything you wouldn't put in an email.

Fallback chains cut both ways, which is my favorite part. Cloud-primary agents drop to a local model when the internet or the API dies; the local-primary workhorse falls back to DeepSeek flash when the local server is busy or dead. Nobody goes fully dark.

Gotchas, the short list

The reasoning: true flag, the 120-second timeout, the $$ escape, and the drop-in shadowing your real Anthropic key are all covered inline in Patterns 1 and 2. Two more:

  • A non-empty plugin allowlist is strict. In OpenClaw, an enabled provider entry that's missing from plugins.allow never loads. No error, no warning, just silence.
  • DeepSeek here is text-only. Check "input" in the model entry before routing vision jobs at it.

Want it fully local instead β€” no API key, no cloud bill? I wrote that one up too: DeepSeek: Running Locally β€” a 4-Step Guide, DeepSeek distills on your own GPU with Ollama, Docker, and Open WebUI. That's the beginner path; this one's for when the hard jobs outgrow your GPU but the private stuff still stays home.


← More AI & Local LLM