Smaller context. Nothing dropped.
JSON becomes a table
Lists of same-shaped objects repeat every key on every row. headforward writes the keys once, the values as rows, and any value shared by every row just once. It rebuilds to the exact original.
Repeats become pointers
Agents re-read the same file and rerun the same tests. A tool result identical to an earlier one becomes a one-line pointer to it.
Logs lose the noise
Repeated lines collapse to one with a count. Terminal color codes, trailing spaces and runs of blank lines go.
Prompt caching keeps working
The same tool output always compresses to the same bytes and earlier turns never change, so Anthropic and OpenAI cache hits still land.
How much it saves depends on what your agent reads.
Data and logs shrink a lot. Source code is left exactly as written, so code-heavy sessions save less. Counted with OpenAI's o200k tokenizer.
One API response: 30 order records as JSON, 1,112 → 90 tokens.
A test session heavy on data: an API result fetched twice, 120 log lines, a file and a test run each repeated. 18,466 → 7,304 tokens.
400 real coding-agent sessions from the public SWE-agent dataset, mostly reading and editing source code. --smart also recognizes lines the agent has already seen.
Your own numbers: headforward stats reports what Anthropic or OpenAI actually billed and what was saved.
Before and after, from the real tool.
API response
[
{"id": 4101, "customer": "Ana Ruiz", "status": "shipped",
"carrier": "DHL", "total": 18.5},
{"id": 4102, "customer": "Ben Okafor", "status": "shipped",
"carrier": "DHL", "total": 42.0},
... 2 more rows
]{"_cols":["id","customer","total"],
"_rows":[[4101,"Ana Ruiz",18.5],[4102,"Ben Okafor",42.0],
[4103,"Chen Wei",9.99],[4104,"Dara Singh",61.25]],
"_same":{"status":"shipped","carrier":"DHL"}}Keys once, rows as values, shared values once. Rebuilds to the exact original.
Server log
INFO GET /api/health 200 3ms INFO GET /api/health 200 3ms ... 22 more identical lines ERROR POST /api/checkout 500: payment timeout
INFO GET /api/health 200 3ms [x24] ERROR POST /api/checkout 500: payment timeout
Repeats become a count. The error is untouched.
Same test run, twice
(the full test output, sent again)
[Same output as tool call toolu_01 above.]
The first copy is still in the conversation, so nothing is lost.
Paste tool output or a prompt.
Runs entirely in your browser. The samples are examples; replace them with your own.
Token counts here are estimates at about 4 characters per token. The script gives exact counts with tiktoken installed.
Pick the route that fits how you run Claude.
Hooks work everywhere Claude Code runs. The proxy routes also compress JSON and repeated reads, in the terminal and, with --https, the desktop app.
Filter noisy commands
Tests, installs, builds, git log, ls -l and grep pass through the filter. Runs in every session, desktop app included.
Compress every request
Starts at login (macOS) and serves Claude Code in every project. Add --https to reach the desktop app too. Off restores your settings.
One session at a time
Starts a private proxy, launches the agent pointed at it, and prints what you saved when you quit.
| Where it runs | Hooks | Always-on proxy | Wrap |
|---|---|---|---|
| Claude Code in a terminal | ✓ works | ✓ works | ✓ works |
| Claude Code in the desktop app | ✓ works | ✓ with --https | – not launchable |
| Codex CLI, Aider | – Claude only | set the URL yourself | ✓ works |
| Your own SDK code | – Claude only | set the URL yourself | – |
Already using a gateway? headforward goes in front of it.
If your Claude Code settings already point ANTHROPIC_BASE_URL at a router, cost tracker or company proxy, desktop on takes that URL as its upstream, so nothing you rely on is skipped.
127.0.0.1:8787shrinks tool outpute.g. 127.0.0.1:17322routing, logging, keysapi.anthropic.comthe modelTurn it on
Turn it off
An ANTHROPIC_BASE_URL exported in your shell beats Claude Code settings and skips the chain. headforward doctor tells you when that happens.
Fewer tokens, without hiding the failure.
The same 7 real command outputs from one Mac, run through each tool. A check mark means every key fact we looked for (failing test names, error lines, list items) was still there.
| Output | Raw tokens | rtk | Headroom | headforward |
|---|---|---|---|---|
| Unit tests, 2 failures | 1,899 | 67 · failures hidden | 1,899 ✓ | 293 ✓ |
| git log --stat, 40 commits | 4,869 | 1,271 ✓ | 4,869 ✓ | 3,800 ✓ |
| grep, 1 file | 963 | 258 · matches cut | 963 ✓ | 963 ✓ |
| grep across 3 paths | 4,921 | 1,741 ✓ | 3,150 ✓ | 3,385 ✓ |
| ls -la, large folder | 10,445 | 3,077 ✓ | 10,445 ✓ | 7,264 ✓ |
| System log, 600 lines | 37,040 | 614 · error cut | 36,279 ✓ | 21,070 ✓ |
| JSON, 25 items | 2,635 | 93 · 1 of 25 shown | 1,592 ✓ | 1,388 ✓ |
| Total saved | 62,772 | 89% · 9 of 19 facts | 6% · 19 of 19 | 39% · 19 of 19 |
rtk 0.43.0 command wrappers, Headroom 0.41.0 default compress(), headforward hook plus proxy. rtk saves its full output to a file the agent can read later. Small benchmark, written by the headforward author; reproduce with python3 bench/compare_tools.py.
One command. No dependencies.
Python 3.9 or newer on macOS, Linux or Windows.
Install from PyPI.
pip install headforwardNo pip? Copy the script instead, save it as
headforward.py, and runpython3 headforward.pywherever this page saysheadforward.# macOS: save what you just copied pbpaste > headforward.pyLinux:
xclip -o -sel clip > headforward.py. Windows: paste into Notepad and save asheadforward.py.Turn on the hook, then start a new Claude Code session.
headforward hooks install globalCheck your setup. It says exactly what to fix.
headforward doctorOptional: exact token counts.
pip install "headforward[exact]"
Read the script before you run it
Loading…
Before you try it.
Does it change the model's answers?
The default rules are lossless: every compressed result can be rebuilt exactly, or points to an identical copy already in the conversation. Whether a model behaves the same on your work is something you can check: headforward eval replays your recorded requests with and without compression and compares the answers.
Is my API key or Claude sign-in safe?
The proxy runs only on your computer, listens on 127.0.0.1, and passes credentials straight to Anthropic or OpenAI. They are never stored or logged. In --https mode it decrypts only api.anthropic.com, with a local certificate that can vouch for nothing else; every other site gets a plain tunnel it never reads.
Does it break prompt caching?
No. Compression is deterministic and never rewrites earlier turns, so each request still begins with the same bytes as the last one and cache hits keep landing.
Does it work with claude.ai or chatgpt.com?
Those sites talk directly to their own servers, so no proxy can sit in between. You can compress text before pasting it: pbpaste | headforward - -l high | pbcopy on macOS.
How do I know it's working?
In a new Claude Code session, run something noisy like your tests. Shortened output carries a line such as [40 passing test lines omitted; full output: headforward show ID]. headforward stats counts every request it touched.
What if something goes wrong?
Undo it in one command: headforward hooks uninstall global or headforward desktop off. Both restore your Claude Code settings from a backup, and plain claude works exactly as before.
What does it cost?
Nothing. It's MIT-licensed, one Python file, no account and no telemetry.
What it does not do.
- It only touches tool output. Your messages and the system prompt reach the model unchanged.
- Savings depend on the work. JSON-heavy and log-heavy sessions save the most. Sessions that mostly read source code save little, because code is left as written.
- History often costs more. Every reply resends the conversation.
/clearbetween tasks and/compactin long sessions save more than any filter. - The desktop app needs
--https. Its Code sessions ignoreANTHROPIC_BASE_URL, sodesktop on --httpsserves them as their HTTPS proxy instead. If that proxy is down, those sessions can't connect until you runheadforward desktop off. - A shell variable wins.
ANTHROPIC_BASE_URLexported in your shell overrides Claude Code settings, including the always-on proxy. - Codex with a ChatGPT login talks to ChatGPT's servers, not the API, so it bypasses the proxy. Use an API key login.
- Chat apps in the browser (claude.ai, chatgpt.com) can't be proxied. Use the prompt compressor and paste.