Kitty keyboard protocol not restored on unclean exit, breaking Ctrl+C/Ctrl+D
Bug description
After exiting Claude Code, Ctrl+C and Ctrl+D sometimes stop working in the shell. Instead of sending the expected signals, the terminal prints CSI-u encoded sequences — 9;5u (tail of \e[99;5u for Ctrl+C) and 0;5u (tail of \e[100;5u for Ctrl+D).
This indicates Claude Code enabled the kitty keyboard protocol (\e[>1u) but did not send the pop sequence (\e[<u) on exit, leaving the terminal in CSI-u mode.
Reproduction
- Open a terminal that supports the kitty keyboard protocol (Ghostty, iTerm2, kitty, WezTerm)
- Run
claude - Exit Claude Code (the bug is intermittent — it may require an interrupted or non-clean exit)
- Press
Ctrl+C— observe9;5uprinted instead of^C - Running
printf '\e[<u'orresetrestores normal behavior
The issue is more noticeable when running Claude Code inside a VM (e.g., Lima), possibly because the escape sequence has an extra PTY hop to traverse.
Expected behavior
Claude Code should always pop the kitty keyboard protocol stack on exit, regardless of how it exits (clean exit, SIGINT, SIGTERM, crash).
Workaround
Add to shell rc to defensively pop the protocol before each prompt:
# bash
PROMPT_COMMAND='printf "\e[<u" 2>/dev/null'
# zsh
precmd() { printf '\e[<u' 2>/dev/null; }
Environment
- Claude Code v2.1.84
- Terminal: Ghostty (but affects any kitty-protocol-capable terminal)
- OS: macOS with Lima VM (also reproducible without VM)
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗