Skip to content

fix: handle 'prompt' key for UserPromptSubmit and deduplicate rule loading - #2

Open
kmmwren wants to merge 1 commit into
adrozdenko:mainfrom
kmmwren:fix/user-prompt-key-and-dedup
Open

fix: handle 'prompt' key for UserPromptSubmit and deduplicate rule loading#2
kmmwren wants to merge 1 commit into
adrozdenko:mainfrom
kmmwren:fix/user-prompt-key-and-dedup

Conversation

@kmmwren

@kmmwren kmmwren commented Mar 27, 2026

Copy link
Copy Markdown

Problem

Two bugs causing prompt-event hookify rules to silently never fire:

1. Wrong key for UserPromptSubmit input

rule_engine.py reads input_data.get('user_prompt', '') but Claude Code's UserPromptSubmit hook sends the user's message under the key prompt, not user_prompt. The result: any rule with field: user_prompt always receives an empty string and never matches.

Affected rules: all prompt-event rules (use-superpowers, decision-capture, meetsync-reminder, etc.).

2. Duplicate rule loading when cwd is home

config_loader.py searches two glob patterns:

  • .claude/hookify.*.local.md (project-level, relative to cwd)
  • ~/.claude/hookify.*.local.md (global)

When the hook runs with cwd=$HOME (which Claude Code does), both patterns resolve to the same files. Every rule is loaded twice, causing duplicate systemMessage output.

Fix

rule_engine.py: fall back to prompt when user_prompt is absent:

return input_data.get('user_prompt') or input_data.get('prompt', '')

config_loader.py: deduplicate by resolved absolute path before loading:

seen = set()
for f in glob.glob(pattern):
    resolved = os.path.realpath(f)
    if resolved not in seen:
        seen.add(resolved)
        files.append(f)

Test

echo '{"session_id":"test","transcript_path":"/tmp/test","prompt":"can you implement a new feature"}' \
  | CLAUDE_PLUGIN_ROOT=/path/to/hookify-plus python3 hooks/userpromptsubmit.py

Should now return a non-empty systemMessage for any matching prompt-event rule.

🤖 Generated with Claude Code

…ading

Claude Code's UserPromptSubmit hook sends the user's message under the key
'prompt', not 'user_prompt'. The rule engine was always reading an empty
string for the user_prompt field, causing all prompt-event rules (use-superpowers,
decision-capture, meetsync-reminder, etc.) to silently never fire.

Also fixes duplicate rule loading: when the hook runs with cwd=$HOME, the
project-level pattern (.claude/hookify.*.local.md) and the global pattern
(~/.claude/hookify.*.local.md) resolve to the same files. Added deduplication
by resolved absolute path before loading.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant