[Critical] Claude Code Glob patterns (/**) in settings.local.json don't work - breaks developer workflow
Environment
- Platform (select one):
- [x] Other: Claude Code in PyCharm IDE
- Claude CLI version: 1.0.98 (Claude Code)
- Operating System: macOS
- Terminal: PyCharm IDE
## Bug Description
The /** glob pattern in .claude/settings.local.json permissions is not granting recursive access to subdirectories and files as expected. Despite
having a wildcard permission for a parent directory, Claude continues to request explicit permission for individual files within that directory tree.
## Steps to Reproduce
- Add permission to
.claude/settings.local.json:"Read(/Users/sam/repos/parcelping/nozzles/**)" - Ask Claude to read a file deep in the directory structure, e.g.,
/Users/sam/repos/parcelping/nozzles/src/core/config.py - Claude requests permission for that specific file despite the parent directory having
/**permission - Must manually approve each individual file access request
## Expected Behavior
When granting permission with glob pattern "Read(/path/to/repo/**):
- Should allow reading ALL files in
/path/to/repo/ - Should allow reading ALL subdirectories recursively
- Should allow reading ALL files in ALL subdirectories recursively
- Should follow standard glob pattern conventions where
/**means "everything recursively"
## Actual Behavior
- Claude requests permission for each individual file
- Parent directory permission with
/**is ignored - Must add redundant permissions for every subdirectory:
```json
"Read(/Users/sam/repos/parcelping/nozzles/)",
"Read(/Users/sam/repos/parcelping/nozzles/src/)",
"Read(/Users/sam/repos/parcelping/nozzles/src/core/)",
"Read(/Users/sam/repos/parcelping/nozzles/docs/)",
- Settings file becomes bloated with hundreds of redundant entries
Additional Context
Impact on Development Workflow:
- Constant interruptions to grant permissions breaks flow
- Settings file becomes unmaintainable with hundreds of entries
- Defeats the purpose of wildcard patterns
- Contradicts standard glob behavior used in gitignore, rsync, find, etc.
Current Workaround:
Must either:
- Grant very broad permissions like "Read(/Users/sam/repos/**)"
- Manually add every subdirectory path (defeats purpose of wildcards)
- Constantly approve individual file access requests during sessions
Severity: High - Significantly impacts developer experience and makes the permissions system unnecessarily cumbersome for real-world development
scenarios where access to entire repository trees is needed.
Showing cached comments. Read the full discussion on GitHub ↗
13 Comments
Found 1 possible duplicate issue:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Wonder if this is causing my issue too. Have you found a workaround or other pattern that works as it seems like this bug keeps coming back to Claude often.
Hi @Latigid-Sam, Thank you for the detailed bug report. After reviewing your issue and our documentation, I believe the problem is with the path format in your permission rules. See https://docs.anthropic.com/en/docs/claude-code/iam#tool-specific-permission-rules.
"Read(/Users/sam/repos/parcelping/nozzles/**)"is being interpreted as a relative path from your settings file location, not as an absolute filesystem path. So Claude Code is looking for{settings-directory}/Users/sam/repos/...which doesn't exist.The following should work:
You could also use:
"Read(~/repos/parcelping/nozzles/**)"if repos is in your home directory"Read(//Users/sam/repos/**)"for broader access to all repositoriesThis should resolve the issue where Claude Code repeatedly asks for permission despite having the glob pattern. The
/**pattern itself is correct for recursive access - it was just looking in the wrong location.Please try updating your settings.local.json with the double-slash format and let us know if this resolves the issue!
The problem is, it's Claude Code that is suggesting and adding the invalid paths, if this suggestion is the fix.
So Claude Code still needs to be fixed.
This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.
I created bug issue #13629 but will allow it to remain closed since I believe it's a duplicate of this one.
The double-slash solution proposed above did not resolve the problem for me. Using "dangerously skip permissions" mode prevents the bug from occurring, as you might expect, but that isn't a real solution.
Since this problem is so fundamental to CC tool-use and permissions, I'd hope it might get some developer attention. I'd be happy to test solutions or provide more information.
Confirming This Solution Works
Just wanted to confirm @bogini's solution completely fixed my permission issues.
What Worked
Changed from:
To:
Both user-level (
~/.claude/settings.json) and project-level (settings.local.json) work correctly with this format.Additional Finding: Bash Path Patterns Don't Work
While testing, I also discovered that path-restricted Bash patterns don't work:
The
//fix only applies to Read/Write/Edit tools. For Bash commands, use wildcards and rely on deny rules for safety.Suggestion
This double-slash requirement should be prominently documented, and Claude Code should generate the correct format when users accept permission prompts.
## Root Cause Identified - Technical Investigation
@bogini Thanks for investigating this! I've completed a detailed technical analysis that shows this isn't a path format issue—the root cause is an undocumented bypass mechanism that completely skips the permission checking system.
### TL;DR
Root Cause: Fast-path bypass at
cli.js:2342(function Rl5) skips entire GL → Es → fC → Vr2 permission chain. Pre-checker computing bypass parameter has bug handlingroot !== "/"scenarios.Evidence: ES6 instrumentation proves ZERO executions of GL/Es/fC/Vr2
Fix: 3-line code change (tested)
Timeline: ~2-3 hours with source access
---
### Why Path Format Theory Doesn't Explain This
The suggestion to use
//Users/...vs/Users/...would only matter if the permission checking code (fC/GL) was executing. Instrumentation proves it never runs:Function Call Counts (for Write operations):
✓ [STARTUP]: 1
❌ [GL]: 0 ← Permission checker NEVER CALLED
❌ [Es]: 0 ← NEVER CALLED
❌ [fC]: 0 ← NEVER CALLED (where path conversion happens)
❌ [Vr2]: 0 ← NEVER CALLED
The entire documented permission system is bypassed.
---
Bypass Mechanism Discovered
Location:
cli.js:2342(function Rl5)```javascript
function Rl5(A,B) {
return dP2.useCallback(async(Q,I,G,Z,Y,J) => {
// When J !== undefined, GL is completely skipped
return (J !== void 0 ? Promise.resolve(J) : GL(Q,I,G,Z,Y))
.then(...)
}, [A,B]);
}
The Fix (3 lines):
---
Investigation Deliverables
Complete package available with:
---
Questions for Team
This explains why this issue has been open since August—the bypass means standard debugging won't find it. Hope this helps unblock the fix!
## Root Cause Identified - Technical Investigation
@bogini @jamesbraza Thanks for investigating! I can confirm the
//workaround works,but I've identified why: it's accidentally avoiding a deeper bug, not fixing it.
### TL;DR
Root Cause: Fast-path bypass at
cli.js:2342(function Rl5) skips entirepermission chain. Pre-checker has bug handling
root !== "/"- the//workaroundaccidentally avoids triggering this bug.
Evidence: ES6 instrumentation proves permission code never executes
Fix: 3-line code change (tested) - will make
//workaround unnecessary---
### Why the
//Workaround Works (But Shouldn't Be Needed)The
//Users/...workaround succeeds because it accidentally bypasses buggyroot-handling logic:
```javascript
// Pre-checker logic (simplified):
if (root !== "/" && pattern.startsWith(root)) {
// Convert absolute → relative (BUGGY for root !== "/")
pattern = pattern.slice(root.length);
}
A fast-path pre-checker computes J before Rl5. This pre-checker has the bug that
the // workaround avoids.
---
The Actual Bug (Found in fC, Likely Replicated in Pre-Checker)
Location: cli.js:2004 (function fC)
// Current code (BUGGY):
The Fix (3 lines):
This fix eliminates the need for the // workaround.
---
Why This Matters
For Users:
For Anthropic:
---
Investigation Package Available
Complete documentation includes:
Confirming this affects Windows (Claude Code v2.1.5)
Environment: Windows 11, Claude Code v2.1.5 (terminal)
Reproduction:
~/.claude/settings.jsonhas 70+ permissions configured (e.g.,Bash(cp:*))cp --versionAlso tested: Manually added
Bash(cp:*)to~/.claude.jsonunderprojects."C:/Dev/repos/AI-projects".allowedTools- also not enforced.Additional observation: The "Yes, and always allow similar commands in this directory" UI option doesn't persist - the
allowedToolsarray remains empty after selection.Symptoms match the root cause analysis in #6881 (permission checking code bypassed entirely). Adding Windows to the affected platforms.
Still need fix on this.
This also did not work the last 2 days.
Hitting this same issue on macOS (Darwin 25.4.0), Claude Code 2.1.133. Filed #57746 independently before finding this thread.
Root cause hypothesis: If the permission matcher uses Python's
pathlib.PurePath.match()(or a JS equivalent with the same semantics),**silently fails to match more than one directory level deep:fnmatch.fnmatch()or any glob library with proper**recursion handles this correctly. If the codebase is Go or Node, the same class of bug exists infilepath.Match(Go, no**support) andpath.matchesGlob(Node <20, no**support).This has been open since v1.0.98 and affects every user who tries to allowlist a directory tree. Would love to see it prioritized.