博客

CLAUDE.md 在每台机器上都不一样,不是因为谁不小心

2026年8月13日untactit

CLAUDE.md 你只写过一次。半年后笔记本上有十八份,而你说不出哪一份才是对的。

这不是假设。我扫了自己的机器,结果正是如此。下面讲的是它为什么会发生,以及那个看上去理所当然的解法为什么解不掉。

副本是工具造出来的,不是你造的

每个智能体都从它自己认定的路径读指令。

工具路径
Claude CodeCLAUDE.md~/.claude/CLAUDE.md
Cursor.cursor/rules/*.mdc
GitHub Copilot.github/copilot-instructions.md
Codex / 其他AGENTS.md

你没有决定要留四份副本。你决定的是用四个工具。副本是跟着工具一起来的。

漂移不是粗心造成的

有三种机制在制造它,没有一种需要谁马虎。

在用的地方就地改。 智能体在任务中间跑偏了。你顺手改掉眼前打开的那个指令文件。那个文件只是四份中的一份,改动也只落在那一份里。

检出目录不是单位。 同一个仓库你克隆了两份 —— 一份跟主分支,一份跟长期分支。两份都带着指令文件。只要有一边被碰过,它们当场就分家了。

主目录里的规则是看不见的。 ~/.claude/CLAUDE.md 不属于任何仓库。它不进任何 CI。那些你不想在评审里争论的规则,最后都落在这里。

用单一源头生成,堵不上这个口子

顺理成章的反应是别再留副本:只写一次 AGENTS.md,其余的都生成出来。

这个我做了。它能用。就是 agent-fanout —— 单文件 Python,零依赖,MIT。

python3 agent_fanout.py

create    CLAUDE.md
create    .cursor/rules/from-agents-md.mdc
create    .github/copilot-instructions.md

生成出来的文件都带一行头注,免得有人直接去改,CI 里加上 --check,谁手改了衍生文件,构建就变红。

这覆盖的是这个仓库,而且是在跑 CI 的地方。 听起来像是全都覆盖了,直到你把漏在外面的部分列出来:

  • 主目录里的全局配置 —— 没有仓库,没有 CI
  • 两次生成之间的窗口 —— 文件一改,智能体立刻就读到;CI 要等推送才发现,前提是有人推送
  • 没有 CI 的仓库 —— 原型、随手克隆的副本、上周的实验。指令被改得最自由的地方,恰好也是把关最少的地方
  • 单位是机器,不是仓库。 智能体跑在一台笔记本上,这台笔记本装着许多检出目录、同一个仓库的好几份副本,还有一个主目录。任何以仓库为范围的东西都看不到这一层。

所以要测量,不能只做预防

预防是制度。检测是测量。制度会以你看不见的方式被绕过去,除非你去测。

agent-drift 扫的是路径而不是仓库,分组依据是内容相似度而不是文件名:

python3 agent_drift.py ~/work ~/side-projects

Scanned 47 instruction files.
DRIFT: 2 documents, 5 distinct versions between them.

  claude-code:CLAUDE.md
    6 copies, 3 versions
      9b01aeaa204d  3 files, 406 lines
      2dc3c616c279  2 files, 411 lines

在这里按文件名匹配是没用的。互不相干的项目有不一样的 CLAUDE.md,这本来就是对的,把这个报成漂移的工具没人会再用第二次。把它指向你整个工作目录,而不是某一个项目 —— 有价值的结果都是跨仓库的那些。

这是两件事,不是一件

范围它回答的问题
agent-fanout单个仓库衍生文件是不是最新的
agent-drift整台机器,多条路径副本是在哪里分的家

生成消掉的是副本存在的理由。检测抓的是那些因为你没预料到的理由而存在的副本。只做一件,你会觉得自己盖住了,这比知道自己没盖住更糟。我自己就掉进去过。

终点在哪

老实说,终点是这两个脚本都不再需要 —— 资产不再以文件的形式散落在一台台机器上,一份评审过的内容自己到达每一台机器。这就是我在 untactit 做的事,目前尚未公开发布。

这两个脚本不依赖它。哪一部分有用就拿哪一部分。

本文也发在 DEV。

相关文章

别再猜智能体在跑什么。

接入一个工作区,约十分钟内,团队在用的每个技能、规则与记忆一览无余。

免费开始 联系我们

无需信用卡。直接接入现有工具。