PreToolUse hooks not executing despite proper configuration

Resolved 💬 3 comments Opened Dec 18, 2025 by excessivereason Closed Dec 18, 2025

Bug Description

PreToolUse hooks are not executing when tools are called, despite being properly configured in ~/.claude/settings.json.

Environment

  • Claude Code Version: Latest (as of 2025-12-18)
  • OS: macOS (Darwin 25.1.0)
  • Hook Type: PreToolUse (Bash matcher)

Evidence

1. Hook is properly configured

~/.claude/settings.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "/Users/jheath/.claude/hooks/pre-tool-use-gh-issue-labels.sh"
          }
        ]
      }
    ]
  }
}

2. Hook script works when tested manually

$ echo '{"tool_input":{"command":"gh issue create --repo excessivereason/claude-base --title \"Test\" --body \"Test\""}}' | ~/.claude/hooks/pre-tool-use-gh-issue-labels.sh
{
  "decision": "block",
  "reason": "GitHub issues must include at least one label. Add labels using --label flag.\n\n..."
}

✅ Hook correctly blocks the command when tested manually.

3. Hook does NOT fire when using Bash tool

When Claude uses the Bash tool to run gh issue create commands without labels:

  • Issues are created successfully (should be blocked)
  • No error message from hook appears
  • Hook is completely bypassed

Test case: Created issues #250 and #252 in excessivereason/claude-base without labels - both went through despite hook being configured to block them.

Expected Behavior

When Claude attempts to run:

gh issue create --repo excessivereason/claude-base --title "Test" --body "Test"

The PreToolUse hook should:

  1. Execute before the Bash tool runs the command
  2. Detect missing labels
  3. Return {"decision": "block", "reason": "..."}
  4. Prevent the command from executing

Actual Behavior

The hook does not execute at all. Commands run without any validation, as if the hook doesn't exist.

Impact

This breaks critical validation workflows. In my case:

  • User policy requires all GitHub issues to have labels
  • Hook was created to enforce this automatically
  • Without working hooks, issues are created without labels, violating policy

Reproduction Steps

  1. Create a PreToolUse hook in ~/.claude/hooks/ that blocks certain Bash commands
  2. Register it in ~/.claude/settings.json with Bash matcher
  3. Use Claude Code to run a Bash command that should be blocked
  4. Observe that the command executes without the hook firing

Additional Context

Other hook types (SessionStart, UserPromptSubmit, SessionEnd) appear to work correctly. The issue seems specific to PreToolUse hooks.

Related

  • Hook script: User's custom validation hook for GitHub issues
  • Use case: Enforce labeling requirements on issue creation

View original on GitHub ↗

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