← 2.1.0 Primitive tested · runtime-test

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.

Evidence & receipt
◇ ed25519 receipt
idprimitive_e251b6eb8e70ae06ba11d9c1
alged25519
pubkey9b87705613b1e2fd064d57fa75a6b679d2856ceafad6b1daa8f982493871b6dd
sig17c918b4a3c8242ff28a84ea1849edd9df982937dca8814523a6ebaa4b52e939b7bac80ecebda18e0d5ada528be4a9d8a0e5689b96c7bc8d0e0441493f8cda05

Signed 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.

Connected