[BUG] Mods: a prompt dropped by a `prompt.submit` hook is put back in the prompt box after text the hook wrote with `$.prompt.fill`

Status Open
Reported on v2.1.295
Maintainer reply None cached
Activity 0 comments · opened Oct 9, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

A mod can block a message and put a suggested replacement in the prompt box for the user to review.

Since 2.1.295, the user sees the suggested replacement followed by the message that was just blocked. If they send that text, the mod blocks it again, and the prompt box then shows a new suggested replacement followed by both earlier messages.

For example, a mod blocks messages that contain an API key and suggests the same message with the key removed. The user sends:

deploy with key sk-12345

The prompt box then shows:

> deploy with key [REMOVED]
  deploy with key sk-12345

It should show only:

> deploy with key [REMOVED]

Technical details

After a prompt.submit hook returns { drop: reason }, Claude Code puts the dropped prompt back in the prompt box. If the hook already wrote text to the box with $.prompt.fill, Claude Code adds the dropped prompt after that text on a new line.

The drop documentation does not mention this restore, the 2.1.295 changelog does not list it, and a hook has no way to turn it off. The problem is still present in 2.1.296.

What Should Happen?

The prompt box contains only the text the hook wrote. Either of these would work:

  1. Claude Code puts the dropped prompt back in the box only when the box is empty.
  2. The { drop } result takes a field that tells Claude Code not to put the prompt back.

Error Messages/Logs

Prompt dropped by a hook: droptest
droptest: box after drop: "FILLED\n#droptest hello"

Steps to Reproduce

  1. Create a mod with this hooks/register.ts:

```ts
import type { Register } from 'claude-code'

export const register: Register = on => {
on('prompt.submit', async ($, e, next) => {
if (!e.text.startsWith('#droptest')) return next(e)
await $.prompt.fill({ text: 'FILLED' })
$.clock.after(100, async () => {
const box = await $.prompt.read()
$.ui.log(box after drop: ${JSON.stringify(box.text)})
})
return { drop: 'droptest' }
})
}
```

  1. Load the mod and send #droptest hello.
  2. Look at the prompt box. It shows:

``
> FILLED
#droptest hello
``

It should show only:

``
> FILLED
``

A prompt with several lines is put back the same way.

Claude Model

Not sure / Multiple models

Is this a regression?

Yes, this worked in a previous version

Last Working Version

2.1.292

Claude Code Version

2.1.296 (Claude Code)

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

iTerm2

Additional Information

These 2.1.295 changelog entries change how dropped prompts and prompt history are handled, and may be the source of the change:

  • "Fixed a prompt that a mod's prompt.submit hook rewrote or dropped still being saved as typed to prompt history and to the transcript's queued-prompt records"
  • "Fixed a queued message being lost when pulled back into the prompt with ↑ or Esc just after ←: prompt history now keeps it"

Other issues about dropped prompts, which report different problems: #99417, #96891.

View original on GitHub ↗