rtk bills itself with a straight punchline: "Rust Token Killer." It is a CLI proxy that sits between an AI coding agent and your shell, intercepts every command the agent runs, compresses the output, and hands the model a filtered version instead of the raw firehose. It shipped as a single Rust binary with no runtime dependencies, and it has been climbing GitHub's Rust trending page this week. As of writing it sits at around 80k stars on GitHub.
The pitch is hard to ignore if you run Claude Code, Cursor, Gemini CLI, or any terminal-based agent for a few hours a day. A long git status comes back to the model as a compact tree. A failing cargo test collapses to the failed cases and a count. The README claims cuts of up to 90% of the bash output the agent reads, with support for over a hundred commands.
What is harder to find in the marketing is the part of the docs that explains what that 90% actually means. It is worth reading before you wire this into everything.
What rtk does
RTK does not replace your commands. It rewrites them. Installing it for Claude Code, for example, registers a PreToolUse hook: when the agent is about to run git status, the hook transparently rewrites it to rtk git status before it reaches the shell. The agent never sees the rewrite, but it gets the compressed output back. The README's happy path is rtk init -g, which installs the hook and an RTK.md, then a restart.
It supports 17 AI tools, each wired slightly differently. Some use hooks (Claude Code, Copilot, Cursor, Gemini CLI), some use rules or instruction files (Codex via AGENTS.md, Windsurf via .windsurfrules), and plugin-based agents like OpenCode and Hermes use their plugin APIs. Since it acts as a proxy in front of a normal shell, the filters themselves are just Rust subcommands: rtk git status, rtk ls, rtk cargo test. The auto-rewrite hook is what removes the need to type rtk yourself.
The compression comes from four strategies applied per command type: smart filtering (dropping noise like comments and progress bars), grouping (files by directory, errors by type), truncation (keeping context, cutting redundancy), and deduplication (collapsing repeated log lines into counts). Some results are striking. A failing cargo test that would print hundreds of lines comes back as something like FAILED: 2/15 tests plus the two failing cases. A git push that normally prints the whole "Enumerating objects" sequence collapses to ok main.
There is a real constraint buried in the README: the hook only fires on Bash tool calls. Claude Code's built-in Read, Grep, and Glob tools bypass it, so their output is not filtered unless you use the shell forms or call rtk read / rtk grep / rtk find directly.
The part everyone skips: what "90% savings" does not mean
This is the section I think most posts about rtk gloss over, and it is the reason to trust the project's honesty.
RTK measures bash output bytes, not your bill. The README is explicit: a 90% cut in bash output is not a 90% cut in cost. The savings chain dilutes at every step. Bash output is one contributor to input tokens, alongside your prompt, the system prompt, and conversation history. Input tokens are themselves only part of the bill, which also counts the output tokens the model writes. So a big reduction in command output produces a smaller reduction in input tokens, and a smaller one again in actual dollars.
The detailed savings-explained doc works through this. The only thing RTK changes is the bytes a shell command sends back; everything it reports as "savings" is measured on those bytes. It never touches what the model writes, and it has no visibility into your prompt or system prompt. Commands with no matching filter pass through untouched and count as 0% savings.
There is one more honest caveat: RTK ships no tokenizer. The rtk gain dashboard estimates tokens as bytes / 4, using the same estimator on both raw and filtered output. Here is the actual helper it uses:
// src/core/tracking.rs
pub fn estimate_tokens(text: &str) -> usize {
// ~4 chars per token on average
(text.len() as f64 / 4.0).ceil() as usize
}// src/core/tracking.rs
pub fn estimate_tokens(text: &str) -> usize {
// ~4 chars per token on average
(text.len() as f64 / 4.0).ceil() as usize
}Because the same estimator is applied before and after, the percentage is reliable: it is a byte ratio, and ratios hold regardless of the estimator's accuracy. The absolute token counts are approximate and will not match your provider's invoice. The docs say to treat Input tokens: 45,230 as an order of magnitude, not a bill line.
Should you use it?
The value proposition is real for agents that burn most of a session running shell commands. Cutting four out of five lines of git and test output means longer effective context and cheaper sessions, and it does not require changing how you work once the hook is in place. The project also answers the obvious questions: it is Apache-2.0, telemetry is off by default and needs explicit consent, and it keeps full output on failure so the model can recall it with rtk recall instead of re-running the command.
The honest framing matters more than any single number. A tool that claims 90% savings and then carefully explains the gap between output reduction and bill reduction is a tool that expects you to read the docs. That is a good sign, and it is the right way to evaluate it: expect a large cut in the noisy part of your context, a smaller cut in your token spend, and judge whichever is worth more to you.
Install it with brew install rtk or winget install rtk-ai.rtk, or grab a prebuilt binary from the releases page. Try rtk init -g, run git status, and see what the model actually reads.