RTK — Rust Token Killer 深度解析:AI 编程时代的 CLI 输出压缩框架
当 AI 编程助手(Claude Code、Copilot、Cursor 等)执行一条 git status 时,它需要消耗 token 来处理命令的原始输出。git status 输出的行数从几行到几十行不等,而 LLM 按 token 收费。
RTK(Rust Token Killer) 是一个高性能 CLI 代理,通过对命令输出进行智能过滤和压缩,实现 60-90% 的 token 节省。一个 30 分钟的 Claude Code 编程会话,原本需要消耗约 118,000 tokens,使用 RTK 后只需约 23,900 tokens,节省 80%。
项目地址:https://github.com/rtk-ai/rtk 官网:https://www.rtk-ai.app
1. 核心问题:LLM 编程助手正在浪费大量 token
Section titled “1. 核心问题:LLM 编程助手正在浪费大量 token”AI 编程助手处理 CLI 命令输出时,面临几个低效问题:
- 大量噪音:ANSI 颜色序列、进度条、空行、重复的日志行
- 冗余信息:测试通过的信息占 80-90%,只需要知道哪些失败了
- 格式浪费:详尽的 diff、完整的环境变量列表不需要完整传给 LLM
- 上下文浪费:上下文窗口被无用的命令输出填满,有价值的信息被截断
RTK 的核心思路是:不是减少 LLM 的处理量,而是改变命令输出的形态,让同样的信息用更少的 token 表示。
2. 系统架构:命令代理模式
Section titled “2. 系统架构:命令代理模式”RTK 采用命令代理(Command Proxy)架构,工作原理非常清晰:
LLM Agent RTK 原始命令 输出───────────────────────────────────────────────────────────────git status ──▶ rtk git status ──▶ git status ──▶ 原始输出 │ │ └─── 过滤压缩 ──▶ ~200 tokens ──▶ LLM六大执行阶段
Section titled “六大执行阶段”Phase 1: PARSE Clap 解析器提取命令和参数 │ ▼Phase 2: ROUTE main.rs match 路由到专门 filter 模块 │ ▼Phase 3: EXECUTE std::process::Command 执行原始命令 │ ▼Phase 4: FILTER 专用模块过滤(正则、JSON、状态机) │ ▼Phase 5: PRINT 着色输出到终端 │ ▼Phase 6: TRACK SQLite 记录 token 节省量关键设计原则:
- 单线程、无 async:启动时间 < 10ms,无运行时开销
- 优雅降级:过滤失败时回退到原始输出,不影响命令执行
- 退出码传播:RTK 永远不吞掉非零退出码,保证 CI/CD 可靠性
- 透明代理:未知命令透传,零配置即可工作
3. 模块组织:42 个命令过滤器
Section titled “3. 模块组织:42 个命令过滤器”RTK 的源码按生态系统组织:
src/cmds/├── git/ # git status/log/diff/add/commit/push/branch├── rust/ # cargo test/build/clippy├── js/ # pnpm/npm/npx, vitest/jest/playwright, tsc/eslint/prettier, prisma├── python/ # ruff, pytest, pip├── go/ # go test/build/vet, golangci-lint├── dotnet/ # dotnet build/test├── cloud/ # aws, docker, kubectl├── system/ # ls, read, grep, find, json├── ruby/ # rake, rspec, rubocop└── mod.rs # 入口核心基础设施(src/core/):
tracking.rs— SQLite token 追踪filter.rs— 代码过滤(aggressive/minimal/none)tee.rs— 命令失败时的完整输出保存config.rs— TOML 配置系统
4. 12 种过滤策略
Section titled “4. 12 种过滤策略”这是 RTK 最核心的部分。根据不同命令的输出特征,RTK 使用了 12 种不同的过滤策略:
策略 1:统计信息提取(Stats Extraction)
Section titled “策略 1:统计信息提取(Stats Extraction)”原始: git log --oneline -5 abc123 Fix authentication bug def456 Add user profile page ... 5 files changed, 142 insertions(+), 89 deletions(-)
过滤后: 5 commits, +142/-89 ✓节省: 90-99%策略 2:仅错误模式(Error Only)
Section titled “策略 2:仅错误模式(Error Only)”原始: stdout + stderr 混合输出过滤后: 仅 stderr 中的错误信息节省: 60-80%策略 3:按规则分组(Grouping by Pattern)
Section titled “策略 3:按规则分组(Grouping by Pattern)”原始: 100 个 lint 错误散落在各文件 error: no-unused-vars (×15, files: a.ts, b.ts, c.ts...) error: semi: missing semicolon (×23, files: x.ts, y.ts...)过滤后: no-unused-vars: 15 semi: 23 prefer-const: 8节省: 80-90%策略 4:去重(Deduplication)
Section titled “策略 4:去重(Deduplication)”原始: [ERROR] 相同的日志行重复 50 次过滤后: [ERROR] Connection timeout (×50)节省: 70-85%策略 5:仅结构(Structure Only)
Section titled “策略 5:仅结构(Structure Only)”原始: {"user": {"id": 123, "name": "Alice", "token": "sk-xxx..."}}过滤后: {"user": {"id": "...", "name": "...", "token": "..."}}节省: 80-95%策略 6:代码过滤(Code Filtering)
Section titled “策略 6:代码过滤(Code Filtering)”FilterLevel::None → 保留全部(0% 节省)FilterLevel::Minimal → 去除注释(20-40% 节省)FilterLevel::Aggressive → 去除注释 + 函数体(60-90% 节省)支持语言: Rust, Python, JS, TS, Go, C, C++, Java策略 7:仅失败(Failure Focus)
Section titled “策略 7:仅失败(Failure Focus)”原始: 运行 100 个测试,95 通过,5 失败过滤后: FAILED: 5 tests test_auth_login: assertion failed at auth.rs:42 test_payment_refund: panic at payment.rs:18节省: 94-99%策略 8:树压缩(Tree Compression)
Section titled “策略 8:树压缩(Tree Compression)”原始: 50 个文件平铺列表过滤后: my-project/ ├─ src/ (8 files) ├─ tests/ (5 files) └─ Cargo.toml节省: 50-70%策略 9:进度条过滤(Progress Filtering)
Section titled “策略 9:进度条过滤(Progress Filtering)”原始: 下载进度条 ANSI 彩色动画过滤后: ✓ Downloaded package.json节省: 85-95%策略 10:JSON/Text 双模式(JSON/TEXT Dual Mode)
Section titled “策略 10:JSON/Text 双模式(JSON/TEXT Dual Mode)”当工具有 JSON 输出可用时(ruff check --format=json): → 解析结构化数据,精确提取错误位置和规则当仅文本输出时: → 正则回退解析节省: 80%+策略 11:状态机解析(State Machine Parsing)
Section titled “策略 11:状态机解析(State Machine Parsing)”pytest 输出格式是文本状态机: test_utils.py::test_parse ... ok test_utils.py::test_format ... FAILED ================ 1 failed, 17 passed ================RTK 跟踪 IDLE → TEST_START → PASSED/FAILED → SUMMARY 状态仅提取关键信息节省: 90%+策略 12:NDJSON 流式解析
Section titled “策略 12:NDJSON 流式解析”go test 输出是 NDJSON 流(每行一个 JSON): {"Action":"run","Package":"pkg1","Test":"TestAuth"} {"Action":"fail","Package":"pkg1","Test":"TestAuth"}逐行解析,聚合结果: 2 packages, 3 failures (pkg1::TestAuth, pkg1::TestPayment)节省: 90%+5. Hook 系统:透明自动改写
Section titled “5. Hook 系统:透明自动改写”RTK 最强大的特性是自动改写钩子(Auto-Rewrite Hook)。
当 LLM 代理要执行 git status 时,Hook 拦截并改写为 rtk git status,整个过程对 LLM 透明。
rtk init -g # Claude Code(推荐)rtk init -g --agent cursor # Cursorrtk init -g --gemini # Gemini CLIrtk init -g --codex # OpenAI Codex工作原理(Claude Code 为例)
Section titled “工作原理(Claude Code 为例)”1. LLM Agent 准备执行: git status │2. settings.json 中注册的 PreToolUse Hook 被触发 │3. Hook 调用: rtk rewrite "git status" │4. rtk rewrite 查询命令注册表,返回: rtk git status │5. Hook 修改 Agent 的执行命令为: rtk git status │6. Agent 执行: rtk git status ──▶ 原始 git status │ └─── 过滤压缩 ──▶ ~200 tokens命令重写管线(Rewrite Pipeline)
Section titled “命令重写管线(Rewrite Pipeline)”复合命令的处理非常精妙。以 cargo fmt --all && cargo test 2>&1 | tail -20 为例:
Step 1: 词法分析(Lexer) cargo fmt --all && cargo test 2>&1 | tail -20 ───────────────────────────────────────────── Tokenize → [cargo][fmt][--all][&&][cargo][test][2>&1][|][tail][-20]
Step 2: 按操作符分割,独立改写 cargo fmt --all && cargo test 2>&1 | tail -20 ├─ rtk cargo fmt ─┤ ├─ rtk cargo test ──┤ ├─ 保持原样 ─┤ rewrite rewrite 不 rewrite
Step 3: 重新组装 rtk cargo fmt --all && rtk cargo test 2>&1 | tail -20关键设计:
&&和;两边都改写|管道只改写左边,右边保持原样(管道右侧通常是 head/wc 等消费端)find/fd在管道前永远不改写(输出格式与 xargs 不兼容)- 改写失败的片段保持原样,不会因为一个失败拖累整个命令
支持的 AI 编程工具(13 种)
Section titled “支持的 AI 编程工具(13 种)”| 工具 | 安装方式 | 方法 |
|---|---|---|
| Claude Code | rtk init -g | PreToolUse Hook |
| GitHub Copilot (VS Code) | rtk init -g --copilot | PreToolUse Hook |
| Cursor | rtk init -g --agent cursor | preToolUse Hook |
| Gemini CLI | rtk init -g --gemini | BeforeTool Hook |
| Windsurf | rtk init --agent windsurf | .windsurfrules |
| Cline / Roo Code | rtk init --agent cline | .clinerules |
| OpenCode | rtk init -g --opencode | TS Plugin |
| OpenClaw | openclaw plugins install | Plugin TS |
| Hermes | rtk init --agent hermes | Python Plugin 适配器 |
| Codex CLI | rtk init -g --codex | AGENTS.md |
| Kilo Code | rtk init --agent kilocode | .kilocode/rules |
| Google Antigravity | rtk init --agent antigravity | .agents/rules |
| Mistral Vibe | 计划中 | 等待上游支持 |
6. Token 节省实测
Section titled “6. Token 节省实测”以一个 30 分钟的 Claude Code 编程会话为例:
| 操作 | 频率 | 原始 tokens | RTK tokens | 节省 |
|---|---|---|---|---|
ls / tree | 10x | 2,000 | 400 | -80% |
cat / read | 20x | 40,000 | 12,000 | -70% |
grep / rg | 8x | 16,000 | 3,200 | -80% |
git status | 10x | 3,000 | 600 | -80% |
git diff | 5x | 10,000 | 2,500 | -75% |
git log | 5x | 2,500 | 500 | -80% |
git add/commit/push | 8x | 1,600 | 120 | -92% |
cargo test / npm test | 5x | 25,000 | 2,500 | -90% |
ruff check | 3x | 3,000 | 600 | -80% |
pytest | 4x | 8,000 | 800 | -90% |
go test | 3x | 6,000 | 600 | -90% |
docker ps | 3x | 900 | 180 | -80% |
| 合计 | ~118,000 | ~23,900 | -80% |
7. TEE 恢复机制
Section titled “7. TEE 恢复机制”当命令执行失败(非零退出码)时,RTK 有一个贴心的TEE 恢复机制:
# cargo test 有 2 个测试失败FAILED: 2/15 tests[full output: ~/.local/share/rtk/tee/1707753600_cargo_test.log]RTK 将完整的原始输出保存到文件,并在输出末尾附上文件路径。LLM 可以直接读取该文件来分析错误,而不需要重新执行命令(避免副作用)。
8. 隐私与遥测
Section titled “8. 隐私与遥测”RTK 提供可选的匿名遥测(默认关闭),收集的内容完全匿名:
- RTK 版本、操作系统、架构、安装方式
- 命令计数、节省 token 量(24h/30d/总)
- 解析失败次数、节省率 < 30% 的命令(用于发现需改进的过滤器)
- 生态系统分布(git 45%, cargo 20%, js 15%…)
不收集:源代码、文件路径、命令参数、密钥、个人信息。
9. 架构亮点分析
Section titled “9. 架构亮点分析”为什么是 Rust?
Section titled “为什么是 Rust?”RTK 选择 Rust 有几个关键原因:
- 启动速度 < 10ms:Rust 无 GC,单线程二进制启动极快,不给 CLI 增加感知延迟
- 内存 < 5MB:lazy_static 延迟编译正则,全局借用,无多余分配
- 二进制体积 < 5MB:strip 后 ~5MB,单文件分发,无需运行时
- 错误处理:anyhow::Result + .context() 模式,filter 失败永远回退原输出
TOML DSL:扩展性设计
Section titled “TOML DSL:扩展性设计”除了内置的 42 个 Rust 过滤器,RTK 还支持 TOML DSL 声明式过滤器:
[filters.my-project-lint]command = "npm run lint"strip = ["^\\s*$", "^✨.*$"]truncate = 50on_empty = "No lint errors"可以放在:
- 内置(编译进二进制)
- 全局:
~/.config/rtk/filters/ - 项目级:
.rtk/filters/(需要 trust 验证)
为什么不 Hook 内置工具?
Section titled “为什么不 Hook 内置工具?”Claude Code 的 Read、Grep、Glob 是内置工具,不经过 Bash Shell,所以 Hook 无法拦截。RTK 的文档建议:对这类操作使用 shell 命令(cat/head/tail、rg、find)或直接调用 rtk read、rtk grep、rtk find。
10. 总结
Section titled “10. 总结”RTK 是一个设计精良的 CLI 输出压缩框架,核心贡献在于:
- 系统性思维:不是做一个
git status的过滤器,而是构建了一个完整的代理架构和过滤器框架 - 12 种过滤策略:针对不同输出类型(JSON、文本状态机、NDJSON、日志去重等)设计专门的解析器
- 透明自动化:Hook 系统让 LLM 零感知地获得压缩后的输出
- Rust 实现:极低的运行时开销,让压缩本身不成为瓶颈
- 可扩展:TOML DSL + 完整的贡献指南,降低了新过滤器开发的门槛
对于频繁使用 AI 编程助手的开发者,RTK 几乎是一个必装工具——它不仅节省 token 成本,更重要的是扩大了 LLM 上下文窗口的有效利用范围,让同样的上下文能处理更长的项目历史和更大的代码库。
参考链接: