[BUG] Linux/VTE (Ptyxis, GNOME Terminal): copy-on-select reports "N characters copied" but never writes the clipboard — OSC 52 ignored, wl-copy fallback unawaited

Status Open
Reported on v2.1.217
Maintainer reply None cached
Activity 2 comments · opened Jul 22, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code

What's Wrong?

On VTE-based terminals (Ptyxis, GNOME Terminal, Tilix, Terminator…), copy-on-select shows "N characters copied" but the system clipboard is never written. The success message is emitted unconditionally — neither copy path is verified.

Both paths fail on this platform:

1. OSC 52 — silently ignored by VTE. This is the primary emission (the return of the setClipboard function). VTE does not implement OSC 52 clipboard writes, so the sequence is swallowed with no error.

Standalone repro, no Claude Code involved — run in Ptyxis/GNOME Terminal on Wayland:

$ wl-copy --clear
$ printf '\033]52;c;%s\007' "$(printf 'HELLO' | base64 -w0)"
$ wl-paste
                      # ← empty. On kitty/foot/WezTerm this prints HELLO.

I also verified it against a live session by injecting the sequence directly into the Claude Code pty (/proc/<pid>/fd/1):

clipboard cleared      -> []
wrote OSC 52 to pty    -> write ok
clipboard after OSC 52 -> []        # nothing

2. wl-copy fallback — fire-and-forget, never awaited, never checked. From the 2.1.217 bundle:

async function dT(e){                                   // setClipboard
  let t = Buffer.from(e,"utf8").toString("base64");
  if(!t6r()) yhu(e);                                    // native copy — NOT awaited
  await lMg(e);                                         // tmux buffer
  ...
  return cw(bS.CLIPBOARD,"c",t)                         // OSC 52 — the actual return value
}

function yhu(e){
  let t = { input: e, useCwd: false, timeout: 2000 };    // spawn helper: SIGTERM after 2s
  switch(Lt()){
    case "linux":
      if(typeof K0e !== "string")
        AQi().then(()=>{ if(typeof K0e === "string") yhu(e) });   // async detection
      else if(K0e === "wl-copy")
        Jr("wl-copy",[],t), Jr("wl-copy",["--primary"],t);        // no --foreground
      ...
  }
}

async function AQi(){                                   // tool detection, async
  if(process.env.WAYLAND_DISPLAY && await Ny("wl-copy")){ K0e = "wl-copy"; return }
  if(process.env.DISPLAY){ /* xclip, xsel */ }
  K0e = null;
}

Three problems here:

  • yhu(e) is not awaited and its exit code is never inspected. Whatever happens, the "copied" message still renders.
  • wl-copy is spawned without --foreground, under timeout: 2000 / killSignal. On Wayland the clipboard is served by a surviving process — the source client must stay alive to answer the compositor's data request. Observed after a copy-on-select: no wl-copy process remains, and the selection is not retrievable.
  • First copy of a session is a no-op. K0e is undefined, so the first call only kicks off async detection and returns; the copy depends on a retry firing later. This is a large part of why it appears intermittent ("works maybe 1 in 10 times").

What Should Happen?

  1. Do not report success unless a copy path actually succeeded. wl-copy/xclip/xsel should be awaited and their exit code checked; when every path fails (or only unverifiable OSC 52 was attempted on a terminal known not to support it), surface a failure instead of "N characters copied".
  2. Spawn wl-copy --foreground detached (or otherwise let the serving process outlive the 2s timeout) so the Wayland selection survives.
  3. Resolve the clipboard-tool detection once at startup, so the first copy of a session isn't a silent no-op.

Steps to Reproduce

  1. Fedora 42 (or any Wayland session), terminal Ptyxis or GNOME Terminal, wl-clipboard installed.
  2. Start claude.
  3. Drag-select any text in the TUI. UI shows "N characters copied".
  4. Paste anywhere (Ctrl+Shift+V, or run wl-paste).
  5. Actual: clipboard unchanged / empty. Expected: the selected text.
  6. ps -eo pid,args | grep wl-copy → no surviving process.

Additional Information

Impact. On VTE terminals there is currently no working in-TUI copy, and the UI actively misreports success — you retry, it says "copied" again, and nothing lands. Compounding it: mouse reporting is enabled, so a plain drag never reaches the terminal's own selection either.

Workaround (reliable, bypasses Claude Code entirely): hold Shift while dragging so VTE takes the selection, then Ctrl+Shift+C.

Note on copyOnSelect: false — not a workaround here, because of #77259 (the fullscreen renderer doesn't consult that gate).

Related but distinct:

  • #77259 — copyOnSelect: false ignored by the fullscreen renderer (about suppressing the copy; this issue is about the copy failing while reporting success).
  • #70550 — asks to prefer OSC 52 over wl-copy; on VTE that would make this worse, since OSC 52 is a dead end there. Any fix should keep the native path on VTE.
  • #74214 — duplicate OSC 52 emission.
  • #66957, #70857 — mouse capture / alternate-screen breaking terminal selection generally.

Claude Code Version

2.1.217 (native install)

Platform

Linux x86_64 — Fedora 42, kernel 6.17.8

Operating System

Fedora Linux 42

Terminal/Shell

Ptyxis 48.5 (VTE) on Wayland, TERM=xterm-256color, bash. Session is local (not SSH). wl-clipboard and xclip both installed and working when invoked manually. "tui": "fullscreen".

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗