Multi-line prompt renders incorrectly after terminal resize; Ctrl+L fixes it

Open 💬 1 comment Opened May 27, 2026 by spamsch

Description

When a terminal emulator opens Claude Code and the PTY's initial size differs from the actual rendered terminal dimensions, the multi-line input prompt can render incorrectly — lines appear in wrong positions, the prompt appears clipped, or adding a newline (Shift+Enter) doesn't visually extend the input area. Pressing Ctrl+L always fixes the display permanently.

This appears to be a cursor-tracking desync in Ink's redraw logic after receiving SIGWINCH. Ink tracks the cursor Y position from the previous frame to erase and redraw the prompt in-place. If the terminal is resized between renders, the stored cursor Y is anchored to the old layout, so the erase and redraw target the wrong rows.

Ctrl+L sends ESC[2J ESC[H, which causes Ink to discard all cursor-tracking state and repaint from row 0. After that, all subsequent redraws are correct — hence "fixes permanently."

Reproduction

  1. Open Claude Code in any terminal emulator that has a startup size mismatch — i.e. the PTY spawns at a default size (e.g. 80×24 or 120×24) and the emulator sends a SIGWINCH shortly after launch with the actual pixel-calculated dimensions.
  2. Before the emulator has settled on its final size, or immediately after first launch, type multi-line input using Shift+Enter (or \ + Enter, or Ctrl+J).
  3. Observe: the prompt rendering is garbled — extra lines appear at wrong positions, or the prompt doesn't grow visually despite the newline being inserted.
  4. Press Ctrl+L. The screen repaints correctly and all subsequent multi-line input works as expected.

The bug is most reproducible when:

  • The initial PTY size is 24 rows and the actual rendered terminal is significantly taller (e.g. 40+ rows in a large pane)
  • The emulator applies a debounce before sending the corrective SIGWINCH (e.g. 80–500ms)
  • The user types or pastes multi-line input in that window

Expected behavior

After receiving SIGWINCH and redrawing, Ink should re-anchor its cursor tracking state to the new terminal dimensions. Multi-line prompt rendering should be correct without requiring a manual Ctrl+L.

Context

Discovered while adding Shift+Enter support to a terminal emulator that wraps Claude Code. The emulator started PTYs at a 120×24 snapshot default and sent the real dimensions after an 80ms debounce — matching the window in which the bug triggers. Eliminating the debounce on the first resize (inspired by how Hyper handles componentDidMount) reduces the frequency significantly, but the core issue is in how Ink handles cursor position after SIGWINCH.

Related: the Kitty keyboard protocol correctly delivers \x1b[13;2u for Shift+Enter, but emulators not implementing the protocol should send \n (0x0A, same as Ctrl+J / chat:newline) rather than \r. This is a separate concern from the redraw bug.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗