Skip to content

Terminal left in dirty state after every exit #39272

@eljobe

Description

@eljobe

Summary

After every interactive Claude Code session exits (clean exit via /exit, Ctrl-D, etc.), the terminal is left in a broken state. Control characters like Ctrl-D, Ctrl-L, and Ctrl-C no longer work — they print garbage characters to the input line instead of being interpreted as signals/actions.

Details

  • stty sane does not restore functionality, which means it's not just the kernel TTY line discipline (echo, canonical mode) that's dirty.
  • reset does fix it, but it fully reinitializes the terminal session (re-reads terminfo, sends full init sequence), which is heavy-handed.

The fact that stty sane is insufficient but reset works suggests Claude Code is leaving terminal emulator state dirty on exit — things like:

  • Bracketed paste mode (\e[?2004h)
  • Application cursor key mode (\e[?1h)
  • Cursor visibility
  • Other DEC private modes

The exit cleanup handler appears to not be sending the necessary escape sequences to restore these terminal modes.

Reproduction

  1. Open a terminal (tested on macOS / Darwin 25.3.0 / Ghostty, zsh)
  2. Run claude
  3. Exit the session (e.g. /exit)
  4. Try Ctrl-L or Ctrl-D — they no longer work; garbage characters are printed instead

Happens on every exit, not intermittently.

Workaround

Run reset after exiting, or wrap claude in a shell function that sends a soft reset:

claude() {
  command claude "$@"
  printf '\e[?2004l\e[?1l\e[?25h\ec'
}

Environment

  • OS: macOS (Darwin 25.3.0)
  • Shell: zsh
  • Terminal: Ghostty

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:tuibugSomething isn't workingduplicateThis issue or pull request already existsplatform:macosIssue specifically occurs on macOS

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions