TECH

上下文管理、Plan Mode、CLAUDE.md——用了一段时间,整理几个差距最明显的做法,以及几个反复踩的坑。

刚开始用 Claude Code 的时候,用法很简单:描述需求,等它写,看到不对再纠正。这样用确实能干活,但稍微复杂一点的任务,总感觉越改越乱——Claude 开始忘掉之前说过的东西,同一个错误改了三遍还在犯。

后来才意识到,Claude Code 不是一个更聪明的代码补全,它是一个有状态的 agentic 工具。它维护着整个对话的上下文,这个上下文会越来越满,越满性能越差。官方文档里对这件事说得很直接:几乎所有最佳实践都基于一个约束——上下文窗口填得很快,填满之后性能下降。

上下文窗口是唯一重要的事

上下文里装着所有对话记录、每次读过的文件内容、每条命令的输出。一个稍微长一点的调试 session,很容易就消耗掉几万 token。窗口越满,Claude 越容易忘掉早期的指令,开始犯低级错误。

所以与其想「怎么给 Claude 更多信息」,不如想「怎么让上下文保持干净」。

最直接的操作:

  • 任务之间跑 /clear 清空上下文,不要把上一个任务的残留带进来
  • 卡住之后反复纠正超过两次——停下来,/clear 重开,写一个更精确的提示,几乎总比继续改快
  • 调查性的任务(「这个模块的结构是什么」「找所有涉及 auth 的文件」)交给 subagent 做,它用自己的上下文读文件,只把结论还给主 session

Esc 键也很有用,随时可以打断 Claude 正在做的事,重新定向,上下文保留不变。如果改坏了,Esc+Esc/rewind 可以回到任意一个检查点,可以只回滚代码,也可以同时回滚对话。

给 Claude 一个自检的方式

官方把这件事列为「单项收益最高的做法」,用下来确实如此。

如果只是描述了一个需求,Claude 给出的结果看起来可能没问题,但在某个边界情况下悄悄出错。你成了唯一的验证环节,每个问题都要自己发现再纠正。

换一种方式:提示里直接给出验证条件。

写一个 validateEmail 函数。测试用例:user@example.com → true,invalid → false,user@.com → false。写完之后跑测试,修掉失败的。

这样 Claude 自己就能知道有没有做对。你只需要看它给的证据——测试输出、命令结果——而不是重新跑一遍。

UI 改动也一样。把截图粘进去,让它截图对比,列出差异,自己迭代。「让 dashboard 好看点」这种提示,写出来的东西只有它自己觉得对。

先规划,再写代码

让 Claude 直接开始写代码,容易解决了一个错误的问题——特别是对不熟悉的代码库,或者改动跨多个文件的时候。

推荐的流程是四步:进入 Plan Mode(Shift+Tab 切换)先探索代码,不做任何修改;然后让它出一份方案,涉及哪些文件、流程怎么走;确认方案没问题之后退出 Plan Mode 开始实现,同时让它跑测试;最后 commit 和 PR。

不过规划本身也有开销,改一行 log、重命名一个变量,直接做更快。Plan Mode 适合的是:方案不确定、改动跨多个文件、这部分代码你不熟悉。

还有一个用法:让 Claude 先来采访你。

我想做 [简短描述]。用 AskUserQuestion 工具采访我——技术实现、UI/UX、边界情况、取舍都要问到。别问显而易见的,挖我没想清楚的地方。采访完写一份完整的 spec 到 SPEC.md。

Claude 会问出你自己没想到的问题。采访结束之后,新开一个 session 来实现,上下文干净,有书面 spec 可以对照。

CLAUDE.md:跨 session 的记忆

Claude 每次都从空白上下文开始,CLAUDE.md 是打破这个限制的方式。它在每次 session 开始时被读取,相当于写给 Claude 的持久说明书。

/init 可以让 Claude 分析你的项目自动生成一份初版,然后手动调整。格式没有要求,保持可读就行:

# Code style
- Use ES modules (import/export), not CommonJS (require)
- Destructure imports when possible

# Workflow
- Typecheck after a series of code changes
- Run single tests, not the full suite

判断标准只有一个:删掉这行,Claude 会不会犯错? 如果不会,删掉。

常见的误区是把 CLAUDE.md 写成项目文档——架构说明、API 介绍、详细流程。越堆越长,长了就被忽略。官方建议控制在 200 行以内,这个上限不是随便定的:CLAUDE.md 本身也进上下文,太长会挤占每次 session 的起始空间,而且 Claude 会开始漏掉其中的规则。

如果发现 Claude 反复问同一类问题,或者反复犯同一类错——那就是提示你该往 CLAUDE.md 里加东西了。

提示词越具体,纠正越少

模糊的提示不是不行,但后续的纠正成本更高。几个对比:

「给 foo.py 加测试」→「给 foo.py 写测试,覆盖用户未登录的情况,不要用 mock」

「修登录的 bug」→「用户反馈 session 超时后登录失败,检查 src/auth/,写个复现的失败测试,修完确认通过,解决根本原因,不要只是压掉错误」

「加一个日历组件」→「看 HotDogWidget.php 的实现方式,按同样的模式做一个日历组件,支持选月和前后翻页,不引入新依赖」

@ 直接引用文件比描述「在某某目录下有个文件」更高效。截图可以直接粘贴或拖进去。错误日志可以 pipe 进来:

cat error.log | claude -p "有没有异常,总结一下原因"

几个容易浪费时间的模式

反复纠正却不清空上下文。 Claude 犯了错,你纠正,还错,再纠正——上下文里全是失败的尝试,继续纠正很难比重开更快。及时认赔,/clear,把学到的东西写进新的提示里。

CLAUDE.md 越写越长。 想到什么就往里加,最后几百行,Claude 读完早就忘了前面写了什么。精简比堆砌更重要,每行都应该是会让 Claude 犯错的信息,其余的删掉。

让 Claude 去「调查」却没有限定范围。 Claude 开始读文件,越读越多,上下文很快就满了。这类任务交给 subagent,主 session 只接收结论。

没有验证方式就算完成。 功能看起来能跑,但没有测试、没有命令验证、没有截图对比,出了问题不知道是什么时候引入的。给 Claude 一个能自检的条件,不只是提升输出质量,也是在替自己省事。


用了一段时间之后,对 Claude Code 的感觉是:你越清楚自己要什么,它越有用。 它不会替你想清楚问题,但能让想清楚之后的落地速度快很多。