一年使用经验的开发者总结 CLAUDE.md 写法的常见错误,包括反复修改指令应入文件、文件规则不等于硬性约束等实用建议。
我在日常开发中使用 Claude Code 已经超过一年了,而在这段时间里,我的 CLAUDE.md 一直在帮倒忙。不是那种戏剧性的反向作用,只是持续的修正代价:反复纠正、遗忘的规则,以及随着一天推移变得越来越慢、越来越迟钝的会话。
以下是我一直在犯的错误,以及真正解决问题的办法。
有好几个月,我都在聊天里反复输入同样的纠正。"用 pnpm,不要用 npm。" "不要碰 migrations 文件夹。" "文档用英式拼写。" 每个会话都是如此。
明显付出的代价是我的时间。不那么明显的代价是 token。每次在聊天中重复一条指令,都是在这个会话中消耗的上下文,而它会在会话结束时消失。写在 CLAUDE.md 里的一条指令只会加载一次,自动加载,每个会话都生效,永远。
我现在的规则:如果一条纠正我输入了两次,在第三次输入之前就把它写进 CLAUDE.md。就这一个习惯就消除了我大部分日常摩擦。
它不是。CLAUDE.md 里的一条指令是一条请求。模型会读取它,通常会遵守,但偶尔不会,特别是在长会话深入下去、早期的上下文已经消退的时候。
当"永远不要直接提交到 main"恰好在关键的那一天失效时,我才明白了这一点。解决办法是意识到 Claude Code 有两个不同的工具来做两件不同的事:
CLAUDE.md 适用于偏好和约定,那些 95% 遵守率就够了的事情。
Hooks 适用于规则,那些 95% 就是失败的事情。一个 PreToolUse hook 会检查命令并以非零值退出,确定性地阻止操作。模型不会忘记一个 hook,因为 hook 不是模型。
现在,任何我会描述为"绝对不能发生"的事情都是 hook。任何我会描述为"偏好这个"的事情就留在 CLAUDE.md 里。把我的规则分成这两个桶花了二十分钟,消除了一整类事故。
默认情况下,我会说"看一下 auth 模块",然后看它拉入数千行代码,其中大部分毫不相关。这些行每一条都占用了本可以存放有用信息的上下文。
解决办法:在提示中具体化("读取 auth/session.ts 中的 validateSession 函数,在 token 检查附近的行"),并在 CLAUDE.md 中加一行,请求用定向读取替代整文件读取。先 grep,读取匹配的区域,只在需要时才扩展。会话保持敏锐的时间明显更长。
我以前习惯整天保持一个会话活着。早上重构,午饭后调试,快结束时写文档。到了下午,模型在每个响应中都拖着早晨的十万多 token 上下文,质量下降的原因很容易归咎于模型而不是我自己。
按领域分新鲜会话永远胜过一个漫长拖沓的会话。重构时的上下文在文档工作期间不只是浪费空间,它还会主动产生偏见。当我切换任务类型时,我就重新开始,让 CLAUDE.md 把持久规则带过去。
压缩是对话摘要,以便工作可以继续,而摘要是会有损的。在 delicate 变更的中途压缩,被丢弃的细节恰恰就是你需要的那一些。
解决办法是时机。我在边界处压缩:任务完成、测试套件变绿、决策记录下来。在压缩之前,我确保当前状态写在磁盘上的某个地方,一个笔记文件或计划文档,这样恢复的会话就可以从文件而不是从摘要中恢复具体细节。
这一点让我意外。每个启用的 MCP 服务器在每次请求时都会将其完整的工具定义注入上下文,无论你是否使用它。我积累了一打服务器,每次请求要为那些一个月才用一次的工具付出数千 token。
审查你的。禁用在两周内没有使用过的任何东西。当真正需要时重新启用只需要几秒钟,而省下来的上下文就用在你的实际代码上。
当我不知道某个东西在哪里时,我会让主会话搜索、打开文件、跟随死胡同。所有这些探索,包括死胡同,都会留在接下来的会话上下文中。
Subagents 解决了这个问题。把探索委托出去("找到速率限制应用的位置并报告文件路径和关键函数"),只有答案会回到主线程。错误的转弯会随着 subagent 一起被丢弃。主会话保持专注在实际变更上。
以上每个错误都是同一类错误穿着不同的外衣:把上下文当作免费的。它不是。它是整个配置中最稀缺的资源,几乎所有感觉像是模型问题的情形,实际上都是我亲手造成的上下文问题。
持久的规则写在 CLAUDE.md 里。硬规则写在 hooks 里。定向读取。按领域分新鲜会话。在边界处压缩。精简 MCP 列表。委托探索。
没有什么是聪明的。但一切都会产生复合效应。
你的 CLAUDE.md 里有什么是你发现自己还是在聊天中重复的?我很好奇是否有其他人以和我一样的方式遇到了指令与强制执行之间的那堵墙。