Skip to content

fix(tui): copy through tmux to the client showing the pane - #63578

Open
Blandinium wants to merge 2 commits into
anomalyco:devfrom
Blandinium:tmux-clipboard
Open

Blandinium wants to merge 2 commits into
anomalyco:devfrom
Blandinium:tmux-clipboard

Conversation

@Blandinium

@Blandinium Blandinium commented Nov 12, 2026 •

Copy link
Copy Markdown

Issue for this PR

Closes #50208

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Inside tmux, OpenTUI sends OSC 52 wrapped in a DCS passthrough. tmux drops it unless allow-passthrough is on, which is not the default, so copying in the TUI never reaches the local clipboard over SSH. A plain OSC 52 would not help either: set-clipboard external, the default, ignores clipboard writes from programs inside tmux.

When $TMUX is set, the TUI now asks tmux which client shows its pane and hands the text to tmux load-buffer -w -t <client> -. tmux then forwards it to that client's terminal as its own set-clipboard setting allows. The -t matters: without it, tmux may pick another attached client. The existing OpenTUI routes still run alongside it, because load-buffer -w exits 0 even when tmux forwards nothing (for example when it doesn't think the outer terminal supports clipboard writes).

How did you verify your code works?

  • Kwi (libghostty) → SSH → tmux next-3.4 (set-clipboard external, allow-passthrough off): selecting text now reaches the local clipboard. Before the change it did not.
  • New test in packages/tui/test/clipboard.test.ts starts a private tmux server, attaches a client in a PTY, and checks that the OSC 52 with the copied text reaches that client; with no client attached the old route is used.
  • bun run check passes.

Screenshots / recordings

Not a visual change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Added by the opencode bot (AI-generated).

Related: #59664, #59052

@opencodejr opencodejr Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix works. With real tmux 3.5a at its defaults (set-clipboard external, allow-passthrough off) and an attached client recording what reaches the outer terminal, a write() through a real OpenTUI renderer sent nothing out of tmux on the base branch. With this change, the OSC 52 carrying the copied text reaches the client. With several clients attached, it picks the client of the pane's own session, and set-clipboard off is respected. The clipboard tests pass.

The public API is unchanged: the new env parameter on createClipboardAdapter is internal to the TUI package.

One concern, inline: when tmux doesn't think the outer terminal supports clipboard writes, load-buffer -w still exits 0 but sends nothing. The adapter then skips the existing OSC 52 route, which can break copying for people who use the allow-passthrough on workaround.

Related: #59664, #59052

Comment thread packages/tui/src/clipboard.ts Outdated
// OpenTUI rejects NUL before any destination; host clipboard text cannot contain it.
const result = await clipboard.writeText(text.replaceAll("\0", ""), {
const clean = text.replaceAll("\0", "")
if (await writeTmux(clean, env)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

load-buffer -w exits 0 even when tmux sends nothing to the client. That happens whenever tmux doesn't think the outer terminal supports clipboard writes. I saw it with an outer TERM=screen-256color, as in nested tmux/screen or terminals not matched by tmux's default xterm*:clipboard feature. In that case this branch writes to the host clipboard only and drops the OpenTUI OSC 52 route. Users who relied on allow-passthrough on (the workaround from #59134) had working copies before and now silently lose them. Keeping destination: "all-available" here would avoid that, at the cost of a harmless duplicate write when passthrough is also on.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, thanks. The OpenTUI routes now always run alongside the tmux route, so the allow-passthrough on workaround keeps working; with passthrough on the terminal just gets the same OSC 52 twice.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I checked 4f07d63d0: the OpenTUI routes now run alongside the tmux route, so a terminal tmux doesn't treat as clipboard-capable no longer loses copying when allow-passthrough is on. The updated test passes here with tmux 3.5a (6/6 in clipboard.test.ts). This resolves my concern.

@opencodejr opencodejr Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My earlier point is addressed: the OpenTUI copy routes now run alongside the tmux route, so tmux exiting 0 without forwarding anything no longer drops them. I checked this with an outer TERM=screen-256color client. With tmux 3.5a at its defaults, a copy still reaches the attached client as an OSC 52 escape sequence, and the clipboard tests pass. The public API is unchanged. No new concerns.

This branch has not been deployed

No deployments
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.

tui: "Copied to clipboard" does not update local clipboard over SSH and tmux

1 participant