[BUG] allowedTools glob patterns never match Windows backslash paths — no pattern format works
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code
What's Wrong?
allowedTools glob patterns cannot match file paths on Windows, regardless of how the pattern is formatted. This makes allowedTools effectively broken for Read, Glob, and Grep on Windows.
Environment
- Windows 11 Pro
- Claude Code shell: bash (Git Bash)
- Claude Code generates backslash paths for tool calls (e.g.,
C:\Users\user\.claude\skills\...)
Reproduction
settings.json allowedTools configuration:
"allowedTools": [
"Read(~/.claude/**)",
"Read(C:/Users/user/.claude/**)",
"Read(C:\Users\user\.claude\**)"
]
Test: Ask Claude to read any file under ~/.claude/ (e.g., a skill reference file).
Expected: Read proceeds without permission prompt (matched by one of the three patterns).
Actual: Permission prompt every time. All three pattern formats fail to match.
Root Cause Analysis
The model generates Windows-style backslash paths in tool calls:
Read(file_path="C:\Users\user\.claude\skills\my-skill\references\file.md")
The glob matcher (likely picomatch or micromatch) treats \ as escape characters, so:
| Pattern Format | Why It Fails |
|---|---|
| Read(~/.claude/**) | Tilde not expanded; forward slashes don't match backslash paths |
| Read(C:/Users/user/.claude/**) | Forward slashes don't match backslash-delimited tool call paths |
| Read(C:\Users\user\.claude\**) | JSON \ becomes literal \, but glob treats \* as escaped wildcard |
No combination of slashes, escaping, or tilde works. The permission matcher needs to normalize path separators before glob matching on Windows.
Impact
allowedToolsis non-functional for path-scoped Read/Glob/Grep on Windows- Users get prompted for every file read in directories they've explicitly allowed
- Workaround: none (the "Always allow" selection also doesn't persist — see #16762)
Suggested Fix
Normalize both the pattern and the tool call path to use the same separator (forward slashes) before glob matching. This is the standard approach in cross-platform tools (VS Code, Node.js path utilities, etc.).
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗