PreToolUse hook systemMessage never renders (rendered:false) — invisible in plan-approval dialog
Summary
A PreToolUse hook's systemMessage is recorded in the session transcript as ahook_system_message attachment carrying rendered: false, and never displays anywhere in the
UI — not in the tool's permission/approval dialog, not in the transcript view. In the same
session, additionalContext attachments (hook_additional_context) rendered 16/16. This makessystemMessage a dead channel for exactly the case it exists for: putting a security-relevant
warning in front of the human at decision time.
Environment
- Claude Code 2.1.278, macOS (Darwin 25.6.0), interactive terminal session
Reproduction
- Register a
PreToolUsehook on matcherExitPlanModethat returns adeny-capable JSON
decision with BOTH channels populated, e.g.:
``json``
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "ask",
"permissionDecisionReason": "This plan describes an operator-reserved action…",
"systemMessage": "This plan describes an operator-reserved action and needs your explicit authorization before it proceeds: privilege escalation (sudo); destructive filesystem operation (rm -rf). Review before approving."
}
}
- In a session governed by that registration, have Claude write a plan (plan mode) that
contains the flagged content and call ExitPlanMode.
- Observe the plan-approval dialog.
Expected
The permissionDecisionReason and/or systemMessage text is visible to the human somewhere at
approval time — ideally inside or adjacent to the plan-approval dialog, since ask exists to
put a reason in front of the user before they approve.
Actual
- The approval dialog is the completely generic plan view ("Claude has written up a plan and is
ready to execute. Would you like to proceed?" + the three standard options). No hook text
anywhere. Verified by a human watching the dialog and copying it verbatim during the exact
round trip where the hook fired.
- The hook demonstrably fired and emitted: the session
.jsonltranscript contains the
hook_system_message attachment with the exact warning text, bound to the ExitPlanMode
tool call's toolUseID, with rendered: false.
- Across the session:
hook_system_messageattachments 0/4 rendered;hook_additional_context
attachments 16/16 rendered. So this is specific to the systemMessage attachment type, not a
general attachment-display problem.
Impact
Any PreToolUse gate that uses ask + systemMessage to surface a warning at approval time is
mechanically live but humanly silent — the permission prompt appears, but the reason it appeared
never reaches the person approving. For security-shaped hooks (flagging privileged/destructive
actions inside plans before approval) this defeats the purpose of the ask decision: the user
sees a normal approval dialog with no indication anything was flagged.