Documentation · Integrations
Use SpendProxy with Claude Code
Claude Code talks to Anthropic over the standard Messages API, and it lets you redirect that traffic with two environment variables. Point it at SpendProxy and every request your coding agent makes is metered — tokens in, tokens out, cache reads, cost, and attribution — with the same cache-accurate math SpendProxy applies to your production traffic.
Cache-accurate cost
Claude Code is cache-heavy — most turns re-read a large tools + system prefix. SpendProxy bills those cache reads at the 0.1× rate, not full price (the bug that makes other tools over-report by ~10×).
No code change
Two environment variables. No SDK, no wrapper required, no flags inside Claude Code. Your API key still works exactly as before.
Per-session attribution
Tag the whole session as one route, or let SpendProxy auto-fingerprint each prompt + toolset. Either way you can answer “what did that coding session cost?”
Quick start
1. Start SpendProxy
SpendProxy sits in the request path, so it needs to be running before you launch Claude Code.
docker run -d -p 4100:4100 -v spendproxy-data:/data spendproxy/proxy:latest 2. Point Claude Code at it
Set these in your shell (or a project .envrc), then run
claude as usual. Claude Code appends
/v1/messages to the base URL, so the Anthropic
route is /anthropic.
# Route Claude Code's Anthropic traffic through SpendProxy
export ANTHROPIC_BASE_URL="http://localhost:4100/anthropic"
# Your existing Anthropic API key — passed straight through, never stored
export ANTHROPIC_API_KEY="sk-ant-..."
claude
That’s the whole integration. Both ANTHROPIC_API_KEY
(sent as x-api-key) and
ANTHROPIC_AUTH_TOKEN (sent as
Authorization: Bearer) are forwarded to Anthropic untouched.
3. Watch it in the dashboard
Open localhost:4100/dashboard. As you work in Claude Code, requests appear in real time — model, tokens, cache reads, cost, and latency per call.
Keep your key in the proxy (gateway mode)
Prefer not to put your real Anthropic key in Claude Code’s environment? Run SpendProxy as a
gateway: store the provider key on the proxy and hand Claude Code only a placeholder token. The
proxy swaps in the real key on the way out, using the
x-ce-use-server-key request header. Claude Code reads
custom headers from ANTHROPIC_CUSTOM_HEADERS (newline-separated
Name: Value pairs).
# Proxy holds the real key (mounted into its .secrets), e.g.:
# docker run -d -p 4100:4100 \
# -v /path/to/anthropic.key:/app/.secrets/anthropic.key:ro \
# -v spendproxy-data:/data spendproxy/proxy:latest
export ANTHROPIC_BASE_URL="http://localhost:4100/anthropic"
export ANTHROPIC_AUTH_TOKEN="spendproxy-gateway" # placeholder; the proxy ignores it
export ANTHROPIC_CUSTOM_HEADERS="x-ce-use-server-key: true
X-CE-Route: claude-code
X-CE-Project: claude-code"
claude
The X-CE-Route header groups the whole session under a
single claude-code line in the dashboard. Drop those two
attribution lines to let SpendProxy auto-attribute instead — it fingerprints the system prompt and
toolset, so you get a chat: /
agent: breakdown with no tagging.
Optional: a one-command wrapper
To avoid exporting the variables every time, drop this script in your
PATH (e.g. ~/.local/bin/claude-spendproxy)
and run claude-spendproxy instead of claude.
It checks the proxy is up, isolates Claude Code’s config so it doesn’t touch your normal profile, and
sets the gateway variables.
#!/usr/bin/env bash
set -uo pipefail
PROXY_URL="http://localhost:4100"
# SpendProxy is in the request path — bail clearly if it isn't running.
if ! curl -fsS -m 2 "$PROXY_URL/health" >/dev/null 2>&1; then
echo "SpendProxy is not running at $PROXY_URL — start it first:" >&2
echo " docker run -d -p 4100:4100 -v spendproxy-data:/data spendproxy/proxy:latest" >&2
exit 1
fi
# Isolated profile so this doesn't disturb your main Claude Code login/history.
export CLAUDE_CONFIG_DIR="$HOME/.claude-spendproxy"
export ANTHROPIC_BASE_URL="$PROXY_URL/anthropic"
export ANTHROPIC_AUTH_TOKEN="spendproxy-gateway" # placeholder; proxy injects the real key
export ANTHROPIC_CUSTOM_HEADERS="x-ce-use-server-key: true
X-CE-Route: claude-code"
export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 # trim telemetry/title-gen noise
echo "▸ SpendProxy session — dashboard: $PROXY_URL/dashboard (route = claude-code)"
exec claude "$@"
Using a real key instead of gateway mode? Replace the ANTHROPIC_AUTH_TOKEN
line with export ANTHROPIC_API_KEY="sk-ant-..." and remove
x-ce-use-server-key: true from the headers.
What the numbers look like
A handful of turns of real Claude Code usage, as logged by SpendProxy. Each turn re-reads Claude Code’s large cached prefix — and SpendProxy prices those cache reads correctly.
| Model | Input | Cache read | Output | Cost |
|---|---|---|---|---|
| claude-opus-4-8 | 2,110 | 0 | 23 | $0.011125 |
| claude-opus-4-8 | 2,110 | 29,027 | 6 | $0.025214 |
| claude-opus-4-8 | 2,110 | 29,027 | 8 | $0.025264 |
Across this session, 87,081 cache-read tokens were billed at the 0.1× rate — $0.0435. A tool that charges cache reads at the full input rate would report $0.435 for the same tokens: a 10× overcharge on the cached portion alone. SpendProxy’s number is the one that reconciles to your Anthropic invoice.
Good to know
- ✓ Keep the proxy running. SpendProxy is in the request path. If it’s
down, Claude Code’s calls fail rather than silently going direct — run it under a restart policy and
health-check
/health. - ✓ Use a dedicated profile. Set
CLAUDE_CONFIG_DIRto a separate directory so the proxied session doesn’t touch your normal Claude Code login or history. - ✓ Quieter dashboards. Set
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1to suppress telemetry and background title-generation calls, so the dashboard reflects real coding work. - ✓ Optimization engines apply too. Budget guardrails, retry-storm suppression, and the what-if savings report all work on Claude Code traffic, just like your production calls.
See the main docs for configuration, attribution, and the security model. The same two-line redirect works for any tool built on the Anthropic, OpenAI, or Google APIs.