PreToolUse hook 'if' field does not filter hook process spawning (v2.1.87)

Resolved 💬 3 comments Opened Mar 31, 2026 by r-akitani-quando Closed Mar 31, 2026

Bug Description

The if field on PreToolUse hooks does not prevent the hook process from spawning. According to the documentation, if should filter at the hook level before the process is started, but in practice the hook script runs for every Bash command regardless of the if condition.

Steps to Reproduce

  1. Add the following to .claude/settings.local.json:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "if": "Bash(git commit *)",
            "command": ".claude/hooks/pre-commit-ci.sh"
          }
        ]
      }
    ]
  }
}
  1. Run any Bash command (e.g. npx prettier --write file.ts)

Expected Behavior

The hook script should NOT be spawned for npx prettier since it doesn't match Bash(git commit *).

Actual Behavior

The hook script IS spawned for every Bash command, including npx prettier, echo, npm run format, etc. The if field is completely ignored.

Workaround

Reading tool_input.command from stdin JSON inside the hook script and filtering manually:

INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // ""')
if ! echo "$COMMAND" | grep -q "git commit"; then
  exit 0
fi

Environment

  • Claude Code version: 2.1.87
  • OS: macOS (Darwin 24.5.0)
  • Session was restarted after changing settings

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗