[BUG] Mods: hardware cursor stays at the prompt while a Client has key focus, so IME composition (Korean) is drawn in the prompt box

Status Open
Reported on v2.1.290
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
  • [x] Observed on 2.1.290; I checked the 2.1.296 build and the same code is there (see Version)

What's Wrong?

While a mod's Client element has keyboard focus (after the user clicks it), Claude Code keeps the terminal's hardware cursor at the prompt input's caret. Terminals that draw IME pre-edit text at the hardware cursor therefore show the composing character in the prompt box, not in the Client the user is typing into. I saw this in Orca, which is built on xterm.js. xterm.js places its composition view at the buffer cursor.

With Korean input, each syllable's in-progress text (ㅇ, then 아, then 안) appears in the prompt box. The Client's onKey gets only the committed syllable. The prompt itself is not changed, but it looks as if the user is typing into both places.

A mod can't fix this. ClientSurface has no way to declare a caret: its members are elements, state, columns, rows, setState, every, onPointer, onKey and post.

What Should Happen?

While a Client holds key focus, the hardware cursor should not stay at the prompt caret. Ideally a Client could declare its caret cell, so Claude Code parks the cursor there the way it does for the prompt and the built-in Input element. At minimum, the cursor should move into the focused Client's region.

Error Messages/Logs

None.

Steps to Reproduce

  1. Make a mod with a Pane whose tree holds a Client with this module:

``js
export default (props, surface) => {
const { Text } = surface.elements
if (surface.state === undefined) {
surface.setState('')
surface.onKey(k => surface.setState(surface.state + k.key))
}
return Text({ children: surface.state || 'click here and type' })
}
``

  1. Start Claude Code with the fullscreen renderer, open the pane and click the Client.
  2. Switch the macOS input source to Korean (2-Set) and type 안.
  3. The pre-edit ㅇ → 아 → 안 is drawn at the prompt caret. The Client shows 안 only after the syllable is committed.

You can check the cursor without an IME in tmux. After clicking the Client and typing into it, tmux display -p '#{cursor_x},#{cursor_y}' still reports the prompt caret cell (2,35 on the ❯ row in a 160x40 window), and #{cursor_flag} is 1.

Claude Model

Not relevant (Haiku 4.5 in the test session)

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.290 (Claude Code). The 2.1.296 darwin-arm64 build has the same Client surface members and no caret declaration.

Platform

Other (Claude Team subscription)

Operating System

macOS 27.0.1

Terminal/Shell

Orca 1.4.220 (xterm.js). Cursor position checked in tmux 3.6a.

View original on GitHub ↗