SLOPSHOPPER

cc-mod-input-wrap-repro

Repro: a focused Claude Code mod Input paints only the first wrapped row of a long value

panecommand
v0.1.0MITupdated 2026-10-16bassic-nerd/cc-mod-input-wrap-repro
A shopper browsing a rack in a slop shop
Preview · a replayed session in a sandbox
claude · ~/work/app · cc-mod-input-wrap-repro
│ ┃ Input wrap ✕ › fix the failing auth test and add an audit log call │ ┃ Type ~150 characters. Enter logs the real │ ┃ length. ⏺ Read(src/auth.ts) │ ┃ describe ⎿ Read 6 lines │ ┃ ⏺ Update(src/auth.ts) │ ┃ ⎿ Added 2 lines, removed 1 line │ ┃ ⏺ Bash(bun test) │ ┃ ⎿ 3 pass, 1 fail │ ┃ │ ┃ ● Done. refresh now rejects expired claims and logs an audit event. │ ┃ │ ┃ ✻ Worked for 42s · done 4:20 PM │ ┃ │ ┃ › /input-wrap │ ┃ ⎿ cc-mod-input-wrap-repro: Input wrap pane opened. Type about 150 │ ┃ │ ┃ │ ┃ │ ┃ │ ┃ │ ┃ │ ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── › ? for shortcuts

Draws

Pane · Input wrap
Type ~150 characters. Enter logs the real length. describe
README

cc-mod-input-wrap-repro

A Pane with one focused Input. Once the typed value wraps past one row, the field paints row 1, a short fragment ending in …, and then blank rows, with the caret on an empty last row.

Environment

  • Claude Code 2.1.300 (still present in 2.1.302), terminal surface
  • macOS; seen in Zed's integrated terminal
  • Mod API: ui.render hook drawing a Pane with the Input element

Install and run

From a terminal session, at the prompt:

/plugin install cc-mod-input-wrap-repro --marketplace bassic-nerd/cc-mod-input-wrap-repro

Answer y to add the marketplace, then pick a scope. Or load it straight from a clone, for one session:

git clone https://github.com/bassic-nerd/cc-mod-input-wrap-repro
claude --plugin-dir ./cc-mod-input-wrap-repro

Then run the slash command /input-wrap. It opens a pane and gives it the keyboard.

The whole mod is one file, hooks/register.tsx.

Repro steps

  1. Run /input-wrap. The pane has one focused Input (placeholder describe) and about 15 free rows below it.
  2. Type about 150 characters (for example, a pasted paragraph), enough to wrap onto 3 rows at a pane roughly 82 columns wide.
  3. Look at the field. Press Enter at the end: the real length is logged, to show the text is all there.

Expected

The focused field shows every wrapped row of its value, or at least the rows around the caret.

Actual

  • Row 1 paints.
  • Row 2 shows a short fragment ending in ….
  • Row 3 onward is blank.
  • The caret sits on the true last row, on an empty line.
  • The field still has focus (the ⏎ submit hint shows) and typing keeps going into the value, so no text is lost. It just cannot be seen. The layout reserves the right number of rows; only the painted text is cut.

Notes

The Input is drawn with a constant empty value, an autoFocus and a no-op onInput, so nothing in the mod redraws while you type. The fault is in how the focused field is painted.

Checks

claude plugin validate .
claude plugin test .
tsc --noEmit -p .

(the last needs the API types in .claude-plugin/types/, which Claude Code lays beside a mod it loads from a folder.)

License: MIT.

Source 1 files
hooks/register.tsx 34 lines
1import type { Register } from 'claude-code'
2
3const PANE = 'input-wrap'
4
5export const register: Register = on => {
6  on('session.start', async ($, e, next) => {
7    await $.command.register({ name: 'input-wrap', description: 'Open the Input wrap repro pane' })
8    return next(e)
9  })
10
11  on('command.run', { command: 'input-wrap' }, async $ => {
12    await $.ui.open({ id: PANE, title: 'Input wrap', focus: true })
13    return { text: 'Input wrap pane opened. Type about 150 characters into the field.' }
14  })
15
16  on('ui.render', { component: 'Pane', requestId: PANE }, ($, e, next) => {
17    if (e.surface !== 'terminal') return next(e)
18    const { Box, Text, Input } = $.ui.resolve(e)
19    return (
20      <Box flexDirection="column" height={20}>
21        <Text dimColor>Type ~150 characters. Enter logs the real length.</Text>
22        <Input
23          key="desc"
24          autoFocus
25          placeholder="describe"
26          value=""
27          onInput={() => {}}
28          onSubmit={v => $.ui.log(`input-wrap: field holds ${v.length} chars`)}
29        />
30      </Box>
31    )
32  })
33}
34