Kitty keyboard protocol enabled for tmux breaks raw Ctrl-A/Ctrl-E (Cmd+Left/Right) when tmux extended-keys is on
Summary
When tmux has extended-keys on, Claude Code enables the kitty keyboard protocol but the handshake doesn't complete properly through tmux. Raw C0 control bytes (0x01 Ctrl-A, 0x05 Ctrl-E) that iTerm2 sends for Cmd+Left/Right are then inserted literally into the prompt instead of acting as line-start/line-end.
Environment
- macOS (darwin arm64)
- iTerm2 3.6.11 with tmux integration (
-CCmode) - tmux with
set -s extended-keys on+set -as terminal-features 'xterm*:extkeys:tmux*:extkeys' - Claude Code v2.1.179
- iTerm2 "Natural Text Editing" key mappings: Cmd+Left →
0x01, Cmd+Right →0x05
Root Cause (identified via binary analysis)
The terminal capability list c_3 includes "tmux":
c_3 = ["iTerm.app", "kitty", "WezTerm", "ghostty", "tmux", "windows-terminal", "WarpTerminal"];
When Claude starts, it sends ESC[>0q (XTVERSION query). tmux responds with its name "tmux", which matches c_3. Claude then enables the kitty keyboard protocol by sending ESC[<u ESC[>1u ESC[>4;2m.
However, tmux's extended-keys is not a full kitty protocol implementation — it's tmux's own modifier-key feature. The kitty protocol handshake is not relayed to the outer terminal (iTerm2). Claude ends up in kitty mode expecting ESC[97;5u for Ctrl-A, but iTerm2 keeps sending raw 0x01. Claude doesn't recognize the raw byte in kitty mode and inserts it literally.
The relevant code path:
function d_3(H) { return c_3.includes(H ?? dH.terminal ?? "") }
function qe() { return d_3() ? x9H + rY7 + oY7 : "" }
// qe() is called during screen init via Z2H()
dH.terminal is set to "tmux" from the XTVERSION response, d_3() returns true, and qe() sends the kitty enable sequence unconditionally.
Proposed Fix
Skip kitty protocol enablement when running inside tmux (i.e. when process.env.TMUX is set), since tmux's extended-keys is not equivalent to full kitty passthrough:
function qe() { return d_3() && !process.env.TMUX ? x9H + rY7 + oY7 : "" }
Or more precisely, remove "tmux" from c_3 — tmux does not implement the kitty keyboard protocol, it has its own separate extended-keys feature that happens to respond to the same XTVERSION query.
Steps to Reproduce
- macOS + iTerm2, open a tmux session (native or
-CCintegration) - Add to
~/.tmux.conf:set -s extended-keys on+set -as terminal-features 'xterm*:extkeys:tmux*:extkeys' - In iTerm2 key mappings, set Cmd+Left → Send Hex
0x01, Cmd+Right → Send Hex0x05 - Launch Claude Code inside tmux
- Type something in the prompt, press Cmd+Left →
^Ais inserted literally instead of moving to line start
Expected: cursor moves to start/end of line
Actual: ^A / ^E inserted as literal characters
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗