CLAUDE.md を書いたのは一度だけです。半年後、ノート PC の中には 18 個あって、どれが正しいのか言えなくなっています。
たとえ話ではありません。自分のマシンをスキャンしたら、そのままの数が出ました。以下は、なぜそうなるのかと、真っ先に思いつく対処がなぜ効かないのかの話です。
エージェントはそれぞれ、自分が決めたパスから指示を読みます。
| ツール | パス |
|---|---|
| Claude Code | CLAUDE.md、~/.claude/CLAUDE.md |
| Cursor | .cursor/rules/*.mdc |
| GitHub Copilot | .github/copilot-instructions.md |
| Codex ほか | AGENTS.md |
コピーを 4 つ持とうと決めた覚えはないはずです。決めたのはツールを 4 つ使うことで、コピーはそれについてきました。
ズレを生む仕組みは 3 つあります。どれも、誰かが雑だから起きるものではありません。
使っている場所で直す。 作業の途中でエージェントの挙動がおかしくなる。目の前で開いている指示ファイルを直す。そのファイルは 4 つのうちの 1 つで、修正も 1 つにしか入りません。
単位はチェックアウトではない。 同じリポジトリを 2 つクローンしている。main 用と、長く生きているブランチ用。どちらにも指示ファイルがあります。片方に手を入れた瞬間に、2 つは分かれます。
ホームディレクトリの指針は見えない。 ~/.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 が回っている、このリポジトリ です。全部に聞こえますが、外に出るものを並べると話が変わります。
防止はルールです。検出は計測です。ルールは、計測しないと見えない形で迂回されます。
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 が違うのは正常であって、それをズレとして報告するツールは使われなくなります。1 プロジェクトではなく、作業ディレクトリ全体に向けてください。見るべき結果は、リポジトリの境界をまたいだところに出ます。
| 範囲 | 答える問い | |
|---|---|---|
| agent-fanout | リポジトリ 1 つ | 派生ファイルは最新か |
| agent-drift | マシン全体、複数のパス | コピーはどこで分かれたか |
生成は、コピーが存在する理由をなくします。検出は、想定していなかった理由で存在してしまったコピーを捕まえます。片方だけやると カバーできている気になる だけで、できていないと分かっている状態より悪くなります。私自身がそこにはまりました。
正直に言えば、行き着く先はどちらのスクリプトも要らない状態です。資産がマシン上にファイルとして散らばっておらず、レビュー済みの 1 つがどのマシンにも届く。属人的な手作業をなくす、という方向です。触らないから、ばらつかない。それを untactit で作っています。現在は公開前です。
スクリプトはそれに依存しません。使えるところだけ持っていってください。