Notes on OSC52
Table of Contents
OSC52 is a set of escape codes to tell the terminal emulator to do something.
For example, this tells the terminal emulator to put the string hello world
into the system clipboard:
printf "\033]52;c;$(base64 <<< "Hello World")\007"
1. A shell function to set the clipboard
clip(){ printf "\033]52;c;%s\007" "$(base64)" }
which can be used by piping input into it.
Or a version that takes a string as an argument
clip(){ printf "\033]52;c;%s\007" "$(printf "%s" "$1" | base64)" }
Note that $(cmd) will strip a trailing newline from the output of cmd so
x="$(echo "hello")" will create a variable that doesn't contain a newline
even if the output of echo does contain a newline.
However, x=$(echo "hello" | base64), then the output of echo contains a
newline, this newline gets base64 encoded. The base64 encoded newline does not
get stripped by $(...).
So doing echo "hello" | clip will put a newline in your clipboard. So either
use echo -n or printf or use the here-string form: clip <<< "hello".
2. How it works and background
The sequence is described in the XTerm Documentation. Although this is not a stadards document, many terminal emulators implement the codes described in this document.
C1 (8-Bit) Control Characters
=============================
The xterm program recognizes both 8-bit and 7-bit control characters.
It generates 7-bit controls (by default) or 8-bit if S8C1T is enabled.
The following pairs of 7-bit and 8-bit control characters are
equivalent:
ESC ]
Operating System Command (OSC is 0x9d).
Operating System Commands
=========================
OSC Ps ; Pt BEL
Ps = 5 2 ⇒ Manipulate Selection Data. These controls may
be disabled using the allowWindowOps resource. The parameter
Pt is parsed as
Pc ; Pd
The first, Pc, may contain zero or more characters from the
set c , p , q , s , 0 , 1 , 2 , 3 , 4 , 5 , 6 , and 7 . It is
used to construct a list of selection parameters for
clipboard, primary, secondary, select, or cut-buffers 0
through 7 respectively, in the order given. If the parameter
is empty, xterm uses s 0 , to specify the configurable
primary/clipboard selection and cut-buffer 0.
The second parameter, Pd, gives the selection data. Normally
this is a string encoded in base64 (RFC-4648). The data
becomes the new selection, which is then available for pasting
by other applications.
Where OSC is \033] and BEL is \007.
When the terminal emulator receives the byte \033, it doesn't draw that
character nor the next ones on the screen until it reads a \007 byte.
What it does with the bytes it receives between those two is to read 52;c; as
a string telling it what operating system command to do (52 is to set the
system clipboard content, c specifies which clipboard if applicable), then
read the rest of the bytes and base64 decode them and put the result in the
system clipboard.
It doesn't matter if this is over SSH because it is the terminal emulator which is running locally that will process this sequence. Since it has access to the system clipboard, assuming it understands OSC52, it will set the system clipboard with the string that was provided.
Send copied text from terminal to system clipboard using OSC52.
3. TMUX
When copying text in TMUX's copy-mode, it uses OSC52 to set that text as the system clipboard. This is how a TMUX session running remotely can still set your local system clipboard.
For applications running inside TMUX who attempt to use OSC52, it is TMUX who receives the sequence. TMUX can do three things
- Set its paste buffer to the string provided
- Set its paste buffer and forward the OSC52 sequence to the terminal emulator thus setting the system clipboard.
- Do nothing
This behavior is controlled with the set-clipboard option.
set -g set-clipboard on
With this setting activated, the printf command should also set the system
clipboard even if run inside TMUX.
4. Integration with editors
Emacs can send a string directly to the terminal like so:
(send-string-to-terminal (concat "\033]52;c;" (base64-encode-string "Emacs has set my system clipboard") "\007"))
evaluating this block will put "Emacs has set my system clipboard"
The Emacs package Clipetty wraps the normal functions for killing text to also send the yanked text to the system clipboard using OSC52s
(use-package clipetty :ensure t :hook (after-init . global-clipetty-mode))
To get around the fact that TMUX's set-clipboard option may not be set to
on, it does some more sophisticated things which require this option
set -ag update-environment "SSH_TTY"
to be set in ~/.tmux.conf.
5. Vim
https://github.com/ojroques/vim-oscyank?tab=readme-ov-file#terminal-support
This works by using something like this (evaluating this block from Terminal Emacs should put "clipetty OSC52" in the system clipboard if the terminal emulator supports it).
Note that in TMUX, the above code will only work if the option set-clipboard
has the value on. However I think clipetty does stuff so that it works in
TMUX no matter what.
The documentation shows that it has a bunch of things regarding TMUX and SSH sessions. For full support, this is needed in the TMUX configuration file.