Skip to content

fix(web): stop auto-sending Ctrl+L from session selection paths#99

Merged
Ark0N merged 1 commit into
Ark0N:masterfrom
TeigenZhang:fix/no-auto-ctrl-l
May 25, 2026
Merged

fix(web): stop auto-sending Ctrl+L from session selection paths#99
Ark0N merged 1 commit into
Ark0N:masterfrom
TeigenZhang:fix/no-auto-ctrl-l

Conversation

@TeigenZhang
Copy link
Copy Markdown
Contributor

@TeigenZhang TeigenZhang commented May 25, 2026

Symptom

Quickly refreshing the page (or an SSE reconnect firing in quick succession) would sometimes silently wipe the current conversation — the active Claude session got cleared with no warning or confirmation.

Root cause

Claude Code 2.x treats Ctrl+L (\x0c) as a two-step "clear conversation" command (first press shows a confirmation prompt, second press clears). The frontend fired \x0c from three places to force Ink to redraw stale CUP-positioned frames in the tailed buffer. When a fast page refresh / reconnect ran the same path twice within Claude's confirmation window, the first \x0c opened the clear prompt and the second \x0c confirmed it — destroying the conversation.

Fix

Removed the \x0c sends from:

  • selectSession() — the main offender, runs on every tab switch & page reload
  • restoreTerminalSize() — manual "restore size" button
  • sendPendingCtrlL() — dead code path (pendingCtrlL was never populated)

Trade-off: occasional stale Ink frame immediately after refresh; the user's first keypress causes Ink to redraw and the artifact vanishes. Losing the conversation silently is far worse than a brief cosmetic glitch.

Test plan

  • esbuild parses app.js / terminal-ui.js cleanly
  • Verified: tab switches / page reloads no longer risk clearing the conversation; transient redraw artifact self-heals on first keypress

🤖 Generated with Claude Code

Claude Code 2.x treats Ctrl+L (\x0c) as a two-step "clear conversation"
command (first press shows the confirmation prompt, second press
clears). The frontend previously fired \x0c from three places to force
Ink to redraw stale CUP-positioned frames in the tailed buffer; if a
page refresh or SSE reconnect ran the same path twice within Claude's
confirmation window the second \x0c silently nuked the user's
conversation.

Removed the \x0c sends from:
- selectSession() — main offender, runs on every tab switch & page reload
- restoreTerminalSize() — manual "restore size" button
- sendPendingCtrlL() — dead code path (pendingCtrlL was never populated)

Trade-off: occasional stale Ink frames immediately after refresh; the
user's first keypress causes Ink to redraw and the artifact vanishes.
Losing the conversation silently is far worse than a brief cosmetic
glitch.
@Ark0N
Copy link
Copy Markdown
Owner

Ark0N commented May 25, 2026

Thank you very much — this is an excellent catch and a really well-reasoned fix. 🙏

Silently wiping the conversation on a fast refresh / SSE reconnect is about the worst failure mode we could have, so trading it for a transient stale Ink frame that self-heals on the next keypress is clearly the right call.

I verified the whole change before merging:

  • pendingCtrlL really is dead — it's only ever read inside sendPendingCtrlL, never assigned anywhere, so the if (!this.pendingCtrlL) guard always returned early. The function was already a no-op in practice and has zero callers, so the explicit stub changes nothing.
  • The user-initiated Ctrl+L keymap in input-cjk.js is correctly left intact — only the automatic/programmatic sends are gone.
  • No correctness regression in the anti-flicker pipeline: redraw correctness there comes from resize/SIGWINCH + the buffering layers; the selectSession \x0c was purely a cosmetic force-redraw.
  • The backend CTRL_L_PATTERN filter only strips form-feed from PTY output, so it's unrelated to these input sends.

Love the "Do NOT re-introduce Ctrl+L here" guard comments too — that'll save a future regression. CI is green. Merging now, thanks again! 🎉

@Ark0N Ark0N merged commit 896dc5b into Ark0N:master May 25, 2026
1 check passed
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.

2 participants