/ DeepSeek Harness 效率分享 2026-06
DeepSeek Harness · AI 编码效率

少烧 Token,多干活

同一个任务,糟糕的用法可能比熟练用法多消耗 5–10 倍 token。这份分享拆解 token 都花在哪、有哪些立竿见影的优化技巧,以及如何量化定位自己的浪费点。

0Token 到底花在哪

很多人以为「token 消耗 = 我打的字 + AI 回复的字」。实际上在 agent 类工具里,真正烧 token 的是上下文(context)每一轮都要重新发送

关键认知:对话是「无状态」的 模型不会「记得」上一轮。它每次都是从零开始读一遍完整对话——所以每问一句,整个历史(系统提示 + 全部历史消息 + 读过的文件 + 工具返回结果)都会作为输入 token 重新发一遍。你以为是在「接着聊」,其实是把整本聊天记录又递了一次。

下图:每一轮你只敲了几个字(绿色),但真正发出去的是整段历史的累积重发橙色越来越长)。这就是为什么长会话越聊越贵——成本几乎随轮数平方增长

第 1 轮
~2k tok
第 2 轮
~6k tok
第 5 轮
~25k tok
第 20 轮
~90k tok
第 50 轮
~250k tok← 你只敲了 1 个字
系统提示 + 工具定义(每轮固定) 累积历史(文件 / 工具输出 / 旧消息,每轮重发) 你本轮真正打的字
~70%
典型会话中,文件内容 + 工具输出占输入 token 的大头
长会话成本近似随轮数平方增长(历史不断累积重发)
≤10%
真正由你输入的文字,往往只占很小比例

四大消耗源

消耗源说明是否可优化
系统提示 + 工具定义每轮固定开销,含工具 schema、CLAUDE.md / AGENTS.md可缓存(cache)
读取的文件内容读大文件、整目录、重复读同一文件✅ 重点优化
工具返回结果巨量 grep 命中、整个 npm install 日志、大 JSON✅ 重点优化
累积的对话历史跑题、反复试错、长会话不清理✅ 重点优化
全篇三条轴四大消耗源全在输入侧,所以省 token 主线是省输入:① 砍输入量(第 1–2 节:控上下文、省工具调用)+ 让重发的输入走缓存(第 3 节)。此外还有两条独立的轴:② 少试几轮(第 4 节,对应上面的 N² 增长)、③ 压缩输出(第 6 节)。CodeGraph(第 5 节)则是①里「探索开销」这个子问题的专用工具。

1控制上下文窗口

这是省 token 收益最大的一类技巧,核心是「只让模型看到它真正需要的东西」

1.1 任务做完就清空:/clear

换一个不相关的任务时,立刻 /clear(或直接开一个新会话)。否则前一个任务读过的所有文件、跑过的所有命令,会在新任务里继续被当作输入反复发送。

✗ 浪费

修完 bug A,不清理,接着在同一会话里改 feature B、写文档 C…… 到第 3 个任务时,前两个任务的几十个文件还在每轮重发。

✓ 省 token

每个独立任务 /clear 一次。会话保持「短而专注」,输入 token 始终维持在低位。

1.2 主动压缩:/compact

当一个任务确实很长、又必须延续上下文时,用 /compact 把历史总结成摘要,丢掉冗长的中间过程(大段文件内容、试错记录),只保留结论。比放任它自动压缩更可控。

技巧/compact 只保留最终方案和改动的文件列表 —— 可以给 compact 附带指令,告诉它该留什么。

1.3 精准读文件:先定位,后精读

读文件是会话里最容易失控的 token 大头。原则就一句:先用搜索把范围缩到具体函数,再只读真正需要的那几十行,别让整文件、整目录无差别地灌进上下文。

✗ 浪费

「帮我看看这个项目」这种没边界的需求,逼它做地毯式探索、Read 一大批文件;或你直接 @ 一个几千行的大文件 / @目录,把整份内容一次灌进来 —— 几千行的文件,一次就两三万 token 起步。

✓ 省 token

给它一个明确目标,比如「只看 login.ts 里的 parseUser() 函数」。剩下交给它:会自己先 grep 定位、再用 Read 区间(offset/limit)精读那几十行 —— 不用你手动敲命令
补充而且就算它真去读整文件,单次 Read最多 2000 行(超出要 offset 续读),不会无限吞。所以真正要你把关的,是别用 @ 亲手把大文件 / 整目录塞进去 —— 正是下面要讲的。

关键认知:@文件 会把「整份内容」直接注入

DeepSeek Harness 支持在输入里用 @ 引用文件(输入 @ 自动补全路径),例如 @src/auth/login.ts。但要分清它到底干了什么

@ 省的是「搜索成本」

你知道代码在哪,直接 @ 指给它 —— AI 不用满仓库 grep 翻找,省下十几次工具调用和大段命中输出。

@ 不帮你「省内容」

@文件 会在你发消息那一刻,就把整个文件内容原样塞进上下文(不是让 AI 自己挑着读)。文件多大,就吞多少 token。
所以按文件大小分情况用
  • 小文件 / 配置文件 → 放心 @,整份也就几百 token,准确又省事。
  • 几千行的大文件 → 别整份 @,直接点名「parseUser() 函数」,剩下交给它定位精读。
  • @目录 → 会带上文件清单、甚至多个文件,范围越大越要克制。

1.4 善用子代理 / 子任务隔离上下文

DeepSeek Harness原生子代理(subagent):在独立的上下文里跑搜索/调研类脏活,只把结论返回主会话。「翻 100 个文件找用法」这种会污染主上下文的活,丢给子代理,主会话只收到一句总结。

主会话 提问 派发子代理 ↓ 收到总结 ✓ 继续干活
🔒 子代理 · 全新独立上下文(父会话历史传入)
grep ×40Read a.tsRead b.ts命中 2k 行Read c.ts…脏输出全留在这
↑ 跑完只把 一条总结 交回主会话,中间这几十次操作主会话完全看不见 → 后续每一轮都不用重发
省的不是「这一次」,而是脏输出挡在主会话之外、后续每轮不再重发;但每开一个子代理自带固定开销,用对场景才净赚(见下)。
  • DeepSeek Harness:内建 subagent / subagent_fork 工具,可并行派发多个独立子任务,各自汇总;更大规模的编排用 Agent Teams 工作流。
关键 nuance:子代理省 token 靠「隔离」,不是「天然更省」 子代理是一个全新的独立上下文:父会话的历史不会传进去,它只拿到你给的那段 prompt(外加项目 CLAUDE.md 的前一小部分);跑完后父会话只收到它最后一条总结,中间几十次 grep / 读文件父会话完全看不见。省就省在这——大段脏输出挡在主会话之外,后续每一轮不用再重发,主上下文短而稳、缓存也更容易命中。
但它不是免费的:每开一个子代理都自带固定开销(独立的系统提示 + 工具定义,几百到几千 token),子代理内部那几轮也会重发它自己读到的脏数据。所以「总 token」是涨是降取决于场景,而不是「总更高」

✓ 净赚

大范围探索 / 一次性调研,且后面还有很多轮对话 —— 隔离省下的「反复重发」远大于那份开销。

✗ 净亏

琐碎小事、一两轮就结束 —— 隔离没省下多少,却白交一份开销,直接做反而更省

1.5 用文件做「中转」,而不是把内容塞进对话

对话历史是「只进不出」的:任何塞进去的东西都会在之后每一轮重发。而文件是「按需读取」的:写进文件后它不占上下文,要用时再读、用完就过。所以凡是「体积大、又不需要全程跟着对话」的内容,都应该落到文件、而不是留在聊天里。

✗ 塞进对话 · 每轮拖着重发
轮1
轮2
轮3
大块内容焊进历史,越聊越大
✓ 落到文件 · 对话保持精简
轮1
轮2
轮3
📄 NOTES.md · 不占上下文,要用时只读几行

典型场景

场景别这样改成
分析大日志把几千行日志贴进对话让它看让它把日志写文件,再 grep/区间读关键片段
中间产物 / 调研结论长篇结论堆在对话里,后面一直重发让它写成 NOTES.md / findings.md,需要时再读
多步任务的计划计划只停留在对话,/compact 后可能丢失写成 PLAN.md / TODO 文件,跨轮次稳定可查
大段数据 / 接口返回整个 JSON 灌进上下文存文件,用 jq 等只取需要的字段

为什么省 token

  • 不重发:内容在文件里,对话历史保持精简,后续每一轮的输入都更小。
  • 可按需、可局部:下次只读需要的那几行(配合 1.3 的区间读取),而不是整坨重新载入。
  • 能复用、抗压缩/compact/clear 会丢掉对话里的细节,但写进文件的内容不会丢——新会话直接读文件即可恢复上下文,省去重新生成。
实操话术「把分析结果写到 findings.md,先别在对话里展开」「把这次的计划存成 PLAN.md,之后按它执行」——主动引导 AI 把大产物外置,是长任务里最容易被忽视、却很有效的省 token 手段。

1.6 把垃圾目录挡在上下文外:沙箱权限 / deny 规则

DSH 的文件沙箱默认只放行 workspace-write(工作区内读写,其余需审批)。在此基础上还能用 deny 规则禁止读取某些路径,从源头不让 node_modulesdist、生成物、lockfile 这类垃圾被整份读进上下文。

配置(会话权限设置 / 权限预设)
# 文件访问 deny 规则(gitignore 风格 glob)
deny: [
  "Read(node_modules/**)",
  "Read(dist/**)",
  "Read(**/*.lock)"
]
命中的路径 AI 读不到,也就不会在地毯式探索里把它们的大段内容灌进来 —— 既防误读,又省下本不该花的 token。(注意:DSH 不会自动套用你的 .gitignore,要挡就得显式写 deny。)

1.7 临时插一句问题:side-question(不进历史)

对话历史是「只进不出、每轮重发」的(呼应 1.5)。聊到一半想顺手问个无关小问题(「这个缩写啥意思」「这段顺便解释下」),直接问会把这段一问一答永久焊进历史,之后每一轮都陪着它重发。若工具提供 /btw 这类「side question」,它不进对话历史、复用现有缓存、单独答一次 —— 问完不污染主线,长任务里尤其值。

取舍side-question 通常没有工具权限、只基于当前上下文答一次、不支持追问。要它查文件 / 多轮深入,还是走正常提问。

2让工具调用更省

工具返回结果是仅次于文件读取的「隐形大户」。一条命令的输出会 100% 进入上下文。

2.1 给命令加过滤,别让 AI 看「全量输出」

✗ 浪费

npm install        # 上千行日志
cat huge.log       # 整个日志吞进来
grep -r "foo" .    # 几千行命中

✓ 省 token

npm install 2>&1 | tail -5
grep -rn "foo" src/ | head -30
rg "foo" --count        # 只要数量
为什么常带 2>&1很多人不解 DSH 为何老在命令后加 2>&1。原因:很多工具(npm、编译器、测试框架……)把报错和警告打到 stderr(标准错误),正常信息打到 stdout(标准输出),二者是两条独立的流。而 | tail / | grep 这类管道默认只接 stdout2>&1 的意思是「把 stderr(文件描述符 2)重定向并入 stdout(文件描述符 1)」,这样两条流合成一条,再一起喂给 tail 截断。不加的话,恰恰是最关键的报错会绕过 tail 直接刷屏 / 或干脆丢失 —— 既没省到 token,又漏看了错误。所以「截断 + 2>&1」要配套使用。
顺序也有讲究:cmd 2>&1 | tail 才对;写成 cmd | tail 2>&1 是错的(那只是把 tail 自己的 stderr 并进去,没用)。
习惯主动叮嘱:「命令输出请用 head/tail/--count 截断」。用 rg(ripgrep) 代替 grep -r,更快且默认更克制。
进阶:用 hook 自动截断,不靠记性嫌每次都要叮嘱截断?给 DSH 配个 hook,把「截断」从手动变成全局默认行为,超长输出再也别想整坨灌进来:
  • 事前(PreToolUse:拦下 Bash 命令、用 updatedInput 给已知啰嗦的命令(npm test / build …)自动补上 | tail,命令压根不会产出整坨。
  • 事后(PostToolUse:用 updatedToolOutput 替换掉模型看到的结果 —— 超过 N 行就只回传头尾 + 一句「已省略 X 行」,作为兜底。
一次配置,全项目所有人受益,比每轮提醒可靠得多。

2.2 测试别全量跑、别贴全量输出

调一个失败用例时,只跑那一个测试(pytest path::test_x / jest -t "name"),而不是整个测试套件把几千行输出塞回来。失败信息让它 tail 关键部分即可。

2.3 警惕 MCP 工具的「工具定义膨胀」

每接入一个 MCP server,它的所有工具 schema 都会进系统提示,每轮都发。装了一堆用不上的 MCP,等于给每轮对话加了固定税。

注意只启用当前真正需要的 MCP server / 工具。DSH 支持按需加载(deferred tools)能缓解,但裁剪掉不用的仍是最干净的做法。

2.4 全局 vs 局部:装在哪,就在哪付费

MCP server 和 Skill 都能装在全局~/.dsh/,所有会话都加载)或项目局部(工作区 / 项目配置,仅该项目加载)。原则一句话:装在哪,就在哪每轮付费。所以——「几乎每个项目都用」的才放全局,专用的放进对应项目,免得在用不上它的仓库里也白交税。

先分清成本,别用错力气MCP 和 Skill 的开销完全不是一回事,克制它们的理由也不同:
类型启动时进 context 的每轮 token 成本该克制的真正理由
MCP工具 schema(或 deferred 模式下的名字)+ server instructions —— 真·每轮固定税,且进缓存前缀省 token(少装、局部装都对)
Skill只有「名字 + 一行描述」;正文 /调用 时才加载很轻 —— 实测全部 Skills 合计仅 ~1.6k不是省 token,而是避免选择污染
别砍错对象「狂砍 Skill 来省 token」是个误区 —— 它启动只占名字 + 描述,省不出多少。克制 Skill 的真正价值是:列表越短,模型越不容易选错工具、越不被无关描述带偏(质量问题)。而 MCP 才是该优先裁剪的省钱大户(呼应 2.3)。

2.5 一次多个独立操作并行发

多个互不依赖的读取/搜索/命令,让 AI 在一条消息里并行调用,而不是一问一答来回好几轮。原理回到第 0 节:每多一轮,整个对话历史就重发一遍。所以轮数本身就是成本——把能并行的合并成一轮,省的是那些被反复重发的历史 token。

✗ 串行(4 轮)

a.ts → 等结果
再读 b.ts → 等结果
git log → 等结果
再跑测试 → 等结果
每一轮都重发前面所有历史。

✓ 并行(1 轮)

同一条消息里同时发起:
a.ts、读 b.tsgit log、跑测试
历史只重发一次,还更快。
串行
4 轮
读 a读 bgit log跑测试
并行
1 轮
读 a 读 b git log 跑测试
墙钟时间 → 并行只用约 1/4 时间,且历史只重发一次

什么能并行、什么不能

  • 能并行:彼此没有依赖的操作 —— 同时读几个文件、几处搜索、查 git 状态 + 跑 lint 等。
  • 不能并行后一步依赖前一步结果的 —— 比如「先搜出文件名,再读那个文件」必须串行;硬并行只会拿到半截信息再补一轮,反而更费。
实操大多数情况 AI 会自动并行无依赖的调用;你也可以明示:「这几个文件一起读」「把状态、日志、测试一次性都查了」。配合 1.3 的 @ 一次指多个文件,一轮就能把信息凑齐。
注意并行省的是轮数(历史重发),不是减少要读的内容总量 —— 该截断的输出(2.1)、该精读的区间(1.3)仍要做。两类技巧叠加才效果最好。

3吃满 Prompt Cache

DeepSeek Harness(DeepSeek API)支持 prompt caching:相同的上下文前缀命中缓存后,价格通常只有正常输入的 ~10%。用好缓存几乎是「免费」省 token。

缓存的铁律:只缓存「前缀」缓存从对话开头开始匹配,一旦中间某处变了,那之后全部失效要重算。所以越靠前、越稳定的内容(系统提示、CLAUDE.md、工具定义)越该保持不变。
前缀没动
✓ 命中
系统提示 CLAUDE.md 工具定义 历史 1–4 本轮提问
中途改了 CLAUDE.md
✗ 之后全失效
系统提示 CLAUDE.md ✎ 工具定义 历史 1–4 本轮提问
命中缓存 · 约 1/10 价 被改动的那块 它之后全部重算 · 全价 本轮新增
缓存从开头逐块比对,一旦中间某块变了,它及其后全部失效。所以越靠前的内容越要稳。

3.1 别在会话中途改动「靠前的稳定内容」

  • 频繁编辑 CLAUDE.md / AGENTS.md 会让整段缓存失效 —— 调稳定后再固定下来。
  • 会话中途增删 MCP / 工具,会冲掉工具定义缓存。

3.2 连续追问比「攒一大批改完重开」更划算

在同一会话里连续交互,前缀稳定、缓存持续命中;反复 /clear 重开会让每次都重新建缓存(首轮无折扣)。所以是权衡:跨任务要清,同任务内则尽量连续

注意时效缓存有 TTL(默认约 5 分钟)。离开去喝杯咖啡再回来,缓存可能已过期,回来那一轮按全价把整个前缀重建一次(注意是一次性重建,之后又能命中,不是「此后每轮全价」)。要继续就别拖太久。
要走之前注意 /compact 救不回缓存 —— 它把历史换成摘要,前缀整个变了,缓存照样失效。它真正省的是回来那次重建的体量:先把 100k 压到 20k 再走,回来全价重算的只是 20k。所以「上下文已经很长 + 要离开较久」时,走之前先 compact;上下文还小就别为了走特地 compact,那次总结本身也要花钱。

3.3 反直觉:会话中途切模型,可能更贵

每个模型有自己独立的缓存。聊到一半(比如已经 100k token)想「换个便宜模型答个简单问题」省钱 —— 结果常常更贵:换过去那一刻整个前缀缓存命不中,要按全价给新模型重建一遍,重建的钱往往超过让原模型直接答省下的那点。同一会话内尽量别来回切模型;真要用不同模型,不如开一个专门的新会话。

更顺手的解如果只是想「用便宜模型答个独立的小问题」,比开新会话更省事的是派一个 subagent:它跑在独立的全新上下文里、可单独指定便宜模型,只付那个小问题的 token,完全不碰主会话缓存 —— 一招同时解决「切模型废缓存」和「污染主上下文」。前提:subagent 从空白起步,看不到你主会话攒的上下文;问题自包含才合适,若它依赖这一长段积累,就得把上下文喂进去,反而失去意义。
同源一招官方做 agent 工具时的经验:需要更新「靠前的稳定内容」时,别去改系统提示(一改全段缓存失效),而是把新信息放进下一条用户消息 / 工具结果里传给模型 —— 前缀不动,缓存照命中。这也是为什么你会看到 <system-reminder> 这类信息总是追加在消息末尾、而不是塞回开头。

4把任务说清楚(减少试错轮数)

最贵的浪费是「方向错了」:AI 读了一堆文件、改了半天,结果不是你要的,推倒重来 —— 前面所有 token 全打水漂,还得重新读一遍。

4.1 一开始就给足约束

✗ 模糊

「优化一下这个函数」
→ AI 猜你要啥,读一堆文件,方向跑偏,来回 4 轮。

✓ 明确

parseUser() 里的正则在空输入时会抛错,只改这个边界处理,别动函数签名」
→ 一轮命中。

4.2 指明文件 / 范围,省掉「搜索成本」

你知道在哪就直接说 src/auth/login.ts,别让 AI 满仓库搜。一句路径,省下十几次工具调用和大段命中输出。

4.3 复杂任务先让它「出计划」再动手

用 plan 模式 / 先要方案,确认方向对了再执行。比「边做边发现不对」省得多。计划阶段的 token 很便宜,返工的 token 很贵。

4.4 用项目记忆文件固化重复约束

把「用 pnpm 不用 npm」「测试放 __tests__」这类每次都要交代的规则写进 CLAUDE.md / AGENTS.md,避免每个会话重复打字解释(而且它在缓存前缀里,几乎免费)。

还有一层:自动记忆(持久化)除了你手写的 CLAUDE.md,DeepSeek Harness 还会把会话历史自动持久化到本地(jsonl / sqlite 会话存储),配合记忆文件体系沉淀「构建命令、踩过的坑、确认过的偏好」。它对 token 友好的关键在于 —— 启动时只加载记忆文件的索引与摘要,具体内容按需才读,记得再多也不会一上来就撑爆上下文;和 CLAUDE.md(你写、每次全量加载)互补。

4.5 主动用 ! 喂精准信息,省掉一轮工具往返

与其让 AI 自己琢磨「该跑哪条命令」再发一轮工具调用,不如你直接把结果喂给它。在输入框打 ! 进入 shell 模式!git status / !npm test 2>&1 | tail 的输出会直接进上下文,AI 拿现成的精准信息接着干 —— 少一轮「它猜命令 → 你确认 → 它再读」的往返(呼应 4.2「给精准信息」、2.5「省轮数」)。

配套输出仍然会进上下文,所以该截断照样截断!… | tail,呼应 2.1)—— ! 省的是「轮数 / 让它搜的成本」,不是免去截断。

5进阶:用代码索引省掉「探索开销」(CodeGraph)

前面那些技巧靠 /clear、控工具、给足约束这些手动办法压低开销,但有一类开销很难靠话术消掉:在陌生代码库里「找代码」这件事本身 —— AI 为了回答「这个功能是怎么实现的」,要反复 grep / glob / Read 一层层摸,每次工具调用的命中和文件内容都进上下文。CodeGraph 这类「代码索引」工具,就是冲着这块开销来的。

它怎么省 token

CodeGraph 通过 MCP 接入 DeepSeek Harness / Cursor 等 agent,把整个代码库预先建成一张语义知识图谱(符号关系、调用图、代码结构,存在本地 SQLite)。之后 AI 一次查询图谱就能拿到入口、相关符号和代码片段 —— 把原本几十次 grep/read 的「探索往返」压成几个工具调用,常常零文件读取就给出答案。

原生:发现阶段 = 几十次小往返
grepglobReadgrepReadReadgrepReadlsgrepRead
每次命中 + 整文件内容都灌进上下文
索引:一次查询直达
codegraph_explore ⟶ 入口 + 调用链 + 片段
常常零文件读取就作答
本质:用「一次大查询」换「几十次小往返」 原生方式下,AI 把预算花在发现(discovery)上 —— find/ls/grep 翻半天才定位到该读的代码。有了索引,它直接问图谱、直接答,探索阶段几乎被消掉。这正是第 0 / 2 节「工具返回结果是输入大户」的对症下药。

官方 benchmark(7 个真实开源库 · Opus 4.8 · 2026-06)

47%↓
总 token(平均)
58%↓
工具调用次数(平均)
16%↓
实际花费(平均)
22%↑
速度(平均更快)
代码库语言 · 规模Token工具调用花费
VS CodeTS · ~10k 文件少 64%少 81%便宜 18%
DjangoPython · ~3k少 60%少 77%便宜 8%
AlamofireSwift · ~110少 64%少 58%便宜 40%
OkHttpJava · ~645少 54%少 50%便宜 25%

方法:同一个架构类问题,headless CLI 模式对每个库跑「带索引 vs 不带索引」各 4 次取中位数。

关键 nuance:token 降得多(47%),花钱降得少(16%) 省下的「碎 grep/read」被换成了少数几个更大、走缓存的工具响应 —— 所以 token 数量砍得狠,但折算成账单没有同比例下降,在响应密集的库上(如 Excalidraw、Tokio)甚至基本打平。看节省效果一定要分清「token 数」和「实际账单」两个口径(呼应第 9 节的诊断思路)。

什么时候值得上

  • 库越大越划算:VS Code 这种万级文件,工具调用直接砍 81%;小库主要省在单价。
  • 探索 / 问架构类任务收益最大:「X 功能怎么跑通的」「改这里会影响谁」(影响分析)。纯改一行的小活用不上。
  • 100% 本地:只用 SQLite,无 API key、不外传代码,对公司内代码合规友好。
  • 局限:只在 AI 直接查图谱时有用;若它仍把活甩给子代理去读文件,反而成了额外开销 —— 所以它的 MCP 指令会引导 AI 直接作答(呼应 1.4 子代理的「用对场景才划算」)。
上手(三步)
# 1. 装 CLI(macOS/Linux,自带运行时,无需 Node)
curl -fsSL https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.sh | sh
# 2. 接入你的 agent(自动检测 DeepSeek Harness / Cursor…)
codegraph install
# 3. 在项目里建索引
cd your-project && codegraph init -i
支持 20+ 语言;文件改动靠原生 OS 事件(FSEvents/inotify)自动增量同步,基本零维护。
定位CodeGraph 针对的是①「输入」轴里一个话术压不掉的子问题——探索开销。话术能让 AI 少 grep,代码索引则从根上把「探索」换成「查询」;两者叠加,陌生大库的探索成本能压到最低。

6省「输出 token」(caveman,冷门,看情况)

前面所有技巧(含 CodeGraph)省的都是输入侧:上下文、历史、工具结果。这是第三条、也最少被提的轴 —— 输出 tokencaveman 是个跨 agent 的 skill,用 /caveman 让模型改用「电报体」作答(丢虚词、留干货、用短句),只压缩输出、不影响它的思考。官方基准称输出平均省 ~65%(22%~87% 不等)。

输入侧 · 上下文 / 历史 / 工具结果(前 1–5 节都在省这块)
输出
编码场景里,输入通常远大于输出 —— caveman 只压右边那一小条,先把左边的大块做扎实更重要。(比例为示意)
先泼盆冷水:编码场景收益有限
  • 输入才是大头:日常编码里,文件 / 历史 / 工具结果(输入)远大于模型回话(输出)。砍输出对总账单的影响,通常远不如前面那些省输入的技巧。
  • 有可读性代价:电报体会牺牲解释的清晰度,团队协作 / 需要留档说明时不一定划算。
  • 真正适合的场景:输出特别啰嗦、又只你自己看的活(大批量解释、长篇总结),且你确实在为输出 token 买单时,才值得开。
一句话:知道有这条轴就行,别当主力。先把省输入的基本功做扎实,再按需考虑它。

7典型浪费案例(对号入座)

案例 A:「万能长会话」

DeepSeek Harness 一整天不关会话,从 bug 修到需求、再到写周报。到下午每一句的输入都是几十万 token。
解法:任务切换即 /clear;长任务中途 /compact

案例 B:「让 AI 自己找」

「这个报错怎么回事」却不贴报错、不给文件,AI 只能全仓库翻。
解法:贴上报错栈 + 相关文件路径,把搜索成本降到零。

案例 C:「全量输出回灌」

跑 build/test 不截断,几千行日志全进上下文,而且接下来每轮都重发。
解法:| tail、只跑单个用例、让它先看摘要再决定要不要细看。

案例 D:「读整个文件改一行」

改一个常量,AI 把 2000 行文件整读进来。
解法:定位行号区间精读;明确告诉它改哪。

案例 E:「MCP 全家桶」

装了十几个 MCP,大半用不上,但每轮都在为它们的工具定义付费。
解法:按项目裁剪启用的 MCP。

案例 F:「方向性返工」

没说清需求,AI 写完一大坨发现不对,推倒重来三次。这是单次成本最高的浪费。
解法:先对齐方案 / plan 模式,再动手。

8实战演练(端到端操作示例)

前面是原则,这一节是可照着敲的完整操作。每个演练都给出「散弹做法 vs 精准做法」的真实流程和 token 对比。(其中的 token 数为量级示意。)

8.1 修一个线上 bug:散弹 → 精准

需求:「登录接口偶尔返回 500」。同一个 bug,两种开法差出近 10 倍 token。

✗ 散弹(~85k token)

你:登录有时候会 500,帮我看看

AI:(开始全仓库探查)
  → Grep "login" 全库          命中 240 行
  → Read src/routes/auth.ts    (整文件 1.8k 行)
  → Read src/services/user.ts  (整文件 1.2k 行)
  → Read src/db/pool.ts        (整文件)
  → 又读了 6 个相关文件…
  → 「能贴一下报错吗?」          ← 绕一圈又回来问你
方向全靠猜,读进十几个整文件,最后还得问你要报错。

✓ 精准(~9k token)

你:登录偶发 500,报错栈如下,
   只看 @src/services/user.ts 的
   getUserByToken(),别动签名:

   TypeError: Cannot read 'id' of null
     at getUserByToken (user.ts:88)
     at authMiddleware (auth.ts:41)

AI:(直接定位)
  → Read user.ts:70-100        只读 30 行
  → 第 88 行 token 过期时 query
    返回 null 未判空 → 修复
报错栈 + @ 指文件 + 限定函数 = 一轮命中,零搜索。
关键动作① 贴完整报错栈(自带文件名+行号,等于帮 AI 定位);② 用 @ 把范围锁到单个文件;③ 用「只改 X,别动 Y」划定边界,杜绝顺手乱改引发的返工。

8.2 长会话该清了吗:用 /context 做决策

不要凭感觉,敲 /context 看构成再决定。下面是一个「该动手了」的典型画面:

Context Usage · DeepSeek Harness (1M) 612k / 1M tokens(已用 ~61%)
↑ 消息占了 540k(88%),且还在涨 —— 典型的「一个会话干了好几件事」

看到这个画面,按情况二选一:

场景:已经换任务了

消息里大半是上一个任务读过的文件/日志,跟现在要做的事无关。
/clear        # 直接清空,从干净的上下文重开
# 需要延续的结论,先让它写进 NOTES.md

场景:还在同一个长任务

历史都相关、不能丢,但中间过程(大段文件、试错)很冗余。
/compact 只保留最终方案、改动的
文件列表和待办,丢掉中间读过的
文件全文和调试输出
# 540k → 通常能压到 30~60k
判断口诀「消息」占比高且含无关内容/clear;占比高但全相关 → 带指令的 /compact。底部状态栏的百分比可以让你不用反复敲命令。

8.3 分析一大坨日志:走文件中转,别贴进对话

需求:「这个 5000 行的崩溃日志,帮我找出根因」。

✗ 贴进对话(~70k,且每轮重发)

你:(把 5000 行日志整段粘贴进来)
   帮我看看崩在哪

→ 5000 行一次性进上下文 ≈ 65k token
→ 之后每追问一句,这 65k
  都跟着重发,越聊越贵

✓ 文件中转(~4k)

你:日志在 @logs/crash-0601.log,
   先别全读。按这个步骤:
   ① grep -n "ERROR\|FATAL" 看有几处
   ② 只读第一个 FATAL 前后 40 行
   ③ 告诉我根因

AI:→ grep 命中 3 处 FATAL
    → Read 该文件 1180-1220 行
    → OOM in image resize
原理日志留在文件里就不占对话上下文,要用时只 grep/区间读关键几十行。对话历史保持精简,后续每一轮的输入都小 —— 这正是第 1.5 节「文件做中转」的实战形态。

8.4 跨文件批量改:子代理探查 + PLAN.md 落地

需求:「把全项目的 moment 换成 dayjs」—— 涉及几十个文件,是最容易把上下文撑爆的活。

# ① 探查交给子代理,主会话不被原始输出污染
你:用一个 subagent 搜出所有 import 了 moment 的文件,
   只返回「文件路径 + 用到的 moment API」清单,别贴文件全文。

子代理(独立上下文里翻了 40+ 文件)→ 只回主会话一张表:
   src/a.ts  → moment().format()
   src/b.ts  → moment().add(), .diff()
   …共 23 个文件、5 种 API

# ② 把计划落到文件,抗 /compact、可跨轮次执行
你:把这张清单和替换方案写进 PLAN.md,按文件分组、能勾选。

# ③ 按 PLAN.md 分批改,每改几个就 /compact 一次
你:按 PLAN.md 改前 5 个文件,改完更新勾选状态。
   (改完)/compact 只留 PLAN.md 进度和约定,继续下一批。
为什么这样最省
  • 子代理隔离:40 个文件的原始内容留在子上下文,主会话只收到一张 23 行的表(呼应 1.4)。
  • 计划外置到 PLAN.md:进度写在文件里,/compact//clear 都冲不掉,随时能接着干(呼应 1.5 / 4.4)。
  • 分批 + 阶段性 compact:避免「23 个文件的改动全堆在一个会话里反复重发」。

8.5 在陌生大库里问架构:探索 → 查图谱(CodeGraph)

需求:刚接手一个万级文件的项目,「扩展进程(extension host)是怎么和主进程通信的?」—— 典型的"问架构"任务,也是第 5 节 CodeGraph 最擅长的场景。下面是 VS Code 仓库上「带索引 vs 不带索引」的真实对比(数字取自官方 benchmark,同一模型 4 次中位数)。

✗ 不带索引(~1.79M token · 21 次工具调用 · $0.83)

你:extension host 怎么和主进程通信?

AI:(全靠在文件系统里摸)
  → Grep "extension host" 全库   命中几百行
  → Glob **/extHost*.ts          列一堆候选
  → Read extHost.ts              (整文件)
  → Read mainThread*.ts          (整文件)
  → 又 grep/read 了十几次…
  → 9 次 Read + 11 次 grep/bash
    才拼出调用链
预算几乎全花在「发现该读哪个文件」上,整文件反复灌进上下文。

✓ 带索引(~640k token · 4 次工具调用 · $0.68)

你:extension host 怎么和主进程通信?
  (项目已 codegraph init -i)

AI:(直接问图谱)
  → codegraph_explore
       "extension host ↔ main
        process communication"
  → 一次返回:入口符号 + 调用链
    + 关键代码片段(RPC 协议、
    proxy/序列化层),零文件读取
  → 直接作答
一次图谱查询替代 20 次 grep/read:token −64%、工具调用 −81%、还更快。
关键动作① 项目接手时先 codegraph init -i 建好索引(一次性);② 问"怎么实现/谁调用了它/改这里影响谁"这类探索型问题时,直接让 AI 走 codegraph_explore / 影响分析,而不是放它去 grep;③ 之后真要改代码,再配合 1.3 区间精读那几个命中文件 —— 探索用图谱,精读用 Read,两段各省各的。
什么时候别用改一行常量、文件你已经知道在哪 —— 直接 @ 指文件(1.3)更快。索引的价值在"不知道在哪"的探索阶段;已经定位到了就回归普通精读。

9如何发现自己在哪浪费

优化的前提是能看见。下面是几种量化 / 定位手段。

9.1 会话诊断三件套:/context · /usage · /cost

三个命令对应三种视角,配合着看才完整:

命令看什么用来定位
/context当前会话的上下文里「装了什么」:系统提示 / 工具 / MCP / Skills / 消息各占多少谁在占满窗口 —— 哪个大户该清
/usage你的套餐 / 账户配额用掉多少:限额、剩余量、距离重置还有多久「最近整体烧太快」的宏观信号
/cost当前会话累计 花费 & token 用量单次会话是不是异常贵
读懂 /context 的一次真实输出
Context Usage · DeepSeek Harness (1M) 65.6k / 1M tokens(已用 ~7%)
↑ 按「已用 token」拆分构成;另有约 93% 窗口空闲(1M 大窗口,这里还很宽裕)
消息(对话历史)46.5k · 4.7%
系统工具14.2k · 1.4%
系统工具(按需加载)11.3k · 1.1%
MCP 工具(按需加载)10.7k · 1.1%
系统提示3.4k · 0.3%
Skills1.6k · 0.2%
从这张图能一眼看出三件事:
  • 「消息」占了一半以上,而且会随对话变长持续上涨 —— 涨到逼近窗口上限,就是该 /compact/clear 的时刻。
  • 工具 / MCP 是「固定税」(这里合计 ~36k),每轮都在付。用不上的 MCP 就该裁(呼应 2.3);好在按需加载(deferred)能把一部分推迟到真正用时再算。
  • 系统提示 / Skills 很小,基本不用操心 —— 别把优化精力花在这。

另外,与其每次手动敲 /context,不如把用量常驻状态栏,让它实时显示、随时扫一眼就知道。

配置状态栏(让上下文用量常驻眼前)
  • 怎么配:跑 /statusline 让它按你的描述自动生成脚本;或在 settings.json 里写 statusLinetype: "command")指向一个脚本。
  • 懒得自己写?用现成的claude-hud 是个开箱即用的状态栏,直接显示上下文用量、本会话花费、模型、git 分支等,装上就有,不用自己拼脚本。
  • 能显示什么:脚本会收到 JSON,含 context_window.used_percentage(已用百分比)、total_input_tokens、模型名、git 分支等,可以拼成一个带进度条的实时条。
  • 零成本:状态栏脚本本地跑、不消耗 API token,纯白赚的可见性。
配好之后,「该不该 /compact//clear」的判断(呼应 8.2)不用敲命令,瞄一眼百分比就有数。

9.2 /insights:从「单次体检」升级到「习惯诊断」

前面三件套看的是「当下这一次」(这个会话装了啥、花了多少、配额还剩多少)。/insights 换一个视角:它会分析你跨多个会话的使用情况,生成一份报告,告诉你常在哪些项目区域工作、习惯怎么和 AI 交互、卡点(friction)出在哪

命令时间尺度回答的问题
/context / /cost当前会话这一次装了啥、花了多少
/usage当前配额周期套餐额度还剩多少
/insights跨会话的长期趋势反复在哪些模式上卡壳 / 浪费
和省 token 的关系 单次的 /context 帮你救一个已经臃肿的会话;/insights 帮你发现系统性的坏习惯 —— 比如「总在让 AI 满仓库搜本可以直接 @ 指的文件」「长会话从不 /clear」这类反复出现的卡点。把根因式的浪费(前面 5、6 节那些案例)一次性改掉,比每次事后补救更省。
说明/insights 偏向工作流 / 交互模式的复盘,不是逐 token 的精确账本 —— 要精确数字仍看 /cost 与控制台 Usage(8.4)。两者互补:/insights 指方向,账单核数字。

9.3 看 Cache 命中率

关注用量里的 cache read vs. input 比例。理想状态是大量 token 走 cache read(便宜)。如果 cache 命中很低,说明你在频繁让前缀失效(中途改 CLAUDE.md、反复重开、间隔太久缓存过期)。

9.4 API:用账单与用量后台

  • OpenAI / Anthropic 控制台的 Usage 页可按天、按模型看 token 走势,定位「哪天哪类任务突然暴涨」。
  • API 响应里的 usage 字段(input_tokens / output_tokens / cache_*_tokens)是最精确的逐请求账本。

9.5 自检三连问

每次感觉「怎么这么慢/这么贵」时,问自己:
  1. 这个会话里,是不是混了好几个不相关任务?(→ 早该 clear)
  2. 上下文里是不是塞着大段我已经不需要的文件/日志?(→ compact)
  3. 我有没有让 AI 去搜本可以直接告诉它的东西?(→ 给路径/贴报错)

9.6 给团队的可观测建议

若用 API/SDK 自建 agent,把每次请求的 usage 落日志,做个看板按「任务类型 / 用户 / 是否命中缓存」聚合。浪费往往集中在少数几种模式上,量化后一目了然。

用对账号:吞 token 的活别走共享池处理知识库、长文档、整库分析这类天然吃 token 的任务时,尽量用自己的个人账号跑,别占用团队共享账号池。原因很现实:池子是团队共享额度,一个大任务就可能把池里账号额度耗干,连累其他人无法工作。
判断口诀:一次性、个人探索、明显吞量大的活 → 走个人账号;池子留给短平快、人人都要用的协作场景。

10速查清单(贴墙版)

场景该做什么
切换到不相关任务/clear / 开新会话
同一任务越聊越长/compact 总结,丢中间过程
知道改哪个文件直接给路径,别让它搜
有报错贴报错栈,别让它复现/猜
跑命令/测试| tail、只跑单测、要 --count
读大文件先定位行号,区间精读
大范围调研/搜索丢给 subagent,只收结论
复杂改动先出 plan,对齐再执行
反复交代的规则写进 CLAUDE.md / AGENTS.md
MCP 一大堆只留用得上的
怀疑在烧 token/cost + /context 体检
临时问个无关小问题side-question(/btw),不进对话历史
手上已有现成信息! 直接喂(记得截断),省一轮工具往返
老忘记截断输出PreToolUse/PostToolUse hook 自动截
垃圾目录老被读进来沙箱 deny 加 Read(...) 规则
想随时盯用量/statusline 把上下文 % 常驻状态栏
一句话总结 上下文越短、越稳定、越精准,token 越省。 让模型只看到必要的内容,保持前缀稳定吃满缓存,把任务一次说清避免返工 —— 这三件事能砍掉绝大部分浪费。
DeepSeek Harness 省 Token 实战 · 内部分享稿 · 2026-06
命令与折扣比例以官方文档为准;不同版本可能略有差异。