headroom compresses coding agents' tool output and keeps the originals
headroom is a local proxy that shrinks bulky command and tool output, like test logs and JSON, before a coding agent sends it to its model, and keeps the originals so the model can fetch any detail that was cut.
- Verdict
- Verdict: Adopt
- Tested
- Commit
76133cf- Source
- headroomlabs-ai/headroom
- Author
- Kahtaf Alam

A coding agent such as Claude Code runs commands and reads files, and every result goes back to its language model as input, from test logs to JSON responses. headroom is a local proxy (a small server on your computer that the agent’s requests pass through) that shortens bulky command and tool output before it reaches the model provider. By default it leaves Claude Code’s own file reads, searches and web fetches unchanged; the HEADROOM_EXCLUDE_TOOLS setting controls that. Our test fed its logs and records through an MCP tool, an add-on tool the agent can call. It keeps the full originals on your machine and gives the model a way to ask for them when it needs a detail that was cut. It is for developers whose agents read large, repetitive output and who want them to send fewer input tokens, the units providers use to count text.
We gave Claude Code two small debugging tasks, once with headroom and once without. With headroom, a task over structured records used 8.2% less input in total; a task over repetitive logs used 57.4% more, because the model kept asking for the cut lines back.
Tested: commit
76133cff59b71284399bf760c5578dc373c97231(v0.41.0) on October 20, 2026. Workflow: Claude Code 2.1.306 with Opus 5.5 fixed two synthetic bugs, each followed by a question about exact details in the tool output, once directly and once through headroom’s proxy at its default settings. Result: all four runs passed the repair tests and returned every requested value. Verdict: adopt with care for tool-heavy workflows where you can check whole-task token use and correctness.
Set up headroom with your coding agent
Paste this into Claude Code or another coding agent that can run commands. It installs headroom’s Python package and asks before it starts the proxy.
Set up headroom (https://github.com/headroomlabs-ai/headroom), a local compression proxy for coding agents. Go one step at a time.
1. In a new Python 3.10+ virtual environment, run: python -m pip install "headroom-ai[proxy]"
(The npm package of the same name has no command-line tool.)
2. Run `headroom --version`. Stop if it fails.
3. Tell me what starting the proxy downloads (it may fetch a compression model) or changes, and wait for my yes. Then run: headroom proxy --host 127.0.0.1 --port 8787
No sudo, and never read or print my keys.
4. Tell me to run `ANTHROPIC_BASE_URL=http://127.0.0.1:8787 claude` in a second terminal and ask it for one small bug fix with a test, while you check the proxy shows compression.
5. Report what you installed and how to undo it. Retry a failure at most once.
headroom shortens tool output and keeps the originals
headroom runs as the proxy we tested or as a library inside an application. Its architecture uses different compression methods for logs, structured data and other content. The shortened request still goes to your provider.
In our record task, a tool returned 25 records as JSON. Each one looked like this:
{
"record_id": "rec-0000",
"tenant": "team-0",
"external_id": "item-0",
"status": "archived",
"region": "zone-0",
"revision": 0,
"detail": "Indexed inventory snapshot 0000; nightly reconciliation complete; source partition 0; retained for audit."
}
What Opus received instead was a table: one header naming each field and its type, then one line per record.
[25]{detail:string,external_id:string,record_id:string,region:string,revision:int,status:string,tenant:string}
Indexed inventory snapshot 0000; nightly reconciliation complete; source partition 0; retained for audit.,item-0,rec-0000,zone-0,0,archived,team-0
For logs, headroom kept the failing-test lines and replaced runs of routine warnings with a note:
2026-09-17T09:00:53Z WARN pool=ledger worker=5 retryable=true queue_depth=40 trace=sample-0053 connection recycled after idle timeout; request retained
[51 lines compressed to 4. Retrieve more: hash=9cb9f120201758e81e112b62]
That hash is how retrieval works: Opus calls headroom’s retrieval tool with the hash. headroom loads the original from local storage and sends it to Opus in an extra request of its own. Only then does it reply to Claude Code, which never sees that extra request. By default, according to its source code, headroom keeps originals for 30 minutes.
To use it, start the proxy in one terminal, then launch Claude Code pointed at it from a second. Setting the variable this way affects only that Claude Code session.
headroom proxy --host 127.0.0.1 --port 8787
ANTHROPIC_BASE_URL=http://127.0.0.1:8787 claude
headroom is Apache-2.0 licensed and releases frequently.
Retrieving originals added work to the log task
The log task was a delete function that left a key in place, then a question asking for a receipt ID from the logs. The record task was a lookup that mixed up two tenants (customer accounts), then a question about the correct record. Both questions asked for the answer as JSON. Each ran once with headroom and once without, so these numbers describe two pairs of runs, not an average saving. The headroom runs went second, after the provider had cached input from the first runs, and Opus varies from run to run, so two pairs cannot show how much of each change came from compression.
| Complete debugging task | Input tokens without headroom | Input tokens with headroom | Change |
|---|---|---|---|
| Repetitive logs | 68,694 | 108,098 | 57.4% more |
| Structured records | 79,335 | 72,795 | 8.2% less |
These totals are what the provider reported for every call in the task: fresh input plus input written to and read from its cache, so they measure usage, not unique text or a bill. Most of the log task’s increase was fresh input: the three extra calls carried 31,526 tokens of retrieved originals back to Opus without using the cache. headroom’s own counter looked better, cutting the first tool-heavy request from 13,040 to 6,688 tokens for logs and from 16,432 to 10,023 for records, but it counts only the conversation in a single request, not the system prompt or the calls that follow.
In the log task, Opus asked for originals nine times across three extra model calls, very helpfully putting text back into a conversation we were trying to shrink. Eight of those requests came during the repair, one during the later question. Each restored the exact original. The record task retrieved nothing; its table kept every value the question needed.
The provider recorded seven model calls for the log task with headroom, against four without it, but Claude Code’s own usage tally left out the three retrieval calls. Count usage from what your provider reports, not from Claude Code’s session total.
Both log-task answers added prose after the JSON we asked for, and the one through headroom wrongly claimed it had never fetched several originals. Check the returned values separately from the agent’s explanation.
Users report smaller requests but mixed savings on whole tasks
These reports cover different releases, models and setups, so their numbers cannot be combined into a typical saving.
In a GitHub comparison using Haiku 5.5 on v0.41.0, the author of a benchmarking tool reported 12% lower cost with unchanged task success, measured with that tool, which they promote. They credit much of it to sending tool descriptions only when needed, a separate feature from shortening tool output; we have not audited their dataset. A Reddit account describes weeks of lower Claude Code token use without noticed quality loss, with no version or method given.
A Hacker News account describes smaller context per call offset by extra turns and higher cost with the Pi coding agent and GPT-5.5. An X demonstration shows token counts falling on sample JSON, logs and code, which does not measure a live agent’s bill.
Adopt headroom with care, and keep it only if whole-task input falls
Adopt headroom with care if your coding agent reads large tool outputs and you can check that compression improves whole tasks. Both of our tasks were fixed correctly and returned the requested values, and the structured records used less input. The log task shows the cost: repeated retrieval of originals and more input across the finished job.
Start with a task you can check yourself. Compare whole-task usage on your provider’s usage page, with and without headroom, and the quality of the fix and answer; keep the proxy only if input falls and quality holds. Without those provider totals, keep your current setup. If your agent keeps needing the cut details, or you would rather not run another local service, use Claude Code’s own context management or trim output at its source; rtk filters command output, and our fast-jev-compaction review covers choosing which tool calls stay in a conversation.