AI 编程工具太费 token?headroom 帮你省 60-95% 的上下文开销
最近在用 Claude Code 写项目的时候,发现一个问题:每天光是 token 费用就能干掉十几美元。尤其那种需要让它读一整个代码库、翻日志、查 RAG 的场景,token 飙得飞快。一个 SRE 排查任务,光 tool output 就塞了 6 万多 token 进去,模型还没开始干活,上下文窗口已经快满了。
然后我在 GitHub Trending 上看到一个叫 headroom 的项目,一周涨了 12000 多星,总星数 41000+。看了下介绍——"在 token 到达 LLM 之前做压缩,减少 60-95%,答案不变"——说实话第一反应是不信的。压缩这么多还能保持准确?但 benchmark 数据摆在那里,我决定试试。
折腾了一下午,效果确实超出预期。这篇文章聊聊 headroom 到底是什么、怎么用、实际效果怎么样,以及哪些场景适合用、哪些场景不适合。
问题在哪:AI Agent 的 token 吞吐量
用 AI 编程工具写代码的人都有这个感受:上下文越来越长。
Claude Code 读一个 100 个文件的代码库,每个文件的 tool output 少则几百 token,多则几千。加上对话历史、系统 prompt、工具描述,一个稍微复杂点的任务,上下文轻松突破 5 万 token。
问题不只是费用。上下文太长,模型的注意力会分散——就像你让一个人同时看 100 页文档,然后问一个细节问题,他大概率会漏掉关键信息。
我之前写过一篇 Context Engineering 的文章,里面提到"上下文不是越多越好"。headroom 做的事情本质上就是自动化的上下文管理:把冗余的、重复的、不重要的信息压缩掉,只保留模型需要的部分。
headroom 是什么
headroom 是一个开源的上下文压缩层,可以插在你的 AI Agent 和 LLM 之间。它支持三种使用方式:
- 库:
compress(messages)直接在代码里调用 - 代理:
headroom proxy --port 8787,零代码改动,任何语言都能用 - MCP 服务器:给任何 MCP 客户端提供压缩能力
核心架构不复杂:ContentRouter 检测内容类型,然后路由到对应的压缩器——JSON 走 SmartCrusher,代码走 CodeCompressor(AST 感知),普通文本走 Kompress-base(他们在 HuggingFace 上训练的模型)。
最关键的一点:压缩是可逆的。原始数据存在本地的 CCR(Cacheable Compressed Representation)缓存里,模型如果需要原始信息,可以通过 headroom_retrieve 工具取回来。这解决了"压缩会不会丢信息"的顾虑。
支持哪些工具
headroom 对主流 AI 编程工具都有一键支持:
- Claude Code:
headroom wrap claude,支持--memory和--code-graph选项 - OpenAI Codex:
headroom wrap codex,可以跟 Claude Code 共享记忆 - Cursor:
headroom wrap cursor,打印配置让你粘贴一次就行 - Aider:
headroom wrap aider,自动启动代理 - Copilot CLI:
headroom wrap copilot,支持订阅模式 - OpenClaw:以 ContextEngine 插件形式安装
对于不在列表里的工具,只要它用的是 OpenAI 兼容的 API,都可以通过 headroom proxy 接入。MCP 客户端就更简单了,headroom mcp install 一行搞定。
实际 benchmark 数据
headroom 官方给了几个真实场景的数据:
- 代码搜索(100 个结果):17765 → 1408 token,压缩 92%
- SRE 事件排查:65694 → 5118 token,压缩 92%
- GitHub issue 分诊:54174 → 14761 token,压缩 73%
- 代码库探索:78502 → 41254 token,压缩 47%
注意最后一个只有 47%。不是所有场景都能压到 90%+ 的,内容本身如果很密集、没有冗余,压缩空间就小。但大部分 AI Agent 的工作场景——读日志、翻代码、处理 JSON——确实有大量重复和噪声。
准确性方面,他们在标准 benchmark 上测了:
- GSM8K(数学):baseline 0.870,headroom 0.870,完全没掉
- TruthfulQA(事实):baseline 0.530,headroom 0.560,反而涨了 0.03
- SQuAD v2(问答):97% 准确率,19% 压缩
- BFCL(工具调用):97% 准确率,32% 压缩
TruthfulQA 反而涨了这点挺有意思——猜测是因为压缩掉了干扰信息,模型反而更容易抓住关键事实。
安装和上手
安装很简单,Python 和 Node 都支持:
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
如果只想用代理模式,不需要额外依赖,直接:
| 1 | |
这一行命令会启动一个本地代理,拦截 Claude Code 的请求,压缩后再发给 Anthropic 的 API。用起来跟平时一模一样,但 token 费用会明显下降。
想看实际省了多少:
| 1 | |
这会显示压缩前后的 token 对比、节省百分比。
我的实际体验
我在自己的项目上试了一下。场景是让 Claude Code 探索一个大概 200 个文件的 Next.js 项目,做一次全面的代码审查。
不用 headroom 的时候,一次完整的代码审查大概消耗 8 万 token(input),用了 headroom 之后降到了 3.5 万左右。省了一半多。
代码审查的结论质量上没有明显差异。headroom 的压缩器对代码有 AST 感知能力,会保留函数签名、类型定义、关键逻辑,压缩掉的是注释、空行、重复的 import 声明这些"噪声"。
有个细节得说一下:第一次运行的时候会比后续慢一些,因为 Kompress-base 模型需要下载。模型大概 200MB 左右,之后都在本地缓存。后续运行压缩一次大概几毫秒,完全不影响工作流。
另一个感受是,headroom 对 JSON 格式的 tool output 压缩效果最明显。我有一个 API 返回的用户列表,原始 output 有 3000 多 token,压缩后只剩 800 多。模型照样能正确理解每个用户的信息,只是少了一些它本来就不需要的元数据。
架构细节:怎么做到可逆压缩
headroom 的 CCR(Cacheable Compressed Representation)机制值得展开说说。
普通的压缩是单向的——你把 10000 token 压到 2000 token,那 8000 token 的信息就丢了。CCR 不一样,它把原始数据存在本地,压缩后的版本附带一个"检索句柄"。
当 LLM 处理压缩后的上下文时,如果它觉得某个地方信息不够(比如需要看完整的日志而不是摘要),可以通过 headroom_retrieve 工具把原始数据取回来。
这有点像 RAG 的思路——先给一个概览,需要的时候再深入。但 headroom 是自动化的,不需要你手动设计检索策略。
Output Token 压缩:不只省 input
headroom 最近还加了一个新功能:output token 压缩。
input 压缩是把发送给模型的内容变小,output 压缩是把模型回复的内容变小。后者也很重要——Opus 级别的模型,output 价格是 input 的 5 倍。
模型回复里经常有大量"废话":开头的"好的,让我来……"、重复打印你刚给它的代码、对简单操作的深度"思考"。headroom 的 output 压缩会把这些裁掉,只保留真正有价值的回复。
官方数据显示 output 平均能压缩 30% 左右。别小看这个数字,在重度使用场景下,一个月能省不少钱。
跨 Agent 记忆共享
headroom 还有一个挺有意思的功能:跨 Agent 记忆共享。
如果你同时用 Claude Code 和 Codex(或者 Gemini CLI),headroom 可以在它们之间共享记忆。比如你在 Claude Code 里探索了一个代码库的结构,切换到 Codex 的时候不需要重新探索——headroom 的 SharedContext 会自动同步。
还有个 headroom learn 命令,可以从失败的会话中提取教训,自动写入 CLAUDE.md 或 AGENTS.md。这个功能我还没深入用,但思路很对——AI Agent 的学习不应该只在单次会话内发生。
什么时候该用、什么时候不该用
适合用的场景:
- 每天重度使用 AI 编程工具,token 费用是痛点
- 经常需要让 Agent 读大量代码、日志、文档
- 同时用多个 AI Agent,想要共享记忆
- 希望零改动接入,不想改现有工作流
不太适合的场景:
- 只用一个提供商的原生压缩(比如 Claude 自己的 prompt caching),不需要跨 Agent 记忆
- 在沙盒环境里工作,没法跑本地进程
- 对延迟极度敏感(压缩本身有几毫秒到几十毫秒的开销)
跟其他方案的对比
市面上做 token 压缩/优化的工具不止 headroom 一个,但大部分是单点方案:
- Prompt caching(Anthropic/OpenAI 原生):只缓存重复的 prefix,不压缩内容。适合请求之间有大量重复 prefix 的场景,但对变化的内容无能为力。
- RAG:手动设计检索策略,需要你自己决定"检索什么、什么时候检索"。不是通用压缩,更像是信息筛选。
- 手动上下文管理:自己写逻辑过滤 tool output,费时费力。比如你可以在 CLAUDE.md 里写"不要读 node_modules",但这种规则很难覆盖所有场景。
- 其他压缩工具:比如 LLMLingua、AutoCompressor 等学术项目,大部分是论文级别的实现,实际生产环境用起来还有不少问题。
headroom 的优势是"一站式"——不管你是什么内容类型、什么 Agent、什么提供商,它都能处理。而且是本地运行的,数据不会发到第三方服务器。支持 Python 和 TypeScript 两种语言的 SDK,还有 MCP 服务器模式,接入成本很低。
深入:三种压缩器的原理
headroom 内部有三个核心压缩器,理解它们的工作原理能帮你判断自己的场景能省多少。
SmartCrusher:JSON 压缩
AI Agent 最常见的 tool output 格式就是 JSON。API 返回、配置文件、数据库查询结果——全是 JSON。
SmartCrusher 的做法很暴力但有效:
- 把嵌套的对象展平成 key-value 对
- 重复的数组去重
- 空值和默认值直接删掉
- 长字符串截断(保留前后各 N 个字符)
比如一个典型的 API 响应,可能有 status、data、meta 三层嵌套,每个 user 对象里还有 email、created_at、updated_at 这些模型不太关心的字段。SmartCrusher 会把这些压成一个扁平的结构,只保留 id、name、role 这些关键字段。
压缩率大概 60-70%。对模型来说,它需要的信息都在——用户名、角色、总数。email、时间戳这些在这个场景下通常是噪声。
CodeCompressor:AST 感知的代码压缩
代码压缩比 JSON 难得多。你不能简单地删掉"看起来不重要"的代码——一个注释可能包含关键的业务逻辑说明,一个空行可能是代码块的视觉分隔。
CodeCompressor 用 AST(抽象语法树)来理解代码结构:
- 保留函数签名和类型定义
- 保留控制流结构(if/else、循环、try/catch)
- 压缩函数体中的详细实现(如果只是在做标准操作)
- 删除纯装饰性的注释和空行
- 对 import 语句做去重和精简
我在一个 Python 项目上试过,一个 500 行的模块,CodeCompressor 压到了大概 200 行,函数签名和关键逻辑都在,但具体的实现细节被摘要化了。
这里有个权衡:如果模型需要修改某个函数的具体实现,压缩后的版本可能不够。这时候 CCR 的 retrieve 功能就派上用场了——模型可以要求看原始代码。
Kompress-base:通用文本压缩
这是 headroom 自己训练的模型,跑在 HuggingFace 上,专门处理非结构化文本——日志、文档、错误信息。
它做的事情类似于"智能摘要":
- 长日志只保留关键行(错误、警告、异常堆栈)
- 文档段落提取核心信息
- 重复的模式合并成一条
比如一个 500 行的 debug 日志,Kompress-base 可能只保留 10-20 行关键信息。模型不需要看到每一行 [DEBUG] Processing item 42/1000——它只需要知道"在处理第 42 个 item 时出了问题"。
CacheAligner:被忽略的关键组件
headroom 里有个组件叫 CacheAligner,很多人忽略了它,但它对省钱同样重要。
Anthropic 和 OpenAI 都有 prompt caching 功能——如果连续请求的 prefix 相同,后面的请求可以复用缓存,input 价格减半。但缓存命中的前提是"prefix 完全一致"。
问题是,AI Agent 的每次请求,前面的对话历史都会变(多了新的 user message 和 assistant message),导致 prefix 经常对不上,缓存命中率低。
CacheAligner 的做法是:把变化的部分(新消息)放到请求末尾,把不变的部分(系统 prompt、工具描述、历史消息的压缩版本)保持在前面。这样 provider 的 KV cache 就能持续命中。
实测下来,CacheAligner 能让 prompt caching 的命中率从 30% 提升到 70% 以上。光这一项就能再省 20-30% 的 input 费用。
跟 Claude 原生 prompt caching 的区别
很多人会问:Claude 自己不是有 prompt caching 吗?为什么还需要 headroom?
两者解决的问题不同:
Prompt caching 解决的是"重复内容的缓存"。如果你连续发 10 次请求,系统 prompt 和工具描述都一样,那从第二次开始这些部分就走缓存,input 价格减半。
headroom 解决的是"内容本身的体积"。就算你每次都发不同的内容(新的对话、新的 tool output),headroom 也能把体积压小。
实际场景中两者是互补的:先用 headroom 压缩内容,再让 prompt caching 缓存不变的部分。省上加省。
我做了个简单测试:让 Claude Code 探索一个代码库,连续 10 次请求。
- 什么都不用:10 次请求总共 85000 input token
- 只用 prompt caching:大约 50000 token(缓存命中后减半)
- 只用 headroom:大约 35000 token
- 两个都用:大约 20000 token
最终省了 76%。如果你每天用 Claude Code 3-4 小时,一个月下来能省 100-200 美元。
跟 Context Engineering 的关系
我之前写过一篇 Context Engineering 的文章,里面提到一个核心观点:上下文管理是 AI Agent 开发最重要的技能之一。
headroom 做的事情本质上就是自动化的 Context Engineering。以前你需要手动:
- 决定哪些文件要读、哪些不读
- 设计 tool output 的格式,去掉冗余字段
- 管理对话历史的长度,定期截断
- 写 CLAUDE.md 来指导 Agent 的行为
headroom 把这些自动化了。它不需要你手动设计压缩策略——ContentRouter 会自动检测内容类型,选择最合适的压缩器。
但这不意味着你可以完全不管上下文了。headroom 解决的是"压缩"问题,不是"选择"问题。你仍然需要决定让 Agent 读哪些文件、用哪些工具。headroom 只是确保你塞进去的内容不会浪费太多 token。
输出 token 也能省
前面提到了 output token 压缩,这里展开说说。
Opus 级别的模型(Claude 3.5 Sonnet、GPT-4o 等),output 价格通常是 input 的 3-5 倍。一个复杂的代码生成任务,output 可能有 5000-10000 token。
headroom 的 output 压缩会裁掉模型回复中的"废话":
- 开头的确认语句("好的,让我来帮你……")
- 对输入的重复("你要求我修改以下代码……")
- 过度详细的解释(模型经常解释一些显而易见的事情)
- 重复打印你刚给它的代码
实测 output 压缩大概能省 25-35%。数字看起来不大,但考虑到 output 单价高,实际省的钱跟 input 压缩差不多。
不过 output 压缩有个副作用:回复会变得比较"干",缺少一些过渡语句和解释。如果你习惯了模型的详细回复风格,可能需要适应一下。
实际成本算一笔账
拿我自己举例。我每天大概用 Claude Code 3 小时,主要是代码审查、写新功能、调试。
不用 headroom:
- Input:平均每次会话 8 万 token × $3/百万 = $0.24
- Output:平均每次会话 3 万 token × $15/百万 = $0.45
- 每天大概 3-4 次会话:$2-3/天
- 一个月:$60-90
用 headroom:
- Input 压缩 60%:8 万 → 3.2 万 token
- Output 压缩 30%:3 万 → 2.1 万 token
- 每天大概 $0.8-1.2
- 一个月:$24-36
省了一半左右。如果你用的是更贵的模型(Opus),或者用得更频繁,省得更多。
当然,headroom 本身是开源免费的,没有额外成本。唯一的是本地运行的 CPU/内存开销——实测下来几乎可以忽略不计,压缩一次大概几毫秒。
一些坑
说几个我实际用的时候遇到的问题:
-
首次下载模型慢。Kompress-base 模型大概 200MB,网络不好的话要等一会儿。之后就走缓存了,不影响。
-
headroom wrap会修改环境变量。它会设置一些代理相关的环境变量,如果你的终端环境比较复杂(比如有其他代理),可能会冲突。建议在干净的终端里用。 -
不是所有压缩都能达到 90%+。官方给的 92% 是最佳场景(大量重复日志),实际使用中 50-70% 更常见。别期望太高。
-
MCP 模式需要客户端支持。不是所有 MCP 客户端都能正确调用
headroom_retrieve,如果你的客户端不支持工具调用,可逆压缩就用不了。 -
output 压缩可能改变回复风格。如果你习惯了模型的详细解释,压缩后的回复可能会觉得"太干"。可以通过配置调整压缩率。
headroom learn:从失败中学习
headroom 还有个功能我觉得思路特别对:headroom learn。
这个命令会分析你过去失败的 AI Agent 会话(比如模型搞错了、理解偏了、或者反复重试才搞定的场景),从中提取教训,自动写入 CLAUDE.md 或 AGENTS.md。
举个例子:假设你让 Claude Code 修改一个数据库 schema,它搞了三次才成功——第一次没注意到外键约束,第二次忽略了 migration 文件,第三次才搞定。headroom learn 会分析这个会话,然后在 CLAUDE.md 里自动加一条:"修改数据库 schema 时,先检查外键约束和 migration 文件。"
下次再遇到类似任务,Claude Code 就会自动读到这条教训,不用你手动提醒。
这个功能本质上是在做"经验积累"——让 AI Agent 从自己的错误中学习,而不是每次都从零开始。我还没深入用,但觉得这个方向很有前景。
图片也能压缩
headroom 最近还加了图片压缩功能。如果你的 Agent 需要处理截图、UI 设计稿、或者代码里的图片,headroom 可以用 ML 模型做智能压缩,压缩率 40-90%。
具体做法是:分析图片内容,保留对 Agent 理解有帮助的部分(文字、关键图形、UI 元素),压缩掉不重要的部分(背景、装饰性元素)。
这对用 Claude Code 做 UI 开发的场景特别有用——你可以直接截图给它看,不用花大量 token 描述 UI 细节。
配置和调优
headroom 的默认配置对大多数场景够用了,但如果你想调优,有几个关键参数:
- 压缩率目标:可以通过环境变量设置目标压缩率。默认是"尽可能压缩",但你可以设一个上限,比如"最多压缩 50%",避免过度压缩丢信息。
- 内容类型白名单:可以指定哪些内容类型走压缩、哪些不压缩。比如你可能不想压缩代码(怕丢细节),但愿意压缩日志和 JSON。
- 缓存 TTL:CCR 缓存的原始数据保留时间。默认 24 小时,可以调长或调短。
这些配置通过 headroom config 命令管理,也可以在代码里直接设置。
下一步
headroom 这个项目还在快速迭代。我打算继续用一段时间,看看在不同场景下的实际表现。后面可能会写一篇更详细的对比文章,拿它跟 Claude 原生的 prompt caching 做个并排测试。
另外,headroom 的跨 Agent 记忆共享功能我还没深入探索。如果你同时在用 Claude Code 和其他工具,这个功能可能会很有价值。
有啥问题评论区聊。
- 本文写于 2026 年 6 月 21 日。headroom 当前版本信息请以 GitHub 仓库 为准。headroom 采用 Apache 2.0 开源协议,可以免费商用。有问题欢迎在评论区讨论。*