[DOCS] Clarify output structure and hookEventName usage for Stop hooks

Resolved 💬 3 comments Opened Dec 27, 2025 by coygeek Closed Jan 23, 2026

Documentation Type

Other

Documentation Location

https://code.claude.com/docs/en/hooks#hook-output

Section/Topic

Hook Output / Stop and SubagentStop Decision Control

Current Documentation

The documentation lists "Stop" and "SubagentStop" as valid hookEventName values in the general Hook Input section.

In the "Stop/SubagentStop Decision Control" section, it shows:

{
  "decision": "block" | undefined,
  "reason": "Must be provided when Claude is blocked from stopping"
}

However, other hooks (like PreToolUse or UserPromptSubmit) typically utilize a hookSpecificOutput object containing the hookEventName to pass data back. The documentation does not explicitly state that Stop hooks should not use hookSpecificOutput or return the hookEventName.

What's Wrong or Missing?

It is unclear if Stop and SubagentStop hooks support the hookSpecificOutput structure used by other hooks to return the hookEventName.

Empirical testing (on v2.0.76) confirms that Stop hooks function correctly using top-level JSON fields (decision and reason) and do not utilize hookSpecificOutput.

The current documentation creates confusion for schema generation and validation. It implies hookEventName might be required for consistency with other hooks, whereas verification shows these specific event types rely solely on the top-level schema.

Suggested Improvement

Please clarify explicitly that Stop and SubagentStop hooks utilize top-level JSON properties for their logic and do not use the hookSpecificOutput wrapper.

Suggested addition to the "Stop/SubagentStop Decision Control" section:

"Note: Unlike other hooks, Stop and SubagentStop do not use the hookSpecificOutput object or return the hookEventName. Control flow is managed entirely via top-level decision and reason fields."

Impact

High - Prevents users from using a feature

Additional Context

Verification Test:
I created a Stop hook returning:
{"decision": "block", "reason": "First stop blocked!"}

Result:
Claude successfully received the block signal and continued working/generating output. This confirms the top-level structure is the correct implementation, despite the ambiguity regarding hookEventName in the general input documentation.

View original on GitHub ↗

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