[BUG] UserPromptSubmit hooks from plugins match but never execute

Resolved 💬 3 comments Opened Oct 24, 2025 by severity1 Closed Oct 27, 2025

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code

What's Wrong?

Summary: UserPromptSubmit hooks defined in plugin hooks.json files are registered and matched correctly but their commands never execute. The same hook configuration works when defined directly in ~/.claude/settings.json.

Environment:

  • Claude Code version: 2.0.24
  • OS: macOS (Darwin 24.6.0)
  • Settings location: /Users/jrpospos/.claude/settings.json

Steps to Reproduce:

  1. Create a plugin with UserPromptSubmit hook in hooks/hooks.json:

``json
{
"hooks": {
"UserPromptSubmit": [
{
"description": "Improves user prompts by adding clarifying questions",
"hooks": [
{
"type": "command",
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/scripts/improve-prompt.py",
"description": "Run the prompt improvement script"
}
]
}
]
}
}
``

  1. Configure plugin in .claude-plugin/plugin.json pointing to the hooks file
  2. Enable the plugin in settings
  3. Start Claude Code and submit any user prompt
  4. Check debug logs with --debug flag

Expected Behavior

The hook command should execute when a user submits a prompt, similar to how Stop, PostToolUse, and SessionStart hook types work in plugins. Based on the hooks documentation, plugin hooks should "function identically to user/project hooks but integrate through a different mechanism."

Actual Behavior

  • The hook is registered correctly: [DEBUG] Registered 2 hooks from 1 plugins
  • The hook is matched correctly: [DEBUG] Matched 2 unique hooks for query "no match query"
  • The hook command never executes - no "Hook output" log line appears
  • No errors are logged

Comparison:

  • ✅ Manual ~/.claude/settings.json hook: Registers → Matches → Executes
  • ❌ Plugin hooks.json hook: Registers → Matches → Silent failure

Error Messages/Logs

Plugin installation (command never executes):

[DEBUG] Loading hooks from plugin: prompt-improver
[DEBUG] Registered 2 hooks from 1 plugins
[DEBUG] Getting matching hook commands for UserPromptSubmit with query: undefined
[DEBUG] Found 2 hook matchers in settings
[DEBUG] Matched 2 unique hooks for query "no match query" (2 before deduplication)

(No execution occurs - no output line)

Manual settings.json installation (works correctly):

[DEBUG] Getting matching hook commands for UserPromptSubmit with query: undefined
[DEBUG] Found 1 hook matchers in settings
[DEBUG] Matched 1 unique hooks for query "no match query" (1 before deduplication)
[DEBUG] Hook output does not start with {, treating as plain text

(Hook executes successfully)

Additional Context

  • The plugin hook structure follows the same format as working marketplace plugins (e.g., hook-auto-docs)
  • Other hook types (Stop, PostToolUse, SessionStart) work correctly in plugins
  • No marketplace plugins currently use UserPromptSubmit hooks, which may explain why this hasn't been caught
  • The ${CLAUDE_PLUGIN_ROOT} variable syntax is correct and matches working plugin examples
  • Complete debug logs available if needed

Workaround: Defining the same hook in ~/.claude/settings.json works as expected:

{
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "python3 ~/.claude/hooks/improve-prompt.py"
          }
        ]
      }
    ]
  }
}

What Should Happen?

  1. UserPromptSubmit hooks defined in plugin hooks.json files should execute their commands after matching, consistent with other hook types
  2. The execution flow should be: Register → Match → Execute → Process output
  3. Plugin hooks and manual hooks should have identical execution behavior for all hook types

View original on GitHub ↗

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