UserPromptSubmit: add a decision that shows output without agent invocation or 'blocked' framing

Resolved 💬 4 comments Opened Apr 1, 2026 by erikmchut Closed Jun 2, 2026

Problem

UserPromptSubmit hooks can handle prompts programmatically via decision: "block", but the UI shows "operation blocked by hook" — framing that implies 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 normal output in the transcript.

This matters for the pattern: programmatic fast-path with agent fallback. A hook intercepts a command (e.g. spr up), runs a binary, and:

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

Today this works via block + exit-code fallback, but "blocked by hook" makes success look like an error.

The other options don't help:

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

Proposed solution

A new decision (e.g. "handled") where the hook's output is displayed as normal transcript output — no "blocked" label, no special framing — and the agent is not invoked:

{
  "decision": "handled",
  "output": "✓ PR #42 updated, CI running at https://github.com/..."
}

The output should render in the transcript exactly like normal text output — indistinguishable from what the agent would produce. The session continues normally, ready for the next prompt.

Why this doesn't exist yet

Built-in /commands (/help, /clear, /compact) already do exactly this: run programmatically, show output, no agent. But this capability isn't exposed to user-defined hooks or commands. The hook protocol has "block" (error-framed) and "context" (agent still runs) but nothing in between.

Use case

We have a Rust CLI (spr) that handles PR workflows. A UserPromptSubmit hook intercepts spr up, spr land, etc. and runs the binary. When it succeeds, we want clean output shown to the user. When it needs judgment (exit code 2), we fall through to the agent with additionalContext. The programmatic-first, agent-fallback pattern works great — except success looks like "blocked by hook."

View original on GitHub ↗

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