Skip to content

Make terminal OSC 52 copy reach the system clipboard - #1

Merged
ru-sh merged 1 commit into
mainfrom
fix/osc52-clipboard
Sep 18, 2026
Merged

ru-sh merged 1 commit into
mainfrom
fix/osc52-clipboard

Conversation

@ru-sh

@ru-sh ru-sh commented Sep 18, 2026

Copy link
Copy Markdown

Copying from the integrated terminal with OSC 52 silently does nothing on web.
Programs that copy this way (tmux, vim, Claude Code) report success and the
clipboard is unchanged.

Cause

xterm's clipboard addon is loaded for every terminal and hands the payload to
IClipboardService.writeText(text, 'clipboard') (xtermTerminal.ts). The
browser implementation opens with:

// With type: only in-memory is supported
if (type) { this.mapTextToType.set(type, text); return }

'clipboard' is not an alternate clipboard, it is the system one, so the write
is filed into a Map and navigator.clipboard is never reached. Electron does
not have the bug because it forwards the type to electron.clipboard.

The OSC 52 provider is the only caller in the tree that passes 'clipboard',
so letting it fall through changes nothing else.

Upstream: microsoft/vscode#318254. Drop patches/osc52-clipboard.diff when a
fix lands there.

Only the write path

readText('clipboard') keeps returning the in-memory value. Letting reads
through would mean a program printing ESC]52;c;? could pull the user's
clipboard back into the terminal as input, which is the usual reason terminals
disable OSC 52 reads.

Requires a secure context

Without HTTPS or localhost, navigator.clipboard is undefined and the
execCommand fallback cannot run, because OSC 52 arrives asynchronously with
no user gesture attached. Chromium works gesture-free in a secure context;
Firefox still requires a gesture and will not copy this way.

Testing

New e2e test in test/e2e/terminal.test.ts grants clipboard permissions, types
printf '\033]52;c;<base64>\a' into a terminal and polls
navigator.clipboard.readText().

Run against a real build over localhost, it fails before the patch
(Expected: "osc52-…", Received: "") and passes after it.

Programs in the integrated terminal copy by emitting OSC 52. xterm's
clipboard addon hands the payload to IClipboardService.writeText with the
type 'clipboard', which the browser implementation filed into an in-memory
map instead of writing out, so on web the copy silently did nothing.

Only the write path changes. readText('clipboard') still returns the
in-memory value, so a read query cannot be used to pull the clipboard back
into the terminal as input.

Needs a secure context: without one navigator.clipboard is undefined and the
execCommand fallback cannot run, since OSC 52 arrives with no user gesture.
@ru-sh
ru-sh force-pushed the fix/osc52-clipboard branch from dde81ba to 3f19e51 Compare September 18, 2026 06:31
@ru-sh
ru-sh merged commit 8b28bf2 into main Sep 18, 2026
19 of 20 checks passed
@ru-sh
ru-sh deleted the fix/osc52-clipboard branch September 22, 2026 06:26
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