Two open-source tools that cut the tokens your AI coding agent burns on tool output. Same goal, different layer. rtk trims at the shell, headroom compresses on the wire. Here is how each works, how intrusive it is, and where each one falls short.
A single Rust binary that sits between the agent's shell call and the command. Runs it, filters the output with deterministic parsers, returns the compact version. Wired in via a hook, transparent to the agent.
Compresses tool outputs, logs, files and RAG chunks in the request itself, between agent and model API. Six compressors. Runs as a proxy, an MCP server, or a library. Compression is reversible via a retrieval tool.
| Dimension | rtk | headroom |
|---|---|---|
| Layer | Shell. Between Bash tool and the command. | Wire. Between agent and model API. |
| Language | Rust, single binary, zero runtime deps | Python 3.10+ (Rust core via Maturin), also TS/npm |
| Compression | 12 deterministic strategies (stats, failures-only, dedup, tree, schema, code body-stripping) | 6 compressors, deterministic or local ONNX model. No remote LLM calls either. |
| Covers file reads | No for Claude Code native Read/Grep/Glob (hook only fires on Bash) | Yes if on the wire (proxy/lib see file content in the request) |
| Covers RAG chunks | No | Yes, that is a core use case |
| Install / intrusiveness | brew install rtk; rtk init. Global hook into agent settings, restart. Zero code change. | Proxy: one env var. MCP: one install. Library: code changes at call sites. |
| Reversible? | Partial. Failed commands tee'd to disk; agent can read the path. | Yes. CCR caches the original under a hash; model calls headroom_retrieve to get it back (TTL ~1h). |
| Cache help | None specific | CacheAligner moves volatile tokens out of the stable prefix so prompt caching keeps hitting |
| Real savings | ~80% on a tool-heavy shell session (README estimate, ~118k→24k) | 60-95% on heavy tool-use, but median 4.8% across 50k+ real sessions |
| Trust surface | Local binary, no network at filter time | Proxy sees all plaintext traffic (requests + responses). Runs locally by default. |
| Agents supported | 15 (Claude Code, Codex, Cursor, Copilot, Gemini, Windsurf, Cline...) | Any OpenAI-compatible client via proxy; MCP for Claude Code/Cursor; framework wrappers |
Six-phase lifecycle per command: parse (Clap) → route → execute (capture stdout/stderr/exit) → filter (command-specific strategy) → print → track (SQLite).
git status/log: 90-99% off.rtk read: strip comments + bodies, keep signatures (8 languages).rtk gain shows actual savings from the SQLite history, not estimates.
A router detects content type per output (via Google's local Magika model), then routes to the matching compressor.
headroom_stats reports compression; the proxy logs per-session ratios.
Read/Grep/Glob never hit the hook, so the biggest context source is untouched unless you force shell or rtk read.Shell-heavy agent work, you want zero code change and pure determinism, and you are willing to nudge the agent toward shell commands or rtk read instead of native file tools.
You need to catch everything on the wire (file content, RAG, anything the agent sends), you want reversible compression, and your sessions are genuinely tool-output-heavy. Mind the proxy trust surface.
They are not mutually exclusive. rtk at the shell, headroom on the wire, is a reasonable stack. And measure first with a burndown so you know whether you even have a tool-output problem before you install either.