[BUG] fullscreen TUI copies via OSC 52 only, bypassing the native pbcopy path — silent clipboard failure in Terminal.app (local, non-SSH)
Summary
With "tui": "fullscreen", selection-copy is routed through OSC 52 only, bypassing the native (pbcopy) path that the platform selector would choose for a local macOS session. In Terminal.app — which has never implemented OSC 52 — the write is silently discarded while the UI reports success ("sent N chars via OSC 52"). Switching to "tui": "default" immediately restores working copy, with no other change to the environment.
This is a root-cause follow-up to #66192, which collects many symptom reports (Terminal.app, iTerm2, GNOME Terminal, Terminator, Termius/SSH). This report isolates the mechanism with the decision functions extracted from the shipped binary, on a local, non-SSH macOS setup where every environmental cause has been individually ruled out.
Environment
| | |
|---|---|
| Claude Code | 2.1.207 (native build, ~/.local/share/claude/versions/2.1.207, Mach-O arm64) |
| OS | macOS (Darwin 25.5.0), Apple Silicon |
| Terminal | Terminal.app (TERM_PROGRAM=Apple_Terminal, TERM=xterm-256color) |
| tmux | no (TMUX unset) |
| SSH | no (SSH_CONNECTION, SSH_TTY both unset — verified in the exact shell) |
| pbcopy | verified working: echo test | pbcopy && pbpaste round-trips correctly |
| settings.json | "tui": "fullscreen" (explicitly set) |
Steps to reproduce
- Set
"tui": "fullscreen"in~/.claude/settings.json. - Open Claude Code in macOS Terminal.app (local session, no SSH, no tmux).
- Select text in the TUI (click-drag, or any selection) and copy (copy-on-select or Ctrl+Shift+C).
- Status line shows:
sent N chars via OSC 52 · if paste fails, hold Fn while selecting for native copy. - Paste anywhere → clipboard was never updated.
Expected
On a local macOS session, copy should use the native clipboard (pbcopy) — which is exactly what the platform selector in the binary says should happen (see below). At minimum, the UI should not report success for a write the terminal is known to drop.
Root-cause analysis (decompiled from the shipped 2.1.207 binary)
The clipboard mode selector does the right thing in principle:
function KOr(){ return lS()?.ssh ?? !!process.env.SSH_CONNECTION } // "is SSH?"
function JOr(){
if(!KOr()) switch($t()){
case"macos": case"windows": case"wsl": return"native"; // local macOS → pbcopy
case"linux": if(typeof LEe==="string") return"native"; break
}
if(process.env.TMUX) return"tmux-buffer";
return"osc52"
}
With SSH_CONNECTION unset and no session SSH flag, KOr() is false and JOr() must return "native" on macOS. Yet the observed status message is the "osc52" branch of the feedback function:
case"osc52": o=`sent ${r} ${n} via OSC 52 · if paste fails, hold ${YOr()} while selecting for native copy`;
So under the fullscreen renderer, the copy path that actually executes is not (or not only) gated by JOr() — OSC 52 is emitted and reported as the mechanism even when the selector's answer for this platform is native. Since Terminal.app does not implement OSC 52 at all, the sequence is dropped with no error, and the success message is false.
Two supporting details from the same binary:
YOr()(the hint-text function) already special-casesApple_Terminal(returns"Fn") — i.e. the code already detects the one mainstream macOS terminal that cannot honor OSC 52, but only uses that knowledge to word the hint, not to pick a mechanism or to suppress the success claim.- The async copy routine (
lC) does call the native write (FEc(e)) when not SSH and also emits OSC 52 — but in fullscreen mode the observed message and the observed clipboard state (unchanged) both correspond to the OSC-52-only behavior. This matches the report in #66192 (comment by aenotiad): "When"tui": "fullscreen"is set … Claude Code automatically sends OSC 52 … On macOS Terminal.app these sequences are silently ignored … but Claude Code still shows 'sent xxx characters via OSC 52'".
Confirmed fix/workaround
Changing ~/.claude/settings.json from "tui": "fullscreen" to "tui": "default" restores working copy immediately (native pbcopy path; mouse selection is also no longer captured, so plain select + ⌘C works again). Nothing else in the environment was changed. This matches multiple confirmations in #66192.
Suggested fixes
- In the fullscreen renderer's copy path, use the same
JOr()mode selection as the classic renderer: local macOS/Windows/WSL → native clipboard; OSC 52 only whenKOr()(SSH) is true or no native path exists. - Independently of (1): when
TERM_PROGRAM=Apple_Terminaland the mechanism is OSC 52, don't report success — Terminal.app is known to drop the sequence. The current message actively misleads ("sent N chars…" reads as success; the failure hint is easy to miss).YOr()shows the terminal is already identified at that point. - Consider a
clipboarddiagnostics line in/doctor(mechanism chosen, terminal OSC 52 capability known/unknown) — most of the pain in #66192 is users having no way to see why copy silently does nothing.
Related
- #66192 (symptom collection; this report isolates the fullscreen/OSC-52 mechanism on a fully-local macOS setup with the shipped binary's own decision functions)