Write/Edit/Read permission allow rules don't match common glob patterns (Bash matcher works)
Summary
permissions.allow rules with the Write(...) (and presumably Edit(...) / Read(...)) prefix don't seem to match any of the obvious glob shapes for file paths. Same session, same /hooks reload, the Bash(...) matcher works perfectly with * at any position — so the asymmetry is surprising.
Environment
- Claude Code:
2.1.123 - Platform: macOS 15 (Darwin 25.3.0), arm64
- Settings file: project-level
.claude/settings.json
Reproducer
.claude/settings.json (relevant block):
{
"permissions": {
"allow": [
"Bash(curl *example.com*)",
"Write(/tmp/anchor-*.json)",
"Write(/tmp/anchor-*)",
"Write(/tmp/**)"
]
}
}
Steps:
- Save settings.json with the rules above.
- Run
/hooksonce mid-session (reloads the config — without this, even Bash rules don't engage at session start, but that's a separate observation). - Have the assistant invoke:
- Bash: a curl to a host matching
example.com→ auto-allows, no prompt ✅ - Write:
file_path: /tmp/anchor-doublestar-test.json, with arbitrary content → prompts for permission ❌
Expected
Write(/tmp/anchor-*.json) should match /tmp/anchor-doublestar-test.json (single-segment * matches doublestar-test, literal .json suffix matches). At minimum, Write(/tmp/**) should match anything under /tmp/ if the documented gitignore-style semantics hold.
Actual
All three of these prompted in the same session, after /hooks reload, with the Bash control rule auto-allowing:
Write(/tmp/anchor-*.json)— literal suffix after*Write(/tmp/anchor-*)— pure trailing*Write(/tmp/**)— gitignore-style recursive double-star
Bash matcher comparison (works correctly)
For contrast, in the same settings file, same session, the Bash matcher matches as documented at any position:
Bash(*test-pure-midstring*)deniesecho "test-pure-midstring"✅Bash(echo *test-prefix-mid*)deniesecho "test-prefix-mid"✅Bash(echo test-prefix-only *)deniesecho test-prefix-only foo✅Bash(curl *example.com*)allows a matching curl ✅
Symmetric across allow/deny within Bash.
Question
Either the matcher for Write/Edit/Read doesn't support the same glob semantics as Bash (and the docs should call this out), or there's an actual bug. If the answer is "use Write(<exact-path>) with no globs," that would also be useful to confirm — we'd know to drop these rules and accept the prompts as a known limitation.
Workaround
Drop the Write allow rules entirely. /tmp staging-file workflows then prompt once each — low volume, livable.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗