[FEATURE] Regex/glob support for Bash permission patterns
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
Problem Statement
Many commands are conditionally safe based on their arguments, not just their prefix:
- find is safe unless using -exec
- git is safe for read operations (status, log, diff) but risky for writes (push --force)
- Nearly any command is safe when called with --help
The current Bash(prefix:) syntax can't express these patterns. You can allowlist find: but can't carve out -exec. You can't allowlist "any command ending in --help" without
enumerating every command individually.
This forces users to choose between overly permissive rules (allow entire commands) or tedious enumeration (list every safe variant).
Proposed Solution
Currently Bash(prefix:*) only supports prefix matching. Expand to support regex or glob patterns:
"allow": ["Bash(regex:^\\w+\\s+--help$)"] // any "cmd --help"
"ask": ["Bash(regex:.*[;|&`$#].*)"] // dangerous metacharacters require approval
This enables both permissive patterns (allow all help flags) and defensive patterns (require approval for chaining/subshells) that aren't possible with prefix-only matching.
Alternative Solutions
_No response_
Priority
High - Significant impact on productivity
Feature Category
CLI commands and flags
Use Case Example
Real Use Case: Claude to freely check command usage with --help flags without prompting me every time, regardless of which command it's checking.
Current workflow:
- Claude encounters an unfamiliar CLI tool (e.g., ffmpeg, jq, rg)
- Claude wants to run ffmpeg --help to understand available options
- I get a permission prompt because ffmpeg isn't in my allowlist
- I approve it manually
- Later, Claude needs jq --help—another prompt
- Then rg --help—another prompt
- This repeats endlessly for every new tool
To avoid this, I'd have to enumerate every possible command:
"allow": [
"Bash(ffmpeg --help)",
"Bash(jq --help)",
"Bash(rg --help)",
"Bash(docker --help)",
"Bash(kubectl --help)",
// ... hundreds more
]
Desired workflow:
- I configure:
"allow": ["Bash(regex:^\\S+\\s+--help$)"]
- Claude runs ffmpeg --help—no prompt
- Claude runs jq --help—no prompt
- Claude runs rg --help—no prompt
- Any <command> --help works automatically
A single pattern replaces an unbounded list of individual rules, and --help is universally safe—it just prints usage information and exits.
Additional Context
_No response_
8 Comments
Another use-case I've run into is that I want to allow all
get/list/describecommands for any AWS service via the AWS CLI.However, the current allow behavior does not let me define something simple like:
I would have to list out the hundreds of options to accomplish this now.
Another use case: git subcommands with optional flags.
I want a single pattern that allows both:
git grep patterngit -C /path/to/repo grep patternCurrent options and their problems:
``
json
``"Bash(git grep:*)",
"Bash(git -C * grep:*)"
Bash(git * grep:*)— but this matches dangerous commands where "grep" appears as a branch/ref name:git push --force origin grepgit reset --hard grepgit branch -D grepWith regex support, this could be expressed safely:
This pattern makes
-C <path>optional while ensuringgrepis the actual subcommand, not a ref name.Use case: Real-world workflow automation with trust boundaries
I'm building automated workflows with Claude Code on a React Native project (TiedSiren51) and I need fine-grained permissions because I can't blindly trust the agent.
My current
settings.local.jsonhas 200+ allow rules, 104 deny rules, and 30 ask rules — and it's still not airtight. Here's a condensed excerpt showing the problem:Problem 1: Blocking hook bypasses requires N rules per git subcommand
With regex, this collapses to one rule:
Problem 2: Env var prefix evasion requires combinatorial explosion
I have a pre-push hook that checks E2E status. Claude sometimes tries to skip it. I need to block every combination:
With regex:
Problem 3: Allow rules can't express "subcommand families"
I allow all read-only
ghoperations but must list each one individually (20+ rules). With regex:The full file (378 lines) is visible in my project at
.claude/settings.local.json. It works, but maintaining it is painful and the combinatorial gaps make it unreliable as a real security boundary.Regex support would make permissions both more expressive and more maintainable for users who are seriously investing in Claude Code workflows.
Use case:
cd <path> && <safe-command>patternsI analyzed my recent sessions and found that 32% of all Bash commands required manual approval (266 out of 820). The #1 cause: commands prefixed with
cd "/path/to/project" && ....Claude Code frequently generates commands like:
I already have
Bash(python3:*),Bash(source:*),Bash(grep:*)in my allow list — but these don't match when the command starts withcd.The core problem: the path after
cdvaries (different subdirectories, different projects), so there's no fixed prefix that captures "cd to any directory, then run a safe command."Bash(cd:*)is too broad — it would auto-approvecd /dir && rm -rf *cd "/specific/path" && python3:*combination is impracticalThis single gap accounts for ~170 manual approvals per session cycle (~64% of all friction).
With regex/glob support, this could be:
Or even more elegantly, a way to compose existing allow rules so they match regardless of
cdprefix.A
PreToolUsehook can implement full regex matching today:Add to
~/.claude/settings.json:This gives you:
find.*-execblocked,find -nameallowed--help,--version,--dry-runauto-approved regardless of the base commandgit pushblocked butgit push --dry-runallowedYou can also load patterns from a config file for easy customization:
Hooks give you full regex support for permission matching — no need to wait for native glob/regex in settings.json:
Full regex support with no limitations —
grep -qEgives you extended regex. You can match command arguments, flags, paths, pipe chains — anything the built-in glob/pattern system can't handle.Closing for now — inactive for too long. Please open a new issue if this is still relevant.
Adding a concrete failure mode I ran into, since it's a sharper version of the same root cause (glob-only Bash matching) and I think it strengthens the case for reopening this.
Bracket expressions (
[0-9]) silently fail closed — no error, rule just never matches.I wrote allow rules intended to match any 4-digit port:
This looks reasonable because Read/Edit permission rules do support gitignore-style bracket expressions. But Bash rules only support a single
*wildcard — there's no bracket-expression spec for them. So[0-9]isn't parsed as "any digit," it's matched as five literal characters:[,0,-,9,]. The rule compiles fine, saves fine, and then simply never matches any real command. There's no warning, no lint, nothing in the UI or logs to indicate the rule is dead on arrival — you only find out when Claude hits an unexpected permission prompt for a command you thought you'd already allowed (or, worse, you don't notice and just assume it's working).Given Read/Edit already implement bracket-expression matching, exposing the same capability for Bash rules seems like a small, well-scoped slice of this larger regex/glob ask — and one that would also close the "silent failure" gap, since a real character-class engine would make
[0-9]behave as users already expect from every other tool that uses gitignore-style globs.Given this is a live, concrete case (not hypothetical) and the two other duplicate threads (#37509, #25495) also just went stale rather than being rejected on the merits, would it be possible to reopen this?