PreToolUse hook `if` pattern does not match commands chained with `&&` or `;`
Resolved 💬 1 comment Opened Apr 10, 2026 by yoon-yoo-sang Closed May 14, 2026
Summary
PreToolUse hook's if pattern matching (e.g., Bash(git commit*)) only matches the beginning of the full Bash command string. When the model chains commands with && or ;, the pattern fails to match and the hook is silently skipped.
Reproduction
Hook configuration in .claude/settings.json:
{
"type": "command",
"if": "Bash(git commit*)",
"command": "bash .claude/hooks/guard-commit-lint.sh",
"statusMessage": "Running pre-commit checks..."
}
git commit -m "msg"— hook fires correctlygit checkout -b branch && git add . && git commit -m "msg"— hook does not fire
The if pattern matches against the full command string, which starts with git checkout, not git commit.
Impact
Users set up PreToolUse hooks to enforce quality gates (linting, tests, branch protection) before specific commands. The model frequently chains commands with && for efficiency, which inadvertently bypasses all hook-based guardrails. This is especially problematic because:
- There is no warning or log when a hook is skipped due to pattern mismatch
- The user has no way to express "match if
git commitappears anywhere in the command" with the currentifsyntax
Possible solutions
- Match the
ifpattern against each individual command in a&&/;/||chain, not just the full string - Support substring or regex matching in
ifpatterns (e.g.,Bash(*git commit*)) - Warn when a Bash call contains a command that would match a hook pattern but is skipped due to chaining
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗