Commit Graph
2 Commits
Author SHA1 Message Date
Zoltan Zombory 4ecf7fa228 fix(terminal): strip OSC 52 from replays and copy each clipboard write once
xterm parses write() data after chunkedTerminalWrite has already cleared
_isLoadingBuffer, so the main terminal's replay gate never held: a tab switch
or reconnect re-copied the newest OSC 52 in the replayed history. Strip every
OSC 52 from the replay beside the DEC 2026 markers (OSC52_STRIP_RE). Tiles
keep their own _bufferLoading gate, which holds there.

One Claude Code copy arrives up to three times (its own OSC 52, tmux
load-buffer -w, set-clipboard forwarding), so identical text within
OSC52_DEDUPE_MS is dropped. The manual-copy fallback opens only in the
focused tab, so a background tab on the same session stays quiet.

The replay tests now drive the real chunkedTerminalWrite into
@xterm/headless and fail without the strip. Test harnesses that supply
DEC_SYNC_STRIP_RE by hand get OSC52_STRIP_RE too, and CLAUDE.md records
the rules next to Auto Copy.
2026-10-13 13:54:15 +02:00
Zoltan Zombory 435a56be10 feat(terminal): copy OSC 52 clipboard writes from the PTY into the browser clipboard
Programs inside the terminal (Claude Code /copy, tmux yanks with
set-clipboard on, vim) set the clipboard with OSC 52. xterm.js registers no
handler for 52, so on a headless host (no xclip, no DISPLAY) those copies
were silently dropped and never reached the remote browser.

Register one handler on the main terminal and on every TerminalTile (split
Pane B, tile grid). It decodes the base64 payload as UTF-8 and copies it
through _copyText, falling back to the manual-copy dialog when the browser
blocks the write. Read queries (`?`) are refused, and nothing is copied
during a buffer replay, so a tab switch or reconnect never re-copies old
OSC 52 sequences.
2026-10-12 20:39:07 +02:00