# Kitty Clipboard (OSC 5522)

> Read and write the clipboard by MIME type, with permission and status: kitty's clipboard protocol.

- **Sequence:** `OSC 5522 ; metadata ; payload ST`
- **ECMA-48:** [§8.3.89 OSC – Operating System Command, p. 51](https://archive.org/details/ecma-48-5th-edition-june-1991/page/n64/mode/1up)
- **Specification:** [Copying all data types to the clipboard, kitty documentation](https://sw.kovidgoyal.net/kitty/clipboard/)

`OSC 5522 ; metadata ; payload ST` extends [OSC 52](https://control-codes.page/osc/clipboard/index.html.md) to
every kind of data the clipboard holds, each by its MIME type, and adds
answers that say whether a request succeeded. Its definition is kitty's
[Copying all data types to the clipboard](https://sw.kovidgoyal.net/kitty/clipboard/).
The metadata is `key=value` pairs separated by `:`; MIME types and data are
Base64.

| Sequence | Does |
| --- | --- |
| `OSC 5522 ; type=read ; types ST` | read the clipboard as these MIME types; `.` as the list asks which types it holds |
| `OSC 5522 ; type=write ST` | start writing the clipboard |
| `OSC 5522 ; type=wdata:mime=type ; data ST` | a chunk of data, at most 4096 bytes before encoding, for one MIME type |
| `OSC 5522 ; type=wdata ST` | the end of the write |

`loc=primary` uses the primary selection instead. The terminal answers a
read with `status=OK`, a `status=DATA` sequence for each chunk, and
`status=DONE`, and a write with `status=DONE`; or with an error:
`EPERM` when permission is refused, `ENOSYS` when the clipboard asked for
is not available, `EBUSY`, `EIO` or `EINVAL`. A program finds out whether
the terminal has the protocol with [DECRQM](https://control-codes.page/csi/decrqm/index.html.md) for mode `5522`,
`0` or `4` meaning no.

A default xterm does not have it and ignores it
([the OSC numbers it knows](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/misc.c#L3476-L3504)),
and answers DECRQM for mode `5522` with `0`. The cases follow xterm.

libghostty-vt hands the clipboard to its host through the same
`CLIPBOARD_READ` and `CLIPBOARD_WRITE` callbacks as OSC 52, and without
them, as here, answers itself: `EPERM` to a read and `ENOSYS` to a write.
It too answers DECRQM for mode `5522` with `0`. The cases where it answers
are known differences.

## Validation

### OSC5522-1: A read is not answered

*A known difference: libghostty-vt does not pass this case.*

Input, one step per line:

```text
\e]5522;type=read;dGV4dC9wbGFpbg==\e\\  # text/plain
```

Expected screen:

```text
|______|
reply none
```

### OSC5522-2: Nor is a write

*A known difference: libghostty-vt does not pass this case.*

Input, one step per line:

```text
\e]5522;type=write\e\\
\e]5522;type=wdata:mime=dGV4dC9wbGFpbg==;SGk=\e\\  # "Hi"
\e]5522;type=wdata\e\\
```

Expected screen:

```text
|______|
reply none
```

### OSC5522-3: Nothing on screen

Input, one step per line:

```text
A
\e]5522;type=write\e\\
\e]5522;type=wdata\e\\
B
```

Expected screen:

```text
|AB____|
cursor 1,3
```

### OSC5522-4: The mode is not recognized

Input, one step per line:

```text
\e[?5522$p
```

Expected screen:

```text
|______|
reply \e[?5522;0$y
```

---

This is the Markdown version of <https://control-codes.page/osc/kitty-clipboard/>. On that page every validation case runs live in libghostty-vt, the terminal emulation core of Ghostty, compiled to WebAssembly.

The validation cases are written in the notation described in <https://control-codes.page/notation/index.html.md>.
