Skip to content

fix(hookify): PostToolUse hooks cannot return permissionDecision: deny#68671

Closed
AZERDSQ131 wants to merge 1 commit into
anthropics:mainfrom
AZERDSQ131:fix/hookify-rule-engine-posttooluse
Closed

fix(hookify): PostToolUse hooks cannot return permissionDecision: deny#68671
AZERDSQ131 wants to merge 1 commit into
anthropics:mainfrom
AZERDSQ131:fix/hookify-rule-engine-posttooluse

Conversation

@AZERDSQ131

Copy link
Copy Markdown

Problem

In plugins/hookify/core/rule_engine.py, the evaluate_rules function returned permissionDecision: "deny" for both PreToolUse and PostToolUse hook events:

# before
elif hook_event in ['PreToolUse', 'PostToolUse']:
    return {"hookSpecificOutput": {"hookEventName": hook_event, "permissionDecision": "deny"}, ...}

PostToolUse fires after the tool has already executed. The Claude Code hook protocol explicitly states that permissionDecision is only meaningful for PreToolUse. Sending it for PostToolUse produces undefined behaviour (the field is silently ignored or causes a protocol error depending on the runtime version).

Fix

Split the two cases:

  • PreToolUse → returns permissionDecision: "deny" as before (correct)
  • PostToolUse and all other non-Stop events → returns only systemMessage (the only valid output for post-execution hooks)

Testing

Covered by reading the hook protocol spec and tracing evaluate_rules call sites in pretooluse.py and posttooluse.py.

🤖 Generated with Claude Code

…olUse block logic

A blocking rule in rule_engine.py returned permissionDecision:"deny" for
both PreToolUse and PostToolUse events. PostToolUse fires after the tool
has already executed; sending permissionDecision:"deny" has no effect and
produces undefined behaviour in the Claude Code hook protocol.

PreToolUse now returns the deny decision as before.
PostToolUse and all other non-Stop events fall through to the plain
systemMessage path, which is the only valid output format for post-execution
hooks.
@AZERDSQ131

Copy link
Copy Markdown
Author

Closing: absorbed by #68673 which is a superset covering the same hookify files

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