8000 Pane loses alternate-screen state, so exiting a fullscreen TUI draws the shell prompt over the old frame · Issue #345 · amirlehmam/wmux · GitHub
[go: up one dir, main page]

Skip to content

Pane loses alternate-screen state, so exiting a fullscreen TUI draws the shell prompt over the old frame #345

Closed

Description

@jpstratman

What happens

I ran Claude Code with "tui": "fullscreen", which uses the alternate screen buffer (ESC[?1049h on start, ESC[?1049l on exit). When I quit, the pane did not return to the screen it showed before Claude Code started. The final Claude Code frame stayed on screen. Claude Code's exit message and the PowerShell prompt were written over the middle of it, mixed with leftover characters from the lines underneath. The structure is shown below, with the actual content replaced by placeholders:

      <line from the final Claude Code frame>
Resume this session with:<remainder of the frame line underneath>

claude --resume <session-id><leftover characters from the frame>
PS C:\...\project> <remainder of the frame line underneath>
      <line from the final Claude Code frame>

This is not only a drawing problem. wmux read-screen --lines 2000 on that pane returns 127 lines:

  • lines 1–11: output from a shell command run before Claude Code started, cut off partway through a table
  • lines 11–127: the Claude Code session, written into the normal buffer as if it were ordinary output
  • lines 50–53: the exit message and prompt, written over that text

So the Claude Code frames went to the normal buffer and its scrollback, not to the alternate buffer. By the time Claude Code sent ESC[?1049l, the pane was already on the normal buffer.

This fits xterm.js's handling of DECRST 1049 in the bundled build: activateNormalBuffer() followed by restoreCursor(). When the pane is already on the normal buffer, the buffer switch does nothing and only the cursor restore runs. The cursor jumps to the position saved when the program started, and everything after that is drawn over the stale frame.

Expected: a pane's alternate-buffer state survives a remount. On exit, the pane returns to the normal buffer as it was before the program started.

Steps to reproduce

Any split-tree change that remounts the pane while a program is on the alternate screen. No Claude Code needed:

  1. Open a terminal pane T. From inside it, run wmux split --down and note the new pane U.
  2. In T, run:
    cls; "MAIN-1"; "MAIN-2"; [Console]::Write("`e[?1049h`e[H"); 1..5|%{"ALT-BEFORE-$_"}; Start-Sleep 12; 1..5|%{"ALT-AFTER-$_"}; Start-Sleep 3; [Console]::Write("`e[?1049l"); "EXITED"
  3. While it sleeps, run wmux close-pane <U> from another pane. This remounts T.
  4. wmux read-screen --surface <T> right after the close shows only MAIN-1 and MAIN-2. The pane is back on the normal buffer while the program is still on the alternate one.
  5. After the script exits, the screen reads EXITED, the prompt, then ALT-AFTER-1..5. EXITED and the prompt overwrote MAIN-1 and MAIN-2 at row 0.

With Claude Code, the common trigger is wmux browser open from inside the session in a workspace with no browser pane. That splits Claude Code's own pane. Closing a neighbouring pane, wmux layout agents/grid and dragging a tab between panes do the same.

Cause

snapshotSurfaceBuffer in src/renderer/hooks/useTerminal.ts serializes with excludeAltBuffer: true. The replacement terminal replays only the normal buffer plus mouse modes, and nothing restores ?1049h. The comment expects the TUI's post-remount redraw to cover it, but the TUI redraws without re-sending ?1049h, so the redraw lands in the normal buffer.

Serializing with the alternate buffer included fixes it. SerializeAddon then writes the normal buffer and its cursor, then ESC[?1049h ESC[H and the alternate screen, so the replacement comes back on the alternate buffer and the saved cursor is the shell's real position. I have a branch with that change and a regression test (real xterm + SerializeAddon, remount on the alternate screen) and can open a PR.

wmux version

2.39.0 (Electron 43.0.0; bundled node-pty 1.1.0 with ConPTY/OpenConsole 1.23.251008001)

Windows version

Windows 11 Home 10.0.26200

Anything else

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      0