How to Use Kompressor: The Beginner's Guide (the Proxy Lesson, First Wrapped Run, the Determinism Rule, and the Bill Arc)
CodexFuse Team · 2026-11-02T13:51:41.007Z · 17 min read min read
Kompressor is the deterministic context compressor for coding agents: one Rust binary that sits between your agent and the model, folds tool output deterministically, and cuts real provider bills. This beginner's guide covers install, your first wrapped run, the determinism rule, and reading the savings honestly.
What Is Kompressor, Exactly?
Learning how to use Kompressor starts with one sentence, straight from the vendor's own README: Kompressor is "deterministic prompt compression for coding agents, in one Rust binary." It sits between your coding agent and the model provider and rewrites machine-generated tool output — build logs, compiler warnings, progress bars — into a shorter form before it ever reaches the context window. Your agent's code, your prompts, and its results pass through byte-identical; only the machine noise gets folded. If you searched "kompressor tutorial" or "coding agent token compression", you are in the right place — this is the beginner's guide to OptScale Kompressor, the open-source project from Hystax, not a machine-learning summarizer and not a model you download. For a second data point on the same launch wave of agent tooling, see our OpenFilm beginner guide.
The mental model that makes Kompressor click: every step a coding agent takes, it re-sends its entire working history to the model — every apt-get log, every compiler warning, every progress bar. On a long task the model re-reads the same build output dozens of times, and you pay for every read. Kompressor breaks that cycle by standing in the middle as a proxy and deterministically rewriting the machine-generated parts. The same input always compresses to the same bytes, every turn, so the provider's prompt-cache discount keeps working — and every removed detail stays one retrieval away.
How Do You Use Kompressor, Step by Step?
The short answer: install the binary, run one wrap command, do your normal agent work, then read the savings honestly. Here is the full arc for your first session:
- Install the binary. Download a pre-built release (Linux x86_64/arm64, macOS arm64/x86_64) or install with Cargo. I verified the 1.0.2 release myself this week — see the install section below.
- Wrap your agent. Run
kompressor wrap codex(orkompressor wrap --listto see the agents it knows: codex, claude, opencode, aider, cursor). The command starts the proxy, points the agent at it, runs the agent, and cleans up on exit. - Do your normal work. Nothing about your agent's behavior changes. Build logs, diffs, grep output, and JSON blobs get folded in flight; your code and prose pass through untouched.
- Read the exit summary. When the session ends, Kompressor tells you what happened: how many requests and messages it compressed, tokens saved gross, and tokens saved net of retrieval.
- Check the numbers before quoting them. Run
kompressor stats summaryand confirmkompressor_stats_dropped_totalon/metricsis zero — otherwise every report is an undercount.
The rest of this guide fills in each step: install routes, what a wrapped session looks like, what compressed output actually looks like (I ran it live), why determinism decides the bill, and how to read the savings honestly.
How Do You Install Kompressor?
Pick one route from this table — they all land on the same single Rust binary with no runtime downloads, no telemetry, and no model files:
| Route | Command | Pick it when |
|---|---|---|
| Pre-built binary | Download from the Releases page (Linux x86_64/arm64, macOS arm64/x86_64) | You want the fastest path — no build tools needed |
| Cargo | cargo install --locked --git https://github.com/hystax/optscale-kompressor kompressor-cli | You already live in Rust (needs Rust 1.90 or newer) |
| From source | git clone https://github.com/hystax/optscale-kompressor, then make release | You want to hack on it; make deb, make rpm, make static, and make docker build packages |
I installed the 1.0.2 release in a sandbox this week to verify the article. The Linux binary printed kompressor 1.0.2 with code-aware (tree-sitter grammars): true, and kompressor --help confirmed the full surface list: compress, detect, retrieve, stats, bench, check-config, serve, mcp, wrap, unwrap, version. If you are deploying the team proxy inside a container, pair this with our Docker beginner guide; if you are building from source, you will want our Git beginner guide for the clone step.
How Do You Run Your First Wrapped Session?
The supported path is one command: kompressor wrap codex. That starts the proxy, points Codex at it, runs Codex, and cleans up on exit — and for most teams, that one command is the simplest way to reduce Codex API bill costs without touching a single agent setting.
There is one wrinkle worth knowing. Codex ignores OPENAI_BASE_URL (measured on Codex 0.155.1), so wrap cannot just set an environment variable the way it does for other clients. Instead it adds a marker-delimited block to ~/.codex/config.toml at startup and removes it on exit, leaving everything else in the file byte for byte. It reads Codex's own auth.json and writes the block that matches your login — API key or ChatGPT plan. If a session is killed and the block is left behind, kompressor unwrap codex removes it.
For other agents the syntax generalizes:
kompressor wrap --list # the agents wrap knows kompressor wrap aider -- --model sonnet # your own arguments go after -- kompressor wrap --env NAME=root|v1 -- your-agent
wrap knows codex, claude, opencode, aider, and cursor (for Cursor it prints the base URL to set in Cursor's settings, and it only applies when Cursor uses your own OpenAI key). cursor-agent is refused with an explanation: it speaks Connect RPC over protobuf, which the proxy cannot read.
When the session ends, Kompressor reports exactly what happened — the README's own example:
kompressor: 26 request(s), 126 message(s) compressed, ~2029706 tokens saved (2015180 net of retrieval)
Read that line the way the vendor does: the gross number is what compression removed; the net number is what you actually kept after the model fetched some fragments back. The section on honest savings below explains why net is the only number that matters.
What Does Compressed Output Actually Look Like?
Here is a real run, not a mockup. I fed a 5,751-byte synthetic build log — 120 near-identical compile lines plus one genuine Rust type error — through the 1.0.2 release with kompressor compress. Twenty lines came back. The error block survived verbatim and the noise folded into one marker:
Compiling serde v1.0.219
Running rustc --crate-name serde --edition=2021 src/lib.rs
Compiling serde v1.0.219
Running rustc --crate-name serde --edition=2021 src/lib.rs
Compiling serde v1.0.219
Running rustc --crate-name serde --edition=2021 src/lib.rs
error[E0308]: mismatched types in src/auth.rs:91
--> src/auth.rs:91:23
|
91 | validate_token(user_id);
| ^^^^^^^ expected &str, found u64
[... 105 log lines omitted [ref:k_1NaWlHTq_XPQ]; 0 ERROR, 0 WARN]
Three things to notice. First, 105 repeated compile lines collapsed into one labeled marker — template folding, the log compressor's signature move. Second, the error block survived intact: Kompressor folds noise, not signal. Third, the marker carries a handle (ref:k_1NaWlHTq_XPQ) that is content-addressed — a truncated BLAKE2b digest of the removed text — so the model can fetch the full 105 lines back on demand. I ran kompressor retrieve k_1NaWlHTq_XPQ and the elided lines came straight back.
kompressor detect classified the payload before compressing: content type build, confidence 0.80, strategy log. Feed it something tiny and it refuses honestly — a 4-line file came back as passthrough with the note "below min_compress_chars (512): the payload was never classified." That is the never-worse rule in action: a compressor that fails to shrink a payload returns the original, and errors, panics, and timeouts all degrade to forwarding the original. As the README puts it: compression subtracts tokens, never availability.
Why Does Determinism Decide Your Bill?
One rule decides everything else: the same input compresses to the same bytes, every turn. Here is why that sentence is the whole product. On agent traffic, most input tokens are billed as prompt-cache reads at roughly a tenth of the fresh price — the vendor measured 93.0% of billed prompt tokens as cache reads on an 89-task run. A compressor that paraphrases logs differently on every turn quietly breaks that cache, and the whole conversation gets re-priced at the fresh rate. Deterministic compression saves tokens while keeping the discount; non-deterministic compression can cost more than it saves.
The engine enforces this structurally. The core crate has no I/O, no clock, and no randomness — no compressor may even look at the conversation around a payload, because ranking a tool result against the question that prompted it would compress harder and would also compress differently on every turn it survives into. Handles are content-addressed, so the same fragment gets the same handle on any machine, in any later run, and 274 recorded vectors pin which payloads compress and to what. I verified it directly: two compressions of the same build log produced byte-identical output (matching md5). Nothing varies between machines, and nothing is fetched at runtime.
This is also the sharp edge against ML-based compressors. A model that rewrites your logs slightly differently each turn destroys the cache hit rate; Kompressor's 0.2 milliseconds per kilobyte of pure rule-based transforms does not. And "removed is not lost": in the default recoverable mode, every elision either sits behind a handle in a SQLite store or is a pointer to text still on screen — and the proxy offers the model a retrieve tool it executes itself, so recovery works even for a client that knows nothing about Kompressor.
How Do You Read the Savings Honestly?
saved_gross is what compression removed. In recoverable mode that is not the whole story: every retrieval puts a fragment back into the prompt and the model pays for it again. The figure that matters is saved_net = saved_gross − retrieved tokens, and it can go negative. A sum of gross savings over a window also over-counts on agent traffic, because every turn re-compresses the same growing history and credits the same bytes again.
So before quoting any number: run kompressor stats summary, which reports both gross and net, and check that kompressor_stats_dropped_total on /metrics is zero — otherwise every report is an undercount. If you gate releases on benchmarks, our GitHub Actions beginner guide shows how to run these checks on every commit.
What Do the Benchmarks Actually Say?
Every figure in this section is vendor-measured — Hystax's own numbers from Terminal-Bench 2.1, not ours. The setup: 89 tasks, Codex CLI on GPT-5.5 ($5.00 / $0.50 / $30.00 per million uncached / cached / output tokens), four arms (no compression; Headroom 0.40 at defaults with its ML model; Headroom at its most aggressive setting; Kompressor). Every figure below is the difference between real provider bills with the prompt-cache discount included — self-reported savings priced at the uncached list rate are not used.
| Per full run | No compression | Headroom (default) | Kompressor |
|---|---|---|---|
| Cost | $107.89 | $99.04 | $83.40 |
| Input tokens | 96.1M | 95.5M | 72.2M |
| Uncached input tokens | 6.68M | 5.16M | 4.46M |
| Tasks solved | 82.2% | 81.6% | 81.1% |
| Requests over 200K tokens | 1.9% | 0.6% | 0.13% |
Against no compression: Kompressor −22.7% on cost (81.1% solved), Headroom default −8.2% (81.6% solved), Headroom at its most aggressive −11.6% (85.1% solved). The solve-rate differences are not statistically significant; the cost and token savings are. Kompressor's saving is 2.0× Headroom's most aggressive setting and 2.8× its default, it was cheaper on 54 of 87 tasks, and the gap sits in long, log-heavy work — ML training, source builds, and data pipelines produced 83% of the total saving, while on short tasks neither tool has much to remove.
Kompressor vs Headroom: What's the Difference?
Headroom is the best-known open-source context compressor, and Kompressor's own acknowledgements say it took the base idea from Headroom (Apache-2.0): routing a payload to a compressor written for its content type, the compress-and-retrieve pattern, and the code body-budget idea. Draw the line once: they are different products in the same lane, and Headroom has grown into a platform while Kompressor is deliberately just a compressor. The vendor audited Headroom 0.40 against optscale-kompressor 0.13 and published this comparison:
| Headroom 0.40 | optscale-kompressor 0.13 | |
|---|---|---|
| Production code | ~240K lines of Python + ~72K lines of Rust | ~33K lines of Rust |
| Proxy configuration | 94 CLI options; ProxyConfig has 139 fields | 5 options; one TOML file of under 100 keys |
| Environment variables | ~420 HEADROOM_* names | ~25 KOMPRESSOR_* names |
| ML models | ModernBERT (261–601 MB, downloaded at runtime), Magika, ONNX Runtime | None |
| Proxy behavior | Python proxy still the default; the Rust proxy compresses nothing unless switched on | One binary, compressing, everywhere |
| Speed | 87 ms/KB (ML on), 1.5 ms/KB (ML off) | 0.2 ms/KB |
| Replay: share of eligible output removed | 22.6% (ML on), 7.3% (ML off) | 62.8% |
On the replayed traffic (6,255 tool outputs, 34.2M characters), Kompressor removed 2.8× as much as Headroom with its ML model on and 8.6× as much without it, in about 1/440 of the time the model needs. Two caveats the vendor states plainly: Headroom's open-source proxy is single-user (state lives in ~/.headroom, identity accepted only from loopback) while Kompressor inside OptScale AI serves many teams at once — and that multi-team story is also the vendor's upsell path, so treat the platform comparisons as what they are: vendor claims. The deterministic-vs-ML cache argument, though, is independently verifiable — and I verified the deterministic half myself.
What About Claude Code?
kompressor wrap claude runs and forwards Claude Code's requests untouched — and the README says that is not a gap waiting to be filled. Claude Code marks its final message as a prompt-cache breakpoint, which pins the whole conversation, and rewriting any byte inside it would invalidate a cache billed at about a tenth of fresh input. What the wrap does give Claude Code is retrieval: it hands Claude Code the retrieve tools as an MCP server it launches itself, so a ref:k_… handle resolves anywhere in the session rather than only while a request is passing through the proxy. Nothing durable is written — no ~/.claude.json, no ~/.claude/settings.json — so there is no unwrap step. An early "compress only what the provider has not cached yet" path exists behind proxy.frozen_prefix = "first_seen", but it has open issues and is off by default.
How Do You Run Kompressor as a Service for a Team?
One binary runs everything. kompressor serve with no flags starts the HTTP API, the MCP tool server, and the reverse proxy on one listener (127.0.0.1:8817), and any client can point at it:
kompressor serve # every surface on 127.0.0.1:8817 export OPENAI_BASE_URL=http://127.0.0.1:8817/v1 # OpenAI Chat Completions or Responses export ANTHROPIC_BASE_URL=http://127.0.0.1:8817 # Anthropic Messages: the root, no /v1
The proxy speaks OpenAI Chat Completions, OpenAI Responses, and Anthropic Messages, plus a WebSocket relay — a subscription session opens a WebSocket, which the proxy relays and compresses (on by default since 0.14.0; relayed turns report no provider usage, so their savings are real but unmeasured). The MCP server (kompressor serve --mcp, streamable HTTP) exposes optscale_kompressor_retrieve, optscale_kompressor_compress, optscale_kompressor_compress_raw, and optscale_kompressor_stats. The HTTP API adds POST /v1/compress, /v1/compress/raw, /v1/retrieve, /v1/detect and GET /v1/stats/*, /healthz, /readyz, /metrics.
Configuration is one TOML file of under 100 keys, read from $KOMPRESSOR_CONFIG, then ./kompressor.toml, then $XDG_CONFIG_HOME/kompressor/config.toml; kompressor check-config prints the effective result with secrets removed. Modes are per-request (options.mode on the API or MCP, the X-Kompressor-Mode header on the proxy), per tenant in config, or global: recoverable (default — the aggressive engine with every elision retained behind a handle), aggressive (lossy — every elision announced by a marker, nothing retained; use from the bare API only if your caller cannot retrieve), lossless (only reversible transforms, nothing dropped), and off (a pass-through that still records statistics). Defaults are a working single-tenant setup: no config file, SQLite for fragments and statistics under ./data, no authentication. A team proxy wants a machine that is always on — if you need a refresher on that side, start with what VPS hosting is.
What Are Kompressor's Surfaces?
Every surface below is the same binary over one implementation of the algorithm — there is no separate daemon to install:
| Surface | How |
|---|---|
| Agent wrap | kompressor wrap <agent> |
| LLM proxy | kompressor serve --proxy: OpenAI Chat Completions, OpenAI Responses, Anthropic Messages, and a WebSocket relay |
| HTTP API | POST /v1/compress, /v1/compress/raw, /v1/retrieve, /v1/detect; GET /v1/stats/*, /healthz, /readyz, /metrics |
| MCP server | kompressor serve --mcp (streamable HTTP): retrieve, compress, compress_raw, stats |
| CLI | kompressor compress, retrieve, detect, stats, bench, check-config |
| Library | The kompressor-engine crate: compress a string or a conversation, no I/O |
To compress a single file with an explanation of what happened, kompressor compress build.log --explain is the one-liner that shows the engine's reasoning without running any agent.
7 Mistakes Beginners Make With Kompressor
| Mistake | What actually happens | Do this instead |
|---|---|---|
| Quoting the gross number as your savings | saved_net can go negative once the model retrieves fragments back | Report saved_net from kompressor stats summary only |
| Wrapping Claude Code expecting compression | Requests are forwarded untouched — deliberately, to protect its cache breakpoint | Use wrap claude for retrieval, and measure other agents for compression |
| Trying to wrap cursor-agent | Refused with an explanation (Connect RPC over protobuf) | Use the --env form with a tool that speaks HTTP |
Forgetting unwrap after a killed session | The marker block stays in ~/.codex/config.toml | Run kompressor unwrap codex to restore the file |
| Using aggressive mode where callers can't retrieve | Elisions are announced by markers but nothing is retained | Stay on recoverable (the default) unless the caller truly cannot retrieve |
| Reporting numbers without the dropped-total check | Every report is an undercount when drops are nonzero | Confirm kompressor_stats_dropped_total is zero on /metrics first |
| Expecting big savings on prose-heavy sessions | Compression is weakest where outputs are tiny or are prose that should not be folded | Measure on your own log-heavy workloads — ML training, builds, data pipelines |
Sources
Every fact in this article was verified during this run (2026-11-02, UTC):
- OptScale Kompressor README (github.com/hystax/optscale-kompressor; raw file fetched and read in full 2026-11-02) — the self-description, install routes, wrap syntax and Codex config behavior, the Claude Code policy, design rules, modes, surfaces, the honest-savings math, and the "not built yet" list
- GitHub REST API for hystax/optscale-kompressor (queried 2026-11-02) — release 1.0.2 (published 2026-10-15), repository created 2026-10-14, 29 stars / 6 forks snapshot (moving)
- "Token Compression for Coding Agents: Kompressor vs Headroom" (optscale.ai/blog/context-compression-coding-agents; fetched 2026-11-02) — the 94-vs-5 CLI options, ~420-vs-~25 environment variables, ModernBERT/Magika/ONNX sizes, marker format, the audit of Headroom 0.40
- "Open Source Agent Tools: October 20, 2026" (my2cents.ai; fetched 2026-11-02) — the HN October 19 launch note, the 22.7% / $83.40-vs-$107.89 / 81.1%-vs-82.2% figures,
kompressor wrap codexas the entry command - PRWeb, "Hystax Releases Open-Source Token Compressor That Cuts AI Coding-Agent Costs by 22.7% Without Changing the Agent" (2026-10-22) — the four design principles (deterministic, recoverable, format-aware, smaller requests), company context
- Author's own live verification (sandbox, this run) — downloaded the 1.0.2 Linux x86_64 release;
kompressor versionprinted "kompressor 1.0.2" with "code-aware (tree-sitter grammars): true"; compressed a 5,751-byte synthetic build log (105 lines folded behindref:k_1NaWlHTq_XPQ, error block intact);detectreported build / 0.80 / log; two runs byte-identical (md5 90885f5ece5e71a5e2991d5ac05f8ebf);retrievereturned the elided lines; a 4-line payload returned passthrough ("below min_compress_chars (512)")
Frequently Asked Questions
Does Kompressor change what the model sees?
No — not the meaning of it. In the default recoverable mode, every removed passage is replaced with a labeled marker the model can fetch back on demand, and the proxy offers the model a retrieve tool that it executes itself. Nothing is summarized or paraphrased; what survives is byte-identical, and what is removed stays one retrieval away.
Will Kompressor break my prompt cache?
No — protecting the cache is the design. The engine has no clock, no randomness, and no I/O: the same input compresses to the same bytes on every turn, so prompt-cache hit rates stay intact. The vendor measured 93.0% of billed prompt tokens as cache reads on their benchmark run; a compressor whose output shifts between turns would destroy that discount and cost more than it saves.
Does Kompressor work with Claude Code?
kompressor wrap claude works, but it deliberately does not compress. Claude Code marks its final message as a prompt-cache breakpoint that pins the whole conversation, and rewriting any byte inside it would invalidate a cache billed at about a tenth of fresh input. The wrap still gives Claude Code the retrieve tools, so ref handles resolve anywhere in the session.
How do I know the savings are real?
Quote saved_net, never saved_gross — net subtracts every token the model retrieved back, and it can go negative. Run kompressor stats summary, which reports both, and confirm kompressor_stats_dropped_total on /metrics is zero; otherwise every report is an undercount. Then measure on your own workload, ideally the log-heavy kind where Kompressor's edge is largest.
Is Kompressor free?
Yes. It is MIT-licensed open source from Hystax — a single Rust binary you download and run, with no subscription, no telemetry, and no model downloads. It is also the compression engine inside Hystax's paid OptScale AI platform, which is where the multi-team dashboards and per-team policies live.
