Skip to content

PreToolUse/PostToolUse hooks don't fire in non-interactive -p mode #30143

Description

@bungles411

Description

When running Claude Code in non-interactive prompt mode (-p), project-level hooks defined in .claude/settings.json (PreToolUse, PostToolUse) do not fire. This appears to affect all hook types, not just PermissionRequest (which is documented as not firing in -p mode).

Steps to Reproduce

  1. Create a project with .claude/settings.json:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash(*)",
        "hooks": [
          {
            "type": "command",
            "command": "echo HOOK_FIRED >> .hook-breadcrumb.log",
            "timeout": 5
          }
        ]
      }
    ]
  }
}
  1. Run Claude in prompt mode:
CLAUDECODE= claude -p "Run 'echo hello' using Bash." \
  --model haiku \
  --dangerously-skip-permissions \
  --output-format stream-json
  1. Check for .hook-breadcrumb.log — it does not exist. The hook never fired.

Expected Behavior

PreToolUse and PostToolUse hooks should fire in -p mode, just as they fire in interactive mode. The documentation states PermissionRequest hooks don't fire in non-interactive mode, but does not mention this limitation for PreToolUse/PostToolUse.

Actual Behavior

No hooks fire at all in -p mode. Tested with:

  • --dangerously-skip-permissions and without
  • Relative and absolute paths in hook commands
  • Both PreToolUse and PostToolUse matchers

Environment

  • Claude Code: v2.1.41
  • OS: Windows 11 (Git Bash / MSYS2)
  • Node.js: v25.6.1

Impact

We use -p mode for automated behavioral testing (SBTF — Sovereign Behavioral Testing Framework). Hooks are the primary enforcement mechanism for governance gates (e.g., requiring verify.sh to pass before commits). Without hooks in -p mode, we had to fall back to git pre-commit hooks as a workaround.

Workaround

Git pre-commit hooks (.git/hooks/pre-commit) fire at the git level regardless of Claude Code mode. We use these for enforcement in automated test runs.

Activity

  1. github-actions commented on Mar 2, 2026

    @github-actions

    Found 1 possible duplicate issue:

    1. [BUG] hooks don't run in headless mode #20063

    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

  2. dicksontsai commented on Mar 3, 2026

    @dicksontsai
    Collaborator

    Your matcher syntax is invalid: Bash(*) isn't a valid pattern. The (*) makes it an invalid regex (quantifier with nothing to repeat), so it silently matches nothing. Instead use:

    "matcher": "Bash"
    

    See https://code.claude.com/docs/en/hooks#matcher-patterns

  3. bungles411 commented on Mar 3, 2026

    @bungles411
    Author

    Thanks @dicksontsai — good catch on the matcher syntax, that was definitely wrong in my repro.

    That said, the underlying question still stands: do PreToolUse/PostToolUse hooks fire in non-interactive -p mode? Issue #20063 reports the same behavior (hooks not running in headless mode) and is still open.

    Our workaround (git pre-commit hooks) works fine for enforcement, but it'd be great to get confirmation on whether -p mode hook support is intended or a known limitation.

  4. github-actions commented on Mar 12, 2026

    @github-actions

    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.

  5. locked as resolved and limited conversation to collaborators on Mar 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:hooksbugSomething isn't workinghas reproHas detailed reproduction stepsplatform:windowsIssue specifically occurs on Windows

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions