作者实践了用AGENTS.md统一生成CLAUDE.md等规则文件并加入CI校验,发现跨仓库同步和全局配置层面仍存在规则漂移问题。
解决"我们的 agent 指令文件不断发散"最直接的办法,就是不再维护多份副本。写一份 AGENTS.md,从中生成 CLAUDE.md、.cursor/rules/*.mdc 和 .github/copilot-instructions.md,搞定。
我实现了这个方案。它能工作。但它并没有真正解决问题——这两种说法之间的差距值得明确说出来,因为我是直到在真实机器上运行之后才看到这一点的。
python3 agent_fanout.py
create CLAUDE.md
create .cursor/rules/from-agents-md.mdc
create .github/copilot-instructions.md
一个源头,多个派生文件,每个文件都带一个头部注释,防止有人不小心直接编辑派生副本:
<!-- Generated from AGENTS.md by agent-fanout. Do not edit this file. -->
把它加到 CI 里,直接编辑 CLAUDE.md 的 PR 就会让构建变红:
- run: python3 agent_fanout.py . --check
这覆盖了这个仓库、在跑 CI 的机器上。听起来像是覆盖了所有场景,直到你列出它没有覆盖的东西。
其他仓库。 你的团队不止有一个。每个仓库都有自己独立的 AGENTS.md,它们之间曾经互相复制粘贴过。生成机制保持了每个仓库内部的一致性,但各个仓库之间却在彼此发散。
全局配置。 Claude Code 除了项目级文件之外还会读取 ~/.claude/CLAUDE.md。Cursor 有人级规则。这些文件存在于任何仓库之外,永远不会进入 CI,而恰恰就是这些地方,人们放入了那些不想在 review 里争论的规则。
两次编辑之间的窗口。 生成脚本在有人运行它时才执行。从那一刻到下一次 CI 运行之间,派生文件可以被编辑和使用。Agent 立即读取它;CI 要到 push 时才注意到(如果有 push 的话)。
没有 CI 的仓库。 原型项目、临时 clone、某个人上周新建的仓库。这些地方指令被随意修改,而且它们恰恰是没有任何把关的地方。
机器,而非仓库。 运行 agent 的单元是一台笔记本。一台笔记本上有多个 checkout、同一仓库的多份克隆、还有 home 目录。任何按仓库维度运作的机制都看不到跨仓库的情况。
预防是一种策略。检测是一种测量。策略会以难以察觉的方式被绕过,直到你开始测量。
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 并不算 drift,如果把这种情况也报成 drift,输出就毫无价值了。(把分组逻辑做对花了三次重写;那部分我单独写过。)
对整个工作目录跑一遍,不要只扫一个项目。有意思的结果往往是跨越仓库边界的那些。
生成机制消除了副本存在的理由。检测机制捕获那些出于你未曾预料的原因而存在的副本。两者缺一不可,只做前者会给你一种虚假的覆盖感——这才是我真正想警告的失败模式,因为它是我自己踩过的坑。
两个脚本都是单文件 Python,无依赖,需要只读的地方只做只读,MIT 协议:
agent-fanout — 写一次 AGENTS.md,生成其余文件
agent-drift — 找出那些不再一致的副本
真正理想的状态是两个脚本都不再需要,因为资产根本不是躺在笔记本上的文件——它们存在于一个经过 review 的地方,触达每一台机器,而无需任何人复制任何东西。这正是我目前在 untactit 正在构建的东西,目前还在 pre-launch 阶段。
这两个脚本独立运作,不依赖上述愿景。尽管用,别管其他的。