Ctrl-based shortcuts don't fire with non-Latin (Cyrillic) keyboard layout — Kitty keyboard protocol reports layout-dependent codepoint

Status Open
Reported on v2.1.208
Maintainer reply ✓ Yes — bcherny
Activity 3 comments · opened Jul 14, 2026
💡 Likely answer: A maintainer (bcherny, collaborator) responded on this thread — see the highlighted reply below.

Description

When a non-Latin keyboard layout (e.g. Russian/Cyrillic) is active, Ctrl-based keyboard shortcuts inside the Claude Code TUI do not fire. Switching the OS layout to a Latin one (US/ABC) makes them work again.

Crucially, the same shortcuts work fine in a plain shell running in the same terminal with the Cyrillic layout active — so this is not a terminal or OS issue. It is specific to how Claude Code consumes keyboard input.

Environment

  • Claude Code: 2.1.208
  • OS: macOS 26.3 (25D125)
  • Terminal: Ghostty (TERM=xterm-ghostty, embedded in agterm)
  • Active layouts: ABC (US) + Russian

Steps to reproduce

  1. Switch the OS keyboard layout to Russian (Cyrillic).
  2. In a plain shell in the terminal, type foo bar and press Ctrl+A → cursor jumps to start of line, Ctrl+E → end. Works. ✅
  3. Launch claude in the same terminal, keep the Cyrillic layout active, and try any Ctrl-based shortcut (e.g. history / undo / reverse-search). Nothing happens. ❌
  4. Switch the layout to English (ABC) → the same shortcuts work. ✅

Expected

Ctrl-based shortcuts should fire regardless of the active keyboard layout, exactly as they do in the shell.

Actual

Ctrl-based shortcuts are silently ignored while a non-Latin layout is active.

Root cause analysis

The difference between the shell and Claude Code is the keyboard input protocol:

  • A plain shell / readline receives Ctrl+A as the legacy C0 control byte 0x01, which is layout-independent (always "a").
  • Claude Code (since 2.1.0, for Shift+Enter support) enables the Kitty keyboard protocol (progressive enhancement / CSI-u). In that mode the terminal reports the layout-dependent Unicode codepoint of the key plus modifier flags. On a Russian layout, physical A produces ф (U+0444), so the terminal sends CSI 1092 ; 5 u (codepoint 1092 = 0x444, modifier 5 = Ctrl). Claude Code's shortcut matcher looks for Ctrl + a (codepoint 97), which never matches.

This is why the shell works (legacy encoding) but Claude Code does not (Kitty protocol + layout-dependent codepoint).

Proposed fix

The Kitty keyboard protocol already provides a layout-independent key via the alternate-keys field (progressive-enhancement flag 0b1000 / "Report alternate keys"). With that flag set, the terminal sends the codepoint as unicode-key-code:shifted-key:base-layout-key, where base-layout-key is the key on the standard US layout, independent of the active layout. Ghostty (and kitty, WezTerm, etc.) report this field.

Claude Code should:

  1. Request the "Report alternate keys" enhancement flag, and
  2. Match Ctrl/Alt-based shortcuts against the base-layout-key (falling back to the primary codepoint) instead of the layout-dependent primary codepoint.

That makes shortcuts fire for any keyboard layout while preserving the Kitty protocol benefits.

Related (closed) issues — same underlying cause, still reproducible on 2.1.208

  • #18221 — Alt/Option keyboard shortcuts break international keyboard layouts
  • #11997 — Alt-arrow word navigation broken with Cyrillic and non-Latin characters
  • #3015 — Ctrl+Backspace and Ctrl+Arrow navigation issues with Cyrillic text
  • #17400 — Kitty keyboard protocol: keys not decoded (Ghostty + German keymap)

View original on GitHub ↗

3 Comments

bcherny collaborator · 1 month ago

Confirmed / reproduced on 2.1.233 (Linux).

I couldn't switch OS keyboard layouts in my test environment, so I injected the exact byte sequences a kitty-protocol terminal sends, straight into a running Claude Code prompt containing foo bar, using Ctrl+W (delete word) as the observable shortcut:

  • Legacy 0x17 → deletes bar ✅
  • CSI-u Ctrl+w with the US codepoint (ESC[119;5u) → deletes bar ✅
  • CSI-u with the Cyrillic codepoint for the same physical key (ESC[1094;5u, i.e. Ctrl+ц) → silently ignored ❌
  • Same sequence with the layout-independent base-key field included (ESC[1094::119;5u) → also ignored ❌

So your analysis holds: shortcuts are matched against the layout-dependent codepoint only, and the alternate/base-layout key the protocol offers isn't consulted. Marking as a confirmed bug — the proposed fix (request the alternate-keys enhancement and match Ctrl/Alt shortcuts on the base-layout key) is a sound direction.

🤖 Generated with Claude Code

sAws · 1 month ago

Same bug on iTerm2, but the failing path is not the kitty CSI-u one — worth noting, because a fix that only touches CSI-u parsing will not fix iTerm2.

Environment: Claude Code 2.1.259, iTerm2 3.6.10, macOS (Darwin 25.5.0), layouts ABC + com.apple.keylayout.Russian.

Captured with script, Claude Code sends both protocols at startup:

ESC[<u   ESC[>5u   ESC[>4;2m

>5u = kitty flags 5, >4;2m = xterm modifyOtherKeys mode 2. With both active, iTerm2 delivers these keys in the modifyOtherKeys form, not CSI-u:

| key | layout | bytes |
|---|---|---|
| Ctrl+V | ABC | ESC[27;5;118~ (118 = v) — works |
| Ctrl+V | Russian | ESC[27;5;1084~ (1084 = U+043C м) — dropped |
| Ctrl+Opt+, | Russian | ESC[27;7;1073~ (1073 = U+0431 б) — dropped |

Only the codepoint differs. Replaying ESC[>5u alone, Ctrl+Opt+, arrives as a plain 0x2c and Ctrl+V as ESC[118;5u — so on iTerm2 it is >4;2m that produces the layout-dependent code.

Two further details:

  1. Claude Code requests kitty flag 4 ("report alternate keys"), but iTerm2 does not emit the base-layout-key subfield — it sends 1084;5u, never

1084::118;5u. So the Latin key cannot be recovered from thfallback has to go through the ASCII-capable layout or thevirtual keycode.

  1. CLAUDE_CODE_ALTGR_AS_TEXT does not help. Its "auto" bION (a Windows Terminal variable), so on macOS the mode isalways "off". Forcing it to 1 makes the key insert the **Cyrillic** character (б) instead of ,` — the forced path is also wrong for non-Latin

layouts.

Workaround for anyone stuck on iTerm2 (Settings → Keys →shortcut while the Cyrillic layout is active, action Send Escape Sequence):

Ctrl+V  ->  [27;5;118~

iTerm2 matches bindings by char+modifiers+keycode, so recording under ABC will not match a Cyrillic keypress. Do not bind Ctrl+C/Ctrl+D this way — key bindings are global and would break SIGINT in plain sheady work.

arbtsv · 29 days ago

Environment: Windows 10, VS Codium (VS Code fork) integrated terminal (PowerShell profile), Claude Code 2.1.272, OS keyboard layout Russian (Cyrillic).

Adding a data point on how the blast radius of this bug just grew. Today's fix for #71700 (merged in 2.1.272) switched Kitty keyboard protocol activation from a terminal-name allow-list to capability detection via the CSI ? u probe. That's the right fix for #71700, but it has a side effect here: VS Code/VS Codium's integrated terminal (xterm.js) was never on the old allow-list, so it always ran in legacy input mode — where Ctrl/Alt shortcuts are layout-independent, same as a plain shell. It does answer the CSI ? u capability query, though, so as of 2.1.272 it gets promoted into Kitty-protocol mode for the first time — and immediately inherits this bug.

Confirmed regression on my end:

  • 2.1.270/2.1.271 in VS Codium's terminal: Alt+<letter> custom keybinding worked fine under a Cyrillic layout.
  • 2.1.272 in the same terminal, same layout: the same keybinding stopped matching.
  • Same 2.1.272 binary in classic cmd.exe (conhost, not a PTY-based terminal): unaffected — consistent with conhost not participating in this capability handshake at all.

Since capability-based detection is clearly the direction terminal support is heading (and #71700 will keep pulling in more previously-unlisted terminals the same way), this bug's impact is going to keep widening rather than staying confined to the terminals already on the old list. Would be great to see it prioritized.