/compact:把失控的上下文拉回来的开关

用 Claude Code 几周后我发现,不管 CLAUDE.md 写得多精简、Skills 用得多巧妙,session 用到后面还是会炸。不是 Claude 变蠢了,是上下文满了。这篇聊聊我是怎么从"每次崩了就 /clear 重来"进化到"用 /compact 优雅续命"的。

我最早发现 Claude Code "后期变笨"的时候,以为是模型问题。

一次重构订单模块,前面几轮聊得很顺。Claude 读了代码、问了几个问题、出了方案、开始执行。改到一半,我让它顺便把支付流水也纳入同一个事务范围。

然后它就崩了。

改出来的代码把我之前确认过的逻辑全部推翻,变量名乱飞,还把一条注释里的 "TODO" 当成了业务需求实现了进去。我盯着屏幕看了十秒,心里想的是:这玩意儿刚才还正常呢。

后来我才反应过来——不是模型问题,是上下文炸了。

上下文满了之后,Claude 在干什么

Claude Code 的每个 session 都有上下文窗口限制。跟 API 调用一样,对话历史太长,模型就装不下了。

但 API 调用炸了会直接报错。Claude Code 不会。它会做 context compaction,把旧的对话压缩成摘要,塞回上下文继续跑。

问题在于:compaction 不是无损压缩。它会把之前的细节"总结"掉,保留大框架。

也就是说:session 用久了,Claude 还记得你之前说过要重构订单模块,但已经不记得你强调过三次"不要碰支付流水的表结构"。它只记得"用户说要改订单",然后凭着压缩后的残影开始自由发挥。

这就是为什么 session 后期 Claude 会"失忆"。

/compact 之前我的 workflow

很长一段时间里,我的解法很粗暴:上下文满了就 /clear

清掉之后一切归零,重新开始。但问题也很明显:

  • 上次 session 确认过的方案要重新说一遍
  • 之前 @ 过的 Skills 要重新 @
  • Claude 又要重新读一遍代码库,重新理解上下文

一整个 session 的时间,30% 花在真正做事上,70% 花在"重新对齐"上。

最惨的一次是周五下午写一个交接脚本。写到第五十分钟上下文满了,我 /clear 重来。第二轮又满了,再 /clear。一个本来一小时能写完的东西,拖了两个小时。

后来我才知道有个 /compact

/compact:不是清空,是压缩

/compact 做的事情跟 Claude 内部的 context compaction 一样,但它是你手动触发的。

区别在于:内部 compaction 是偷偷摸摸做的,你不知道它什么时候压缩、压缩了什么。而 /compact 是显式操作,压缩的时机由你控制。

具体效果:session 的对话历史被压缩成一段摘要,放在上下文的最前面。Claude 之后的回复会基于这段摘要,而不是原始的完整对话。

操作很简单:

/compact        # 压缩当前上下文

或者你发现 Claude 开始"失忆"了,直接敲这个命令。接下来它会说"我已经压缩了之前的上下文",然后继续干活。

我第一次用的时候半信半疑——压缩完真的还记得住吗?

试了一次之后发现:只要你在压缩前把关键结论写进对话,或者让 Claude 在 compact 之前输出一份"当前状态摘要",compact 之后它基本能续上。

具体怎么用

配合 /plan 的方案文件

Plan Mode 生成的方案文件存在磁盘上,不依赖上下文。所以最佳 workflow 是:

  1. 用 Plan Mode 出方案
  2. 批准执行
  3. 执行过程中如果上下文变满,/compact
  4. compact 之后告诉 Claude "读取方案文件继续"

方案文件在磁盘上,不会因为 compact 消失。Claude 每次 compact 后只需要重新读一遍方案,就能继续。

手动维护"状态快照"

有时候没有方案文件,比如我正在帮人 debug 一个线上问题,对话很长,上下文快满了。

这时候我会让 Claude 输出一份当前状态:

输出当前状态:已知条件、已排除的可能、下一步计划

Claude 输出的这段文字会被留在上下文里。然后我 /compact。压缩之后,Claude 依然记得"已知条件是 X,已排除 Y,下一步是 Z"。

这个技巧我用得很多。本质上是在 compact 之前做一次"checkpoint"。

/compact 之后如何验证 Claude 没丢东西

compaction 之后我会做一件事:让 Claude 复述当前进度。

你现在还记得我们要做什么吗?说一下当前状态

如果它能准确说出来,说明压缩有效。如果它开始胡说八道,说明压缩过度或者之前的摘要不够——这时候我直接 /clear 重来,不浪费时间。

Tricks

Trick 1:在 CLAUDE.md 里设置 compact 触发条件

我在 CLAUDE.md 末尾加了这样一行:

## Context Management
当上下文使用超过 70% 时,主动建议使用 /compact。
如果用户说"继续"且之前没有 compact 记录,先 compact 再执行。

Claude 看到这行之后,会在对话到一定长度时主动提醒我"上下文使用率较高,建议 /compact"。不用我自己盯着 token 数看。

Trick 2:用 /compact 做"阶段性重置"

除了救急,我还会主动用 /compact 做阶段性分隔。

比如一个大的重构任务,我把它拆成三个阶段。每个阶段做完,/compact 一次。下一阶段开始时,Claude 只需要知道"第一阶段完成了什么"就够了,不需要知道第一阶段中间的十几次来回讨论。

这相当于手动做了一次"会话分片"。

Trick 3: Skills 在 compact 后需要重新加载

这个坑我踩过:/compact 之后,Claude 不会自动重新加载你之前 @ 过的 Skills。

如果你在一个 session 里用了 @error-handling,然后 /compact,再之后要处理错误相关的任务——Claude 可能已经忘了 @error-handling 的存在。

我的解决方法是:在 compact 之后主动说一句"加载 @error-handling"。或者更懒一点,在 CLAUDE.md 里列出常用 Skills,compact 后 Claude 会从 CLAUDE.md 里看到。

Trick 4:批量对话时 /compact 能省大量 token

这个场景很常见:我让 Claude 批量 review 十个文件。

前三个文件聊得很细,上下文已经快满了。但后面还有七个文件要 review。这时候 /compact 一次,把前面三个文件的结论压缩成摘要,后面七个文件还能继续。

没有 /compact 的话,要么分多个 session(每个 session 都要重新读代码),要么硬着头皮继续(后面质量直线下降)。

注意事项 / 踩坑

坑一:/compact 不是银弹,它会丢细节

compaction 是摘要,不是全量保留。如果某个细节你之后需要用到,而那个细节只出现在原始对话里、没被你写进任何文件或摘要——那它就丢了。

具体表现:Claude 在 compact 之后会"忘记"某个变量的命名约定、某个文件的具体路径、某条你随口提的要求。

所以 compact 之前,把重要的细节写下来。要么写进文件,要么让 Claude 输出一份状态摘要。

坑二:连续 compact 会导致"抽象层崩溃"

如果一个 session 被 compact 了太多次,每次压缩都是对摘要的再摘要。几次之后,摘要里只剩下最粗的框架,细节全部丢失。

我给自己定的规则:同一个 session 里 compact 不超过三次。 超过三次说明这个 session 的对话量已经失控了,直接 /clear 开新 session 更划算。

坑三:/clear 和 /compact 不要混着用

/clear 是清空一切从头开始。/compact 是压缩后继续。

我见过有人 /clear 之后又 /compact——这没有意义。/clear 之后上下文是空的,没有东西可以 compact。

正确的顺序是:要么 /compact 保留状态继续,要么 /clear 放弃状态重来。二选一。

坑四:Plan Mode 下 compact 之后方案状态会变

Plan Mode 的方案文件在磁盘上,不会变。但 Claude 对方案的理解是在上下文里的。

如果在执行阶段中途 /compact,Claude 压缩后的摘要可能只保留了"方案说要改三个文件",但丢了"执行顺序"和"每个文件的具体改动"。这时候 compact 之后要重新打开方案文件确认一下。

我一般是在 Plan Mode 的 approve 之前 compact,执行阶段尽量不复用同一个 session 太久。如果执行阶段很长,干脆分 session 执行:session 1 出方案,session 2 按方案执行。

一个反直觉的事实

很长一段时间里,我觉得 /clear 是"认输"——意味着这个 session 废了,要重开。

后来我才明白:能主动 compact 的 session,才是健康的 session。

好的 workflow 不是让一个 session 从早跑到晚,而是有意识地控制 session 的生命周期。一个 session 完成一个阶段的任务,compact 后进入下一个阶段。每个阶段都有清晰的起点和终点。

那种一个 terminal 窗口开三天不关的习惯,其实是把上下文管理搞成了玄学。你永远不知道 Claude 什么时候开始"失忆",也不知道它失忆之后会做出什么事。

/claude 和 /compact 放在一起用,是我在 Claude Code 上效率提升最明显的两个改变。前一个解决"不知道怎么跟 Claude 说清楚"的问题,后一个解决"说清楚了之后怎么保持"的问题。

好,接下来聊聊 MCP Servers 配置与使用——把 Claude Code 从一个本地编辑器变成万能控制台的那个东西。

评论

此博客中的热门博文

我写了半年 prompt,这是我发现的最好的技巧