[FEATURE] Mods: let a prompt.submit hook consume a prompt silently (no "Prompt dropped by a hook" row)
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
Problem Statement
A mod that refuses a prompt in a prompt.submit hook (return { drop: reason }) always leaves a system row in the transcript: Prompt dropped by a hook: <reason>. There is no way for the plugin to drop a prompt silently.
That makes one class of mod noisy by design: a mod whose whole job is to hold incoming prompts quietly and deliver them later. Our case is a /dnd (Do Not Disturb) mod. While it is on, it holds everything that is not from the operator (Monitor and background task notifications, crons and /loop, peer pings, relays), so the operator can read what the agent just wrote in peace, and delivers all of it as one batch when DND ends. A live test held 3 Monitor events and 1 peer ping and delivered them correctly. But the transcript showed one Prompt dropped by a hook: dnd row per held message, which is exactly the interruption DND exists to remove.
The other delivery path already has the right semantics: session.receive → { consumed } keeps a delivery out of the session and leaves no row. Local notifications (task-notification, scheduled-trigger, peer, …) however arrive through prompt.submit (in our test a peer ping arrived there with origin peer, not through session.receive), and there the only refusal is drop.
What we tried on 2.1.288, none of which removes the row:
PromptSubmitResult.dropis the only refusal variant; its doc: "The text is shown to the user as the reason."- The row is a
session.appendwithdoor: 'notice':{"type":"system","name":"informational","content":[{"type":"text","text":"Prompt dropped by a hook: <reason>"}]}. It is not a render site, soui.rendercannot skip drawing it. session.appendhook rewritingcontentto[]: accepted, but the row is shown as(no content).session.appendhook answering withoutnext: skipped ("returned an answer without next (the row is kept)"). PerSessionAppendResult, only a plugin's own append (doornote) may be refused.
Our current workaround is to rewrite the notice text to a short line (🔕 held · task-notification · 3 waiting). It is less noisy, but it is still one row per held message, and the docs note that the screen may show the original text briefly before the rewrite lands.
Proposed Solution
Let a prompt.submit hook consume a prompt without leaving a transcript row, mirroring session.receive:
on('prompt.submit', async ($, e, next) => {
if (shouldHold(e)) {
await stash(e)
return { consumed: 'dnd' } // prompt does not enter, no row; reason goes to the debug log only
}
return next(e)
})
drop keeps its current, visible behaviour, which is the right default for a refusal the user should notice.
Alternative Solutions
{ drop: reason, silent: true }on the existing variant.- Allow a
session.appendhook to refuse anoticerow that was raised by a drop from a hook of the same plugin (narrower than letting plugins refuse arbitrary engine notices).
Either works for us. { consumed } seems the cleanest because session.receive already defines the same semantics.
Priority
Medium - Would be very helpful
Feature Category
Developer tools/SDK
Use Case Example
- The operator types
/dnd 30while reading a long answer from the agent. - A Monitor fires three events, a cron ticks, and another session pings this one.
- The mod stashes each prompt and returns
{ consumed }. Nothing appears in the transcript, and the agent does not start a new turn. A band above the prompt shows🔕 DND · 5 waiting. - The operator turns DND off (or the 30 minutes elapse). The mod submits one message that lists every held item with its sender and time, and the agent handles them together.
Today step 3 adds five Prompt dropped by a hook: dnd rows to the transcript.
Additional Context
- Claude Code 2.1.288 (mods / hooks modules), macOS, terminal.
- Related request extending the mods API: #91870 (
$.keybinding.register). - Unrelated to settings
UserPromptSubmithooks. This is about function hooks in a mod.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗