Skip to content

feat: add OSC 52 clipboard fallback for remote sessions#94

Merged
agavra merged 1 commit intoagavra:mainfrom
martintrojer:osc52
Jan 15, 2026
Merged

feat: add OSC 52 clipboard fallback for remote sessions#94
agavra merged 1 commit intoagavra:mainfrom
martintrojer:osc52

Conversation

@martintrojer
Copy link
Copy Markdown
Collaborator

Problem

The current clipboard implementation using arboard relies on system clipboard access (X11, Wayland, or platform-native APIs). This fails silently in common development scenarios:

  • SSH sessions to remote servers or VMs
  • Docker/Podman containers without X11 forwarding
  • WSL without proper clipboard integration
  • Headless servers and CI environments
  • tmux/screen sessions on remote machines

Solution

This commit adds OSC 52 as a fallback when arboard fails. The clipboard export now:

  1. Attempts arboard (system clipboard) first
  2. Falls back to OSC 52 if arboard fails
  3. Reports which method was used in the status message

What is OSC 52?

OSC 52 is an ANSI escape sequence (Operating System Command #52) that instructs the terminal emulator to copy text to the system clipboard. The format is: ESC ] 52 ; c ; BEL

The key insight is that escape sequences are interpreted by the LOCAL terminal emulator, not the remote system. When you SSH into a server and an application emits OSC 52, the bytes travel back through the SSH connection and your local terminal handles the clipboard operation.

This means clipboard access "just works" over SSH without requiring:

  • X11 forwarding (-X flag)
  • Additional tools like xclip/xsel on the remote
  • Complex clipboard synchronization setups

Terminal Support

OSC 52 is widely supported by modern terminals:

  • iTerm2 (macOS) - enabled by default
  • Alacritty - enabled by default
  • kitty - enabled by default
  • Windows Terminal - enabled by default
  • foot - enabled by default
  • WezTerm - enabled by default
  • xterm - requires: allowWindowOps: true
  • gnome-terminal - requires: gsettings set org.gnome.Terminal.Legacy.Settings enable-osc52 true (GNOME 45+)
  • tmux - requires: set -g set-clipboard on

For terminals that support it, no user configuration is typically needed. The feature works transparently.

Dependency Impact

This adds base64 v0.22 as a direct dependency. However, base64 is already present in the dependency tree as a transitive dependency via:

syntect -> plist -> base64

Testing

Added 4 new unit tests covering:

  • Correct OSC 52 escape sequence format
  • Empty string handling
  • Unicode/emoji encoding
  • Round-trip encoding of actual markdown content

The implementation is refactored to accept a generic Writer, making it fully testable without capturing stdout.

Problem
-------
The current clipboard implementation using arboard relies on system
clipboard access (X11, Wayland, or platform-native APIs). This fails
silently in common development scenarios:

- SSH sessions to remote servers or VMs
- Docker/Podman containers without X11 forwarding
- WSL without proper clipboard integration
- Headless servers and CI environments
- tmux/screen sessions on remote machines

Solution
--------
This commit adds OSC 52 as a fallback when arboard fails. The clipboard
export now:
1. Attempts arboard (system clipboard) first
2. Falls back to OSC 52 if arboard fails
3. Reports which method was used in the status message

What is OSC 52?
---------------
OSC 52 is an ANSI escape sequence (Operating System Command agavra#52) that
instructs the terminal emulator to copy text to the system clipboard.
The format is: ESC ] 52 ; c ; <base64-encoded-text> BEL

The key insight is that escape sequences are interpreted by the LOCAL
terminal emulator, not the remote system. When you SSH into a server
and an application emits OSC 52, the bytes travel back through the SSH
connection and your local terminal handles the clipboard operation.

This means clipboard access "just works" over SSH without requiring:
- X11 forwarding (-X flag)
- Additional tools like xclip/xsel on the remote
- Complex clipboard synchronization setups

Terminal Support
----------------
OSC 52 is widely supported by modern terminals:
- iTerm2 (macOS) - enabled by default
- Alacritty - enabled by default
- kitty - enabled by default
- Windows Terminal - enabled by default
- foot - enabled by default
- WezTerm - enabled by default
- xterm - requires: allowWindowOps: true
- gnome-terminal - requires: gsettings set org.gnome.Terminal.Legacy.Settings
    enable-osc52 true (GNOME 45+)
- tmux - requires: set -g set-clipboard on

For terminals that support it, no user configuration is typically
needed. The feature works transparently.

Dependency Impact
-----------------
This adds base64 v0.22 as a direct dependency. However, base64 is
already present in the dependency tree as a transitive dependency via:

  syntect -> plist -> base64

Testing
-------
Added 4 new unit tests covering:
- Correct OSC 52 escape sequence format
- Empty string handling
- Unicode/emoji encoding
- Round-trip encoding of actual markdown content

The implementation is refactored to accept a generic Writer, making it
fully testable without capturing stdout.
Copy link
Copy Markdown
Owner

@agavra agavra left a comment

Choose a reason for hiding this comment

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

LGTM! Thanks for the fix, would be great to be able to use this in a tmux session or part of ssh.

@agavra agavra merged commit 42d7425 into agavra:main Jan 15, 2026
4 checks passed
@martintrojer martintrojer deleted the osc52 branch January 17, 2026 10:50
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.

2 participants