Getting Started
Install in one command, route your coding agent (Claude Code, Codex, Gemini CLI) through Distil with distil wrap — no code change — and watch genuine savings on your real traffic. Prefer to kick the tyres first? distil bench certifies the numbers offline with no API key.
Install
Distil ships as a PyPI package (distil-llm) with a stdlib-only core — zero runtime dependencies. The corpus is bundled in every distribution.
pipx install distil-llm # then: distil bench
No pipx? Zero-install with uv: uvx --from distil-llm distil bench. Everything else below is an alternative, not a requirement.
distil-llm but the command is distil (the bare distil name was taken on PyPI). So it's pipx install distil-llm → run distil …. pipx install distil installs the wrong thing.
pip install with error: externally-managed-environment (PEP 668). Every method below is isolated and safe.
uvx
Run straight from PyPI, no install step. Prereq: uv.
uvx --from distil-llm distil bench
pipx
Permanent install in its own venv — PEP 668-safe. Prereq: Python 3.11+, pipx (brew install pipx).
pipx install distil-llm distil certify
Homebrew
Installs into an isolated keg — doesn't touch your Python. Prereq: Homebrew and git (third-party taps are cloned with git — run brew install git if you see Error: Git is unavailable).
brew install dshakes/tap/distil distil bench
Docker
Reproducible image, ideal for CI or sandboxed environments. Prereq: Docker.
docker build -t distil . docker run distil bench
Zipapp (.pyz)
One portable executable — copy it anywhere. Prereq: Python 3.11+ (no install).
make pyz python dist/distil.pyz bench
pip
For embedding the library in your own project. Prereq: an active virtualenv.
python3 -m venv .venv && source .venv/bin/activate pip install distil-llm
distil proxy (or distil wrap -- <your-agent>) and point your SDK's baseURL at it. No code changes, any language. The CLI needs Python 3.11+; your app does not.
Use it on your agent — the 30-second path
Easiest: let distil onboard set you up and hand you the exact commands for your environment — it detects your agent and billing, wires the status line, and prints a guided tour:
distil onboard # one command: detects your setup, wires the status line, guides you
Or do it by hand. distil wrap launches your coding agent with its API traffic routed through compression — no config, no code change.
# Claude Code on a metered API key — saves real $$: distil wrap --expand -- claude # Claude Code on a Pro/Max subscription — flat-rate, ToS-safe (trims context, not $): distil wrap --lossless-only -- claude # Codex, Gemini CLI, or any agent — same pattern: distil wrap --expand -- codex
Then watch genuine, measured savings from your traffic (not estimates):
distil leaderboard # cumulative tokens + $ saved, from the local ledger distil dashboard # live terminal TUI — token-trim + decision-equiv bars, Ctrl-C to exit distil doctor # diagnose your setup: ledger, shadow, proxy self-test, wiring
Wire the status line in one step with distil setup. The status line and distil dashboard auto-detect a flat-rate Claude subscription — the per-token dollar figure is notional, so it's dropped and the token reduction leads (override with DISTIL_SUBSCRIPTION=0/1). Inside Claude Code, /distil-stats, /distil-shadow, /distil-dashboard, and /distil-doctor surface this on demand.
Tired of typing distil wrap each session? Make it the default — once:
distil default # managed shell alias so `claude` always routes through distil distil default --always-on # or a persistent proxy service covering every SDK distil offboard # later: remove distil's footprint (alias, service, status line) before uninstalling
distil default detects your shell (zsh / bash / fish / PowerShell) and billing mode, writes the right line to the rc file your shell actually reads, and tells you what it detected; distil default --undo reverses it. distil offboard is the clean inverse of onboarding — it undoes each piece (asking first), keeps your savings ledger unless --purge, and prints the right uninstall command. See the CLI reference for both.
Billing-grade tokenizer (optional)
The default tokenizer is an offline heuristic — compression ratios are robust, but absolute dollar figures are approximate. For billing-grade token counts and live-model certification, install the live extra:
# with pipx (isolated): pipx install 'distil-llm[live]' # or one-off with uvx: uvx --from 'distil-llm[live]' distil certify --runner anthropic export ANTHROPIC_API_KEY=sk-ant-… distil savings --tokenizer anthropic distil certify --runner anthropic
Validate it preserved your outcomes
Compression is only safe if your agent makes the same decision it would have on full context. --shadow proves that on your live traffic: it samples a fraction of requests and runs each one twice — once compressed, once with the full prompt — then compares the agent's chosen next action (the tool call it decides to make), not the prose. The two are decision-equivalent when those signatures match.
distil wrap --shadow 0.1 -- claude # one command: wraps your agent + shadows 10% distil shadow-stats # live decision-equivalence rate (or /distil-shadow)
The rate also shows in the status line once shadow has samples — read it as “of the requests I checked, N% produced the identical next action with vs without compression.” Start at 0.1; if equivalence holds high, dial compression up — if it dips, back off. Distil fails safe to full context.
Honest scope: this certifies next-action equivalence — a proxy, not end-to-end task success. On real SWE-bench Verified (E7) the proxy does not fully transfer once compression gets aggressive — which is exactly why you monitor the live rate and keep the gate conservative.
60-second quickstart
Three commands cover the core workflow. All run against the bundled multi-domain corpus — no API key required. Run them in order the first time: bench to confirm savings and the gate pass, certify to inspect a single strategy, prune to see what's actually free to drop.
1. Benchmark savings across 7 domains
distil bench is the corpus-wide CI gate. It prices four strategies, certifies Distil is non-inferior on every trajectory, and confirms the gate rejects the aggressive lossy strategy. Run this in CI to catch any regression.
$ distil bench corpus gate — 7 trajectories | model claude-opus-4-8 | tokenizer=heuristic domain trajectory $ saved distil aggr pruned --------------------------------------------------------------------------- ops/sre sre-disk-incident 33.1% PASS FAIL 615 coding coding-bugfix 28.7% PASS FAIL 736 support support-refund 32.6% PASS FAIL 765 research research-synthesis 25.7% PASS FAIL 809 data-analysis data-analysis-sql 18.1% PASS FAIL 965 devops devops-rollback 25.0% PASS FAIL 857 finance finance-reconcile 29.1% PASS FAIL 1014 --------------------------------------------------------------------------- aggregate: distil cuts $0.14212 -> $0.10402 (26.8% cheaper) reversibly; 5761 tokens causally prunable. GATE: PASS — every trajectory certified non-inferior; aggressive rejected on all.
2. Certify a strategy
Run the TOST non-inferiority gate on a single trajectory and strategy. Exits 0 on pass, 1 on fail — plug it directly into any CI pipeline.
$ distil certify --strategy distil certifying strategy 'distil' on 'sre-disk-incident' (runner=deterministic) turn 0: ok turn 1: ok turn 2: ok turn 3: ok decision-equivalence match rate: 100.0% TOST non-inferiority (margin=0.02, alpha=0.05): mean diff=+0.000, p=0.0000 VERDICT: PASS (certified non-inferior)
3. Discover causally inert blocks
distil prune ablates each context block, replays the trajectory, and identifies what never changed a decision. Those blocks are provably free to drop — not heuristically likely, provably safe.
$ distil prune causal ablation over 'sre-disk-incident' — what is free to drop? block occ tokens verdict doc-0 4 312 PRUNE (causally inert) doc-1 4 303 PRUNE (causally inert) obs-0 4 234 keep (changed a decision) obs-1 4 198 keep (changed a decision) system 4 218 keep (changed a decision) tokens provably free to drop: 615 across 2 block(s).
Drop-in adoption: wrap(client)
The fastest path to production compression — no changes to your call sites. Wrap your existing Anthropic client once and every subsequent messages.create call is transparently compressed and cache-pinned.
import anthropic from distil.adapters.anthropic import wrap # One-line drop-in — no call-site changes needed client = wrap(anthropic.Anthropic()) # Works exactly like the original client response = client.messages.create( model="claude-opus-4-8", max_tokens=1024, system="You are a helpful assistant.", messages=[{"role": "user", "content": "Analyse this log output…"}], )
The wrapper applies Tier-0 lossless transforms (JSON minification, run-length collapse) and Tier-1 reversible digests to large tool results. It also pins the stable system prefix for cache-control so repeated calls get the ~10× cache-read discount automatically.
messages.create(**kwargs) method. It imports nothing from the Anthropic SDK itself, so it also works in test environments where the SDK is not installed.
Alternative: provider proxy
Prefer a network-level approach that works with any SDK, framework, or language? See the Adapters page for distil proxy.
Use it on your workflow — recipes
Pick the row that matches you. Every command is real; watch it work with distil leaderboard (genuine cumulative savings) and the x-distil-* response headers.
Coding agents — Claude Code · Codex · Gemini CLI
Wrap the agent; its traffic routes through compression with zero code change.
# subscription/OAuth-safe (ToS-safe, no tool injection) distil wrap --lossless-only -- claude # interactive: model sees content un-digested (Tier-0 only) distil wrap --lossless-only --verbatim -- claude # PAYG: aggressive reversible digest; the model recovers detail on demand distil wrap --expand -- claude # coding sessions with re-reads: send the diff, not the whole file distil wrap --session-delta -- claude
Any SDK app — chatbots, RAG, agents, batch (non-coding)
# standalone proxy — point any base_url SDK at it, any language distil proxy distil proxy --upstream https://generativelanguage.googleapis.com # Google Gemini
# or in-process, no sidecar (LiteLLM / LangChain) from distil.integrations import litellm as distil_litellm distil_litellm.completion(model="claude-opus-4-8", messages=[...])
See it, prove it, get more out of it
| Goal | Command |
|---|---|
| Set up + a guided tour (start here) | distil onboard |
Make distil the default (no per-session wrap) | distil default · undo distil default --undo |
| Remove distil's footprint (before uninstalling) | distil offboard · clear data distil offboard --purge |
| Diagnose your setup (ledger, shadow, proxy self-test, wiring) | distil doctor |
| Wire the savings status line into Claude Code | distil setup |
| Watch genuine savings accumulate | distil leaderboard · live TUI distil dashboard |
| Live decision-equivalence on real traffic | distil wrap --shadow 0.1 -- claude → distil shadow-stats |
| Certify on your domain | distil ingest --input prod.jsonl --out ./mycorpus → distil conformal --corpus ./mycorpus |
| Let agents recover digested detail (MCP) | distil mcp — exposes distil_compress/_expand/_savings |
| Live savings in your Claude Code status line | install the plugins/distil plugin → distil statusline |
| Self-improving keep policy | distil learn / distil online (flywheel; only ever gets more conservative) |
--lossless-only (add --verbatim). PAYG / autonomous → default digest (add --expand). Coding sessions with re-reads → add --session-delta.
What to read next
- Concepts — why decision-equivalence beats byte-equivalence, how the certificate works, and why cache misses (not token size) dominate cost.
- Techniques — every compression technique in depth: cache stabilization, causal pruning, recoverable compression, cross-turn dedup, and more.
- Benchmark — the live head-to-head against real installed packages (LLMLingua-2, Headroom), graded by
claude-opus-4-8. - CLI Reference — every flag and sample output for all commands.