Preflight Checklist
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:
{
"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.json pointing to the hooks file
- Enable the plugin in settings
- Start Claude Code and submit any user prompt
- 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?
- UserPromptSubmit hooks defined in plugin
hooks.json files 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
Preflight Checklist
What's Wrong?
Summary: UserPromptSubmit hooks defined in plugin
hooks.jsonfiles are registered and matched correctly but their commands never execute. The same hook configuration works when defined directly in~/.claude/settings.json.Environment:
/Users/jrpospos/.claude/settings.jsonSteps to Reproduce:
hooks/hooks.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" } ] } ] } }.claude-plugin/plugin.jsonpointing to the hooks file--debugflagExpected Behavior
The hook command should execute when a user submits a prompt, similar to how
Stop,PostToolUse, andSessionStarthook 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
[DEBUG] Registered 2 hooks from 1 plugins[DEBUG] Matched 2 unique hooks for query "no match query"Comparison:
~/.claude/settings.jsonhook: Registers → Matches → Executeshooks.jsonhook: Registers → Matches → Silent failureError Messages/Logs
Plugin installation (command never executes):
(No execution occurs - no output line)
Manual settings.json installation (works correctly):
(Hook executes successfully)
Additional Context
Stop,PostToolUse,SessionStart) work correctly in plugins${CLAUDE_PLUGIN_ROOT}variable syntax is correct and matches working plugin examplesWorkaround: Defining the same hook in
~/.claude/settings.jsonworks as expected:{ "hooks": { "UserPromptSubmit": [ { "hooks": [ { "type": "command", "command": "python3 ~/.claude/hooks/improve-prompt.py" } ] } ] } }What Should Happen?
hooks.jsonfiles should execute their commands after matching, consistent with other hook types