[BUG] Plugin Input empties on Enter while the hook still draws the same value

Status Open
Reported on v2.1.296
Maintainer reply None cached
Activity 0 comments · opened Oct 13, 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?

In a function-hooks plugin, an Input shows an empty field after Enter, although the hook keeps drawing the same value and onSubmit got the text. The next key then calls onInput with that one character, so the text the plugin held is replaced.

InputProps.value is documented as "the text the field holds when drawn; the person's typing replaces it until the hook draws another". Nothing there says Enter clears it.

I hit this in a mod's search field: after Enter the filter stays applied, the field looks empty, and the next key starts a new search.

What Should Happen?

After Enter the field shows the value the hook draws (abc), and typing d gives abcd. If clearing on submit is intended, the docs should say so; a hook that wants an empty field can draw value="".

Error Messages/Logs

None. What the pane shows at each step (the second line is the hook's own value and submit count):

after typing abc   │ abc  ⏎ submit
                   │ value prop drawn: "abc" · submits: 0
after Enter        │   ⏎ submit
                   │ value prop drawn: "abc" · submits: 1
after typing d     │ d  ⏎ submit
                   │ value prop drawn: "d" · submits: 1

Steps to Reproduce

  1. Make a plugin folder input-probe with these three files.

.claude-plugin/plugin.json:

{ "name": "input-probe", "version": "0.0.0", "description": "Input value after Enter" }

hooks/hooks.json:

{ "modules": ["./register.tsx"] }

hooks/register.tsx:

export const register = on => {
  let value = ''
  let submits = 0
  on('session.start', async ($, e, next) => {
    await $.command.register({ name: 'probe', description: 'Open the Input probe' })
    return next(e)
  })
  on('command.run', { command: 'probe' }, async $ => {
    await $.ui.open({ id: 'probe', title: 'probe', focus: true, closeOnEscape: true })
    return { text: '' }
  })
  on('ui.render', { component: 'Pane', requestId: 'probe' }, ($, e) => {
    const { Box, Text, Input } = $.ui.resolve(e)
    return (
      <Box flexDirection="column">
        <Input
          key="field"
          autoFocus
          value={value}
          onInput={text => { value = text; $.ui.invalidate('ui.render') }}
          onSubmit={text => { value = text; submits += 1; $.ui.invalidate('ui.render') }}
        />
        <Text>{`value prop drawn: "${value}" · submits: ${submits}`}</Text>
      </Box>
    )
  })
}
  1. claude --plugin-dir ./input-probe (claude plugin validate ./input-probe passes).
  2. Run /probe. The pane opens with the field focused.
  3. Type abc. The line under the field says value prop drawn: "abc" · submits: 0.
  4. Press Enter. The field is empty; the line says value prop drawn: "abc" · submits: 1.
  5. Type d. The field shows d and the line says value prop drawn: "d".

Claude Model

_No response_

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.296 (Claude Code)

Platform

Anthropic API

Operating System

Other Linux

Terminal/Shell

Other

Additional Information

Arch Linux (kernel 7.2.9), kitty 0.49.2, inside herdr 0.9.3; I first saw it in kitty alone. The probe needs no login: it reproduces in a fresh CLAUDE_CONFIG_DIR before signing in.

View original on GitHub ↗