A linter for the files your AI assistants read.
CLAUDE.md, AGENTS.md, .cursorrules and friends are full of instructions
like "read docs/architecture.md before touching the router". Then the file
moves, gets renamed, or grows into a folder — and the instruction quietly
becomes a lie. Nothing errors. The assistant just silently fails to find it and
carries on without the context you meant it to have.
agents-sync reads those files, follows every path they mention, and tells you
which ones point nowhere — plus, where it can, where the file actually went.
$ agents-sync
✗ broken-ref CLAUDE.md:3
docs/architeture.md — not found
→ docs/architecture.md (did you mean?)
✗ broken-ref CLAUDE.md:4
src/config.ts — not found
→ src/config/index.ts (moved — fixable)
2 broken-ref
agents-sync apply rewrites the confident ones. The typo above is offered but
never applied on its own — near-misses are a human's call.
If you keep the same facts in more than one of these files, it compares those too; see Comparing facts.
Pointed at six public repositories carrying a
CLAUDE.md, it reported three dead references and nothing else. All three were real:haddock3had moveddocs/todocs/pages/, andreact-data-table-componenthad convertedapi.mdtoapi.astro— in both cases without updating the instructions.
Zero dependencies, no build step — clone it and run it.
git clone https://github.com/berkdemir18/agents-sync.git
cd agents-sync
npm linknpm link puts agents-sync on your PATH. If you would rather not, call it
directly instead: node /path/to/agents-sync/bin/agents-sync.js.
Requires Node 18+.
agents-sync # report disagreements (exit 1 if any)
agents-sync report # build an HTML page you can actually look at
agents-sync apply # rewrite stale values from the authoritative file
agents-sync init # write agents-sync.json listing the files it found| Option | Meaning |
|---|---|
--dir <path> |
directory to scan (default: current directory) |
--out <file> |
with report: where to write the page |
--open |
with report: open the page in your browser |
--json |
machine-readable output |
--quiet |
findings only, skip the file listing |
--no-refs |
skip the broken-reference check |
--no-facts |
skip the fact-comparison check |
--no-backup |
with apply: don't write .agents-sync.bak copies |
Paths are picked up however they are written:
- in prose — "read docs/architecture.md first"
- in backticks —
`scripts/deploy.sh` - as markdown links —
[guide](docs/guide.md) - as
[[wikilinks]], for note vaults
A token only counts if it carries a file extension and a separator, which is
what keeps and/or, npm run build and bare URL hosts out of the results. Code
fences are skipped entirely, and a path already captured in backticks is not
matched a second time as prose.
Precision matters more than recall — a linter that cries wolf gets uninstalled. A reference is only reported when the tool can say something useful about it: either the parent folder exists, so the file was clearly meant to be there, or a plausible candidate was found elsewhere. Three cases are deliberately treated as fine:
- Partial paths.
850-Companion/Last-Session.mdwhen the real file isvault/00 - Sistem/850-Companion/Last-Session.md. A reader follows that without trouble, so it counts as resolved. - Paths belonging to somewhere else. If it cannot be placed and nothing resembles it, it is more likely to be another project's file than a mistake.
- Same name, unrelated folder.
notes/core.mdis not "fixed" to acore.mdsitting in some cache directory. A candidate has to live in a folder the reference actually names.
If the same fact lives in more than one of these files, it is compared too:
stale — the same key holds different values in two files. The file that disagrees with the authoritative one is reported, with both values shown.
duplicate — one file states the same key twice with different values. No assistant can tell which one you meant.
agents-sync report --openWrites a single self-contained HTML file — no server, no build, no network — and opens it. It shows the same findings as the terminal, plus the part the terminal cannot: every fact your assistants hold, which file each came from, how fresh that file is, and where two files say different things. There is a filter box and an "only disagreements" toggle.
The page is a snapshot of your memory files, so it contains whatever they contain. It is gitignored by default — keep it that way.
agents-sync scheduleWindows only. The scheduled task, the notification and its buttons all use Windows APIs. Everywhere else the CLI works exactly the same — put it in cron (see the end of this section) and you get the weekly run, just without the toast.
Registers a weekly Windows task — Sunday 10:00 by default, --day and --at
to change it. Four things make it liveable:
- A missed week is not a skipped week. If the machine is off at the scheduled moment, Windows runs the task the next time you log in.
- It only speaks up about things you have not seen. Findings are remembered between runs, so a conflict you decided to live with does not come back every Sunday. Only genuinely new ones raise a notification.
- The notification waits for you. It stays on screen until you deal with it rather than sliding away while you are in another room.
- You fix it from the notification. Three buttons: Fix n applies every auto-fixable finding right there, Open report shows the page, Remind me tomorrow schedules a one-off nudge for the same findings. No terminal involved — which matters, because typing a command every Sunday is a habit nobody keeps.
Those buttons need somewhere to go, so schedule also registers an
agents-sync:// URI handler under HKCU\Software\Classes — per user, no admin
rights. agents-sync schedule --remove deletes both the tasks and the handler.
agents-sync schedule --status # when it last ran, when it runs next
agents-sync schedule --run-now # trigger it right now
agents-sync schedule --remove # unregister itElsewhere, cron does the same job:
0 10 * * 0 agents-sync report --notify --dir ~By default, whichever file was updated most recently. Freshness comes from a
frontmatter date (son_guncelleme, updated, last_updated, date, …) when
there is one, otherwise from the file's modification time.
To decide it yourself, run agents-sync init and set an authority number —
higher wins:
{
"files": [
{ "path": "docs/stack.md", "authority": 100 },
{ "path": "AGENTS.md" },
{ "path": ".claude/CLAUDE.md" }
],
"roots": [],
"ignoreKeys": ["status"],
"ignoreRefs": ["example.com"]
}ignoreKeys skips a key entirely. ignoreRefs mutes any reference containing
one of the given strings (case-insensitive) — useful for the placeholder paths
that show up in prose.
Files can be absolute paths, so a repo's AGENTS.md can be checked against a
notes vault living somewhere else entirely.
Without a config file, these are auto-detected in the current directory:
AGENTS.md, CLAUDE.md, .claude/CLAUDE.md, GEMINI.md, .cursorrules,
.cursor/rules/*.mdc, .windsurfrules, .github/copilot-instructions.md,
.aider.conf.md, memory/MEMORY.md, and Claude Code's per-project memory
folders.
Only shapes that are unambiguous:
- rows of a two-column markdown table (the header row is skipped, wider tables are ignored — those are data, not facts)
- **Key:** valuedefinition lines, but only when that key also appears as a table key somewhere, so section headings like**Why:**are never compared across unrelated files
Values are compared after markdown emphasis, link syntax and italic side notes
are stripped. If one value merely elaborates on the other (Postgres 16 vs
Postgres 16 (managed)), that is not a conflict.
Most instruction files are prose and have no such tables, in which case this check simply finds nothing and stays out of the way.
agents-sync exits 1 when it finds something, so it drops into a workflow as-is:
- run: node path/to/agents-sync/bin/agents-sync.js --quietOr as a pre-commit hook:
agents-sync --quiet || exit 1agents-sync apply rewrites two things, and only the referenced text itself —
table pipes, list markers and surrounding prose are left alone:
- a broken reference with exactly one confident candidate, written back in the same style it used (relative or absolute, forward or back slashes)
- a stale value, replaced with the authoritative one
Every edited file gets a .agents-sync.bak copy first (--no-backup opts out).
If a line changed since the scan, that fix is skipped rather than guessed at.
Never auto-fixed: near-miss suggestions, references with more than one candidate, and duplicates. Each of those needs a human to decide what was meant.
Built by @berkdemir18 with AI assistance — the idea, scope and design calls are mine, the implementation was written with an AI coding assistant. Which is, fittingly, how the problem this tool solves turned up in the first place.
AI asistanlarının okuduğu dosyalar için bir denetleyici.
CLAUDE.md, AGENTS.md, .cursorrules gibi dosyalar şu tarz talimatlarla
dolu: "router'a dokunmadan önce docs/architecture.md dosyasını oku."
Sonra o dosya taşınır, adı değişir ya da bir klasöre dönüşür — ve talimat
sessizce yalan olur. Hiçbir hata çıkmaz. Asistan dosyayı bulamaz, sana
vermek istediğin bağlam olmadan cevap verir.
agents-sync bu dosyaları okur, içlerinde geçen bütün yolları takip eder ve
hangisinin boşa çıktığını söyler — mümkün olduğunda da dosyanın nereye
gittiğini gösterir.
✗ broken-ref CLAUDE.md:4
src/config.ts — not found
→ src/config/index.ts (moved — fixable)
git clone https://github.com/berkdemir18/agents-sync.git
cd agents-sync
npm linkBağımlılığı yok, derleme adımı yok. Node 18+ yeterli.
| Komut | Ne yapar |
|---|---|
agents-sync |
Sorunları listeler (bulursa çıkış kodu 1) |
agents-sync report |
Bakılabilir bir HTML sayfası üretir |
agents-sync apply |
Şüphe olmayanları düzeltir, yedek alır |
agents-sync schedule |
Haftalık arka plan çalışması kurar (Windows) |
- Ölü yol — var olmayan bir dosyayı işaret eden referans. Düz cümlede,
ters tırnak içinde, markdown linkinde veya
[[wikilink]]olarak yazılmış olabilir; hepsi okunur. - Bayat bilgi — aynı bilgi iki dosyada farklı yazıyorsa, hangisinin daha yeni olduğuna bakıp eskisini bildirir.
- Çift kayıt — bir dosya aynı şeyi iki kez farklı söylüyorsa.
Yanlış alarm veren bir denetleyici silinir, o yüzden kesinlik her şeyin önünde. Bir referans ancak araç onun hakkında işe yarar bir şey söyleyebiliyorsa bildiriliyor: ya üst klasörü duruyordur (dosyanın nerede olması gerektiği bellidir), ya da başka bir yerde makul bir aday bulunmuştur. Bilerek sorun sayılmayan üç durum var:
- Kısmi yollar. Gerçek dosya
vault/00 - Sistem/850-Companion/Last-Session.mdiken metinde850-Companion/Last-Session.mdyazması. İnsan bunu takip edebiliyor, araç da edebiliyor. - Başka yere ait yollar. Yerleştirilemiyor ve benzeri de yoksa, muhtemelen başka bir projenin dosyasıdır, hata değil.
- Aynı ad, alakasız klasör.
notes/core.mdreferansı, bambaşka bir klasördekicore.mdile "düzeltilmez". Aday, referansın adını verdiği klasörün içinde olmak zorundadır.
agents-sync scheduleWindows Görev Zamanlayıcısı'na haftalık görev ekler (varsayılan: Pazar 10:00). Bilgisayar o an kapalıysa hafta atlanmaz — açtığında çalışır. Yalnızca daha önce göstermediği bir şey bulursa bildirim gönderir, yani her hafta aynı şeyi tekrarlamaz. Bildirim sen ilgilenene kadar ekranda durur ve üstünde Fix düğmesi vardır; terminale girmen gerekmez.
Zamanlama, bildirim ve düğmeler Windows'a özeldir. Diğer sistemlerde komut satırı aynen çalışır; haftalık çalıştırmayı cron'a koyabilirsin:
0 10 * * 0 agents-sync report --notify --dir ~
@berkdemir18 tarafından yapay zekâ yardımıyla geliştirildi — fikir, kapsam ve tasarım kararları bana ait, kodu bir yapay zekâ asistanıyla yazdım. Bu aracın çözdüğü problem de zaten tam olarak böyle ortaya çıktı.
MIT