[BUG] UserPromptSubmit hooks from plugins match but never execute
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:
- 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"
}
]
}
]
}
}
- Configure plugin in
.claude-plugin/plugin.jsonpointing to the hooks file - Enable the plugin in settings
- Start Claude Code and submit any user prompt
- Check debug logs with
--debugflag
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.jsonhook: Registers → Matches → Executes - ❌ Plugin
hooks.jsonhook: 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?
- UserPromptSubmit hooks defined in plugin
hooks.jsonfiles should execute their commands after matching, consistent with other hook types - The execution flow should be: Register → Match → Execute → Process output
- Plugin hooks and manual hooks should have identical execution behavior for all hook types
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗