Token Efficiency: Where the Tokens Go

RTK: reducing token usage in LLM workflows

LLM-assisted development has a token problem. A git diff on a moderately sized PR dumps 10,000 tokens into context. A cargo test failure shows 200+ lines of boilerplate before the actual error. A grep across a codebase returns every match verbatim when you just need a count. The LLM reads all of it, and you pay for all of it.

RTK (Rust Token Killer) intercepts shell commands and rewrites their output before it reaches your LLM. The tool sits between your CLI tool and the agent, applies four compression strategies (smart filtering, grouping, truncation, deduplication), and returns the essential facts.

The impact is measurable. In a typical 30-minute Claude Code session, RTK reduced token consumption from 118,000 to 23,900 tokens across common dev operations. That is 80% savings.

How it works

RTK is a single Rust binary with no external dependencies. You run rtk init -g to hook it into your shell, and it transparently rewrites commands.

Without RTK:

$ git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
[... 15 lines of status ...]

Around 200 tokens.

With RTK:

$ git push
ok main

Around 10 tokens.

The hook works by rewriting each Bash command before it runs. git status becomes rtk git status, cargo test becomes rtk cargo test. The LLM agent sees the compact output, not the original.

What it filters

RTK handles 100+ commands across git, cargo, npm, Docker, AWS CLI, and test runners. For each command type, it applies specific compression rules.

Git: Strips progress lines, merge status, and formatting. git log -n 10 shows one-line commits with timestamps. git diff condenses to a skeleton: file paths and line counts, no hunks.

Test runners: Strips passing tests and boilerplate. Cargo test output goes from 150+ lines on failure down to 20, showing only the panic and the assertion. Jest and pytest follow the same pattern.

Cargo/npm: Build output gets grouped by error type, truncated to 50 lines total, with a pointer to the full log if needed.

AWS CLI: Queries like aws ec2 describe-instances return a compact table instead of full JSON. aws logs get-log-events emits only the message lines, timestamped.

File operations: ls becomes a tree structure. grep or rg returns only match counts and file names, not every match verbatim. cat on a large file returns the first N lines with a note about the total size.

The filtering is per-command-type. You can customize it via ~/.config/rtk/config.toml or per-project via custom_filters in the config.

Testing it out

I cloned the RTK repo and built it from source to see the compression in action.

A simple directory listing:

$ rtk ls .

Shows only directories and a count of files per directory, stripped of permission bits and owner info:

.worktrees/
briefs/
crew/
ilo/
[... more directories ...]
site-docs-refresh/

Around 150 tokens instead of 800 for the full ls -la output.

A git log:

$ rtk git log -n 5

Returns:

5a149a7 Merge pull request #2092 from rtk-ai/fix/cicd/mit-to-apache (16 hours ago)
e132896 fix(cicd): MIT to Apache 2.0 (16 hours ago)
39f044e fix(hook): collapse bash line continuations before matching (#1572) (22 hours ago)
3c356b3 fix: remove remaining noise and rework comments (23 hours ago)
6e76f91 fix(ls): preserve permission info as octal when -l/-la is passed (#1675) (23 hours ago)

A git status in a clean repo:

$ rtk git status
* develop...origin/develop
clean - nothing to commit

One line instead of 20.

How much do you save?

The README publishes a breakdown from a real 30-minute session:

OperationFrequencyStandardRTKSavings
ls / tree10x2,000400-80%
cat / read20x40,00012,000-70%
grep / rg8x16,0003,200-80%
git status10x3,000600-80%
git diff5x10,0002,500-75%
cargo test5x25,0002,500-90%

The difference compounds. At 80% savings per command, a tool that runs 50+ times in a session cuts context bloat by a factor of five. Your token budget stretches further.

Setup

RTK runs on macOS, Linux, and Windows (with WSL recommended). Install via Homebrew:

brew install rtk

Or cargo:

cargo install --git https://github.com/rtk-ai/rtk

Then initialize for your AI tool:

rtk init -g

This installs a hook into your shell config and creates an RTK.md file that documents the compression for your agent. Restart Claude Code (or your editor) and the hook is live.

To verify it is working:

rtk gain

Shows cumulative token savings. rtk gain --history shows per-command stats. rtk discover finds commands in your recent sessions that were not rewritten.

Where the tradeoff bites

RTK’s compression is aggressive and intentional. You lose context in exchange for token savings. If a test failure needs you to read full stack traces, RTK’s truncated version is not enough. The tool handles this via a “tee” feature: when a command fails, RTK saves the full uncompressed output to disk and tells you where to find it.

FAILED: 2/15 tests
[full output: ~/.local/share/rtk/tee/1707753600_cargo_test.log]

You can read the raw log without re-running the command.

The hook does not rewrite Claude Code’s built-in tools (Read, Grep, Glob), only Bash commands. If you want RTK compression on those, use explicit Bash commands instead: rtk read file.rs, rtk grep pattern ., rtk find "*.rs" ..

Why it matters

Token efficiency is not just about cost. It is about context depth. An agent with a shrinking context budget can ask fewer follow-up questions, run fewer diagnostic steps, and tends toward brute-force approaches. An agent with breathing room can chain operations, explore alternatives, and think before acting.

RTK buys back context with minimal overhead (under 10ms per command). The trade-off is straightforward: you lose noise in exchange for breathing room.