Windows: select-to-copy text is lost by RDP clipboard redirection (double clipboard write races rdpclip)

Status Open
Reported on v2.1.234
Maintainer reply None cached
Activity 0 comments · opened Aug 18, 2026

Windows: select-to-copy text is lost by RDP clipboard redirection (double clipboard write races rdpclip)

Environment

  • Claude Code 2.1.234, running on the RDP server machine
  • Windows Server 2025, build 10.0.26100 (client machine also Windows)
  • Claude Code hosted in Windows Terminal 1.24.260710001
  • The machine is accessed over RDP with clipboard redirection enabled

(reproduced with an MSTSCAX-based client; the failure is generated
server-side, so any RDP client is affected)

Symptom

Selecting text in the Claude Code TUI shows "copied N chars to clipboard".
Pasting on the same machine works. Pasting on the RDP client machine
does nothing — the client's clipboard ends up with no text format at all
(Get-Clipboard returns empty). Copies from every other app on the server
(Notepad, PowerShell Set-Clipboard, clip.exe) cross the RDP boundary
fine, so users conclude RDP clipboard sharing works except for Claude Code.

Reliable user-facing repro:

  1. RDP into a Windows machine (clipboard redirection on).
  2. Run Claude Code in Windows Terminal inside that session.
  3. Select any transcript text → "copied N chars to clipboard".
  4. Ctrl+V in any app on the client machine → nothing pastes.

What actually happens (both sides instrumented)

A WM_CLIPBOARDUPDATE listener on the server recorded one select-to-copy:

17:05:38.002  owner=WindowsTerminal  formats=4  CF_UNICODETEXT=yes   ← write #1 (OSC 52 handled by WT)
17:05:38.288  owner=powershell       formats=6  CF_UNICODETEXT=yes   ← write #2 (Claude Code's spawned writer)
17:05:38.291  owner=none             formats=6  CF_UNICODETEXT=yes   (writer process already exited)
17:05:38.294  owner=none             formats=6  CF_UNICODETEXT=yes

So one "copy" performs two clipboard writes ~200–290 ms apart:

  1. OSC 52 is emitted and Windows Terminal writes 4 clean text formats.
  2. A cold-spawned powershell child performs a WinForms/OLE-style write

(final state: DataObject, CF_UNICODETEXT, Ole Private Data,
CF_LOCALE, CF_TEXT, CF_OEMTEXT) in multiple clipboard
transactions, then exits (clipboard owner dies).

A no-read watcher on the client (logs sequence/owner/format count via
CountClipboardFormats/IsClipboardFormatAvailable only — deliberately
never reads data, because reading materializes the delayed offer and masks
the bug) captured the corresponding arrivals:

17:08:36.556  owner=<rdp client>  formats=8  CF_UNICODETEXT=True    ← offer for write #1: good
17:08:36.707  owner=<rdp client>  formats=3  CF_UNICODETEXT=False   ← offer for write #2: NO TEXT FORMATS

rdpclip on the server snapshots write #2's format list in the middle of
its multi-step transaction
— at a moment when only
[DataObject, Ole Private Data, CF_LOCALE] exist and the text formats have
not been written yet — and advertises that truncated list. The client
faithfully replaces the good offer from write #1 with a text-less offer.
Result: the client clipboard has no CF_UNICODETEXT/CF_TEXT at all, so
paste is a no-op and Get-Clipboard returns empty, even though the
server clipboard ends in a perfectly correct state (which is why the
bug is invisible to any server-side inspection after the fact).

Negative controls, all of which sync correctly to the client:

  • a single atomic Win32 write (OpenClipboard/EmptyClipboard/

SetClipboardData(CF_UNICODETEXT)/CloseClipboard);

  • an identical-signature ephemeral WinForms SetDataObject(..., true)

writer whose process exits (dead owner, DataObject marker present);

  • two-writer bursts replicating the real sequence at 169/191/404/426 ms

gaps, with identical text, including a 4-format first write and writes
triggered at the exact mouse-release instant.

Only Claude Code's real writer loses the race deterministically — its
cold-spawned child's write steps are spread widely enough for rdpclip's
snapshot to land inside the transaction every time.

Suggested fix

On Windows, write the clipboard once and atomically: a single
OpenClipboard/EmptyClipboard/SetClipboardData(CF_UNICODETEXT)/
CloseClipboard transaction (what clip.exe does), instead of the current
combination of (a) OSC 52 → the hosting terminal writes, plus (b) a
multi-transaction OLE/WinForms write from a spawned process. Either write
suppressed (or both replaced by one raw write) removes the mid-transaction
window that rdpclip's format-list snapshot can hit. As-is, every RDP user
who runs Claude Code on a remote machine silently loses select-to-copy
across the session boundary.

Workarounds until fixed

  • Paste into any app on the server (e.g. Notepad) and re-copy from there.
  • Any clipboard-history/monitor tool on the client that polls with reads

incidentally "rescues" the first offer before it is replaced.

View original on GitHub ↗