Skip to content

fix(terminal): repaint full-screen programs after a replay - #18

Merged
jkyberneees merged 3 commits into
mainfrom
fix/terminal-blank-after-reattach
Nov 2, 2026
Merged

jkyberneees merged 3 commits into
mainfrom
fix/terminal-blank-after-reattach

Conversation

@jkyberneees

Copy link
Copy Markdown
Contributor

A long Claude Code session could come back blank or with only a few rows.

Cause. Full-screen TUIs send cell diffs against what they drew earlier. Once their last full paint has left the 512 KB replay ring, a reattach (page reload, the Mac app reloading after its web process dies, the backpressure resync) rebuilds a mostly blank screen. The same-size resize sent on attach is no signal, so nothing repaired it.

Fix.

  • After such a replay the PTY is one row shorter for 150 ms, so the program repaints. Real Claude Code with only diffs in the ring (32 KB for the run): 0 of 30 rows before, 30 of 30 and identical after.
  • Terminals repaint and restore canvas settings on window focus and when the page becomes visible. WebKit has no contextlost/contextrestored. This is a precaution: that loss was not reproduced.

Found in review and fixed. Resizing or writing to a killed session threw and could exit the whole server (the resize path predates this PR); sendReplay cut the first line of complete replays; a reattach at a new size was nudged needlessly.

Not covered. Inline TUIs on the normal screen (Claude Code's classic renderer) and programs that ignore SIGWINCH. A program stalled past 150 ms sees no change. The missing title bar buttons are a separate issue, still not reproduced. DESIGN.md round 12 has the details.

🤖 Generated with Claude Code

jkyberneees and others added 2 commits November 2, 2026 18:49
Full-screen TUIs such as Claude Code send cell diffs against what they drew
earlier. Once their last full paint left the 512 KB replay ring, a reattach
(page reload, the Mac app reloading after its web process dies, the
backpressure resync) rebuilt a mostly blank screen, and the same-size resize
sent on attach is no signal, so nothing repaired it.

After such a replay the PTY is one row shorter for 150 ms, which makes the
program repaint. Real Claude Code with only diffs in the ring (32 KB for the
run): 0 of 30 rows restored before, 30 of 30 and identical after.

WebKit has no contextlost/contextrestored events, so pixels discarded in the
background would stay blank now that unchanged rows are skipped. Terminals
repaint in full on window focus and when the page becomes visible; that loss
itself was not reproduced.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Resizing or writing to a killed session threw "Terminal is closed" while the
  shell was still dying; a throw in a WebSocket handler or timer exits the
  server and every terminal with it.
- sendReplay uses the exact ringTrimmed flag instead of guessing from the byte
  count, which cut the first line of complete replays.
- A reattach at a new size relies on that resize, with no nudge on top.
- Coming back to the window restores the canvas settings as well as the pixels.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

🚀 Deploying Preview to Cloudflare 🚀

Preview Deployments by commit

Status Deployment URL Commit Updated (UTC) See this deployment's details
  • Build: Failed ❌

View logs ↗
62113c4 2026-11-02T18:06:26.449Z View logs ↗
  • Build: Failed ❌

View logs ↗
f603dc8 2026-11-02T18:02:17.640Z View logs ↗

dash leaves the cursor after its prompt, so on a fresh alternate screen the
marker is indented and the prompt-aware line() helper never matched it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jkyberneees
jkyberneees merged commit 3bc5a43 into main Nov 2, 2026
4 of 5 checks passed
@jkyberneees
jkyberneees deleted the fix/terminal-blank-after-reattach branch November 2, 2026 18:10
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.

1 participant