← 所有文章

如何用 5 个工具 + 自定义 Hooks 把 Claude Code Token 消耗砍掉 90%+

我们在实际开发过程中经常会发现Claude Pro套餐几个来回额度就见底,活还没干完;随手发一句 test,背后可能已经滚掉几百 token;一次代码检索直接冲到 400K token,会话二十分钟就烧完

我们在实际开发过程中经常会发现Claude Pro套餐几个来回额度就见底,活还没干完;随手发一句 test,背后可能已经滚掉几百 token;一次代码检索直接冲到 400K token,会话二十分钟就烧完。你以为是在写代码,实际上token都消耗在看不见的地方了。

所以省 token 不能只靠“少说两句”或者“换个便宜模型”。真正要做的是把整条链路拆开:代码检索先走 CBM,长输出先进 context-mode,Shell 原始结果先交给 RTK 压缩,再由 Headroom 做全量压缩,最后用 Caveman 限制 Claude 废话输出。

这套方案的核心很简单:不要指望模型自觉,要把省 token 变成默认执行。

处理路径

你的 Prompt
    │
    ▼
Layer 1: CBM(知识图谱查代码)         ← cbm-code-discovery-gate 封 Read/Grep
    │
    ▼
Layer 2: context-mode(大输出沙箱)    ← PreToolUse hook 导流到 ctx_batch_execute
    │
    ▼
Layer 3: RTK(Shell 输出原地压缩)     ← bash-ban-raw-tools 封 cat/grep
    │
    ▼
Layer 4: Headroom(出机器前全量压缩)  ← shell wrapper 拦截 claude 二进制
    │
    ▼
Layer 5: Caveman(Claude 自己少说话)  ← 插件自动激活,无需额外 hook
    │
    ▼
Anthropic API

图1

可以把它理解成五道闸门。每一层只处理自己那一段的消耗,不指望一个工具包解决所有问题。

图2

第一层:CBM + cbm-code-discovery-gate

工具:Codebase Memory MCP

仓库:github.com/DeusData/codebase-memory-mcp

图3

CBM 用 tree-sitter AST 把代码库解析成持久化知识图谱,支持 66 种语言。查函数定义、调用链、模块关系时,Claude 可以直接问图,而不是把几十个文件塞进上下文。

原文里的数字很夸张,但也说明问题:5 次结构查询,CBM 大约用了 3,400 token;逐文件 grep 大约 412,000 token。差距是 99.2%。

门禁:cbm-code-discovery-gate

这里靠两个 Hook 搭一个很小的状态机。

PreToolUse hook(cbm-code-discovery-gate)做三件事:

第一次看到 Grep / Glob / Read / Search,直接 exit 2 拦掉,并提示先用 CBM。

同时写一个 /tmp/cbm-code-discovery-gate-$PPID 标记,说明已经提醒过。

后续再遇到文件搜索,先看 /tmp/cbm-mcp-used-$PPID 是否存在。存在就放行;不存在但已经拦过一次,也放行,避免死循环。

PostToolUse hook(cbm-mcp-marker)负责补第二个标记。只要调用过 mcp__codebase-memory-mcp__*,就 touch /tmp/cbm-mcp-used-$PPID。

SessionStart hook(cbm-session-reminder)在 startup / resume / clear / compact 时重新注入 CBM 使用规则。长会话跑着跑着,Claude 很容易忘掉前面的约束,这一步就是给它补一遍记忆。

这层的重点很简单:只写“建议使用 CBM”没用。Claude 总会滑回 Read 和 Grep。要省 token,就得把捷径堵上。

图4

第二层:context-mode + PreToolUse 导流

工具:context-mode

仓库:github.com/mksglu/context-mode

图5

context-mode 处理大输出。它让命令在沙箱子进程里跑,完整输出留在本地并建 BM25 索引,进对话窗口的只有摘要。之后需要细节,再用搜索把相关片段捞出来。

原文给的效果是:同样 200K 上下文窗口,会话从大约 30 分钟延到 3 小时以上。

常用工具:

门禁:PreToolUse Hook 导流

安装分两步:

claude plugin marketplace add mksglu/context-mode
npm install -g context-mode

插件和 npm 包都要有。插件让 Claude Code 认识它,npm 包给 Hook 调 CLI。

Hook 挂在 PreToolUse、PostToolUse、PreCompact、SessionStart 上,统一调用:

context-mode hook claude-code

测试命令值得单独管。npm test、pytest、go test ./… 这类命令一跑就是几千行输出。可以加一个非阻塞 PreToolUse hook:不强拦,只提醒 Claude 改用 ctx_batch_execute。测试日志不应该直接灌进上下文。

第三层:RTK + bash-ban-raw-tools

工具:RTK(Rust Token Killer)

仓库:github.com/rtk-ai/rtk

图6

RTK 是一个 Rust 二进制文件,专门压 CLI 输出。它会删样板、合并重复内容、截断长输出、去重。开销小于 10ms,不联网。

它和 context-mode 的分工不一样:context-mode 管大输出,尤其是 20 行以上的测试和构建日志;RTK 负责中小型 shell 输出,比如 git status、npm install、短测试结果。

RTK 随 Headroom 捆绑安装,一般不用单独配。

门禁:bash-ban-raw-tools

这里要防的是 Bash 绕路。

Claude 可以不用 Read / Grep,直接跑:

cat file.py
grep "pattern" src/
命令 用途
/caveman:compress 把 CLAUDE.md 和 memory 文件永久压成 caveman 格式
/caveman:caveman-commit 压缩 commit message,标题不超过 50 字符
/caveman:caveman-review 压缩 review 意见,每行只写位置、问题、修法
/caveman-help 查看模式和命令

这样原始输出会绕过前面的压缩策略。bash-ban-raw-tools 就是专门堵这条路的 Bash PreToolUse hook。

它会拦:

cat、head、tail、find、grep、rg、wc 这类裸命令

没走 RTK wrapper 的命令

| head / | tail 这种看起来在截断、实际上已经把大量输出推到工具层的管道

也要留逃生门。真需要原始输出时,可以临时解锁:

touch /tmp/bash-raw-unlock-$PPID   # 当前会话放行
touch /tmp/bash-raw-unlock         # 全机放行
指标 原始状态 加工具 + Hook 后 怎么理解
会话时长(200K 窗口) ~30 分钟 3+ 小时 约 6 倍以上,不是 token 降幅
单次代码探索 token ~400K ~3.4K 约 99.2% 降幅,主要来自 CBM 替代逐文件读取
autocompact 触发时上下文占用 100% ~70%(很少撞顶) 说明窗口压力下降,但依赖任务类型
Shell 输出进入上下文的比例 100% 10-40% 剩余比例,不是总账单比例
API payload 100% 8-53% Headroom 报告的请求载荷压缩范围
Claude 回复冗长度 100% 25-50% Caveman 压的是回复风格,不是推理成本本身

两个标记 10 分钟后过期。

第四层:Headroom + shell wrapper

工具:Headroom

仓库:github.com/chopratejas/headroom

前面三层都在控制“什么进入上下文”。Headroom 管的是另一件事:请求离开本机、发给 Anthropic API 之前,把整个 prompt 再压一遍。

它压的不只是工具输出,还包括对话历史、系统提示、CLAUDE.md、规则文件等。很多 token 就藏在这些地方,普通工具碰不到。

它主要由四块组成:

门禁:shell wrapper

Headroom 的 install.sh 会在 shell 配置里注入一个 claude 函数。

bash / zsh:

headroom wrap claude -- "$@"

fish:

headroom wrap claude -- $argv

这里的 – 不能省。后面的 –resume、-p “query” 等参数要靠它正确穿透。

这个 wrapper 会启动本地代理、设置 ANTHROPIC_BASE_URL,再拉起 Claude。RTK 也内嵌在 Headroom 二进制里,安装 Headroom 后会自动注册为内部 CLI 代理。

组件 作用
CodeCompressor AST 感知代码压缩,支持 Python / JS / Go / Rust / Java / C++
SmartCrusher 压 JSON 数组和对象
Kompress-base HuggingFace ML 模型,用 agentic traces 训练
CacheAligner 稳定 prompt 前缀,提高 KV cache 命中率

第五层:Caveman + 插件自激活

工具:Caveman

仓库:github.com/JuliusBrussee/caveman

还有一种浪费经常被忽略:Claude 自己太啰嗦。

Caveman 把 Claude 的回复压成“寄存器模式”。客套话、铺垫、重复解释都砍掉,技术信息保留。

压缩前:

“Sure! I’d be happy to help you with that. The issue you’re experiencing is likely caused by a race condition in the authentication middleware where the token expiry check uses a strict less-than comparison instead of less-than-or-equal.”

压缩后:

“Bug in auth middleware. Token expiry check use < not <=. Fix:”

常用命令:

强度有三档:lite、full、ultra。默认是 full。

门禁:插件自激活

Caveman 不需要手写 Hook。装成 Claude Code 插件后,它会在 SessionStart 和 UserPromptSubmit 上自动注册。

"enabledPlugins": {
  "caveman@caveman": {},
  "context-mode@context-mode": {}
}
变量 值 含义
CLAUDE_AUTOCOMPACT_PCT_OVERRIDE 50 上下文窗口用到 50% 就触发压缩,别等默认 95% 才救火
CLAUDE_CODE_SUBAGENT_MODEL sonnet-4-6 子 agent 用 Sonnet 4.6,比 Opus 便宜
ENABLE_PROMPT_CACHING_1H 1 把提示缓存 TTL 从 5 分钟拉到 1 小时

装好就生效。它自己就是门禁。

Hook 事件 用途
flutter-ctx-redirect PreToolUse Bash Flutter / Dart 输出走 context-mode
memory-repo-symlink SessionStart 把 agent memory 限定到当前项目
sync-copilot-on-edit PostToolUse Edit 把 slash command 镜像到 VS Code Copilot
sync-runner-tools-on-edit PostToolUse Edit 编辑后重写 e2e runner 工具白名单,顺手绕过子 agent MCP 继承 bug #30280

完整 settings.json 怎么看

五层工具最后会落到同一份配置里。

环境变量

"env": {
  "CLAUDE_AUTOCOMPACT_PCT_OVERRIDE": "50",
  "CLAUDE_CODE_SUBAGENT_MODEL": "claude-sonnet-4-6",
  "ENABLE_PROMPT_CACHING_1H": "1"
}

模型与推理

"model": "claude-opus-4-7",
"effortLevel": "xhigh",
"advisorModel": "opus"
工具 用途
ctx_batch_execute 一次跑多条命令,索引全部输出,并支持多查询搜索
ctx_search 搜索当前会话已经索引的内容
ctx_execute / ctx_execute_file 在沙箱里跑代码,只把摘要送进上下文
ctx_fetch_and_index 抓 URL、建索引,返回约 3KB 预览
ctx_stats 查看本轮会话省了多少 token

effortLevel: xhigh 保留强推理;advisorModel: opus 让 advisor 走更强的模型。

插件

"enabledPlugins": {
  "caveman@caveman": {}
}

Hook 路由表

PreToolUse:

Bash → context-mode + bash-ban-raw-tools + flutter-ctx-redirect + rtk

Grep|Glob|Read|Search → cbm-code-discovery-gate

PostToolUse:

所有工具 → context-mode

MCP 调用 → cbm-mcp-marker

Edit|Write|MultiEdit → sync-copilot-on-edit + sync-runner-tools-on-edit

PreCompact:

context-mode

SessionStart:

context-mode + memory-repo-symlink + cbm-session-reminder

CLAUDE.md 该写什么

CLAUDE.md 只写 Claude 在会话里能看到、能执行的规则。Headroom 和 RTK 在会话外运行,Claude 不知道它们存在,写进去也没意义。

建议保留这些内容:

基本原则:DRY / KISS / YAGNI / SSOT。先读代码再动手。破坏性操作先问。

实现流程:索引 → Skill gate → 澄清 → CBM 探索 → 方案 → 是否委派 → Ripple → TDD → 验证 → Advisor。

Ripple 检查:增删改前用 trace_path 查调用点,不要相信“只在这里用到”。

工具速查:查定义用 search_graph,查调用链用 trace_path,跑代码用 ctx_execute,抓网页用 ctx_fetch_and_index。

封禁列表:不要用 cat / head / tail / grep / find 读文件。走 Read / Grep / Glob,并接受门禁控制。

子 agent 策略:研究、多文件重构、审计、多文件影响分析时委派;并行上限 3。

回复风格:先给答案,少铺垫,少总结。

按语言拆规则文件

~/.claude/rules/ 可以按技术栈拆文件,再通过 @ import 加载。一个文件只管一个栈,维护起来更轻。

每个规则文件的结构可以固定成两段:先加载对应 skill,再列容易踩的坑。

Flutter 示例:

加载 building-flutter-apps skill

notifier 里每个 await 之后都检查 if (!ref.mounted) return;

不写 _buildXxx(),拆成独立 Widget

React / Next 示例:

加载 vercel-react-best-practices skill

Server Components 默认,只有交互处写 “use client”

重计算用 useMemo

不用 enum,改用 as const 对象

其他好用的 Hook

最后的效果展示

数字因统计口径的不同仅供参考。

这套方案的核心是分层堵漏——CBM 管代码探索,context-mode 管大输出,RTK 压 shell,Headroom 在 API 层再压,Caveman 少废话输出。工具和门禁一起上才省 token。

参考内容

https://medium.com/@abdulgafoorabid/how-i-cut-claude-code-token-usage-by-90-with-4-tools-custom-hooks-and-enforcement-d3f8d2488cd6

https://github.com/sgaabdu4/claude-code-tips

https://github.com/DeusData/codebase-memory-mcp

https://github.com/mksglu/context-mode

https://github.com/rtk-ai/rtk

https://github.com/chopratejas/headroom

https://github.com/JuliusBrussee/caveman

https://github.com/getagentseal/codeburn

https://github.com/vercel-labs/agent-browser

https://docs.flutter.dev/tools/mcp

https://code.claude.com/docs/en/claude-code/slash-commands

https://github.com/anthropics/claude-code/issues/30280

原文发布于 X:https://x.com/vincemask/status/2060298054599934424

评论

加载评论…