Skip to content

fix(tui): reset terminal modes and position epilogue cleanly on exit - #49089

Closed
winter765 wants to merge 1 commit into
anomalyco:devfrom
winter765:tui-exit-cleanup
Closed

winter765 wants to merge 1 commit into
anomalyco:devfrom
winter765:tui-exit-cleanup

Conversation

@winter765

Copy link
Copy Markdown

fix(tui): reset terminal modes and position epilogue cleanly on exit

Fixes #48776 · Refs #38860

Problem

When the TUI exits, the terminal can be left in a corrupted state and the
session epilogue can overprint restored shell content:

  1. @opentui/core's teardown does not disable every mode the renderer
    enabled (mouse reporting, application cursor keys, kitty keyboard
    protocol, bracketed paste). Mouse movement and key presses then emit raw
    escape sequences into the shell. Previously reported in TUI leaves terminal in raw/corrupted state on /exit under Alacritty + zellij-windows (Windows ConPTY) #48776, Mouse tracking state not reset on exit (/exit) #38860,
    TUI: incomplete terminal teardown on exit — mouse tracking, alt-screen, bracketed paste left enabled #32336, Terminal left in raw mode on exit (Alacritty, Ubuntu 24.04, zsh, v1.17.9) #34397.
  2. After leaving the alternate screen, the cursor position is decided by the
    terminal emulator. Apple Terminal restores it to the top-left corner, so
    the epilogue (logo + Session/Continue lines) written on exit overprints
    restored shell content and the shell prompt ends up on the wrong line.

Change

  • packages/tui/src/util/renderer.ts
    • Add terminalReset(): synchronously writes a minimal ANSI reset sequence
      (application cursor keys off, show cursor, default cursor shape, kitty
      keyboard off, mouse reporting off, bracketed paste off, SGR reset). No-op
      when stdout is not a TTY.
    • destroyRenderer() now emits terminalReset() right after
      renderer.destroy().
  • packages/tui/src/app.tsx
    • Register process.on("exit", terminalReset) so modes are restored even
      when the process exits without going through the scoped renderer teardown
      (e.g. an uncaught error).
    • Before writing the epilogue, emit \x1b[2J\x1b[H (clear screen + home) so
      the epilogue renders at the top of a clean screen regardless of where the
      terminal restored the cursor.

How did you verify your code works?

  • bun typecheck in packages/tui — passes, no new errors.
  • Built a standalone binary with
    bun ./packages/opencode/script/build.ts --single and smoke-tested
    opencode --version.
  • Ran the built TUI in a pty harness (simulated xterm-256color terminal),
    opened a session, and exited via /exit:
    • \x1b[?1000l (mouse off), \x1b[?1l, \x1b[>1u, \x1b[?2004l are all
      emitted after the last enable.
    • \x1b[2J\x1b[H is emitted immediately before the epilogue.
    • The shell prompt returns cleanly after the epilogue.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

@github-actions github-actions Bot added the needs:compliance This means the issue will auto-close after 2 hours. label Sep 15, 2026
@github-actions

Copy link
Copy Markdown
Contributor

This PR doesn't fully meet our contributing guidelines and PR template.

What needs to be fixed:

  • PR description is missing required template sections. Please use the PR template.

Please edit this PR description to address the above within 2 hours, or it will be automatically closed.

If you believe this was flagged incorrectly, please let a maintainer know.

@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Found one potentially related PR:

PR #48878: fix(tui): force terminal reset on exit for Windows ConPTY

This PR is related because it also addresses terminal reset issues on exit, though it's Windows ConPTY-specific while PR #49089 provides a general cross-platform terminal reset mechanism. These PRs may complement each other or could be consolidated depending on their implementation approaches.

@github-actions

Copy link
Copy Markdown
Contributor

This pull request has been automatically closed because it was not updated to meet our contributing guidelines within the 2-hour window.

Feel free to open a new pull request that follows our guidelines.

@github-actions github-actions Bot removed the needs:compliance This means the issue will auto-close after 2 hours. label Sep 15, 2026
@github-actions github-actions Bot closed this Sep 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TUI leaves terminal in raw/corrupted state on /exit under Alacritty + zellij-windows (Windows ConPTY)

1 participant