[BUG] Hookify warn rules don't educate Claude AI - messages only shown to user

Resolved 💬 3 comments Opened Dec 23, 2025 by markcheret Closed Dec 27, 2025

Bug Description

Hookify warn rules are intended to educate the AI agent about best practices while allowing operations to proceed. However, warn rule messages are only shown to the user (via systemMessage), not to Claude, defeating the primary purpose of educational warnings.

Expected Behavior

When a hookify warn rule triggers:

  1. The operation should proceed (not be blocked) ✅ Works
  2. Claude should receive the educational message and learn from it ❌ Broken
  3. The user should also see the message in verbose mode ✅ Works

Actual Behavior

When a warn rule triggers:

  • The operation proceeds ✅
  • The message goes to systemMessage which is only visible to the user
  • Claude never sees the message and cannot learn from it
  • Warn rules are useless for their intended purpose of AI education

Use Case

I have a hookify rule to educate Claude about maintenance mode requirements before kubectl apply:

---
name: warn-kubectl-apply
enabled: true
event: bash
pattern: kubectl\s+apply
action: warn
---

# ⚠️ KUBECTL APPLY - MAINTENANCE MODE REQUIRED

[Educational content about maintenance mode workflow...]

Intended behavior: When Claude tries to run kubectl apply, it sees this message and learns to use the maintenance mode workflow.

Actual behavior: Claude runs kubectl apply without seeing any warning. Only I (the user) see it in verbose logs.

Root Cause

In plugins/hookify/core/rule_engine.py, warn rules only set systemMessage:

if warning_rules:
    messages = [f"**[{r.name}]**\n{r.message}" for r in warning_rules]
    return {
        "systemMessage": "\n\n".join(messages)  # Only visible to user
    }

According to the hooks documentation:

  • systemMessage → Shown to user only
  • permissionDecisionReason → Shown to Claude (when deny)
  • additionalContext → Shown to Claude (for UserPromptSubmit)

There is no field to pass messages to Claude while allowing the operation to proceed.

Proposed Solution

Add support for passing warn messages to Claude via additionalContext:

if warning_rules:
    messages = [f"**[{r.name}]**\n{r.message}" for r in warning_rules]
    combined = "\n\n".join(messages)
    return {
        "hookSpecificOutput": {
            "hookEventName": hook_event,
            "additionalContext": combined  # Show to Claude
        },
        "systemMessage": combined  # Keep for user
    }

Related Issues

  • #12446 - Block rules also missing permissionDecisionReason (similar pattern)
  • #13962 - Stop event rules firing incorrectly on all tool uses

Impact

Warn rules are completely broken for AI education use cases. Users expecting Claude to learn from warn rules will find:

  • Block rules work (Claude sees the error)
  • Warn rules silently fail to educate (Claude sees nothing)

This makes hookify's educational purpose only half-functional.

Reproduction

  1. Create a warn rule in .claude/hookify.test-warn.local.md:

```yaml
---
name: test-warn
enabled: true
event: bash
pattern: echo\s+test
action: warn
---

# TEST WARNING
This should appear to Claude.
```

  1. Run command that triggers it: echo test
  2. Expected: Claude sees the warning message
  3. Actual: Command executes, no warning visible to Claude

Environment

  • Claude Code version: Latest (December 2025)
  • Hookify plugin: Latest from official plugins
  • OS: macOS (Darwin 24.6.0)

Verification

Block rules DO work (Claude sees the message):

  • Tested dangerous command patterns → Claude received full blocking message
  • This proves hookify is loaded and functioning

Warn rules DON'T work:

  • Tested kubectl apply → No warning shown to Claude
  • Tested docker pull → No warning shown to Claude
  • Tested markdown file edits → No warning shown to Claude

View original on GitHub ↗

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