博客

同一个 CLAUDE.md,在一台笔记本上有 18 个版本

2026年8月11日untactit

你们团队在用 Claude Code、Cursor 和 Copilot。它们动手之前都会先读一个文件 —— CLAUDE.md.cursor/rules/*.mdc.github/copilot-instructions.md。这些文件会被复制出去:复制进另一个仓库,复制到另一台笔记本,复制进某个人的临时目录。

然后有人改了其中一份。

不报错。没有警告,没有 diff,没有测试失败。那台机器上的智能体只是行为不一样了 —— 六周前有人删掉的一条规则,或者只有半个团队的智能体知道的一条约定。它以“在我机器上是好的”的形式浮出来,而且没有东西可以二分定位。

我写了个脚本,把这些文件找出来,告诉你哪些副本对不上。

curl -O https://raw.githubusercontent.com/untactit/agent-drift/main/agent_drift.py
python3 agent_drift.py ~/work
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
        ~/work/api/CLAUDE.md
        ~/work/web/CLAUDE.md
      2dc3c616c279  2 files, 411 lines
        ~/work/infra/CLAUDE.md

单个文件,只用标准库,Python 3.8+。只读 —— 它从不写它扫过的文件。MIT。

有意思的部分是我错在哪

最朴素的那版我花了十分钟写完,然后毫无用处。真正的内容是那三处修正。

按文件名分组是错的

第一版:把每一个 CLAUDE.md 收集起来,算哈希,把不一样的报出来。

在自己机器上跑了一遍。它报出21 个文件属于同一个文档,有 18 个版本

当然会这样。互不相干的项目本来就有互不相干的指令。它们从来就不该一致。把这个报成漂移的工具就是噪音,而噪音工具比没有工具更糟 —— 跑到第三次你就不看它了。

两个文件是不是同一份文档,由内容说了算,不是由文件名说了算。

词袋也不够用

于是:归一化空白,分词,用 Jaccard 相似度比较,阈值 0.7。

还是一个大团。我去测了具体的文件对,看看为什么:

012Hki23QBMr ↔ 016ct6suZ14M : 0.000
012Hki23QBMr ↔ 016avoYh97Eu : 0.764

给同一个工具写的指令文件,用词几乎完全重合。claudeskillagentfilecommitneveralways。两份毫无关系的文档,当成词集合看照样高度重叠。

换成 5 词 shingle —— 把文本里每一段连续 5 个词的短语收成一个集合。用词可以撞,措辞很少撞。重新测:不相干的文件对掉到 0.000,真正分叉出来的文档落在 0.53–0.76。这个分离度正是你要的,而它来自实测,不是来自推理。

单链接聚类会把所有东西串到一起

还是一个大团。这个是经典问题。

并查集加上“和任意一个成员相似就算”,意味着 A 并进 B,B 并进 C,于是 A 和 C 明明毫无共同点却进了同一个簇。一条弱连接,整棵树就被这个簇吞掉。

现在每个簇都保留一个代表元 —— 簇里最大的那份 —— 一个文件只有直接和这个代表元相似才会加进来。不管扫描顺序如何,簇都保持内聚。

在我机器上的最终结果:15 个文件,其中 9 个与代表元的相似度在 0.53–0.65。这些确实是同一份模板分叉出来的。检测是对的,而且数量小到可以动手处理。

把它放进 CI

- run: python3 agent_drift.py . --fail-on-drift

存在漂移就以 1 退出。团队指令的两份副本对不上的那一天构建就变红,而不是半年后有人问“智能体为什么不遵守某条规则了”你才发现。

--json 会给你完整报告,你想自己做后处理就用它。

覆盖了哪些工具

Claude Code、Codex/AGENTS.md、Cursor、GitHub Copilot、Gemini、Windsurf、Cline、Aider、Continue、Zed。这些路径模式就是文件顶部的一个常量 —— 少了你在用的那个,提 PR 或开 issue。

找出来之后呢

检测是这件事里难度低的那一半。副本的存在是有原因的,原因不消失,漂移就会回来。真正让它消失的,是一份评审过的源头,不靠任何人粘贴就到达每一台机器。

这就是我做 untactit 要解的问题 —— 尚未公开发布。这个脚本不依赖它,以后也不会。

仓库:github.com/untactit/agent-drift

本文也发在 DEV。

相关文章

别再猜智能体在跑什么。

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

免费开始 联系我们

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