Repository navigation
fix(web): clearing a running terminal keeps its screen and input modes - #36380
Conversation
Fails on main: a cleared event fully resets the Ghostty core, dropping the alternate screen, application cursor keys, mouse tracking and Kitty keyboard flags the live program negotiated. Co-Authored-By: Claude Opus 5.5 <[email protected]>
A cleared event became an empty reset update, which fully resets the emulator and drops the alternate screen, Kitty keyboard flags, cursor-key mode and mouse tracking the still-running program negotiated. Clear now appends an erase of the screen and scrollback instead, so attached emulators keep their modes and a replay from the start restores them. The retained output records where displayed text begins, so the mobile text fallback still shows an empty buffer after Clear. Fixes #36006 Co-Authored-By: Claude Fable 5.2 <[email protected]>
…rminal binaries Older native binaries are fed the whole history as initialBuffer and recreate their emulator when it stops extending the last one. They now get the full replay, so Clear appends its erase. The text fallback takes the displayed text from the output state instead. Co-Authored-By: Claude Fable 5.2 <[email protected]>
The erase was appended within the retention budget, so on a full buffer it trimmed the oldest output. A replay then no longer extended what older native binaries were fed, and could lose the program's mode setup. Co-Authored-By: Claude Fable 5.2 <[email protected]>
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — Clearing a terminal now erases its visible content without resetting the running program’s screen and input modes. The change is limited to client-side display and replay handling, with separate handling for mobile text fallbacks. You can add or adjust custom eligibility rules. Learn more. |
|
No actionable comments were generated in the recent review. Walkthrough
Merge Risk:
|
No code change in this round; the head is unchanged at 95ae7c8. Watched pull request #36380 until its checks and bot reviews finished: all 36 checks passed on 95ae7c8 (mergeable state clean), Macroscope approved with no findings (Correctness Check and Approvability Check both success), and CodeRabbit reported 'No actionable comments were generated' with all four of its pre-merge checks passed and no line comments. No finding rated high or above is open, so the watch was stopped.
CodeRabbit's description check, though passed, noted two things about the pull request description that are for the pipeline, not the code: the Evidence section is still a placeholder, and the 'Not in this change' bullets contain a duplicate and a contradictory line about whether the 9-byte overage after Clear is bounded (it is: at most the 9-byte erase sequence over budget until the next output, snapshot or restart). The description also says only clearOutput changed, while the diff also adds textStartOffset, terminalOutputReplay and the mobile call-site changes.
The fix as it stands: a
clearedevent appends an erase of screen and scrollback (ESC[H ESC[2J ESC[3J) to the client's retained output instead of resetting it, so attached emulators keep the running program's alternate screen, Kitty flags, cursor-key mode and mouse tracking; displayed text for the mobile text fallback starts after the clear; older native binaries get the full replay as initialBuffer; and Clear never trims retained output.Fixes #36006
Reproduction on main
On origin/main 9efd960: started
T3CODE_DEV_SEED=0 vp run devin a fresh worktree, paired a headless Chromium (Playwright) web client, and opened the terminal drawer ('Toggle terminal drawer') on a new thread. In the terminal I ran a probe script that prints ESC[?1049h ESC[>7u ESC[?1;1000;1006h ESC= (alternate screen, Kitty flags 7, application cursor keys, SGR mouse), thenstty raw -echo; exec cat > log, so every byte the viewer sends is logged. Clicked in the terminal and pressed ArrowUp and 'a': the program received ESC[<0;5;3M/ESC[<0;5;3m, ESC[1;1:1A/ESC[1;1:3A, and a plus ESC[97;1:3u. Then sent terminal.clear (the mobile Clear toolbar's RPC) for that thread/term-1 over the app's own /ws URL from the page; the server replied Exit Success. Repeated the click, ArrowUp and 'a' with the same program still running: the click produced nothing, ArrowUp sent ESC[A, and 'a' sent a with no release event. Also added a unit test in apps/web/src/terminal/ghostty/core.test.ts that applies aclearedevent through applyTerminalAttachStreamEvent, readTerminalOutputUpdate and writeTerminalOutputUpdate on the real Ghostty WASM core; on main it fails, with alternateScreen, applicationCursorKeys and mouseTracking going from true to false and the Kitty flags from ESC[?7u to ESC[?0u.Evidence
Evidence for #36006: real Chromium web client, 1280×800, light theme, fresh synthetic data on each commit. Enable the reported terminal modes once; click, press ArrowUp and a; invoke terminal.clear; repeat with the same program still running. The probe displays actual received bytes. Both sides work before Clear; only base loses mouse and Kitty events afterward. scenarios:prove exited 0.
Scenario source and probe.
Not shown:
Tests
None run locally this round (no code change). On the pull request at 95ae7c8: all 36 CI checks passed, including Test, Test Web 1 and 2, Test Server 1-8, Lint, and Build and Typecheck; Macroscope Correctness Check and Approvability Check succeeded; CodeRabbit completed with no actionable comments.
Not in this change
Who did the work
Run by the t3code factory in T3 Code.