Project-level .claude/rules/ symlinks (files and directories) are never loaded — neither at startup nor via paths: trigger (2.1.241, 2.1.251)
Summary
Symlinks inside a project-level .claude/rules/ directory are never loaded:
- symlinked files → not loaded at startup (no frontmatter)
- symlinked directories → not loaded at startup
- symlinked directories containing
paths:-scoped rules → not injected even when a matching file is read into context
Meanwhile, a symlinked directory in the user-level ~/.claude/rules/ loads fine, and plain copies of the same files in the project-level rules directory also load fine (including paths: lazy injection). Only project-level symlinks are broken.
Environment
- Claude Code 2.1.241 and 2.1.251 (both reproduced)
- macOS (Darwin 24.6.0, arm64)
- Verified with fresh headless sessions (
claude -p) using marker strings
Minimal reproduction
# 1. Create a rule directory anywhere outside the project
mkdir -p ~/shared-rules/myteam
cat > ~/shared-rules/myteam/style.md <<'EOF'
---
paths:
- "**/*.ts"
---
# Team style probe
If this rule is loaded, the marker SYMLINK_RULE_PROBE_7f3a is present.
EOF
# 2. Symlink it into the project's rules directory
cd /path/to/project
mkdir -p .claude/rules
ln -s ~/shared-rules/myteam .claude/rules/myteam
# 3. New session referencing a file that matches the paths glob
claude -p "Read @src/example.ts, then check whether your instructions contain SYMLINK_RULE_PROBE_7f3a. Answer yes/no only."
# → no
# 4. Control: replace the symlink with a plain copy
rm .claude/rules/myteam
cp -r ~/shared-rules/myteam .claude/rules/myteam
claude -p "Read @src/example.ts, then check whether your instructions contain SYMLINK_RULE_PROBE_7f3a. Answer yes/no only."
# → yes
Symlinked files (.claude/rules/foo.md -> ~/shared-rules/foo.md) behave the same way: not loaded when symlinked, loaded when copied. The failure is independent of the symlink target location (home dir, /tmp, and other paths were all tested).
Behavior matrix (all verified empirically)
| Layout | Loaded? |
|---|---|
| project .claude/rules/*.md (regular file) | ✅ |
| project .claude/rules/subdir/*.md (regular dir, recursed) | ✅ |
| project .claude/rules/foo.md (symlinked file) | ❌ |
| project .claude/rules/subdir (symlinked dir) | ❌ |
| …symlinked dir + paths: rule + matching file read | ❌ (no injection) |
| user ~/.claude/rules/subdir (symlinked dir) | ✅ |
| regular file with paths: + matching file read | ✅ (lazy injection works) |
Expected behavior
The memory docs describe sharing rules across projects with symlinks ("Share rules across projects with symlinks"), with examples of symlinking directories from outside the project into .claude/rules/. The changelog also shows symlinked rules being actively maintained (2.1.239/2.1.240 fixes for claudeMdExcludes matching on symlinked .claude/rules files), which implies they are supposed to load.
Relationship to previous issues
- #764 was closed as completed on 2.1.233 after the maintainer could not reproduce — but the verified scenario there was a user-level
~/.claudesymlink (stow) with commands, not project-level.claude/rules/symlinks. This specific surface does not appear to be covered by that verification. - #25903 (user-level symlinked rule file +
paths:not loaded) was closed as a duplicate of #764 by the reporter.
So there is currently no open issue tracking the project-level .claude/rules/ symlink case.
Testing note
When reproducing, make sure no stale copies of the rule files remain inside .claude/rules/ (e.g. renamed backups): the loader recurses into regular subdirectories, and leftover copies will make a symlink test falsely pass.