A prompt blocked by a UserPromptSubmit hook is still sent to the model API in print mode
Version: Claude Code 2.1.294, macOS (Darwin 27.0.0, arm64), model haiku
Steps to reproduce
- Make a project with this hook in
.claude/settings.json:
``json`
{"hooks":{"UserPromptSubmit":[{"hooks":[{"type":"command","command":"python3 hook.py"}]}]}}
hook.py
prints {"decision": "block", "reason": "blocked"} for a prompt that starts with block`. For other prompts, it prints nothing.
- Point
ANTHROPIC_BASE_URLat a local recording proxy. - Run
claude -p --input-format stream-json --output-format stream-json --verbosewith 2 user messages: firstblock: SECRET-MARKER, thenpass: reply with ok. - Look for
SECRET-MARKERin the recorded request bodies.
Expected: no request to the model API holds the blocked prompt. The hook blocked it.
Actual: 1 request to /v1/messages, with no tools and 1 message, holds the blocked prompt. It occurred in 9 of 9 runs. The requests of the main conversation do not hold it. In the interactive CLI, no request held the prompt in 9 of 9 runs.
Why it matters: a hook can block a prompt because the prompt must not leave the machine, for example a secret or a message for another system. In print mode, the prompt still goes to the API.
Reproduction script: scripts/spike_hook_display.py in mohanraj00/verbatim-relay. The data is in proofs/spikes/hook-display.json.
I also sent this report with /bug.