Path-based rules (.claude/rules/ with paths: frontmatter) are not loaded on Write tool — only on Read
Problem
Path-based rules defined in .claude/rules/ with a paths: frontmatter are only injected into context when Claude reads a file matching the pattern. They are not injected when Claude writes/creates a file matching the same pattern.
This means that any rule targeting file creation conventions (e.g., "add a specific header to new .md files", "enforce a comment on new .ts files") is silently ignored when a new file is created, because Claude never sees the rule at the time of writing.
Reproduction Steps
Setup
- Create a path-based rule
.claude/rules/testing/instructions/create.md:
---
paths:
- "**/*.md"
---
# Create Instructions
When **creating** a new .md file, ALWAYS add `# created` as the very first line.
- Create a complementary rule
.claude/rules/testing/instructions/update.md:
---
paths:
- "**/*.md"
---
# Update Instructions
When **editing** an existing .md file, ALWAYS replace the first line with `# updated`.
Test 1 — Write (rules NOT loaded)
Ask Claude: _"Create a file toto.md with content toto"_
Result: Claude creates toto.md with just toto. The create.md rule was never injected — Claude had no knowledge of the "add # created" instruction.
Test 2 — Read (rules loaded)
Ask Claude: _"Edit toto.md, replace content with 1"_
Claude calls Read on toto.md first (required before Edit). This time, the system-reminder injects both create.md and update.md rules. Claude sees the update instruction and correctly applies # updated as the first line.
Test 3 — Proof the rule existed
The create.md rule was valid and correctly configured — it just was never surfaced to Claude during the Write operation. The same rule loads perfectly when Read is called on any matching .md file.
Expected Behavior
Path-based rules matching the target file path should be injected into context for all file operations — Write, Edit, MultiEdit, and Read — not just Read.
When Claude creates a new file matching **/*.md, any rule with paths: ["**/*.md"] should be visible before or during the Write, so Claude can apply the instructions (like adding a required header).
Current Workaround
We implemented a PostToolUse hook on Write that injects an additionalContext message asking Claude to Read the file it just created, which forces rule loading. Claude then applies a corrective Edit if rules require it.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write",
"hooks": [
{
"type": "command",
"command": "bash hooks/post-write-rules-loader.sh"
}
]
}
]
}
}
This works (tested with both .md and .ts path-based rules), but it's a 3-step workaround (Write → Read → Edit) for what should be a 1-step operation (Write with rules already in context).
Why This Matters
Path-based rules are the primary mechanism for granular, targeted instructions by file type. The most critical use case — enforcing conventions on file creation — is the exact scenario where they don't work. This forces users to either:
- Duplicate all creation rules into
CLAUDE.md(losing the granularity benefit of path-based rules) - Implement PostToolUse hooks as workarounds (adds complexity and an extra round-trip)
- Accept that creation rules are silently ignored
Environment
- Claude Code CLI
- macOS (Apple Silicon)
- Rules with
paths:frontmatter in.claude/rules/
This issue has 9 comments on GitHub. Read the full discussion on GitHub ↗