Uh oh!
There was an error while loading. Please reload this page.
fix: restore terminal state on exit to prevent mouse escape sequence … - #21429
fix: restore terminal state on exit to prevent mouse escape sequence …#21429wangliang01 wants to merge 3 commits into
Conversation
…garbage After the TUI exits, the terminal was left with mouse tracking enabled (\x1b[?1003l / \x1b[?1006l SGR mode), causing subsequent terminal input to print raw escape sequences like ^[<35;61;11M instead of being interpreted normally. Root cause: renderer.destroy() relies on native destroyRenderer() to send the mouse-disable sequences, but process.exit() in index.ts fires before those writes are flushed to stdout. Fixes: - exit.tsx: explicitly write mouse-disable + cursor-restore sequences to stdout before renderer.destroy(), and register a process 'exit' handler as a last-resort guarantee that fires synchronously on process exit. - prompt/index.tsx + session/index.tsx: add double-confirm for Ctrl+C exit (press twice within 3 s) matching the behaviour of claude code and similar TUI tools; inline hint replaces the toast for the first press. - win32.ts: tighten the ENABLE_PROCESSED_INPUT enforcement poll from 100 ms to 16 ms so the guard reacts faster after console-mode resets. Closesanomalyco#13276
Thanks for updating your PR! It now meets our contributing guidelines. 👍 |
rekram1-node
commented
May 15, 2026
Automated PR Cleanup Thank you for contributing to opencode. Due to the high volume of PRs from users and AI agents, we periodically close older PRs using automated criteria so maintainers can focus review time on the most active and community-supported contributions. This PR was closed because it matched the following cleanup criteria:
PRs created within the last month are not affected by this cleanup. If you believe this PR was closed incorrectly, or if you are still actively working on it, please leave a comment explaining why it should be reopened. A maintainer can review and reopen it if appropriate. Thanks again for taking the time to contribute. |
…garbage
After the TUI exits, the terminal was left with mouse tracking enabled (\x1b[?1003l / \x1b[?1006l SGR mode), causing subsequent terminal input to print raw escape sequences like ^[<35;61;11M instead of being interpreted normally.
Root cause: renderer.destroy() relies on native destroyRenderer() to send the mouse-disable sequences, but process.exit() in index.ts fires before those writes are flushed to stdout.
Fixes:
Issue for this PR
Closes#13276
Type of change
What does this PR do?
When the user exits opencode (Ctrl+C twice), the terminal was left in a broken state: mouse tracking escape sequences continued to be emitted as visible garbage text (
^[<35;61;11M) because the native renderer cleanup didn't finish beforeprocess.exit()terminated the process.This PR fixes the issue in two layers:
Explicit terminal reset before
renderer.destroy()(exit.tsx): writes the mouse-disable sequences (?1003l,?1006l,?1000l) and cursor-restore (?25h) directly to stdout synchronously, so they are guaranteed to flush regardless of whether the native cleanup runs in time.process.on('exit', ...)last-resort handler (exit.tsx): theexitevent fires synchronously right before the Node/Bun process terminates, giving a second chance to write the reset sequences even ifprocess.exit()is called from an unexpected path.Double-confirm Ctrl+C exit (
prompt/index.tsx,session/index.tsx): instead of exiting immediately on the first Ctrl+C, the user now has to press it twice within 3 seconds — the same UX as Claude Code and similar tools. The first press shows an inline hint in the status bar rather than a floating toast.Faster Windows console-mode enforcement (
win32.ts): theENABLE_PROCESSED_INPUTguard poll interval is reduced from 100 ms to 16 ms so it catches and reverts console-mode resets more promptly on Windows Terminal.How did you verify your code works?
Tested manually on Windows 11 + Windows Terminal v1.21:
Started opencode, ran a prompt, then pressed Ctrl+C twice to exit. After exiting, typed freely in the terminal — previously this produced lines of
^[<35;61;11M ...garbage; after the fix the terminal is clean.Pressed Ctrl+C once with an empty prompt — confirmed the inline hint
ctrl+c again to exitappeared in the status bar and auto-dismissed after ~3 s.Pressed Ctrl+C twice quickly — confirmed the app exited cleanly with no garbage output.
During an active session, verified Escape still interrupts the running session and Ctrl+C still triggers the two-step exit flow (not session interrupt).
Ran
bun typecheckinpackages/opencode— no type errors.Screenshots / recordings
If this is a UI change, please include a screenshot or recording.
Checklist
If you do not follow this template your PR will be automatically rejected.