[Bug] CLAUDE.md loaded twice when ~/.claude is a symlink into a project directory (no realpath dedup) — macOS
Bug Description
When ~/.claude is a symlink pointing to a .claude directory inside a project
tree, Claude Code loads the same physical CLAUDE.md twice — once as the user-level~/.claude/CLAUDE.md and once as the project-level <project>/.claude/CLAUDE.md —
instead of deduplicating by real path (inode). Both copies are injected into context
in full, so every session working inside that project pays the file's token cost twice.
This is the macOS/symlink twin of #26584 (Windows junction links, closed as stale /
NOT_PLANNED). Filing fresh as requested by the bot there; still fully reproducible
on current versions.
Environment
- Claude Code version: 2.1.198
- OS: macOS (Darwin 24.2, arm64)
- Setup:
~/.claude -> /Users/me/myproject/.claude(directory symlink)
Steps to Reproduce
mkdir -p ~/myproject/.claude && echo "# marker ABC123" > ~/myproject/.claude/CLAUDE.md- Move your existing
~/.claudecontents into~/myproject/.claude, remove~/.claude,
then ln -s ~/myproject/.claude ~/.claude (or any equivalent setup where ~/.claude
is a symlink into the project).
cd ~/myproject && claude- Inspect the injected context (e.g. via /context or by asking the model what
system context it received).
Expected
CLAUDE.md content appears once. Paths that resolve to the same real file
(realpath/inode) should be deduplicated before injection.
Actual
The same 12.6KB file is injected twice, under both path spellings:
Contents of /Users/me/.claude/CLAUDE.md (user's private global instructions ...)Contents of /Users/me/myproject/.claude/CLAUDE.md
stat confirms both paths are the same inode. Every session inside the project
wastes ~2x the file's tokens (for us ~3-4k tokens per session, on every session,
across the whole team).
Suggested Fix
Deduplicate the CLAUDE.md load list by realpath() before injection — same class
of fix as the case-insensitive dedup issue on Windows (#24236) and junction issue
(#26584).