Claude Code 上下文管理:/clear、Plan Mode、CLAUDE.md 与 subagent
我第一次认真用 Claude Code 做跨文件改动时,把同一个登录跳转的 bug 修了三轮。第一轮它改了路由,没生效;我贴上报错让它再看,它改了中间件,还是没生效;第三轮它开始动我根本没让它碰的 session 逻辑。修到这里我才反应过来——问题不在 Claude Code,在我。前两轮的废补丁、报错日志、我那些反复的纠正,全堆在上下文里,Claude 每轮都带着这一堆噪音重新判断,等于让它在垃圾堆里找钥匙。
我 /clear 重开,把复现步骤一次写清楚,第一次就修好了。
从那以后我慢慢意识到一件事:Claude Code 不是一个代码补全工具,是一个有记忆的对话系统。 和它说的每句话、读过的每个文件、跑过的每条命令,全存在那个 200K token 的上下文窗口里。窗口越满,它就越容易忘掉早期的关键指令,开始在旧信息里打转。所以用好 Claude Code,本质上就是管好这个窗口——让里面装的都是有用的东西。
Anthropic 自己的最佳实践文档也说了同一句话:大多数最佳实践都基于同一个约束,上下文窗口填得很快,填满之后性能会下降。
最重要的一个键:/clear
200K token 听着很多,但实际填得飞快。读三五个上千行的源文件,加上几轮命令输出,几万 token 就没了。一个稍长的调试 session 用掉一半很常见。
我现在的习惯是每做完一个任务就 /clear。不是因为窗口真的满了,而是不想让上一个任务的残留影响下一个。用 /context 可以随时看占用,但说实话我很少看——养成顺手清的习惯比反复检查更省心。
最反直觉的一条:卡住之后不要反复纠正。 这是我踩过最多次的坑。Claude 改错了,你告诉它哪里不对,它再改,还是不对,你继续纠正。每一轮纠正都在往上下文里塞失败方案,Claude 要带着越来越多的噪音做判断。纠正超过两次,停下来 /clear,把你从失败中学到的东西写进一个新的、更精确的提示里。这几乎总比继续改快。
Esc 也很有用,随时可以打断 Claude 正在做的事。改坏了的话 /rewind 可以回到任意检查点回滚。
给 Claude 一面镜子
最佳实践文档把这件事放得很靠前,用下来确实收益最高:给 Claude 一个它自己能跑的验证条件。
不给验证条件会怎样?Claude 写的东西看起来没问题,但某个边界情况悄悄出错,你就成了唯一的 QA。不如直接在提示里说清楚怎么算对:
写一个 validateEmail 函数。测试用例:user@example.com → true,invalid → false,user@.com → false。写完之后跑测试,修掉失败的。
这样你看它给的测试输出就行了,不用自己再跑一遍。Claude 从「我觉得对了」变成「测试过了」,差别很大。
UI 改动也一样——把截图粘进去让它对比,比说「让 dashboard 好看点」靠谱得多。后者只有 Claude 自己觉得对,你还得肉眼验一遍。
Plan Mode 和「采访模式」
直接让 Claude 开始写代码,有时候它会很认真地解决一个错误的问题。代码库不熟、改动跨多文件的时候尤其如此。
Shift+Tab 进 Plan Mode,Claude 只探索代码、出方案,不改任何东西。等你确认方案没问题再退出来实现。这个流程在改动范围不确定的时候非常好用。
%% caption: 要不要开 Plan Mode:能一句话说清最终 diff 就直接做;方案不确定、跨文件、代码不熟就走四步流程
flowchart TD
Q{"能一句话说清<br/>最终 diff 吗?"}
Q -->|能,比如改一行 log / 改个名| Direct["直接做"]
Q -->|不能:方案不确定 / 跨文件 / 代码不熟| P1["进 Plan Mode(Shift+Tab)<br/>先探索代码,不做修改"]
P1 --> P2["出方案:涉及哪些文件、流程怎么走"]
P2 --> P3["确认没问题,退出 Plan Mode<br/>实现 + 跑测试"]
P3 --> P4["commit 和 PR"]
class Direct keep
classDef keep fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#0a0a0a
不过 Plan Mode 本身也有开销。改一行文案、重命名一个变量,直接做更快。别什么都先规划——过度规划和不规划一样浪费时间。
还有一种我很喜欢的玩法:让 Claude 先来采访你。
我想做 [简短描述]。先不要写代码,先采访我:
- 技术实现有哪些不确定点?
- 有哪些边界情况?
- 哪些取舍需要我决定?
采访完之后整理成 SPEC.md,写清楚涉及哪些文件、哪些不动,以及最后用什么命令验证。
Claude 会问出你自己没想到的问题,非常好用。采访完之后新开一个 session 来实现——上下文干净,有书面 spec 可以对照,比边聊边改效果好。
CLAUDE.md:写给 Claude 的规矩,不是项目文档
Claude 每次都从空白上下文开始。CLAUDE.md 是打破这个限制的方式——session 启动时自动加载进上下文,相当于 Claude 的持久记忆。跑 /init 可以自动生成一份初版,然后手动精简。
这东西最容易写砸的方式就是当项目文档来用。架构说明、API 介绍、详细流程,想到什么就往里塞,最后几百行,Claude 读完早忘了前面写了什么。官方建议控制在 200 行以内——CLAUDE.md 本身也占上下文,太长会挤占正事的空间。
判断标准就一条:删掉这行,Claude 会不会犯错? 不会就别留着。
什么时候该加东西?Claude 反复问同一类问题,或者反复犯同一类错,说明这条规矩值得固化下来。比如「用 ES modules 不要用 CommonJS」「跑单个测试不要跑全套」这类,不写就会反复踩坑的东西。
临时背景不要往里塞。某个功能的上下文、当前正在调的 bug 细节,这些放当前提示或 SPEC.md 里就好,别永久污染每次启动。
提示词具体一点,省的是你自己的时间
模糊的提示不是不能用,但后续纠正的时间远超你多打那几个字的时间。几个对比:
「给 foo.py 加测试」→「给 foo.py 写测试,覆盖用户未登录的情况,不要用 mock」
「修登录的 bug」→「用户反馈 session 超时后登录失败,查 src/auth/,写个复现的失败测试,修完确认通过」
「加一个日历组件」→「看 HotDogWidget.php 的实现方式,按同样的模式做一个日历组件,支持选月和前后翻页,不引入新依赖」
区别不在于字数多了多少,在于 Claude 不需要猜你要什么。猜意味着猜错的概率,猜错意味着你要花时间纠正,纠正意味着上下文变脏。用 @ 引用文件比描述路径高效,截图可以直接粘进去,错误日志可以 pipe 过来:
cat error.log | claude -p "有没有异常,总结一下原因"
subagent 适合甩脏活,不适合当主力
上下文满了怎么办?一部分答案是 subagent。调查性的任务特别适合甩给它——「auth 相关的文件有哪些」「这个模块的数据流怎么走」——subagent 用自己的上下文去读文件、grep 代码,只把结论还给主 session,主上下文几乎不受影响。
但 subagent 不是万能的。需要连续判断的主线实现别交给它,否则只是把上下文问题换了个地方。它适合探索和归纳,不适合写需要贯通多轮上下文的核心代码。
回过头看,用好 Claude Code 真正要改的只有一个旧习惯:出了问题不要硬纠正。开头那个登录 bug,三轮没修好不是 Claude 的问题,是我一直带着失败上下文在硬试。/clear 之后一次过——省下的不只是那一天的来回,是之后每次想「再试一轮吧」时会多想一秒。