[*] Chore: make CLAUDE.md a symlink to AGENTS.md#8643
Conversation
CLAUDE.md only pointed readers at AGENTS.md. Replacing it with a symlink keeps Claude Code reading a single source of truth and prevents the two files from drifting. Note: this is a git symlink (mode 120000). It resolves transparently on macOS/Linux; on Windows checkouts without core.symlinks=true it will appear as a small text file containing "AGENTS.md". Happy to drop this if that tradeoff isn't worth it.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
etrepum
left a comment
There was a problem hiding this comment.
Claude itself claims that the best way to do this is to have a file with the contents @AGENTS.md
Why Claude Code "handles" it at all. Claude Code reads CLAUDE.md by opening that path. If CLAUDE.md is a genuine filesystem symlink, the OS resolves it transparently and hands back AGENTS.md's contents — Claude Code never has to know it followed a link. So on macOS/Linux, or on Windows where the symlink is a real symlink, this works without any special-casing. This matters because, as of mid-2026, Claude Code does not read AGENTS.md natively — it reads CLAUDE.md, and a repository containing only an AGENTS.md loads zero project instructions, with no error. The symlink (or an @-import) is the bridge. Bestagent
Where Windows actually breaks. The failure isn't Claude Code declining to follow a symlink — it's that on Windows the symlink may never exist as a symlink. When git checks out a repo without core.symlinks=true (or without the privilege to create symlinks — historically requires Developer Mode or SeCreateSymbolicLinkPrivilege), it materializes the "symlink" as an ordinary one-line text file whose content is the literal target path, i.e. a CLAUDE.md containing the string AGENTS.md. Claude Code then reads that file and gets the four characters AGENTS.md as your entire project instruction set — silently, with no warning. On Windows, git may need core.symlinks=true to handle symlinks; most modern Git for Windows installs do this by default, but if symlinks appear as plain text files you have to set it explicitly. SSW.Rules
So "does Claude correctly handle it" splits into two answers: yes for a real symlink (it's OS-transparent), and the Windows stub case isn't really Claude Code's to handle — by the time CC runs, the damage is done at checkout.
The more portable fix. Rather than relying on symlinks surviving a Windows checkout, keep a real (non-symlink) CLAUDE.md whose first line imports the shared file: Claude Code supports importing external files with @-syntax, so writing @AGENTS.md at the top of CLAUDE.md pulls in that file's contents. That's a normal tracked file on every platform, no symlink privilege needed, and it sidesteps the stub problem entirely. The tradeoff is that the import expands inline and still counts against the context window, but for a single instructions file that's negligible. Medium
If you specifically want the symlink approach to survive Windows clones, the durable answer is committing core.symlinks=true expectations into onboarding (and confirming Developer Mode), since you can't force it purely from repo contents.
One caveat worth verifying yourself: native AGENTS.md support is an open request on the tracker (referenced as anthropics/claude-code#34235), so if you're reading this later, it's worth checking whether that shipped — it would make the whole symlink dance unnecessary. Want me to check the current status of that issue?
Description
CLAUDE.mdcurrently just points readers toAGENTS.md. This replaces it with a symlink (CLAUDE.md→AGENTS.md, git mode120000) so Claude Code reads a single source of truth and the two files can't drift.This follows up on review feedback in #8634, where @etrepum suggested a symlink rather than duplicating guidance across both files. Splitting it into its own PR so it can be evaluated independently of the backwards-compatibility doc change.
Caveat: this is a git symlink. It resolves transparently on macOS/Linux. On Windows checkouts without
core.symlinks=trueit will materialize as a small text file containing the stringAGENTS.mdrather than the file contents. If that tradeoff isn't worth it for a repo with diverse contributor environments, happy to close this — no strong opinion.Test plan
git ls-files -s CLAUDE.mdreports mode120000(symlink).cat CLAUDE.mdresolves to the contents ofAGENTS.md.