Fix Claude Code Native Terminal Cursor Tracking for Screen Readers (NVDA, VoiceOver, BRLTTY), CJK IME, and Accessibility — on Linux, macOS, and Windows
Claude Code's TUI renderer did not position the terminal's native cursor to follow the text input caret. This broke screen readers (BRLTTY, NVDA, JAWS, VoiceOver, Orca, Narrator) which track the cursor to decide what to display, caused CJK IME preedit/composition text to appear at the bottom-left corner instead of at the insertion point, and prevented screen magnifiers from following user input. The native cursor remained stuck at the bottom of the screen, making it impossible for blind and low-vision users to edit prompts or know where their cursor was. Root cause: the custom TUI renderer uses a full-screen overwrite model where the last render write determines cursor position — the cursor was not declaratively positioned to follow the text input caret. Fixed in v2.1.84 when qing-ant added declarative cursor positioning. Latest version as of June 2026 is v2.1.177.
Symptoms
- Screen readers (BRLTTY, NVDA, JAWS, VoiceOver, Orca, Narrator) cannot track cursor position or read back typed characters in Claude Code prompt input
- CJK IME preedit/composition text appears at the bottom-left corner of the terminal instead of at the insertion point — because terminal emulators render IME text at the physical cursor position
- Screen magnifiers cannot follow text input because the native cursor is not at the caret position
- Native terminal cursor remains stuck at the bottom of the screen during prompt editing, at the position where the last TUI render write landed
- Blind and low-vision users cannot navigate or edit prompt text character by character — pressing left/right arrow keys produces no screen reader feedback
- Affects all platforms: Windows (NVDA, JAWS, Narrator), macOS (VoiceOver), Linux (BRLTTY, Orca, Fenrir)
Possible causes
- Claude Code's custom TUI renderer uses a full-screen overwrite rendering model — after each frame render, the terminal's native cursor is left wherever the final `write()` operation landed, typically at the bottom-left corner of the screen. The renderer did not include a declarative cursor positioning step to move the native cursor to the text input caret position.
- Terminal emulators render IME preedit/composition text at the physical cursor position reported by the terminal. When the native cursor is stuck at the bottom-left corner (where the last render write landed), CJK/Japanese/Chinese/Korean composition text appears there — completely disconnected from where the user is typing in the prompt input area.
- Screen readers such as BRLTTY, NVDA, and VoiceOver use the terminal's native cursor position to determine which part of the screen to present to the user. When the cursor stays at the bottom, screen readers show that area — not the prompt input line where the user is typing.
- This was a regression introduced in the 2.1.8x release series. Earlier Claude Code versions positioned the native cursor correctly, but a TUI renderer refactor removed the cursor tracking behavior without realizing it broke the accessibility and IME integration contract between the terminal and assistive technologies.
Solutions
Use External Editor for Prompt Input (Pre-v2.1.84 Workaround for Blind Users)
Before upgrading to v2.1.84+, blind and low-vision users can bypass the Claude Code TUI cursor issue by editing prompts in an external editor where screen reader cursor tracking works correctly. Press Ctrl+X Ctrl+E to open the current prompt in $EDITOR, edit there with full screen reader support, then save and exit — the text is sent as the Claude Code prompt.
- Set the EDITOR environment variable to a terminal editor with good accessibility: `export EDITOR=vi` (or nano, emacs -nw)
- Verify $EDITOR is set: run `echo $EDITOR`
- In Claude Code, type your prompt and press Ctrl+X Ctrl+E to open it in the external editor
- Edit the prompt in the external editor where screen reader cursor tracking works correctly — move character by character, fix typos, etc.
- Save and exit the editor (:wq in vi, Ctrl+O Ctrl+X in nano) — the edited text is sent as the Claude Code prompt
Commands
export EDITOR=vi
export EDITOR=nano
echo $EDITOR
# Make editor selection persistent:
echo 'export EDITOR=vi' >> ~/.bashrc
Config examples
export EDITOR=vi
export EDITOR=nano
Risks
- Adds extra steps for every prompt — not suitable for rapid iterative prompting workflows
- Requires familiarity with a terminal-based text editor (vi, nano, emacs)
- The external editor inherits the terminal's cursor behavior — some editors may have their own screen reader quirks
- Tool authorization dialogs and questionnaires (covered by related issue #39900) still use Claude Code's TUI and are not bypassed by this workaround
Verification
- Step 1: Run `echo $EDITOR` → expect: path to installed editor (e.g., /usr/bin/vi)
- Step 2: In Claude Code, press Ctrl+X Ctrl+E → expect: configured editor opens with current prompt text
- Step 3: In the editor, move cursor character by character using arrow keys → expect: screen reader announces each character position correctly
Upgrade to Claude Code v2.1.84+ (Official Fix — Declarative Cursor Positioning)
Update Claude Code to v2.1.84 or later (latest: v2.1.177 as of June 2026). qing-ant added declarative cursor positioning to the TUI renderer so the native terminal cursor now follows the text input caret. This fixes screen reader tracking, CJK IME composition text placement, and screen magnifier following. First check your current version with `claude --version` — if below v2.1.84, upgrade immediately.
- Check your current Claude Code version: run `claude --version` or `npm list -g @anthropic-ai/claude-code`
- If version is below v2.1.84, update to the latest: run `npm update -g @anthropic-ai/claude-code`
- Verify the update succeeded: run `npm view @anthropic-ai/claude-code version` to see latest, then `claude --version` to confirm your installed version matches
- Restart any running Claude Code sessions and your terminal if needed for cursor changes to take full effect
- Start a new Claude Code session and type a prompt — screen readers should now track the cursor and CJK IME text should appear at the insertion point
Commands
claude --version
npm list -g @anthropic-ai/claude-code 2>/dev/null | grep claude-code
npm update -g @anthropic-ai/claude-code
npm view @anthropic-ai/claude-code version
# If npm update doesn't work, force reinstall:
npm install -g @anthropic-ai/claude-code@latest
Risks
- May require terminal restart for cursor positioning changes to fully take effect
- Menu cursor positioning was fixed later (v2.1.88+) — see related issue #39900 for menu-specific cursor behavior in questionnaires and tool authorization dialogs
- Some terminal emulators (Windows Terminal, ConPTY) may have their own cursor tracking quirks independent of Claude Code
Verification
- Step 1: Run `claude --version` → expect: v2.1.84 or later (latest as of June 2026: v2.1.177)
- Step 2: Run `npm view @anthropic-ai/claude-code version` → expect: number >= '2.1.84'
- Step 3: Start Claude Code and type a prompt → expect: screen reader (NVDA/VoiceOver/BRLTTY) tracks cursor character by character and reads back typed text
- Step 4: For CJK users, activate IME and start composing Chinese/Japanese/Korean text → expect: preedit/composition text appears at the text input insertion point, not at the bottom-left corner
- Step 5: For screen magnifier users, move cursor left/right through prompt text → expect: magnifier viewport follows the cursor position at the text input line
Agent JSON
Canonical machine-readable representation of this issue:
{
"issue_id": "9cccafe4-f7d9-4a93-acd0-20ea06514f9a",
"slug": "fix-claude-code-native-terminal-cursor-tracking-for-screen-readers-nvda-voiceover-brltty-cjk-ime-and-accessibility-on-li-xbfxie",
"verification_status": "unverified",
"canonical_json": "https://codekb.dev/v1/issues/fix-claude-code-native-terminal-cursor-tracking-for-screen-readers-nvda-voiceover-brltty-cjk-ime-and-accessibility-on-li-xbfxie"
}