[BUG] Bash(foo *) wildcard does not match bare command with no arguments, contrary to docs

Status Fixed / completed
Reported on v2.1.44
Maintainer reply ✓ Yes — ashwin-ant
Activity 6 comments · opened Feb 17, 2026 · closed Apr 18, 2026
💡 Likely answer: A maintainer (ashwin-ant, collaborator) responded on this thread — see the highlighted reply below.

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

The docs at https://code.claude.com/docs/en/permissions#wildcard-patterns state that Bash(ls ) with a space before "enforces a word boundary, requiring the prefix to be followed by a space or end-of-string." This implies Bash(git stash *) should match both git stash list (space) and bare git stash
(end-of-string). In practice, it does not match the bare command — the user is prompted for permission.

The deprecated : syntax (Bash(git stash:)) does correctly match both cases.

What Should Happen?

Bash(foo *) should match foo (bare, no arguments) in addition to foo <args>, as documented.

Error Messages/Logs

Steps to Reproduce

  1. Add "Bash(git stash *)" to .claude/settings.json allow list (no bare "Bash(git stash)" entry)
  2. Start a Claude Code session
  3. Have Claude run git stash (bare, no arguments)
  4. Observe: user is prompted for permission (should be auto-allowed)
  5. Now replace with "Bash(git stash:*)" (deprecated colon syntax)
  6. Repeat step 3
  7. Observe: command runs without prompting (correct behavior)

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.44

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

iTerm2

Additional Information

The workaround is to use the deprecated : syntax, which handles both cases. Alternatively, users can double every entry with both Bash(foo ) and Bash(foo), but this is verbose. The docs should either be corrected to note that * requires at least one argument, or the behavior should be fixed to match the documented "end-of-string" semantics.

View original on GitHub ↗

6 Comments

github-actions[bot] · 6 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/24815
  2. https://github.com/anthropics/claude-code/issues/20449
  3. https://github.com/anthropics/claude-code/issues/25120

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

ucwillg · 6 months ago

some of those issues overlap, but they aren't obviously describing quite the same behavior

tonglil · 6 months ago

I am here because I find the documentation on wildcard patterns completely wrong about this topic:

The space before matters: Bash(ls ) matches ls -la but not lsof, while Bash(ls) matches both. The legacy : suffix syntax is equivalent to * but is deprecated.

-- https://code.claude.com/docs/en/permissions#wildcard-patterns

The legacy syntax is what works - the new syntax with a space does not work. By the way this report is completely human generated an

I have this in allow:

      "Bash(git add *)",

But when I accept always allow, claude adds this rule:

      "Bash(git add:*)"

After:

<img width="724" height="269" alt="Image" src="https://github.com/user-attachments/assets/eb2ede61-3b4d-45f3-afb2-35506b3e3419" />

claude --version
2.1.50 (Claude Code)
yurukusa · 5 months ago

The wildcard Bash(foo *) not matching bare foo (no arguments) is a pattern-matching bug. A hook handles both cases:

INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
[ -z "$COMMAND" ] && exit 0
BASE=$(echo "$COMMAND" | sed 's/^\s*//' | awk '{print $1}')
case "$BASE" in
    ls|cat|head|tail|grep|find|git|npm|node)
        jq -n '{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow",permissionDecisionReason:"Command auto-approved by hook"}}'
        ;;
esac
exit 0

The hook extracts the base command name (awk '{print $1}') and matches it. ls, ls -la, ls /path — all match the same ls case. No wildcard syntax issues, no argument-dependent matching problems.

{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Bash",
      "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/command-allow.sh" }]
    }]
  }
}
ashwin-ant collaborator · 4 months ago

This was fixed in v2.1.72 — Bash permission patterns like Bash(git stash *) now also match the bare command with no arguments, as documented. If you're still seeing this in the latest version, please comment with your version and repro and we'll reopen.

github-actions[bot] · 4 months ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.