UserPromptSubmit hook systemMessage does not render in the Desktop app (or VS Code extension)

Status Open
Reported on v2.1.204
Maintainer reply None cached
Activity 2 comments · opened Jul 16, 2026

Summary

A UserPromptSubmit hook that returns only {"systemMessage": "..."} (a non-blocking advisory message, no decision field) is silently dropped — it never reaches the user's view. This is reproducible on both the Claude Desktop app and the VS Code extension. The blocking case ({"decision":"block", "reason":"..."}) is unaffected and renders correctly everywhere via its own dedicated UI treatment.

Environment

  • Claude Code CLI version: 2.1.204 (bundled version string found in the installed npm package; exact claude --version may differ by channel)
  • Reproduced on: Claude Desktop app (CLAUDE_CODE_ENTRYPOINT=claude-desktop)
  • Same underlying gap previously confirmed on the VS Code extension (CLAUDE_CODE_ENTRYPOINT=claude-vscode) — worked around downstream, see below

Repro steps

  1. Register a UserPromptSubmit hook that, for some prompts, emits only:

``json
{"systemMessage": "example advisory message"}
`
with no
decision field and no hookSpecificOutput.additionalContext`.

  1. Run a Claude Code session from the Desktop app (or the VS Code extension) and submit a prompt that triggers this hook output.
  2. Observe: the hook fires (confirm via the hook's own logging/exit code — ours logs to a debug file and exits 0), but no message appears anywhere in the session UI, and the assistant's context does not reflect it either.

Expected

systemMessage should render to the user (e.g. as an inline notice) the same way it does in the raw CLI terminal, regardless of which client surface (CLI, Desktop, VS Code, JetBrains) is hosting the session.

Actual

systemMessage is silently dropped on at least Desktop and VS Code. Only hookSpecificOutput.additionalContext reliably reaches the session (via the model's context, since the model can relay it in a reply) — but that's a workaround, not equivalent to a genuine user-facing UI element, and it depends on the model choosing to mention it.

Downstream impact / workaround

We maintain a UserPromptSubmit hook (a model/effort right-sizing advisor) that hit this exact gap. We worked around it hook-side by also populating hookSpecificOutput.additionalContext with the same text whenever CLAUDE_CODE_ENTRYPOINT is anything other than the CLI baseline, so the model relays the message in its reply. That's a reasonable mitigation for us, but it shouldn't be necessary — systemMessage is documented as the mechanism for surfacing a hook notice to the user, with no documented caveat that it's CLI-only.

Additional notes

  • The decision:"block" path is unaffected — it renders via its own dedicated "Prompt blocked by a hook" UI treatment on both Desktop and VS Code, confirmed independently.
  • We could not find any existing documentation (hooks.md / hooks-guide.md) noting a client-specific difference in systemMessage rendering, nor any existing issue reporting this.
  • Happy to share the specific hook payloads/JSON we used to reproduce if useful.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗