claude code: kitty keyboard protocol garbage
• 280 words • 2 min
Upon quitting Claude Code, pressing C-c
in the terminal produces garbage like this instead of the expected ^C:
❯ 0;5u9;5u0;5uc9;5u9;5u9;5u9;5u9;5uSomething similar happens with C-a, C-e, C-l, etc. I am using zsh.
What’s happening #
Claude Code enables the kitty keyboard
protocol (“CSI u mode”) for
enhanced key input handling. Whenever the program exits cleanly, it restores the
terminal to its original state. However, if the cleanup doesn’t fully complete
(crash, SIGKILL, etc.), the terminal remains in CSI u mode.
In this mode, keypresses are sent as escape sequences rather than being
interpreted by the shell. For example, Ctrl-C sends \e[99;5u (keycode 99 =
c, modifier 5 = Ctrl) instead of being interpreted as SIGINT. Multiple rapid
keypresses concatenate into the garbled output above.
Fix #
Reset the terminal:
resetOr, more targeted — disable CSI u mode explicitly:
printf '\e[<u'…though no one can remember this. reset is standard and simple, though it
could be easily confused with clear.
Prevention #
Add a precmd hook to ~/.zshrc so the protocol is disabled before every
prompt:
precmd() { printf '\e[<u' 2>/dev/null }For bash, use PROMPT_COMMAND instead:
PROMPT_COMMAND='printf "\e[<u" 2>/dev/null'This is a no-op when the terminal is already in normal mode, so there’s no downside to having it always run.
This is what Claude says, but I’d rather not clutter my precmd due to Claude.
For now, I am happy to run reset manually when needed.
I suspect this is well-known but they have many open bugs in their GitHub issue tracker, I couldn’t pinpoint it to a specific issue.
Update: well, someone reported it just 5 minutes ago at the time of this post.