Skip to content

Claude Terminal tmux mouse copy does not reach browser clipboard unless copy-selection-and-cancel -w is used; OSC52 also needs frontend handling #125

Description

@kirkande1

GitHub Issue Draft: Claude Terminal tmux mouse copy does not reach browser clipboard without -w and OSC 52 frontend handling

Title

tmux mouse copy does not reach browser clipboard unless copy-selection-and-cancel -w is used; OSC 52 also needs browser-side handling in ttyd frontend

Body

Summary

In Claude Terminal 2.5.1 running inside Home Assistant via ttyd and tmux, mouse selection copied text into the tmux internal buffer but did not update the browser/macOS clipboard.

After debugging, the problem appears to have two parts:

  1. The tmux mouse-copy binding copies into tmux's internal buffer but does not explicitly write the selection to the external terminal clipboard.
  2. Once tmux emits valid OSC 52, the ttyd/browser frontend receives the OSC 52 data, but Chrome does not place it onto the system clipboard without browser-side handling.

A local workaround fixed the behavior so the final workflow is:

drag-select text in Claude Terminal → release mouse → Cmd+V elsewhere

Environment

Claude Terminal: 2.5.1
Terminal frontend: ttyd 1.7.7
tmux session: claude
Browser: Chrome on macOS
macOS Version: Tahoe 26.5.2
Home Assistant access: HTTPS
Active tmux config: /data/home/.tmux.conf
Packaged tmux config/template: /opt/scripts/tmux.conf

ttyd process example:

ttyd --port 7681 --interface 0.0.0.0 --writable --ping-interval 30 \
  --client-option enableReconnect true \
  --client-option reconnect 10 \
  --client-option reconnectInterval 5 \
  --client-option theme {...} \
  --client-option fontSize 14 \
  bash -c tmux new-session -A -s claude 'claude'

Original behavior

  1. Drag-select text inside the Claude Terminal browser tab.
  2. tmux reports that text was copied.
  3. tmux show-buffer shows the selected text correctly.
  4. Cmd+V outside the terminal pastes the previous clipboard content, not the selected terminal text.

So tmux selection itself was working, but system/browser clipboard sync was not.


tmux capability checks

Commands run:

tmux show -s set-clipboard
tmux info | grep -i 'Ms:'
tmux show -g terminal-overrides
tmux display-message -p 'client_termname=#{client_termname} client_termfeatures=#{client_termfeatures}'

Observed output:

set-clipboard on
193: Ms: (string) \033]52;%p1%s;%p2%s\a
terminal-overrides[0] linux*:AX@
terminal-overrides[1] "*:Ms=\\E]52;%p1%s;%p2%s\\007"
client_termname=xterm-256color client_termfeatures=bpaste,ccolour,clipboard,cstyle,focus,title

The attached tmux client was checked with:

tmux list-clients -F 'tty=#{client_tty} term=#{client_termname} features=#{client_termfeatures} session=#{session_name}'

Observed:

tty=/dev/pts/0 term=xterm-256color features=bpaste,ccolour,clipboard,cstyle,focus,title session=claude

There was only one attached client, so this was the ttyd/browser client.


Direct OSC 52 test

A direct tmux clipboard export was tested:

tmux set-buffer 'TMUX-OSC52-DIRECT-TEST'
tmux show-buffer
tmux set-buffer -w 'TMUX-OSC52-DIRECT-TEST'

A browser diagnostic userscript detected the real OSC 52 sequence:

[OSC52 REAL FOUND] "\u001b]52;;VE1VWC1PU0M1Mi1ESVJFQ1QtVEVTVA==\u0007"

The Base64 payload decodes to:

TMUX-OSC52-DIRECT-TEST

This proved:

tmux -w → OSC 52 → ttyd WebSocket → Chrome

works.


tmux binding issue

The original mouse binding was:

bind -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-selection-and-cancel

This copied into tmux's internal buffer, but did not emit OSC 52.

Changing it to this caused real OSC 52 to be emitted when releasing the mouse selection:

bind -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-selection-and-cancel -w

Suggested config diff:

-bind -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-selection-and-cancel
+bind -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-selection-and-cancel -w

After reloading:

tmux source-file /data/home/.tmux.conf

mouse selection produced genuine OSC 52 data in the browser diagnostic:

[OSC52 REAL FOUND] "\u001b]52;;SWYgdGhpcyBpcyBhbiBhdXRvbWF0ZWQ..."

and also:

[OSC52 REAL FOUND] "\u001b]52;c;SWYgdGhpcyBpcyBhbiBhdXRvbWF0ZWQ..."

Browser/frontend issue

Even after the tmux binding emitted valid OSC 52, Chrome did not place the selection onto the system clipboard automatically.

A local Tampermonkey userscript fixed this by:

  1. intercepting ttyd WebSocket output,
  2. detecting real OSC 52 sequences beginning with ESC ] 52 ;,
  3. decoding the Base64 payload,
  4. writing to the browser clipboard with:
navigator.clipboard.writeText(text)

This made the final behavior work:

drag-select text → release mouse → Cmd+V outside terminal

Expected behavior

Given that Claude Terminal's tmux configuration comments indicate that drag-copy should copy to the browser clipboard via OSC 52, mouse selection should place the selected text onto the browser/system clipboard without requiring a custom Tampermonkey script.


Actual behavior

Without the local fixes:

  • mouse selection copied text into the tmux internal buffer,
  • the browser/system clipboard was not updated,
  • Cmd+V pasted previous clipboard contents.

With only the tmux -w fix:

  • real OSC 52 reached the ttyd WebSocket,
  • but browser/system clipboard still did not update until a browser-side OSC 52 handler was added.

Suggested fixes

1. tmux config

Update the mouse-copy binding to include -w:

bind -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-selection-and-cancel -w

2. Frontend OSC 52 handling

Add or enable browser-side OSC 52 handling in the Claude Terminal/ttyd frontend so that valid OSC 52 sequences received by the web terminal are decoded and written to the browser clipboard, subject to browser permission and security constraints.


Notes

Testing OSC 52 through Claude Code's ! command facility was misleading because Claude Code captured/sanitized the command output before rendering it.

The clean transport test was:

tmux set-buffer -w 'TMUX-OSC52-DIRECT-TEST'

This directly proved tmux-generated OSC 52 reached the browser.


Security consideration

OSC 52 allows terminal output to request clipboard updates. Any frontend implementation should likely be opt-in or scoped carefully, with reasonable payload limits and validation.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions