Token Saving · Part 3 companion

rtk vs headroom

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.

rtk Rust · 62k★ · Apache-2.0 headroom Python · 28k★ · Apache-2.0 both deterministic, no LLM-based compression

The one-line each

rtk

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.

headroom

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.

Where each one sits

rtk — shell layer agent --git status--> rtk --> shell --> git (filter stdout/stderr, ~5-15ms, no network) headroom — wire layer agent --> headroom (proxy / mcp / lib) --> model API (compress messages before they reach the model)

Feature map

Dimensionrtkheadroom
LayerShell. Between Bash tool and the command.Wire. Between agent and model API.
LanguageRust, single binary, zero runtime depsPython 3.10+ (Rust core via Maturin), also TS/npm
Compression12 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 readsNo 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 chunksNoYes, that is a core use case
Install / intrusivenessbrew 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 helpNone specificCacheAligner 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 surfaceLocal binary, no network at filter timeProxy sees all plaintext traffic (requests + responses). Runs locally by default.
Agents supported15 (Claude Code, Codex, Cursor, Copilot, Gemini, Windsurf, Cline...)Any OpenAI-compatible client via proxy; MCP for Claude Code/Cursor; framework wrappers

How each works

rtk · deterministic shell filters

Six-phase lifecycle per command: parse (Clap) → route → execute (capture stdout/stderr/exit) → filter (command-specific strategy) → print → track (SQLite).

  • Stats extraction for git status/log: 90-99% off.
  • Failure focus for test runners: a state machine keeps only failures, 94-99% off.
  • Code filtering for rtk read: strip comments + bodies, keep signatures (8 languages).
  • Tree / dedup / schema for ls, logs, JSON.

rtk gain shows actual savings from the SQLite history, not estimates.

headroom · content-aware compressors

A router detects content type per output (via Google's local Magika model), then routes to the matching compressor.

  • SmartCrusher samples JSON arrays statistically, keeps errors/anomalies unconditionally.
  • LogCompressor dedups and normalises timestamps, preserves stack traces.
  • CodeCompressor is AST-aware but gated off by default to protect correctness.
  • CCR caches originals so nothing is truly lost.

headroom_stats reports compression; the proxy logs per-session ratios.

The cons, honestly

rtk · watch out for
  • Native file reads bypass it. Claude Code Read/Grep/Glob never hit the hook, so the biggest context source is untouched unless you force shell or rtk read.
  • Silent passthrough. If the hook errors, the raw command runs and nothing warns you. You can think you are saving when you are not.
  • Native Windows has no hook (WSL only). Pipes and heredocs have edge cases.
headroom · watch out for
  • Median gain is modest. 4.8% across all traffic. The 60-95% is heavy tool-use only.
  • Proxy is a trust surface. It sees all plaintext, including secrets in prompts and tool output.
  • Lossy by design. Code and RAG mostly pass through (intentional), so the wins are concentrated in JSON/logs/search. "Same answers" is author-run small-N benchmarks, no third-party eval.
  • Beta (v0.25), Rust build step, retrieval TTL ~1h.

When to reach for which

reach for rtk

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.

reach for headroom

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.