What changed when we took context compression from Codex to Claude Code on Opus 5.5: compress only what the provider has not cached yet, keep the cache alive while tools run, and price every decision on the real bill.
In Part 1 we measured OptScale Kompressor on Codex and GPT-5.5. It took 22.7% off the real bill, about twice Headroom's savings, by rewriting repetitive tool output deterministically so the prompt cache kept working. Claude Code was the obvious next target, and the most stubborn. It pins its whole conversation to the prompt cache, so there is almost nothing left to compress. Its bill turned out to be driven less by what the agent reads than by how often the cache expires while the agent waits for a tool. This part is about what we changed to handle that, and what it measurably bought.
Where we left off
Part 1 ended with a list of things still to do. Here is where they stand:
- Claude Code was forwarded untouched. It is now compressed, but only the part the provider has not cached yet (section 2.1).
- Feedback from the open-source release. Readers put the engine through real logs and edge cases, and their findings are fixed (section 2.4).
- More agents and models than Codex on GPT-5.5. This part measures Claude Code on Opus 5.5.
optscale-kompressor is open source under the MIT licence. Everything described here is in the current release, and that release is what we measured.
1. Why Claude Code is a different problem
Codex re-sends its history and lets the provider cache whatever prefix matches. Claude Code marks its conversation with explicit cache breakpoints, so almost every request is a long cached prefix plus a short new tail. Three facts follow:
1. Almost everything is already cached. In our measurements, 92–95% of billed prompt tokens were cache reads. Rewriting any byte inside the cached prefix invalidates it, so the old rule from Part 1 holds even more strongly: never change what the provider has already cached.
2. Cache reads are nearly free, and cache writes are not.
A token written to the cache costs 25 times a token read from it.
3. The cache expires while the agent waits. A default cache entry lives five minutes. A training run, a full build or a long simulation can keep the agent idle for longer. When it comes back, the whole prefix is written to the cache again at full price. Without compression, that happened 33 times in an 89-task run and re-wrote 927K tokens. That is a third of everything billed at full price.
So on Claude Code the question is less "how much can we remove?" and more "how much can we avoid paying twice?".
2. What changed
2.1 Compress only what the provider has not cached yet
Kompressor now tracks, per conversation, which messages the provider has already seen and cached. On Anthropic, every message inside that frozen prefix is left byte-identical. Only the new tail is compressed, the first time it is sent. In a typical 89-task run about 1,800 messages, or roughly 2.2M tokens, were protected this way. That is the correct outcome, not a missed opportunity.
Two Anthropic-specific settings keep compression from costing more than it saves:
- A minimum saving of 4,000 characters per elision. On Claude Code, a retrieval round re-sends a large prefix, so a small elision that triggers even one retrieval costs more than it saved. Anything smaller ships whole.
- No function-body elision. On Opus 5.5, eliding code bodies cost more in retrieval rounds than it saved, so it is switched off for this provider.
2.2 Keep the cache alive while tools run
Keep-warm. While the agent is running a tool, Kompressor re-sends the last request body every 4.5 minutes, with max_tokens: 1. The provider reads the cached prefix, which costs $0.20 per million tokens instead of $5, and the entry's five-minute clock restarts. Keep-warm stops:
- at the agent's next request;
- after 11 pings, about 50 minutes;
- at the first failed ping;
- if a ping reads no cached tokens, because that ping has already paid for a full write.
Adaptive one-hour TTL. Anthropic also offers one-hour cache entries, at a higher write price. Kompressor switches a conversation to one-hour entries after its first idle gap longer than five minutes. On a replay of earlier Anthropic runs:
- always using one-hour entries cost 2.3% more overall;
- switching adaptively cost 7.7% less, and never more than 1.6% more on any single run.
2.3 Price every decision on the real bill
Kompressor sometimes has to decide whether to rewrite a message the model keeps retrieving. It now prices that decision on what Anthropic actually charges:
- per-model cache prices, so Opus 5.5 reads at a twentieth of its input price;
- the system prompt and tool definitions it never compresses, about 13.6K tokens per Claude Code request;
- Anthropic's 20-block cache lookback.
Before this, a hit-rate bug made every such decision look as if the whole prompt were already cached, and requests billed at about 23K tokens looked like 9.3K.
2.4 Engine fixes from the field
- Honest markers. A fold over lines that differ now reads
[×N similar ref:…]instead of claiming exact repeats. Plain text folds only adjacent runs. - Better routing:
- code behind a listing (
ls && cat x) is found: one 621-line interpreter went from 17,577 to 3,223 characters; - several files printed by one
catare split back into separate files; - JavaScript, C and Java are no longer mistaken for Java, Rust and Go;
- assembly ships whole;
- long symbol-list lines, such as
nmoutput, are clipped.
- code behind a listing (
- Errors stay visible in uniform logs. A long, uniform log such as a training run used to be sampled head-and-tail, so an error in the middle could end up behind the marker. Such logs now go to the error-scored path when they carry error signal, with a wider error vocabulary that includes crashes, OOM kills, timeouts and full disks. The marker reports error counts only when it actually searched for them.
- No silent losses. If one fragment was too large to retain, compression for the whole payload used to be discarded silently. Now only that fragment is declined, and the rest still folds.
3. How we measured
We count every API request because Harbor's own cost only sees the requests in the agent's trajectory. Without compression, Harbor reported $32.00 against $35.35 billed. On the Kompressor runs it missed the keep-warm pings.
Agents do not take the same path twice, and that matters for how the results are read (section 4.4).
4. Results
4.1 The bill
Individual Kompressor runs cost between $27.86 and $28.68 and solved 80–81 tasks.
4.2 Where the money went
Cache writes are three quarters of the difference. The extra spend on pings and one-hour entries comes to under a dollar, about a sixth of what the writes saved.
4.3 The cache did most of the work
Each bridged gap would otherwise have ended in a full rewrite of the prefix. That rewrite cost is what the uncompressed agent actually paid: 927K tokens per run. Net of the pings, keep-warm saved about $3.9 per run, roughly 11% of the uncompressed bill, on its own. In most runs no turn lost its cache at all.
4.4 Reading the result honestly
Agents do not take the same path twice. Four tasks account for the whole net difference: winning-avg-corewars, regex-chess, sam-cell-seg and crack-7z-hash. On the first three, the uncompressed agent took a much longer path: 45–72 steps against 19–26. Kompressor was cheaper on 44 of the 89 tasks.
Splitting tasks by whether they wait on long-running tools separates the two effects:
The first row is the mechanism doing its job: where the cache would expire, keep-warm and adaptive TTL make each step cheaper. The second row is the honest limit. On a typical short task a step costs what it did before, and the rest of that cohort's saving comes from shorter paths, not cheaper steps. The mechanism-level estimate is what we expect to hold up across repeated measurements:
- about 11% from keeping the cache alive;
- plus a few percent from compressing the tail.
4.5 What compression still does on Claude Code
The biggest contributor is cross-message de-duplication: tool output that repeats lines an earlier message already showed. Next come plain text, listings and config.
Removal is far below the 62.8% we measured on Codex traffic, by design:
- the engine only sees the uncached tail;
- it skips elisions under 4,000 characters;
- it leaves code bodies alone on this provider.
The model almost never needs to retrieve anything, so compression adds no retrieval cost of its own.


