# lean-ctx vs Headroom > **Last updated:** July 2026 | Both expose a drop-in `compress(messages, model)`, > but that shared surface hides the real difference: Headroom is a stateless > compression *library*; lean-ctx is a stateful context-engineering *layer* that > remembers, proves, and (next) replays the context it shapes. ## Overview | | lean-ctx | Headroom | |---|---|---| | **Approach** | Local context-engineering layer with a deterministic compression funnel | Compression library + proxy with optional ML compression | | **Drop-in API** | `compress(messages, model)` (Py + TS) | `compress(messages, model)` (Py + TS) | | **Runtime** | Single Rust binary + loopback daemon | Python package (`headroom-ai`) / Node package | | **License** | Apache-2.0 | Apache-2.0 | | **Determinism** | Byte-stable output, prompt-cache safe (#498) | Not a stated contract | | **Locality** | 100% local, no telemetry by default | Local library; proxy/ML modes optional | | **Beyond compress()** | 80 MCP tools, session memory, code intelligence | Cross-agent memory, `headroom learn`, ML compression | ## The core difference **Headroom** is a compression library first: `compress()` inline, a transparent proxy for zero-code integration, an MCP server, and an optional ML compressor ("Kompress", requires `torch`). Its reach comes from a broad set of framework wrappers (LiteLLM, LangChain, Agno, Strands) and agent-wrap commands. **lean-ctx** is a context-engineering *layer*. The same `compress()` contract is one surface of a Rust daemon that also does cached file reads (10 modes), 95+ shell-output compression patterns, hybrid semantic search, call-graph/impact analysis, and a temporal knowledge graph — all 100% local, behind 29 published stability contracts. Its `/v1/compress` is **deterministic by contract**: the same `(messages, model)` produces byte-identical output, so Anthropic (90%) and OpenAI (50%) prompt-cache discounts survive compression. The gap is structural, not cosmetic. A `compress()` call is stateless by design: it sees one message list and returns a shorter one. lean-ctx keeps a stateful record *around* that call — a Context Ledger of why each item was kept or dropped (with Φ-scores), a signed Context Proof of what the model saw, plus session memory and a temporal knowledge graph that persist across runs. That state is the foundation for the **Context Time Machine** (direction; see [`docs/concepts/context-time-machine.md`](../concepts/context-time-machine.md)): a git-anchored, signed snapshot you can rewind, reproduce, resume, or share. A stateless library has nothing to anchor such a timeline to. ## Feature comparison | Feature | lean-ctx | Headroom | |---------|:--------:|:--------:| | Drop-in `compress()` (Py + TS) | Yes | Yes | | Transparent proxy | Yes (multi-provider) | Yes | | MCP server | 80 tools | `headroom_compress/retrieve/stats` | | Reversible (reference retrieval) | CCR (#482/#493) + `/v1/references/{id}`, `ctx_expand`/`ctx_retrieve` | `headroom_retrieve` store | | Deterministic / prompt-cache safe | Yes (#498, CI-guarded) | Not stated | | Vercel AI SDK middleware | `leanCtxMiddleware` / `withLeanCtx` | `headroomMiddleware` / `withHeadroom` | | LiteLLM hook | `LeanCtxLiteLLMHandler` | `HeadroomCallback` | | LiteLLM proxy guardrail (`pre_call` sidecar) | Yes — `/v1/compress` speaks the guardrail wire contract (#700) | Yes — native `guardrail: headroom` (July 2026) | | LiteLLM CCR agentic loop (`hash=` markers + `/v1/retrieve/{hash}`) | Yes — regex-locked contract test (#702) | Yes (native) | | LangChain | `compress_messages` + retriever | wrap model | | ML / learned compression | No (deterministic by design) | Yes (Kompress, torch) | | JSON array crusher (row dedup) | `json_crush` — lossless + opt-in lossy with CCR, deterministic (#935) | Smart Crusher (statistical) | | Active prompt-cache breakpoints | Anthropic `cache_control` injection, opt-in (#939) | Cache aligner | | Volatile-field cache alignment | Detector (#940) **+ opt-in tail-relocate (#974)**, deterministic | Cache aligner (relocate) | | Compression-learning loop | Retrieve-coupled session backoff, deterministic (#941) | CCR learning | | Cross-agent shared memory | Knowledge graph + handoff | `SharedContext` | | File-read compression | 10 modes, ~13-token cached re-reads | — | | Shell-output compression | 95+ patterns | — | | Semantic search / call graph | Hybrid BM25+vector / multi-hop | — | | Single binary | Rust | Python / Node | ## Compression: deterministic funnel vs ML lean-ctx's `/v1/compress` runs every text payload through a deterministic funnel (dedup, structural prose squeeze, tool-output patterns). Because it is rule-based it is **reproducible and cache-stable**, but it does not learn — highly novel prose compresses modestly, while repetitive tool output, logs and RAG dumps compress heavily (the same engine reaches up to ~99% on file reads and powers 95+ shell patterns). For the array-of-objects JSON that dominates API responses, DB dumps and RAG chunks, lean-ctx ships `json_crush` (#935) — the deterministic counterpart to Headroom's statistical Smart Crusher. It hoists every key shared across all rows to a single `_defaults` block and keeps only per-row deviations, so the lossless stage is **exactly reconstructible**; an opt-in lossy stage drops near-unique high-entropy columns (timestamps, UUIDs) only behind a content-addressed `ctx_expand` handle, so a dropped datum is never irrecoverable. Unlike a statistical crusher, the output is a pure function of the input (no mean/stddev sampling), so it stays byte-stable and cache-safe. The accuracy floor is CI-guarded: a model-free A/B gate (`Condition::JsonCrush`, #942) proves the crush keeps every gold answer while cutting tokens on a redundant payload. Headroom additionally offers an **ML** compressor (Kompress) for prose, at the cost of a `torch` dependency and non-deterministic output. **Rule of thumb:** choose lean-ctx when the payload is code, tool output, logs or RAG context and you need local, deterministic, cache-preserving output; consider Headroom's ML mode when you specifically need learned prose compression. ## Reversibility Compression is only safe if the model can get the original bytes back when it needs them. lean-ctx never throws content away — it moves it to a content-addressed store and leaves a deterministic handle. There are **five** recovery paths, so reversibility holds whether you drive lean-ctx as a proxy, an SDK or an MCP server: 1. **Archive + `ctx_expand`** — any truncated tool output keeps an archive id; the agent calls `ctx_expand(id, …)` (or `head`/`tail`/`grep`) to stream the rest. 2. **`ctx_retrieve`** — fetches the verbatim original for a stored reference id. 3. **Proxy CCR (#482)** — when the proxy prunes an old `tool_result`, it persists the verbatim original to the shared tee store and embeds the file path as the retrieval handle, recoverable with the agent's *native* file read (no MCP needed). The handle is a pure function of the content hash, so it never breaks the prompt cache (#448). 4. **In-band CCR (#493)** — for a remote proxy with no shared filesystem, the stub advertises a compact `` marker; when the model echoes it, the proxy splices the verbatim original back inline next turn. 5. **`GET /v1/references/{id}`** — an HTTP endpoint that resolves a reference id to its original, for SDK/HTTP clients. All five are deterministic and content-addressed (see [`rust/src/proxy/ccr.rs`](../../rust/src/proxy/ccr.rs)). Headroom is also reversible — via its `headroom_retrieve` store — so any third-party table that lists lean-ctx as "Reversible: No" is simply out of date. ## Benchmark (reproduce it yourself) Numbers depend entirely on the corpus, so we ship a harness instead of cherry- picked figures. It runs **both** libraries over the *same* files with the *same* tokenizer and emits JSON (ratio + latency). A tool that is not installed is reported `available: false` — never estimated. ```bash # Optional head-to-head + accurate tokens: pip install headroom-ai tiktoken # lean-ctx side needs the daemon with /v1/compress: lean-ctx dev-install python bench/compress/benchmark.py --corpus docs/ --model gpt-4o --out report.json ``` A daemon-free lean-ctx data point (deterministic funnel, `o200k_base`) over this repo's 27 `docs/reference/*.md` files, via `cargo test -p lean-ctx --lib proxy::compress_api::tests::bench_real_corpus_o200k -- --ignored --nocapture`: ```json { "files": 27, "original_tokens": 69594, "compressed_tokens": 57615, "tokens_saved": 11979, "saved_pct": 17.2, "tokenizer": "o200k_base" } ``` Prose docs are a conservative corpus; tool-output / log payloads — the common agent case — compress far more. See [`bench/compress/`](../../bench/compress/README.md). ## Where Headroom leads - **Momentum & mindshare** — a fast-moving, popular library with broad adoption, amplified by the **native LiteLLM guardrail** (July 2026): `guardrail: headroom` ships in LiteLLM ≥ v1.92, giving Headroom first-mover distribution on every LiteLLM gateway. (lean-ctx speaks the same sidecar wire contract — see below — so the channel is open to both; the mindshare is theirs.) - **Learned compression** — the ML (Kompress) path can beat rule-based squeezing on free-form prose. - **More framework wrappers out of the box** — Agno, Strands, agent-wrap commands. - **Single-language install** — pure `pip install headroom-ai`, no separate daemon for the inline library path. ## Where lean-ctx leads - **Determinism & prompt-cache safety** — byte-stable output is a CI-guarded contract (#498); compression never breaks Anthropic/OpenAI cache discounts. - **Deterministic equivalents of Headroom's adaptive stages** — the JSON crusher (#935), active Anthropic cache-breakpoint injection (#939), volatile-field cache-aligner relocate (#974) and retrieve-coupled compression-learning loop (#941) deliver Smart-Crusher / cache-aligner / CCR-learning behaviour *without* sampling, ML weights or non-deterministic output. - **It's a whole layer** — compression is 1 of 80 MCP tools alongside cached reads, shell compression, semantic search, code intelligence and memory. - **Stateful, with a temporal axis** — a Context Ledger, signed proofs, session memory and a temporal knowledge graph wrap every compression, and are composing into a git-anchored **Context Time Machine** (rewind / reproduce / resume / share). A stateless `compress()` library has no equivalent. - **100% local, single Rust binary** — no Python runtime, no telemetry by default. - **Stability contracts** — 29 published contracts, frozen surfaces SHA-256-locked in CI; integrations can't silently break. ## When to use which ### Choose Headroom if you... - Want a pure-Python (or Node) library with no separate daemon for the inline path - Need learned/ML prose compression and accept a `torch` dependency - Use Agno / Strands or want the widest set of prebuilt framework wrappers Running a LiteLLM gateway is **not** by itself a reason to pick either: the guardrail's `api_base` can point at a lean-ctx daemon just as well (deterministic, prompt-cache-safe output — see the [compress() SDK cookbook](../guides/compress-sdk.md#litellm-proxy-guardrail-zero-code-gateway-side)), which makes a one-URL A/B between the two trivially easy. ### Choose lean-ctx if you... - Need deterministic, prompt-cache-preserving compression - Want compression *and* cached reads, shell compression, search, and memory - Require 100% local operation in a single binary with stability guarantees - Are compressing code, tool output, logs or RAG context ## Migration (Headroom → lean-ctx) The contracts line up, so migration is mostly imports: ```python # Headroom from headroom import compress result = compress(messages, model="gpt-4o") messages = result.messages # lean-ctx from lean_ctx import ProxyClient result = ProxyClient().compress(messages, model="gpt-4o") messages = result.messages # result.saved_tokens / result.saved_pct ``` ```ts // Headroom → lean-ctx (Vercel AI SDK) - middleware: headroomMiddleware() + middleware: leanCtxMiddleware({ model: "gpt-4o" }) ``` See the [compress() SDK cookbook](../guides/compress-sdk.md) for full recipes. --- *Both projects are open source (Apache-2.0). Star counts and ML results move fast — run the benchmark on your own corpus and choose what fits.* [Get started with lean-ctx](https://leanctx.com/docs/getting-started) | [Headroom on GitHub](https://github.com/chopratejas/headroom)