UserPromptSubmit: add a 'handled' decision (show output, skip agent, no 'blocked' framing)

Open 💬 0 comments Opened Jun 29, 2026 by atomarch

Problem

UserPromptSubmit hooks can short-circuit a prompt via decision: "block", but the
UI renders this as "operation blocked by hook" — framing that reads as an error or
denial. There's no way for a hook to say "I handled this successfully, here's the
output" and have it appear as ordinary transcript text.

This blocks a useful pattern: programmatic fast-path with agent fallback. A hook
intercepts a command, runs a binary, and:

  • On success → show the result to the user, no agent needed
  • On failure → fall through to the agent for judgment

Today this works via block + exit-code fallback, but a successful run still looks
like an error.

The existing options don't fit:

  • additionalContext — the agent still runs (latency + token cost for nothing)
  • continue: false — halts the whole session
  • !shell — no agent fallback; the user must know the exact command
  • user-defined /commands — prompt templates that always invoke the agent

Proposed solution

A new decision (e.g. "handled") whose output renders as normal transcript text —
no "blocked" label — and which does not invoke the agent:

{
"decision": "handled",
"output": "✓ Done — 3 files updated"
}

Ideally the handled command's stdout/stderr is also surfaced to the agent (as !command
does today), so the agent stays aware the action occurred on subsequent turns.

Prior discussion

Originally raised in #42178 (closed as stale). Re-filing per the stale bot's request,
since it's still relevant and had +1s from multiple users hitting the same wall —
including a VS Code case where block reason text isn't rendered in the chat window at all.

Use case

A team uses a custom CLI to handle routine workflow commands. A UserPromptSubmit hook
intercepts those commands and runs the binary directly. On success we want clean output
shown to the user with no agent round-trip; when the command needs judgment (e.g. exit
code 2) we fall through to the agent via additionalContext. The programmatic-first,
agent-fallback pattern works well — except a successful run is framed as "blocked by hook."

View original on GitHub ↗