--- title: OpenCode + DeepSeek description: Configure OpenCode to route DeepSeek traffic through the Headroom proxy for compression, output shaping, and savings visibility. --- Cut DeepSeek API costs with Headroom's context compression proxy: tool outputs, logs, and search results are compressed before they reach the model, and responses can be shaped to be more concise. ## How it works ``` OpenCode → Headroom Proxy (:8787) → DeepSeek API ↑ compresses input + shapes output ``` The proxy sits between OpenCode and DeepSeek. It compresses tool outputs, logs, and search results before they reach the model, then shapes responses to be concise. DeepSeek's API is OpenAI-compatible — one flag and you're running. --- ## 1. Install Headroom ```bash pip install "headroom-ai[proxy]" # or via uv: uv tool install "headroom-ai[proxy]" ``` You get SmartCrusher (structural compression), the proxy, output shaping, and the MCP server — everything you need. --- ## 2. Get your DeepSeek API key Sign up at [platform.deepseek.com](https://platform.deepseek.com) and generate an API key. Store it somewhere safe: ```bash export DEEPSEEK_API_KEY="sk-your-deepseek-key-here" ``` --- ## 3. Start the proxy ```bash headroom proxy \ --port 8787 \ --openai-api-url https://api.deepseek.com/v1 ``` The proxy auto-detects `api.deepseek.com` and labels itself "DeepSeek" on the dashboard. Verify it's running: ```bash curl http://127.0.0.1:8787/health # → "status": "healthy" ``` To see which models the proxy exposes: ```bash curl -s http://127.0.0.1:8787/v1/models \ -H "Authorization: Bearer sk-your-key" | jq '.data[].id' ``` ### With output shaping (optional) Output shaping makes the model's responses shorter — fewer tokens, lower cost: ```bash HEADROOM_OUTPUT_SHAPER=1 HEADROOM_VERBOSITY_LEVEL=2 \ headroom proxy --port 8787 --openai-api-url https://api.deepseek.com/v1 ``` Verbosity levels: | Level | Behavior | |---|---| | `1` | Skip preambles/postambles | | `2` | + Don't restate code/file content already in context (**recommended**) | | `3` | + Omit rationale unless asked | | `4` | Maximum — fragments, zero fluff | --- ## 4. Configure OpenCode **Note:** If you have an existing `~/.config/opencode/opencode.json` (for MCP servers, etc.), merge the provider section into that file. Having both `.json` and `.jsonc` in the same directory can cause conflicts. Edit `~/.config/opencode/opencode.json`: ```jsonc { "$schema": "https://opencode.ai/config.json", "model": "headroom/deepseek-v4-pro", "provider": { "headroom": { "npm": "@ai-sdk/openai-compatible", "name": "Headroom Proxy", "options": { "baseURL": "http://127.0.0.1:8787/v1", "apiKey": "sk-your-deepseek-key" }, "models": { "deepseek-v4-pro": { "name": "DeepSeek V4 Pro", "limit": { "context": 1000000, "output": 384000 } }, "deepseek-v4-flash": { "name": "DeepSeek V4 Flash", "limit": { "context": 1000000, "output": 384000 } } } } }, "mcp": { "headroom": { "type": "local", "command": ["headroom", "mcp", "serve"], "enabled": true } } } ``` **Important:** Only include model IDs that appear in the proxy's `/v1/models` response. OpenCode validates config models against the proxy's model list. The current DeepSeek model names are `deepseek-flash` and `deepseek-v4-pro`. The retired `deepseek-v4-flash` and `deepseek-v4-flash-vision-exp` are still accepted and billed at the Flash price; `deepseek-chat` and `deepseek-reasoner` are deprecated compatibility aliases. ### Model comparison All prices are USD per 1M tokens, at DeepSeek's **off-peak** tier. Peak hours — Beijing 09:00-12:00 and 14:00-18:00, i.e. 01:00-04:00 and 06:00-10:00 UTC — cost exactly twice these rates. | Model | Input / Output (per 1M, off-peak) | Context | Max Output | Vision | |---|---|---|---|---| | `deepseek-flash` (V4.1-Flash) | $0.15 / $0.60 | 1M | 384K | yes | | `deepseek-v4-pro` | $0.66 / $1.98 | 1M | 384K | no | Both models support **thinking mode** for step-by-step reasoning (see below). Switch models at any time with `/model` in OpenCode. --- ## 5. Start OpenCode ```bash opencode ``` Run `/models` to confirm both DeepSeek models appear under "Headroom Proxy". Select one with `/model deepseek-flash` or `/model deepseek-v4-pro`. --- ## 6. Check savings ```bash curl http://127.0.0.1:8787/stats | python3 -m json.tool | grep -A5 compression ``` Or open the dashboard at [http://127.0.0.1:8787/dashboard](http://127.0.0.1:8787/dashboard). --- ## Thinking mode (reasoning) Both models support thinking mode natively, and DeepSeek enables it by default. This replaces the deprecated `deepseek-reasoner` (R1) model. See [DeepSeek's thinking mode docs](https://api-docs.deepseek.com/guides/thinking_mode) for details on switching between thinking and non-thinking modes. --- ## Common issues ### "Authentication Fails" / Unauthorized The `apiKey` in OpenCode's config is missing or wrong. OpenCode must send the API key to the proxy, and the proxy forwards it to DeepSeek. Make sure `"apiKey": "sk-..."` is set under `options`. ### Models don't appear under "Headroom Proxy" 1. Verify the proxy is running: `curl http://127.0.0.1:8787/health` 2. Check which models the proxy exposes: `curl -s http://127.0.0.1:8787/v1/models -H "Authorization: Bearer sk-your-key"` 3. Make sure your config model IDs match **exactly** what the proxy returns 4. Don't use both `opencode.json` and `opencode.jsonc` in the same config directory — use one file ### Models appear but requests fail You ran `headroom wrap opencode` without telling it about DeepSeek. Without an explicit upstream the proxy it starts forwards OpenAI-compatible traffic to OpenAI, so wrap leaves the `apiKey` and `models` entries from step 4 out of the `headroom` provider rather than send your DeepSeek key there. Pass `--openai-api-url` as shown in the next section, or launch OpenCode directly with `opencode` against the proxy you started in step 3. ### I used `headroom wrap opencode` and get "Incorrect API key provided" ``` Incorrect API key provided: sk-13005***********************898d. You can find your API key at https://platform.openai.com/account/api-keys. ``` That 401 comes from **OpenAI**, not DeepSeek. `headroom wrap opencode` starts the proxy for you, and unless it is told otherwise the proxy forwards OpenAI-compatible traffic to its default upstream, `https://api.openai.com/v1`. Your DeepSeek key is then presented to OpenAI, which rejects it and points you at a dashboard for a key you never had. Pass the upstream to wrap, exactly like `headroom proxy --openai-api-url`: ```bash headroom wrap opencode --openai-api-url https://api.deepseek.com/v1 ``` The equivalent environment variable also works, and is honored by both commands: ```bash OPENAI_TARGET_API_URL=https://api.deepseek.com/v1 headroom wrap opencode ``` If a proxy is already running on the port with a different upstream, stop it first (`headroom unwrap opencode`) — wrap will not silently re-point a proxy that other clients may be sharing. ### When is `headroom wrap opencode` safe? - **Safe as-is** when your traffic goes to the default upstreams — OpenAI (`api.openai.com`) or Anthropic (`api.anthropic.com`). - **Needs `--openai-api-url`** (or `OPENAI_TARGET_API_URL`) for any third-party OpenAI-compatible provider: DeepSeek, Together, OpenRouter, Groq, a self-hosted gateway, and so on. - **Keep the step 4 provider entries.** OpenCode only offers the `headroom/` models listed under `provider.headroom.models`, and DeepSeek needs your key in `options.apiKey` (for example `"{env:DEEPSEEK_API_KEY}"`). With `--openai-api-url`, wrap keeps both. It rewrites the provider's `npm`, `name` and `baseURL` and adds its default `gpt-4o` and `gpt-4.1` ids next to your models. Without the flag it leaves your key and models out, because the proxy would forward them to OpenAI. ### "headroom" command not found `uv tool install` puts binaries in `~/.local/bin/`. Add it to your PATH: ```bash export PATH="$HOME/.local/bin:$PATH" ``` ### Output shaping shows no savings Output savings are measured against a learned baseline (it compares "what the model actually emitted" vs "what it would have emitted unshaped"). After a few sessions, run: ```bash headroom learn --verbosity --apply ``` This builds the baseline, and `/stats` will show output savings numbers. The shaper is active immediately — the numbers just need calibration. --- ## What's NOT in this guide - **Claude or GPT models** — this setup uses DeepSeek exclusively - **Deprecated model names** — `deepseek-chat` and `deepseek-reasoner` are compatibility aliases slated for removal; use `deepseek-v4-pro` and `deepseek-v4-flash` instead - **Kompress (ML compression)** — requires extra dependencies; SmartCrusher handles the majority of use cases - **Any code changes** — headroom ships full DeepSeek support natively (model tables, pricing, tokenizers, domain detection)