Public/Write-ClaudeHookResponse.ps1
|
function Write-ClaudeHookResponse { <# .SYNOPSIS Emits a JSON response from a hook script to Claude Code. .DESCRIPTION Constructs and outputs the hook response JSON. All parameters are optional. Providing -StopReason sets continue:false. -BlockingError emits JSON then exits with code 2 (the hard-blocking error signal per the hooks spec). All other calls return normally so the hook can continue additional logic. .PARAMETER StopReason Message shown when Claude is stopped. Presence implies continue:false. .PARAMETER SystemMessage Non-blocking informational message shown to the user. .PARAMETER SuppressOutput Omits the response from the debug log when $true. .PARAMETER Decision Top-level decision field (e.g. 'block') for events like Stop, UserPromptSubmit. .PARAMETER Reason Explanation shown with -Decision. .PARAMETER HookSpecificOutput Hashtable of event-specific output fields merged under hookSpecificOutput. .PARAMETER BlockingError Emits the JSON response then immediately calls exit 2 (blocking error). Use only at the top level of a hook script, not inside testable functions. .EXAMPLE # Inject a system message (non-blocking) Write-ClaudeHookResponse -SystemMessage 'Lint passed.' Emits a non-blocking system message that is shown to the user without stopping Claude. .EXAMPLE # Stop Claude with a reason Write-ClaudeHookResponse -StopReason 'Build failed: 3 errors in src/' Emits a stop response that sets continue:false and shows the reason to the user. .OUTPUTS System.String .LINK about_ClaudeHooks .LINK https://code.claude.com/docs/en/hooks.md #> [OutputType([string])] [CmdletBinding()] param( [string]$StopReason, [string]$SystemMessage, [switch]$SuppressOutput, [string]$Decision, [string]$Reason, [hashtable]$HookSpecificOutput, [switch]$BlockingError ) $response = [ordered]@{} if ($PSBoundParameters.ContainsKey('StopReason')) { $response['continue'] = $false $response['stopReason'] = $StopReason } if ($PSBoundParameters.ContainsKey('SystemMessage')) { $response['systemMessage'] = $SystemMessage } if ($SuppressOutput) { $response['suppressOutput'] = $true } if ($PSBoundParameters.ContainsKey('Decision')) { $response['decision'] = $Decision } if ($PSBoundParameters.ContainsKey('Reason')) { $response['reason'] = $Reason } if ($HookSpecificOutput) { $response['hookSpecificOutput'] = $HookSpecificOutput } $json = ConvertTo-ClaudeHookJson -InputObject $response Write-Output $json if ($BlockingError) { exit 2 } } |