Skip to content

Commit b7c3c30

Browse files
Ark0Nclaude
andcommitted
fix: send Ctrl+L after tab switch to clear stale Ink CUP frames
Tailed terminal buffers contain multiple CUP-positioned Ink frames from different time points. When replayed in xterm, old frames at viewport positions not covered by the latest frame persist as ghost content (e.g. duplicate "bypass permissions" bars). After buffer load, send Ctrl+L via the session input API to trigger a full Ink redraw, which overwrites all stale frame content with the correct current state. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 0d80524 commit b7c3c30

1 file changed

Lines changed: 13 additions & 3 deletions

File tree

src/web/public/app.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2240,9 +2240,19 @@ class CodemanApp {
22402240
});
22412241
}
22422242

2243-
// Fire-and-forget resize — don't await to avoid blocking UI.
2244-
// The resize triggers an Ink redraw in Claude which streams back via SSE.
2245-
this.sendResize(sessionId);
2243+
// Fire-and-forget resize + Ctrl+L to force Ink redraw.
2244+
// Tailed buffers accumulate stale CUP-positioned Ink frames that overlap
2245+
// in the viewport (e.g. duplicate "bypass permissions" bars). Ctrl+L
2246+
// triggers a full Ink redraw which overwrites all stale frame content.
2247+
// sendResize may be a no-op if dimensions match, so Ctrl+L is essential.
2248+
this.sendResize(sessionId).then(() => {
2249+
if (selectGen !== this._selectGeneration) return;
2250+
fetch(`/api/sessions/${sessionId}/input`, {
2251+
method: 'POST',
2252+
headers: { 'Content-Type': 'application/json' },
2253+
body: JSON.stringify({ input: '\x0c' })
2254+
}).catch(() => {});
2255+
});
22462256

22472257
// Defer secondary panel updates so they don't block the main thread
22482258
// after terminal content is already visible.

0 commit comments

Comments
 (0)