# Long-poll hooks-approval for Stop (plan mode) decisions # Only activates when permission_mode is 'plan' and stop_hook_active is false # Returns Stop decision JSON per Claude Code docs: # { "decision": "block", "reason": "..." } to continue implementing # {} or empty to let Claude stop param([string]$agent = "") if ($agent) { $logFile = "$PSScriptRoot/../.claude-$agent/debug/hooks.log" } else { $logFile = "$PSScriptRoot/../.claude/debug/hooks.log"; $agent = "local" } $ts = Get-Date -Format "HH:mm:ss.fff" $b = [Console]::In.ReadToEnd() Add-Content $logFile "[$ts] [PLAN] Hook fired for agent=$agent stdin_len=$($b.Length)" $j = $b | ConvertFrom-Json Add-Content $logFile "[$ts] [PLAN] permission_mode=$($j.permission_mode) stop_hook_active=$($j.stop_hook_active)" if ($j.permission_mode -ne 'plan' -or $j.stop_hook_active) { Add-Content $logFile "[$ts] [PLAN] Skipping (not plan mode or stop_hook_active)" exit 0 } $url = 'http://localhost:4101/api/hooks-approval/plan' $sep = '?' $pty = $env:AGENT_UI_PTY_SESSION if ($pty) { $url += "${sep}pty_session=$pty"; $sep = '&' } if ($agent -and $agent -ne 'local') { $url += "${sep}agent=$agent" } try { Add-Content $logFile "[$ts] [PLAN] POSTing to backend..." $r = Invoke-RestMethod -Uri $url -Method POST -Body $b -ContentType 'application/json' -TimeoutSec 125 $ts2 = Get-Date -Format "HH:mm:ss.fff" if ($r -and $r.decision) { $out = $r | ConvertTo-Json -Depth 10 -Compress Add-Content $logFile "[$ts2] [PLAN] Got response: $out" $out } else { Add-Content $logFile "[$ts2] [PLAN] Empty/timeout response (no decision)" } } catch { $ts2 = Get-Date -Format "HH:mm:ss.fff" Add-Content $logFile "[$ts2] [PLAN] ERROR: $($_.Exception.Message)" }