I found 18 versions of the same CLAUDE.md on one laptop A developer has released agent_drift, an open-source Python script that detects when copies of AI agent instruction files such as CLAUDE.md, .cursor/rules/*.mdc, and .github/copilot-instructions.md have drifted out of sync across a codebase. The tool uses 5-word shingles and a representative-based clustering algorithm to identify genuine forks of the same document, and it can be integrated into CI to fail builds when drift is detected. The developer is also building a related product called untactit, but the script is independent. Your team runs Claude Code, Cursor, and Copilot. Each of them reads a file before it acts — CLAUDE.md , .cursor/rules/ .mdc , .github/copilot-instructions.md . Those files get copied: into another repo, onto another laptop, into someone's scratch directory. Then somebody edits a copy. Nothing errors. No warning, no diff, no failing test. The agent on that machine just behaves differently — a rule someone removed six weeks ago, a convention only half the team's agents know about. It shows up as "works on my machine" with nothing to bisect. I wrote a script to find those files and tell you which copies disagree. 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 One file, standard library only, Python 3.8+. Reads only — it never writes to the files it scans. MIT. The naive version took me ten minutes and was useless. The three fixes are the whole story. First version: collect every CLAUDE.md , hash them, report the ones that differ. Ran it on my own machine. It reported 21 files as one document with 18 versions . Of course it did. Unrelated projects have unrelated instructions. They were never supposed to match. A tool that reports that as drift is noise, and a noisy tool is worse than no tool — you stop reading it by the third run. Files are the same document when their content says so, not when their filename does. So: normalise whitespace, tokenise, compare with Jaccard similarity, threshold 0.7. Still one giant cluster. I measured actual pairs to find out why: 012Hki23QBMr ↔ 016ct6suZ14M : 0.000 012Hki23QBMr ↔ 016avoYh97Eu : 0.764 Instruction files written for the same tool share almost all of their vocabulary. claude , skill , agent , file , commit , never , always . Two documents with nothing in common still overlap heavily as word sets. Switched to 5-word shingles — the set of every consecutive 5-word phrase. Vocabulary can collide; phrasing rarely does. Re-measured: unrelated pairs dropped to 0.000, genuinely forked documents landed at 0.53–0.76. That separation is what you want, and it came from measuring, not from reasoning about it. Still one cluster. This one is a classic. Union-find with "similar to any member" means A joins B, B joins C, and now A and C are in the same cluster despite sharing nothing. One weak link and the cluster swallows the tree. Each cluster now keeps a representative — its largest member — and a file joins only if it resembles that representative directly. Clusters stay coherent regardless of scan order. Final result on my machine: 15 files, 9 of them 0.53–0.65 similar to the representative. Those really are forks of one template. Correct detection, and the number is small enough to act on. - run: python3 agent drift.py . --fail-on-drift Exit 1 when drift exists. The build goes red the day two copies of your team's instructions stop matching, instead of you finding out in six months when someone asks why the agent stopped following a rule. --json gives you the full report if you'd rather post-process it. Claude Code, Codex/ AGENTS.md , Cursor, GitHub Copilot, Gemini, Windsurf, Cline, Aider, Continue, Zed. The patterns are one constant at the top of the file — PR or issue if yours is missing. Detection is the easy half. The copies exist for a reason, and until that reason is gone the drift comes back. What removes it is one reviewed source that reaches every machine without anyone pasting anything. That's the problem I'm building untactit https://untactit.com around — it's pre-launch. This script doesn't depend on it and never will.