// terminal escape sequence · xterm standard

OSC 52
Clipboard Protocol

How a short escape sequence lets a program running inside any terminal — local, SSH, tmux — push text directly into your operating system's clipboard.

What is OSC 52?

Terminals are just text streams. But over the decades, a set of escape sequences were standardised to let programs talk to the terminal emulator itself — not just print characters. These sequences are invisible; the terminal intercepts and acts on them.

OSC stands for Operating System Command. It's a family of escape sequences (all starting with ESC ]) that let a program make OS-level requests. There are many OSC codes: OSC 0 sets the window title, OSC 8 creates hyperlinks, and OSC 52 reads or writes the system clipboard.

Why does this matter?
Without OSC 52, copying text from a remote session (SSH, tmux, container) means the text never leaves the remote machine. OSC 52 lets the terminal emulator on your local machine — the one that actually has a clipboard — receive the content directly over the terminal byte stream.

Which terminals support it?

Kitty, Alacritty, WezTerm, iTerm2, foot, and most modern VTE-based terminals. tmux and Zellij can forward OSC 52 sequences if configured. The classic xterm invented it; some older terminals silently ignore it.

Anatomy of the sequence

The full OSC 52 write sequence looks like this:

// OSC 52 escape sequence — write clipboard
ESC ]
OSC opener
\033] in bash. Bytes 0x1B 0x5D.
52
Command code
Identifies this as a clipboard operation.
;
Separator
Separates the code from parameters.
c
Selection
c = clipboard. Others: p primary, q secondary, s select.
;
Separator
Separates selection from data.
BASE64…
Payload
The clipboard text, base64-encoded.
BEL
OSC terminator
\007 (bell char) or ESC \ (ST).

So for the text hello, the full sequence sent to the terminal is:

 raw bytes (escape notation)
\033]52;c;aGVsbG8=\007

Where aGVsbG8= is hello in base64. The terminal emulator sees this invisible sequence in its input stream, decodes the payload, and places hello into the OS clipboard — ready for Cmd+V anywhere.

PartValueDescription
\033]ESC + ] — begins an OSC sequence. ESC is byte 0x1B.
52The OSC command number for clipboard access (XTerm standard).
;Delimiter between command number and first parameter.
cclipboardWhich selection buffer to target. c = system clipboard.
;Delimiter between selection and payload.
DATAbase64The actual text you want in the clipboard, base64-encoded.
\007BELTerminates the OSC sequence. Alternatively ESC \ (ST).

Why base64?

Escape sequences are byte streams parsed by the terminal. If the clipboard payload contained raw bytes — especially control characters like newlines (0x0A), nulls (0x00), or another ESC (0x1B) — the terminal parser would misinterpret them as sequence terminators or new commands, corrupting or truncating the data.

Base64 encodes arbitrary binary as only printable ASCII characters (A–Z a–z 0–9 + / =), none of which are control characters. This guarantees the payload passes through the terminal parser intact, regardless of content — multi-line code, binary paths, Unicode, anything.

⚠ Size limit
Some terminals cap OSC 52 payloads (tmux historically limited to ~74 KB). For very large copies you may hit this silently. Most modern terminals have raised or removed the limit.

End-to-end flow

1
Text is piped into the script via stdin Any program can feed text to osc52copy through a pipe: echo "hello" | osc52copy, or a clipboard hook from an editor.
2
stdin is base64-encoded base64 -w 0 reads all of stdin and produces a single-line base64 string with no wrapping.
3
OSC 52 sequence is assembled and printed printf wraps the encoded string inside the escape sequence and writes it to stdout — which must be connected to the terminal.
4
The terminal emulator intercepts the sequence The terminal sees the invisible bytes, recognises the OSC 52 pattern, decodes the base64 payload, and writes the result to the OS clipboard.
5
OS clipboard is set The text is now in your system clipboard and can be pasted anywhere with Ctrl+V / Cmd+V.
// data flow
stdin your text base64 -w 0 encode payload printf \033]52;c;DATA\007 Terminal emulator → OS Clipboard

The osc52copy script

Three lines. Click the i marker on any line to reveal its explanation.

 osc52copy  ·  bash
1
#!/usr/bin/env bash
i
Shebang. Tells the OS which interpreter to use. /usr/bin/env bash finds bash via the PATH, making the script portable across systems where bash isn't at a fixed location like /bin/bash.
2
buf=$(base64 -w 0)
i
Read stdin → base64. $(…) runs a subshell and captures its output into $buf. base64 reads all bytes from stdin and encodes them. The -w 0 flag disables line-wrapping — without it, base64 inserts newlines every 76 characters, which would break the OSC sequence by introducing a premature terminator.
3
printf '\033]52;c;%s\007' "$buf"
i
Emit the OSC 52 sequence. printf is used instead of echo because it reliably interprets escape sequences. \033 is the ESC byte (octal 033 = hex 0x1B). %s is substituted with $buf. \007 is the BEL byte — the OSC sequence terminator. The whole sequence flows to stdout, which must be the terminal device for the terminal emulator to intercept it.
click on a line to toggle its explanation
✓ Usage
Pipe any text into the script: echo "hello world" | osc52copy or cat file.txt | osc52copy. As long as the script's stdout reaches the terminal emulator, the clipboard will be set.