[Bug] A path-scoped rule file is never registered, while a byte-identical copy at any other path loads
Summary
One path-scoped rule file is never registered. Reading a file its paths: globs match loads nothing from it, while four sibling rule files in the same directory load normally. A byte-identical copy of the same file at any other path loads correctly, so the content, the frontmatter, and the globs are all fine. The only discriminator I could find is the exact path, and I could not determine what property of that path causes the skip.
I could not reduce this to a fresh repo, so I am reporting the bisection instead of a minimal repro. Everything below was run against the real case.
Environment
- Claude Code 2.1.267
- macOS 26.6.2 (darwin 25.6.0), arm64
- Node v22.23.1
- Project rules live in
.claude/rules/house/*.md, five files, each with apaths:frontmatter list
Expected
Reading a file matched by a rule's paths: glob loads that rule.
Observed
.claude/rules/house/github.md declares:
---
paths:
- .github/**
- .githooks/**
- .env.example
---
All three match tracked files in the repo. Reading any of them loads nothing from this rule. Its four siblings (claude-code.md, docs.md, engineering.md, testing.md) load normally on their own globs.
How it was observed
An InstructionsLoaded hook appends one JSON line per load event (file_path, load_reason, session_id, timestamp). The log carries zero events for this file across every session in it, spanning several days, while recording loads for all four siblings.
Bisection
I copied the file verbatim and read a matching file after each step, checking the log each time.
| Path | Content | Loads |
|---|---|---|
| .claude/rules/house/github.md | original | no |
| .claude/rules/house/github2.md | byte-identical copy | yes |
| .claude/rules/probe/github.md | byte-identical copy, same basename | yes |
| .claude/rules/zz-probe4.md | byte-identical copy | yes |
So it is not the content, not the frontmatter, not the basename, and not the directory.
A throwaway rule file carrying only .github/** also loaded on the same read that the original ignored, so the glob itself matches. ** does cross directory boundaries here: .claude/** reaches a file two directories down.
New rule files are picked up mid-session, so this is not a session-start scan artifact.
Ruled out
- Frontmatter encoding. Byte-clean, verified with
sed -n l: no BOM, no CRLF, no tabs. Structurally identical to the siblings that work. - Extended attributes.
xattr -lreturnscom.apple.provenanceand nothing else, matching all four siblings. - Git state. Tracked, and
git check-ignoreexits 1 for it. - Settings. Nothing at user or project scope excludes it. No rule-exclusion setting is present in either file.
- Stale file cache. Rebuilding the file with a fresh inode and mtime (copy out, delete, copy back, content unchanged) changes nothing.
- Competition between rules. With every probe removed, reading a
.github/**file that had never been opened before still loaded nothing from it. No other rule matched that read. - A dedupe on already-loaded content. The failure predates every copy I made; the log shows zero events for it going back through the whole file.
Impact
The rule is advisory text that no session has ever loaded, and nothing surfaces that. A rule whose glob never matches and a rule that is silently skipped look identical from inside a session, which is why this went unnoticed for days. /context not listing path-scoped rules after they load mid-session (#93094) makes it harder to spot from the other direction too.
Happy to run any diagnostic that would help narrow it.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗