@@ -123,7 +123,7 @@ Ask AI
123123```
124124
125125- ** matcher** : Pattern to match tool names, case-sensitive (only applicable for
126- ` PreToolUse ` and ` PostToolUse ` )
126+ ` PreToolUse ` , ` PermissionRequest ` , and ` PostToolUse ` )
127127
128128 - Simple strings match exactly: ` Write ` matches only the Write tool
129129 - Supports regex: ` Edit|Write ` or ` Notebook.* `
@@ -313,6 +313,7 @@ Prompt-based hooks work with any hook event, but are most useful for:
313313- ** SubagentStop** : Evaluate if a subagent has completed its task
314314- ** UserPromptSubmit** : Validate user prompts with LLM assistance
315315- ** PreToolUse** : Make context-aware permission decisions
316+ - ** PermissionRequest** : Intelligently allow or deny permission dialogs
316317
317318### [ ​] ( https://code.claude.com/docs/en/hooks\# example:-intelligent-stop-hook ) Example: Intelligent Stop hook
318319
@@ -582,7 +583,8 @@ Ask AI
582583 "tool_input": {
583584 "file_path": "/path/to/file.txt",
584585 "content": "file content"
585- }
586+ },
587+ "tool_use_id": "toolu_01ABC123..."
586588}
587589```
588590
@@ -609,7 +611,8 @@ Ask AI
609611 "tool_response": {
610612 "filePath": "/path/to/file.txt",
611613 "success": true
612- }
614+ },
615+ "tool_use_id": "toolu_01ABC123..."
613616}
614617```
615618
@@ -723,21 +726,24 @@ Ask AI
723726
724727## [ ​] ( https://code.claude.com/docs/en/hooks\# hook-output ) Hook Output
725728
726- There are two ways for hooks to return output back to Claude Code. The output
729+ There are two mutually-exclusive ways for hooks to return output back to Claude Code. The output
727730communicates whether to block and any feedback that should be shown to Claude
728731and the user.
729732
730733### [ ​] ( https://code.claude.com/docs/en/hooks\# simple:-exit-code ) Simple: Exit Code
731734
732735Hooks communicate status through exit codes, stdout, and stderr:
733736
734- - ** Exit code 0** : Success. ` stdout ` is shown to the user in transcript mode
735- (CTRL-R), except for ` UserPromptSubmit ` and ` SessionStart ` , where stdout is
736- added to the context.
737- - ** Exit code 2** : Blocking error. ` stderr ` is fed back to Claude to process
738- automatically. See per-hook-event behavior below.
739- - ** Other exit codes** : Non-blocking error. ` stderr ` is shown to the user and
740- execution continues.
737+ - ** Exit code 0** : Success. ` stdout ` is shown to the user in verbose mode
738+ (ctrl+o), except for ` UserPromptSubmit ` and ` SessionStart ` , where stdout is
739+ added to the context. JSON output in ` stdout ` is parsed for structured control
740+ (see [ Advanced: JSON Output] ( https://code.claude.com/docs/en/hooks#advanced-json-output ) ).
741+ - ** Exit code 2** : Blocking error. Only ` stderr ` is used as the error message
742+ and fed back to Claude. The format is ` [command]: {stderr} ` . JSON in ` stdout `
743+ is ** not** processed for exit code 2. See per-hook-event behavior below.
744+ - ** Other exit codes** : Non-blocking error. ` stderr ` is shown to the user in verbose mode (ctrl+o) with
745+ format ` Failed with non-blocking status code: {stderr} ` . If ` stderr ` is empty,
746+ it shows ` No stderr output ` . Execution continues.
741747
742748Reminder: Claude Code does not see stdout if the exit code is 0, except for
743749the ` UserPromptSubmit ` hook where stdout is injected as context.
@@ -747,6 +753,7 @@ the `UserPromptSubmit` hook where stdout is injected as context.
747753| Hook Event | Behavior |
748754| --- | --- |
749755| ` PreToolUse ` | Blocks the tool call, shows stderr to Claude |
756+ | ` PermissionRequest ` | Denies the permission, shows stderr to Claude |
750757| ` PostToolUse ` | Shows stderr to Claude (tool already ran) |
751758| ` Notification ` | N/A, shows stderr to user only |
752759| ` UserPromptSubmit ` | Blocks prompt processing, erases prompt, shows stderr to user only |
@@ -758,7 +765,11 @@ the `UserPromptSubmit` hook where stdout is injected as context.
758765
759766### [ ​] ( https://code.claude.com/docs/en/hooks\# advanced:-json-output ) Advanced: JSON Output
760767
761- Hooks can return structured JSON in ` stdout ` for more sophisticated control:
768+ Hooks can return structured JSON in ` stdout ` for more sophisticated control.
769+
770+ JSON output is only processed when the hook exits with code 0. If your hook
771+ exits with code 2 (blocking error), ` stderr ` text is used directly—any JSON in ` stdout `
772+ is ignored. For other non-zero exit codes, only ` stderr ` is shown to the user in verbose mode (ctrl+o).
762773
763774#### [ ​] ( https://code.claude.com/docs/en/hooks\# common-json-fields ) Common JSON Fields
764775
@@ -881,13 +892,21 @@ Ask AI
881892
882893#### [ ​] ( https://code.claude.com/docs/en/hooks\# userpromptsubmit-decision-control ) ` UserPromptSubmit ` Decision Control
883894
884- ` UserPromptSubmit ` hooks can control whether a user prompt is processed.
895+ ` UserPromptSubmit ` hooks can control whether a user prompt is processed and add context.** Adding context (exit code 0):**
896+ There are two ways to add context to the conversation:
885897
886- - ` "block" ` prevents the prompt from being processed. The submitted prompt is
887- erased from context. ` "reason" ` is shown to the user but not added to context.
888- - ` undefined ` allows the prompt to proceed normally. ` "reason" ` is ignored.
889- - ` "hookSpecificOutput.additionalContext" ` adds the string to the context if not
890- blocked.
898+ 1 . ** Plain text stdout** (simpler): Any non-JSON text written to stdout is added
899+ as context. This is the easiest way to inject information.
900+ 2 . ** JSON with ` additionalContext ` ** (structured): Use the JSON format below for
901+ more control. The ` additionalContext ` field is added as context.
902+
903+ Both methods work with exit code 0. Plain stdout is shown as hook output in
904+ the transcript; ` additionalContext ` is added more discretely.** Blocking prompts:**
905+
906+ - ` "decision": "block" ` prevents the prompt from being processed. The submitted
907+ prompt is erased from context. ` "reason" ` is shown to the user but not added
908+ to context.
909+ - ` "decision": undefined ` (or omitted) allows the prompt to proceed normally.
891910
892911Copy
893912
@@ -904,6 +923,10 @@ Ask AI
904923}
905924```
906925
926+ The JSON format is not required for simple use cases. To add context, you can
927+ just print plain text to stdout with exit code 0. Use JSON when you need to
928+ block prompts or want more structured control.
929+
907930#### [ ​] ( https://code.claude.com/docs/en/hooks\# stop/subagentstop-decision-control ) ` Stop ` /` SubagentStop ` Decision Control
908931
909932` Stop ` and ` SubagentStop ` hooks can control whether Claude must continue.
@@ -1006,8 +1029,12 @@ if issues:
10061029
10071030For ` UserPromptSubmit ` hooks, you can inject context using either method:
10081031
1009- - Exit code 0 with stdout: Claude sees the context (special case for ` UserPromptSubmit ` )
1010- - JSON output: Provides more control over the behavior
1032+ - ** Plain text stdout** with exit code 0: Simplest approach—just print text
1033+ - ** JSON output** with exit code 0: Use ` "decision": "block" ` to reject prompts,
1034+ or ` additionalContext ` for structured context injection
1035+
1036+ Remember: Exit code 2 only uses ` stderr ` for the error message. To block using
1037+ JSON (with a custom reason), use ` "decision": "block" ` with exit code 0.
10111038
10121039Copy
10131040
@@ -1091,7 +1118,7 @@ if tool_name == "Read":
10911118 output = {
10921119 "decision": "approve",
10931120 "reason": "Documentation file auto-approved",
1094- "suppressOutput": True # Don't show in transcript mode
1121+ "suppressOutput": True # Don't show in verbose mode
10951122 }
10961123 print(json.dumps(output))
10971124 sys.exit(0)
@@ -1209,7 +1236,7 @@ This prevents malicious hook modifications from affecting your current session.
12091236- ** Input** : JSON via stdin
12101237- ** Output** :
12111238
1212- - PreToolUse/PostToolUse/Stop/SubagentStop: Progress shown in transcript (Ctrl-R )
1239+ - PreToolUse/PermissionRequest/ PostToolUse/Stop/SubagentStop: Progress shown in verbose mode (ctrl+o )
12131240 - Notification/SessionEnd: Logged to debug only (` --debug ` )
12141241 - UserPromptSubmit/SessionStart: stdout added as context for Claude
12151242
@@ -1262,7 +1289,7 @@ Ask AI
12621289[DEBUG] Hook command completed with status 0: <Your stdout>
12631290```
12641291
1265- Progress messages appear in transcript mode (Ctrl-R ) showing:
1292+ Progress messages appear in verbose mode (ctrl+o ) showing:
12661293
12671294- Which hook is running
12681295- Command being executed
0 commit comments