[BUG] Terminal left in enhanced keyboard mode after exit — Ctrl-C/Ctrl-D broken

Resolved 💬 22 comments Opened Mar 25, 2026 by dashorst Closed Apr 18, 2026
💡 Likely answer: A maintainer (dltn, contributor) responded on this thread — see the highlighted reply below.

Describe the bug

After exiting Claude Code, the terminal remains in an enhanced keyboard input mode (modifyOtherKeys / kitty keyboard protocol). Ctrl-C, Ctrl-D, and other control key combinations stop working — they produce escape sequences like 9;5u instead of sending the expected signals (SIGINT, EOF, etc.).

To reproduce

  1. Open Ghostty inside tmux
  2. Run claude
  3. Use Claude Code normally
  4. Exit Claude Code (Escape, or /exit)
  5. Press Ctrl-C or Ctrl-D in the shell

Expected: Ctrl-C sends SIGINT, Ctrl-D sends EOF — normal shell behavior.
Actual: Ctrl-C produces 9;5u, Ctrl-D produces 0;5u, etc. Terminal is stuck in enhanced key mode.

Workaround

Running reset or printf '\e[>4;0m\e[>0m' restores normal terminal behavior.

Environment

  • Claude Code version: latest (issue started in last 1-2 releases)
  • OS: macOS (Darwin 24.6.0)
  • Terminal: Ghostty
  • Multiplexer: tmux
  • Shell: zsh

Additional context

  • The root cause is that Claude Code enables modifyOtherKeys or the kitty keyboard protocol for enhanced input, but does not properly restore terminal state on exit.
  • Terminals that support these protocols (Ghostty, Kitty, and other modern emulators) are affected. Older terminals that ignore the escape sequences are not.
  • Related issue in another project with the same symptoms: https://github.com/atuinsh/atuin/issues/2256

View original on GitHub ↗

22 Comments

github-actions[bot] · 3 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/38720
  2. https://github.com/anthropics/claude-code/issues/38647
  3. https://github.com/anthropics/claude-code/issues/38625

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

thiagowfx · 3 months ago

I can reproduce. The workaround works for me.

dashorst · 3 months ago

Confirmed that the specific protocol being left enabled is the kitty keyboard protocol, not modifyOtherKeys.

The fix that works is:

printf '\e[<u'    # pop kitty keyboard mode (didn't work via tmux)
printf '\e[=0u'   # disable kitty keyboard protocol flags — this one works

Environment: Ghostty + tmux + zsh on macOS.

bebeal · 3 months ago

I can reproduce. Confirmed printf '\e[<u' works as a workaround
Env: Arch + Ghostty + zsh

connormclaud · 3 months ago

Confirming this is reproducible in my environment.

  • Claude Code: v2.1.84
  • Terminal: WezTerm 20260117-154428-05343b38
  • OS: Linux 6.19.4 (Ubuntu)
  • Shell: bash
  • WezTerm config: enable_kitty_keyboard = true

After exiting Claude Code, Ctrl+D prints 0;133u, Ctrl+W prints 9;133u — partial CSI u sequences with modifier 133 (Ctrl + NumLock). Hotkeys work fine if Claude Code is reopened in the same terminal.

printf '\e[=0u\e[<99u' restores normal behavior; stty sane does not.

capocasa · 3 months ago
printf '\e[<u'

works!

yurukusa · 3 months ago

Until this is fixed upstream, a Stop hook can restore terminal state automatically on every exit:

// ~/.claude/settings.json
{
  "hooks": {
    "Stop": [{
      "matcher": "",
      "hooks": [{
        "type": "command",
        "command": "printf '\\e[<u\\e[>0m'"
      }]
    }]
  }
}

\e[<u pops the kitty keyboard protocol stack, \e[>0m disables modifyOtherKeys. Covers both protocols so it works across Ghostty, Kitty, WezTerm, etc.
If you use tmux, the escape sequences need to pass through — \e[=0u may work better (as @dashorst noted). You can chain both:

"command": "printf '\\e[<u\\e[=0u\\e[>0m'"

This runs on every session exit, so even if Claude crashes or you Ctrl-C out, the terminal resets.

alexaandru · 3 months ago

I came here for the same. I use EndeavourOS, ghostty v1.3.1-arch1, claude v2.1.84

SpenderJules · 3 months ago

I reproduce with:

  - OS: macOS (Darwin 24.6.0)
  - Terminal: Ghostty 1.3.1 (stable)
    - Zig 0.15.2, ReleaseFast, Metal renderer, kqueue
  - Shell: zsh
  - Claude Code: 2.1.84
  - TERM: xterm-ghostty
whitinger · 3 months ago

Confirming this is reproducible in my environment, as well.

  • Claude Code: v2.1.84
  • Terminal: Ghostty 1.2.3
  • OS: Ubuntu 24.04.2 LTS
  • Shell: bash

The behavior is inconsistent. I can open a new session and exit, and the bug does not trigger. If I open a new session and send a message of "ping" and get "pong" back, and then /quit, I see the problem. Ctrl+D prints 0;133u, Ctrl+W prints 9;133u`, etc.

alberti42 · 3 months ago

There is a related issue that I filed some hours ago, #39252. The root cause is the same. I described a solution to the problem in https://github.com/anthropics/claude-code/issues/39252#issuecomment-4135113317

Maybe I am wrong, but I think the problem is fundamental to the fact that there is no way for Claude Code to learn about CSI u protocol configuration and precisely how modifier keys are reported (mode 0, 1 or 2)—unless someone proposes a new protocol. To my understanding, not even the enhanced kitty protocol allows probing this state (correct me if I am wrong).

This is why I was stating in the other issue that the problem is more of a lack of documentation. I cannot see how this can be fixed upstream other than explaining to the user how to cope with it, for example, creating shim functions.

kovidgoyal · 3 months ago

You are wrong, at least as far as as the kitty keyboard protocol is concerned. Its existence and state can both be queried. https://sw.kovidgoyal.net/kitty/keyboard-protocol/#progressive-enhancement

alberti42 · 3 months ago

Hi Kovid (@kovidgoyal),

Thank you for the heads-up about the Kitty keyboard protocol query mechanism. I am aware of it and it is awesome. Thank you very much for creating it and promoting it.

However, my concern is about something different: XTMODKEYS (CSI > 4 ; N m, the older modifyOtherKeys protocol). Claude Code enables XTMODKEYS mode 2 (\e[>4;2m) for its own key handling, but does not restore the previous state when spawning subprocesses (e.g. via $EDITOR) or on exit. This leaves the terminal in a broken state for applications that expect legacy key encoding.

I am not using the Kitty keyboard protocol myself, precisely because tmux does not yet support it, and I work inside tmux. But even when testing Claude Code directly in Kitty (no tmux), the problem persists: Claude Code does not restore the XTMODKEYS state on exit, leaving the terminal unusable for my applications.

The core issue, as far as I can tell, is that there is no standard way to query the current XTMODKEYS state. I tested \e[?4m as a possible query, but the response did not reflect the mode I had set, so it does not appear to work. Without a reliable query mechanism, any application that modifies XTMODKEYS cannot save and restore the previous state.

Do you know of a way to query the current XTMODKEYS state in Kitty? Or is this something that could be added to the protocol? A CSI ? > 4 m query (analogous to CSI ? u for the Kitty protocol) that returns CSI > 4 ; N m would be the natural solution.

Thank you again for your work on the Kitty keyboard protocol. It is a great improvement for the world terminal applications!

Best,
Andrea

dltn contributor · 3 months ago

Fixes are on the way in the next releases! (Kitty today, XTMODKEYS tomorrow). Thank you for reporting everyone!

kovidgoyal · 3 months ago

On Thu, Mar 26, 2026 at 11:37:18AM -0700, Andrea Alberti wrote:

alberti42 left a comment (anthropics/claude-code#38761) Do you know of a way to query the current XTMODKEYS state in Kitty? Or is this something that could be added to the protocol? A CSI ? > 4 m query (analogous to CSI ? u for the Kitty protocol) that returns CSI > 4 ; N m would be the natural solution.

No, this is one of the many problems with modifyOtherKeys, see
https://sw.kovidgoyal.net/kitty/keyboard-protocol/#why-xterm-s-modifyotherkeys-should-not-be-used
for a longer list.

alberti42 · 3 months ago

Thanks, Kovid. Yes, your analysis confirms it perfectly:

There is no robust way to query it or manage its state from a program running in the terminal.

and agrees with what I was saying before.

I had some time ago (about more than 1 year) a PR in Tmux for related terminal protocol things, and I remember I had discussed with Nicholas about including some parts of your kitty protocol. If I recall correctly, there was no consensus back then to move to Kitty Protocol. Maybe I (or someone else) should study the protocol in depth and then submit a complete PR to tmux. I believe, up to date, the enhanced kitty protocol is not recognized by tmux.

Tmux honors the modifyOtherKeys and supports the two modes. This is probably the only option available for the tmux users until now.

But generally, I so much agree with you that it is important to reach a wide adoption of Kitty's protocol and leave behind all these problems of the past with ambiguous key encoding. It is in a way a pity in 2026 to still have this conversation and fight against keystroke encodings in the terminal. But I am optimistic for the future. Everything moves in the right direction.

kovidgoyal · 3 months ago

On Thu, Mar 26, 2026 at 11:45:22PM -0700, Andrea Alberti wrote:

I had some time ago (about more than 1 year) a PR in Tmux for related terminal protocol things, and I remember I had discussed with Nicholas about including some parts of your kitty protocol. If I recall correctly, there was no consensus back then to move to Kitty Protocol. Maybe I (or someone else) should study the protocol in depth and then submit a complete PR to tmux. I believe, up to date, the enhanced kitty protocol is not recognized by tmux.

There is already a PR for this in tmux, most likely it will be merged
soon. Am away from my computer so not searching now, but should be easy
to find. tmux just wasted a few years chasing modifyOtherKeys just like
it is currently wasting a few years chasing sixel.

alberti42 · 3 months ago

Thanks for the heads-up. This is awesome to hear. I am looking forward to it. tmux is indeed a bit on the defensive / conservative side. But otherwise it is a wonderful PTY. I so much love it.

When working on the tmux PR, I remember we had to validate all changes in tmux against the xterm app, but LOL essentially none of modern people have xterm installed anymore ... and if my memory is not mistaken, the xterm app was somehow inconsistent with the "holy" protocol itself https://invisible-island.net/xterm/modified-keys.html (but I may say something wrong here, I would have to recheck it).

PS: The PR is probably tihs https://github.com/tmux/tmux/pull/4912 and it was opened only 3 weeks ago. 🤞

arogulin · 3 months ago

@dltn thank you so much for the attention to this issue! I can confirm it is resolved as of 2.1.86. ❤️
Fingers crossed this one https://github.com/anthropics/claude-code/issues/18170 will also get some attention. 🤞

RyosukeDTomita · 3 months ago

printf '\e[<u' is work my environment.

  • Ubuntu 24.04.4 LTS
  • ghostty: 1.2.3
  • zsh 5.9
  • vi-mode
  • Claude Code: 2.1.84
ashwin-ant collaborator · 2 months ago

This was fixed in v2.1.86 — The terminal's enhanced keyboard mode is now properly disabled on exit, so Ctrl+C/Ctrl+D work normally in the shell afterwards. If you're still seeing this in the latest version, please comment with your version and repro and we'll reopen.

github-actions[bot] · 2 months ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.