Claude Code + Jev: relevance-based context compaction
September 20, 2026 · View on GitHub
Português · English
A practical guide to putting a LiteLLM gateway between Claude Code and the Anthropic API, using the Jev model (TypeSafe AI) to drop tool results that no longer serve the current task, before they reach the expensive model.
Originally written in Portuguese, because almost no material on this exists in PT-BR. This English version is a full translation.
Warning
This setup takes your session off the Pro or Max subscription and starts billing per token against your API account. If you use Claude Code inside a subscription, it will likely raise your cost, not cut it. Read Who pays the bill before Step 1.
The problem
In a long agent session, the history piles up tool results that are no longer useful: a file read ten turns ago, a search that found nothing, a grep down a path you abandoned.
That dead weight keeps being sent as input tokens on every following request. You pay again, every turn, for information that is already spent.
The solution
Jev is a model that reads text but never writes text back. It takes a state and returns typed decisions with calibrated probability.
As a LiteLLM guardrail, it evaluates each completed tool exchange and answers a binary question: is this still needed to finish the current task?
Anything below the threshold is replaced by a removal notice. The cut is all or nothing per block: a result is either kept in full or erased. Nothing is summarized or paraphrased, so whatever survives stays auditable.
Claude Code -> LiteLLM (localhost:4000) -> Anthropic API
|
v
Jev API
(decides what to cut)
Who pays the bill
Step 5 points Claude Code at the gateway with its own credential
(ANTHROPIC_AUTH_TOKEN). From that moment on, your claude.ai subscription is
no longer used in that session: the credential replaces the login, the plan's
usage limits no longer apply, and usage is billed per token to whoever owns the
key the gateway forwards, which here is your Claude Console account.
Anthropic's documentation says it outright:
While a gateway credential variable or
apiKeyHelperis active, a developer's claude.ai subscription isn't used: the credential replaces the subscription login for that session, and the subscription's usage limits don't apply. That traffic is billed per token to whoever owns the credential the gateway forwards.
At list price, that is $5 / $25 per million tokens (input / output) on Claude Opus 5 and $2 / $10 on Claude Sonnet 5.
What that means in practice:
- The savings land on the API bill, never on the subscription. If you run Claude Code inside Pro or Max today, this setup trades zero marginal cost for per-token billing. Cutting 30% off a number that used to be zero is still more than zero.
- Jev is a second meter. Every request that goes through the guardrail is a billed call to TypeSafe, and it reads the whole history to decide what to cut. Add both up before concluding it came out cheap.
- Set a ceiling before you start the proxy. Set a workspace spend limit in the Claude Console (how). It is the only protection that does not depend on you remembering to check.
- With no database you measure nothing. Without
DATABASE_URLthe proxy writes no spend logs, so the savings stay a guess while the invoice does not.
ANTHROPIC_BASE_URL on its own does not change the billing. The credential
does.
Can you keep the subscription and still go through the gateway? Not here.
On paper, yes. Anthropic's docs say that setting only ANTHROPIC_BASE_URL,
with no gateway credential, leaves the saved claude.ai login as the active
credential, so its limits and billing apply. LiteLLM even ships a tutorial for
Claude Code Max subscriptions built on forward_client_headers_to_llm_api: true, which is supposed to forward the user's OAuth token upstream instead of
substituting the proxy's own key.
It does not work on the route Claude Code actually uses. Tested on LiteLLM
1.103.0rc1:
/statusreports it correctly:Login method: Claude Max accountandAnthropic base URL: http://127.0.0.1:4000. The client side is fine.- The request still fails at the proxy. With
forward_client_headers_to_llm_api: trueand noapi_keyon the models, LiteLLM refuses before forwarding:Missing Anthropic API Key. - Add a dummy
api_keyto get past that validation and LiteLLM sends the dummy upstream instead of the client's OAuth token:invalid x-api-keyfrom Anthropic.
Claude Code talks to /v1/messages, which LiteLLM serves through its
experimental_pass_through Anthropic handler. Client-header forwarding does not
reach it. If a later release fixes this, the config change is small: drop every
api_key from model_list, drop master_key, add
forward_client_headers_to_llm_api: true, and set only ANTHROPIC_BASE_URL on
the client.
Until then the trade is real: gateway or subscription, not both. Which means if you are on Pro or Max and were not paying for API usage anyway, this compaction saves input tokens that already cost you nothing.
To go back to the subscription for one project, use claudeoff from
zshrc-snippet.sh.
Requirements
- macOS or Linux with Python 3.10 or newer
- An Anthropic API key
- A TypeSafe AI key (Jev access)
- Claude Code installed
Step 1: install LiteLLM
Heads up: the
typesafeguardrail is not in the stable release yet. The--preflag is mandatory.
mkdir -p ~/litellm-jev && cd ~/litellm-jev
python3 -m venv .venv
source .venv/bin/activate
pip install --pre -U 'litellm[proxy]'
Confirm the guardrail came along:
ls .venv/lib/python3.*/site-packages/litellm/proxy/guardrails/guardrail_hooks/ | grep -i typesafe
If it does not print typesafe, try the latest code from the repository:
pip install -U 'litellm[proxy] @ git+https://github.com/BerriAI/litellm.git@main'
Step 2: environment variables
Add to your ~/.zshrc (or ~/.bashrc):
export TYPESAFE_API_KEY="your-typesafe-key"
export ANTHROPIC_API_KEY="your-anthropic-key"
export LITELLM_MASTER_KEY="sk-generated-below"
To generate the master key:
echo "sk-$(openssl rand -hex 24)"
Then:
source ~/.zshrc
chmod 600 ~/.zshrc
Step 3: config.yaml
Copy config.yaml.example from this repository to ~/litellm-jev/config.yaml.
Do not use editors that turn straight quotes into curly ones (macOS TextEdit, for one). It breaks the YAML silently. Prefer
cat > filewith a heredoc, VS Code, or nano.
What matters in that file:
mode: pre_callis mandatory, because the guardrail only transforms the inputdefault_on: truecompacts every request, no opt-in- The
model_name: "*"block catches any Anthropic model, including Claude Code's background model and future releases relevance_threshold: 0.2is the cutoff, tune it later
Step 4: start the proxy
First run in the foreground, so you can see errors:
litellm --config ~/litellm-jev/config.yaml
Look for the loaded models in the output and the line
Uvicorn running on http://0.0.0.0:4000.
For daily use, copy the functions from zshrc-snippet.sh in this repository.
After that, jevup is all you need.
Step 5: point Claude Code at the proxy
The global settings.json applies to every project, current and future.
This is the step that switches the billing. After it, the session leaves the subscription and starts spending API credits. See Who pays the bill.
If the file already exists, back it up and merge. Overwriting wipes
permissions,hooks,enabledPlugins, and the rest of your configuration.
cp ~/.claude/settings.json ~/.claude/settings.json.bak 2>/dev/null
python3 - << 'PY'
import json, pathlib, os
p = pathlib.Path.home() / ".claude"
bak = p / "settings.json.bak"
data = json.loads(bak.read_text()) if bak.exists() else {}
env = data.setdefault("env", {})
env["ANTHROPIC_BASE_URL"] = "http://127.0.0.1:4000"
env["ANTHROPIC_AUTH_TOKEN"] = os.environ["LITELLM_MASTER_KEY"]
(p / "settings.json").write_text(json.dumps(data, indent=2, ensure_ascii=False))
print("preserved keys:", list(data.keys()), "| env:", list(env))
PY
chmod 600 ~/.claude/settings.json
Step 6: verify
curl -i -s http://127.0.0.1:4000/v1/messages \
-H "Authorization: Bearer $LITELLM_MASTER_KEY" \
-H "Content-Type: application/json" \
-H "anthropic-version: 2023-06-01" \
-d '{"model":"sonnet","max_tokens":5,"messages":[{"role":"user","content":"hi"}]}' \
| grep -i "guardrail\|HTTP/"
Expected:
HTTP/1.1 200 OK
x-litellm-applied-guardrails: jev-compaction
/v1/messages is the endpoint Claude Code actually uses. Validating only
/v1/chat/completions does not prove it works in the real flow.
Step 7: use it
cd ~/any-project
claude
Nothing changes in your workflow. The compaction is invisible.
Traps that cost time
API Error: 400 No connected db.
The message is misleading. With no database, the master key is the only accepted
credential, and any other key produces this error. Translated: the key the
client sent does not match the proxy's master key. There is already a PR in
LiteLLM to turn this into a 401.
You rotated the master key and it still fails The proxy reads the master key only at startup. Restart it after changing.
Detected a custom API key in your environment
Claude Code asks whether it should use ANTHROPIC_API_KEY from the environment.
Answer No, otherwise it may talk to Anthropic directly and bypass the proxy.
If it still bypasses it:
env -u ANTHROPIC_API_KEY claude
claude.ai connectors disabled Expected, and it is the visible symptom of the switch described in Who pays the bill: the gateway credential replaces the claude.ai login, so the account connectors are unavailable and the session is billed per token. For a project that needs them:
env -u ANTHROPIC_BASE_URL -u ANTHROPIC_AUTH_TOKEN claude
A model with a suffix, like opus[1m]
The wildcard model_name: "*" block in the config handles it. Without it, any
undeclared model breaks.
The Admin UI at /ui opens empty
It depends on a database. With no Postgres there are no spend logs and no
guardrail metrics. To measure the savings with real numbers, run with
DATABASE_URL pointing at a Postgres.
A future update breaks everything silently
A pip install -U litellm without --pre reinstalls the stable version, which
does not have the guardrail. The proxy starts up normally and the compaction
simply stops happening.
Environment variables leak into the proxy through a side door
Two of them override your config without saying so, because LiteLLM reads them
straight from the environment of the process you started it in. If you launch
the proxy from a shell that sourced your .zshrc, they are there:
LITELLM_MASTER_KEYre-enables master-key auth even after you removedmaster_keyfromconfig.yaml. Symptom:400 No connected db.ANTHROPIC_API_KEYis used to call Anthropic even with noapi_keyon the models, so it silently bills your API account. Symptom:Your credit balance is too lowwhile you believed you were on the subscription.
Launch the proxy with env -u VAR for whichever one must not apply.
Honest limitations
- It only acts on completed tool exchanges. System messages, the last user message, and the most recent exchange are never touched. A short conversation with no tool use has nothing to compact.
- It does not measure itself. With no database, there is no way to quantify the savings.
- It fails open by default. If TypeSafe is down, the request goes through
uncompacted, with a warning in the log. To fail closed, use
unreachable_fallback: fail_closed. - It is not free. The setup trades the subscription for per-token billing and adds the TypeSafe bill on top. See Who pays the bill.
- Pre-release. The integration has not reached the stable channel yet.
References
License
MIT