Feature Request: IME cursor position support for CJK input (Japanese/Chinese/Korean)

Resolved 💬 5 comments Opened Jan 19, 2026 by koshikawa-masato Closed Feb 6, 2026

Summary

When using Claude Code in terminals like Ghostty, the IME (Input Method Editor) candidate window for CJK (Japanese/Chinese/Korean) input appears at the bottom-left corner of the screen instead of at the cursor position. This makes CJK input difficult as users cannot see the conversion candidates near where they are typing.

Problem

Ink-based TUI applications hide the terminal's real cursor and render a visual cursor using ANSI styles. However, IME systems use the terminal's real cursor position (via firstRect on macOS) to determine where to display the candidate window.

Current behavior:

  • IME candidate window appears at bottom-left of terminal
  • User must look away from their input location to see candidates

Expected behavior:

  • IME candidate window appears at the cursor/input position
  • Natural input experience similar to native applications

Proposed Solution

I've created an Ink fork that adds enableImeCursor option to solve this:

Repository: https://github.com/koshikawa-masato/ink-ime-fork/tree/ime-cursor-support

How it works

  1. Add a CURSOR_MARKER (\^[[999m - invisible SGR sequence) in the render tree at the desired cursor position
  2. During rendering, replace the marker with \^[[s (Save Cursor Position)
  3. After output is written, send \^[[u\^[[?25h (Restore Cursor Position + Show Cursor)
  4. The terminal's real cursor moves to the marker position, allowing IME to display candidates correctly

Usage in Ink

import { render, CURSOR_MARKER } from 'ink';

// In component: place CURSOR_MARKER where the cursor should appear
<Text>{textBeforeCursor}{CURSOR_MARKER}{textAfterCursor}</Text>

// Enable IME cursor in render options
render(<App />, { enableImeCursor: true });

Key files changed

  • src/cursor-marker.ts - Marker constant and ANSI sequence handling
  • src/log-update.ts - Save/restore cursor position logic
  • src/render.ts - enableImeCursor option
  • src/ink.tsx - Option propagation

Environment

  • Terminal: Ghostty (also affects other terminals with IME support)
  • OS: macOS
  • Languages affected: Japanese, Chinese, Korean (any language using IME)

Additional Context

This is a common issue for CJK users of terminal-based applications. The solution has been tested and confirmed working in Ghostty terminal with Japanese input.

I'm happy to contribute a PR if this feature is welcome.

View original on GitHub ↗

This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗