Skip to content

fix(desktop): strip ESC[3J to prevent terminal scrollback jump on reattach#963

Merged
Kitenite merged 3 commits intomainfrom
reimpl-fix
Jan 26, 2026
Merged

fix(desktop): strip ESC[3J to prevent terminal scrollback jump on reattach#963
Kitenite merged 3 commits intomainfrom
reimpl-fix

Conversation

@Kitenite
Copy link
Copy Markdown
Collaborator

Summary

  • Add stripClearScrollbackSequence() function to strip ESC[3J (clear scrollback) sequences while preserving ESC[2J (clear screen) and other escape sequences
  • Filter ESC[3J in renderer before xterm.write() to prevent viewport jumps on live stream and restore
  • Filter ESC[3J in persistence layer (headless terminal and history) to prevent replaying clears on reattach

Root Cause

Claude Code emits ESC[2J (clear screen) plus ESC[3J (clear scrollback) and cursor home during long sessions and on paste/redraw. When ESC[3J is persisted in snapshots/history and replayed on terminal reattach, it clears the scrollback buffer and resets the viewport, causing the terminal to "jump" to another position.

Test plan

  • Start Claude Code session in the desktop terminal
  • Generate enough output to create scrollback
  • Detach/reattach (switch panes, close/reopen, or reconnect)
  • Verify viewport and scrollback are preserved without unexpected jumps
  • Verify clear command and Cmd+K still work correctly (ESC[2J preserved)

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 26, 2026

Warning

Rate limit exceeded

@Kitenite has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 11 minutes and 8 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Kitenite Kitenite force-pushed the reimpl-fix branch 6 times, most recently from b9cc7e8 to 97e28d4 Compare January 26, 2026 17:11
…ttach

Claude Code emits clear-scrollback control sequences (ESC[3J) during long
sessions and on paste/redraw. When persisted and replayed on reattach, these
sequences clear scrollback and move the viewport, causing the terminal to
"jump" to another position.

The fix strips ESC[3J while preserving ESC[2J (clear screen) in both:
- Renderer: filter before xterm.write() in stream and restore hooks
- Persistence: filter before writing to headless terminal and history
Pending events are live PTY data queued during restore, not stored
snapshots. They should pass through unfiltered like the live stream.
Remove stripping from persistence and snapshot replay paths.
The only place that needs stripping is flushPendingEvents which
processes buffered events during terminal reattach.
@Kitenite Kitenite merged commit 7ee9b5c into main Jan 26, 2026
9 checks passed
@Kitenite Kitenite deleted the reimpl-fix branch January 26, 2026 17:26
@github-actions
Copy link
Copy Markdown
Contributor

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ⚠️ Neon database branch
  • ⚠️ Electric Fly.io app

Thank you for your contribution! 🎉

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