Windows: Write(.claude/**) permission glob doesn't match backslash paths
Bug Description
Global permission Write(.claude/**) (forward slashes) does not match Windows paths with backslashes, causing an unexpected permission prompt.
Steps to Reproduce
- On Windows 11, add
Write(.claude/**)to global~/.claude/settings.jsonallow list - Run a workflow (e.g., ralph-loop skill) that writes to
.claude/state/in any project directory - Get prompted for permission despite the global allow rule
Expected Behavior
Write(.claude/**) should match .claude\state\ralph-wiggum-loop\per-element-accuracy-80.json — the path normalization documented in the permissions guide should convert backslashes to forward slashes before glob matching.
Actual Behavior
Permission prompt appears:
Write(.claude\state\ralph-wiggum-loop\per-element-accuracy-80.json)
Do you want to make this edit to per-element-accuracy-80.json?
> 1. Yes
2. Yes, and allow Claude to edit its own settings for this session
3. No
Note the backslashes in the prompted path vs forward slashes in the glob pattern.
Environment
- OS: Windows 11 Pro 10.0.26200
- Shell: bash (Git Bash / MSYS2)
- Claude Code model: claude-opus-4-6 (1M context)
Settings
Global ~/.claude/settings.json includes (paths redacted):
{
"permissions": {
"allow": [
"Write(.claude/**)",
"Write(//c/Users/<USERNAME>/.claude/**)",
"Write(//c/Users/<SHORT_USERNAME>/.claude/**)"
]
}
}
The project has no project-level settings files — only a .claude/state/ directory. No deny rules anywhere.
Analysis
The permissions documentation states:
On Windows, paths are normalized to POSIX form before matching.
This normalization appears to not be happening (or not happening correctly) for the Write tool's path argument before it's checked against the allow list glob patterns. The prompt displays the raw Windows path with backslashes, suggesting the match is attempted before normalization.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗