[PR #11019] fix(tui): disable mouse tracking on exit to prevent terminal corruption #13629

Open
opened 2026-02-16 18:18:28 -05:00 by yindo · 0 comments
Owner

Original Pull Request: https://github.com/anomalyco/opencode/pull/11019

State: open
Merged: No


Fixes #6912

Problem

When pressing Ctrl+C to exit OpenCode on Windows, the terminal is left in mouse tracking mode. This causes raw SGR mouse tracking escape sequences to flood the terminal on every mouse movement, rendering the terminal unusable:

[555;58;25M[555;58;26M[555;57;25M[555;57;24M...

The issue occurs because:

  1. SIGINT handler wasn't properly cleaning up terminal state
  2. process.exit(0) was called before cleanup sequences could be flushed
  3. The async nature of renderer.destroy() meant sequences might not reach the terminal

Solution

Added synchronous terminal cleanup using fs.writeSync() to ensure ANSI disable sequences are written immediately before process exit:

  • cleanupTerminal() - Synchronously writes disable sequences directly to stdout (fd 1)
  • destroyRenderer() - Exported function for SIGINT handler to properly cleanup
  • SIGINT handler - Registered in tui() to catch Ctrl+C and call cleanup

ANSI Sequences Covered

The fix disables all common mouse tracking modes:

Sequence Mode
\x1b[?1000l X11 mouse tracking (button press/release)
\x1b[?1002l Button-event tracking (press/release/motion with button)
\x1b[?1003l Any-event tracking (all motion)
\x1b[?1006l SGR extended mouse mode
\x1b[?1015l URXVT extended mouse mode
\x1b[?25h Show cursor

Changes

  • packages/opencode/src/cli/cmd/tui/context/exit.tsx:

    • Added cleanupTerminal() for synchronous cleanup
    • Added destroyRenderer() export for external use
    • Call cleanup before renderer.destroy()
  • packages/opencode/src/cli/cmd/tui/app.tsx:

    • Import destroyRenderer from exit context
    • Register SIGINT handler in tui() function
    • Update ErrorComponent to use destroyRenderer()

Testing

  1. Run bun dev or opencode
  2. Press Ctrl+C to exit
  3. Mouse movements should NOT produce escape sequence output
  4. Terminal should be in normal state

Related Issues

  • Fixes #6912 - Ctrl+C does not disable mouse tracking (Windows)
  • Related to #8908 - Mouse wheel triggering abnormal ASCII codes after exit
  • Related to #7861 - Terminal becomes unusable after opencode exits (macOS)

Note

This PR provides a similar fix to #8355 but with improvements:

  • More comprehensive ANSI sequences coverage
  • Better code organization with JSDoc comments
  • Consistent cleanup across all exit paths (normal exit, Ctrl+C, error component)
**Original Pull Request:** https://github.com/anomalyco/opencode/pull/11019 **State:** open **Merged:** No --- Fixes #6912 ## Problem When pressing Ctrl+C to exit OpenCode on Windows, the terminal is left in mouse tracking mode. This causes raw SGR mouse tracking escape sequences to flood the terminal on every mouse movement, rendering the terminal unusable: ``` [555;58;25M[555;58;26M[555;57;25M[555;57;24M... ``` The issue occurs because: 1. SIGINT handler wasn't properly cleaning up terminal state 2. `process.exit(0)` was called before cleanup sequences could be flushed 3. The async nature of `renderer.destroy()` meant sequences might not reach the terminal ## Solution Added synchronous terminal cleanup using `fs.writeSync()` to ensure ANSI disable sequences are written immediately before process exit: - **`cleanupTerminal()`** - Synchronously writes disable sequences directly to stdout (fd 1) - **`destroyRenderer()`** - Exported function for SIGINT handler to properly cleanup - **SIGINT handler** - Registered in `tui()` to catch Ctrl+C and call cleanup ## ANSI Sequences Covered The fix disables all common mouse tracking modes: | Sequence | Mode | |----------|------| | `\x1b[?1000l` | X11 mouse tracking (button press/release) | | `\x1b[?1002l` | Button-event tracking (press/release/motion with button) | | `\x1b[?1003l` | Any-event tracking (all motion) | | `\x1b[?1006l` | SGR extended mouse mode | | `\x1b[?1015l` | URXVT extended mouse mode | | `\x1b[?25h` | Show cursor | ## Changes - `packages/opencode/src/cli/cmd/tui/context/exit.tsx`: - Added `cleanupTerminal()` for synchronous cleanup - Added `destroyRenderer()` export for external use - Call cleanup before `renderer.destroy()` - `packages/opencode/src/cli/cmd/tui/app.tsx`: - Import `destroyRenderer` from exit context - Register SIGINT handler in `tui()` function - Update `ErrorComponent` to use `destroyRenderer()` ## Testing 1. Run `bun dev` or `opencode` 2. Press `Ctrl+C` to exit 3. Mouse movements should NOT produce escape sequence output 4. Terminal should be in normal state ## Related Issues - Fixes #6912 - Ctrl+C does not disable mouse tracking (Windows) - Related to #8908 - Mouse wheel triggering abnormal ASCII codes after exit - Related to #7861 - Terminal becomes unusable after opencode exits (macOS) ## Note This PR provides a similar fix to #8355 but with improvements: - More comprehensive ANSI sequences coverage - Better code organization with JSDoc comments - Consistent cleanup across all exit paths (normal exit, Ctrl+C, error component)
yindo added the pull-request label 2026-02-16 18:18:28 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#13629