Bash wildcards
Prefix, suffix, and middle patterns work; one rule covers many commands.
Bash wildcards in permission rules allow a single pattern to match multiple commands via * at prefix, suffix, or middle positions.
How Wildcards Match
The wildcard * can occupy any single position within a Bash() permission rule and matches zero or more characters in the full command string. The pattern Bash(npm *) matches npm install, npm run, npm test; Bash(* install) matches npm install, pnpm install, yarn install; Bash(git * main) matches git log main, git show main, and so on. Spaces are significant—they are part of the match, not delimiters.
Test Setup and Results
Three patterns were tested against actual command execution in Claude Code's Bash tool permission system on 2026-01-07. Each pattern was evaluated with a command that should match and one that should not:
Prefix wildcard Bash(npm *) was tested with npm --version (passed) and pnpm --version (blocked as intended). Suffix wildcard Bash(* install) allowed echo install to run without approval. Middle wildcard Bash(git * main) permitted git log main to attempt execution (it failed for lack of a main branch, but the permission check itself passed).
All three positions succeeded. The pattern is command-based: it matches the full command string as entered, not parsed tokens.
Why This Matters
Prefix wildcards such as Bash(npm *) or Bash(docker *) reduce permission fatigue by grouping related commands—one rule replaces many individual approvals. Permission systems can still be explicit and secure because wildcards are declared per rule, not implicit defaults. Caveats: some commands (such as pwd, ls, echo) may already have default permissions separate from wildcard rules, so wildcards add to the allowed set rather than replacing it. The full command string (including arguments and flags) participates in matching, so Bash(npm *) does not match npm, only strings that begin with npm (with a space).
Use Cases
{
"permissions": {
"allow": [
"Bash(npm *)",
"Bash(git *)",
"Bash(* --help)",
"Bash(* --version)"
]
}
}
One rule covers an entire tool family, reducing management overhead without sacrificing the explicit, auditable nature of permission rules.
- commitdf087b8 ↗
primitive_e251b6eb8e70ae06ba11d9c1ed255199b87705613b1e2fd064d57fa75a6b679d2856ceafad6b1daa8f982493871b6dd17c918b4a3c8242ff28a84ea1849edd9df982937dca8814523a6ebaa4b52e939b7bac80ecebda18e0d5ada528be4a9d8a0e5689b96c7bc8d0e0441493f8cda05Signed with an ed25519 key held off the repo. Anyone can verify against the published public key; nobody without the secret key can forge it. Click verify: it recomputes the signature in your browser. The signature proves integrity and authorship of this exact content — not a third-party timestamp or that the underlying claim is objectively true. signedAt is when the @f3/attest pipeline ran, not when the work happened; the evidence refs carry the source dates.
- instance-of Sandbox / Capability Class
- introduces (in) Claude Code 2.1.0 (Night Zero) Release
- verifies (in) Bash wildcards — runtime test Test