Edit permission glob ** pattern does not recursively match nested directories
Description
The ** glob pattern in Edit() permission rules (settings.json allow list) does not recursively match files in deeply nested subdirectories. This appears to be a regression -- the same configuration worked in earlier versions.
Reproduction
settings.json allow rule:
"Edit(/Users/me/.config/myproject/**)"
File being edited:
/Users/me/.config/myproject/worktrees/my-branch/scripts/db.py
Expected: Auto-approved (path is under the allowed ** pattern)
Actual: Prompts for user approval
Root cause hypothesis
Python's pathlib.PurePath.match() does not support ** for recursive directory matching the way POSIX glob or fnmatch do:
from pathlib import PurePath
path = PurePath('/Users/me/.config/myproject/worktrees/branch/scripts/file.py')
path.match('/Users/me/.config/myproject/**') # False (unexpected)
path.match('/Users/me/.config/myproject/*/*/*/*') # True
If Claude Code uses PurePath.match() to evaluate permission patterns, ** will silently fail to match files more than one level deep. fnmatch.fnmatch() handles ** correctly for this case.
Environment
- Claude Code version: 2.1.133
- OS: macOS (Darwin 25.4.0)
- The pattern matches files directly in the allowed directory (1 level deep) but fails for 2+ levels of nesting.
Impact
Users with Edit(/path/**) allow rules get unexpected approval prompts for nested file edits. This affects git worktree workflows where files are several directories deep under the allowed root.
This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗