OSC 88 Terminal Resume Protocol
A proposal for a program to tell its terminal how to relaunch it when the terminal itself is restarted.
OSC 88 ; op ; key=value … ST
- Specification
- Terminal Resume Protocol (TRP), OSC 88 Specification, v1
The Terminal Resume Protocol lets a long-running program, an editor, a multiplexer, an SSH session, tell its terminal how to start it again after the terminal itself restarts, whether it crashed, the machine rebooted, or the terminal was upgraded. The terminal keeps that declaration for the pane and, when it restores the pane, runs the command. The program announces; the terminal acts on its own schedule. Apart from an optional query, nothing is sent back.
This summarizes version 1 of the specification as it stood at commit aabe19c, where its status is Proposal. Its authors name Otty as the reference implementation and say the protocol is not specific to it.
The sequence
OSC 88 ; op [ ; key=value ]… ST
The first field after 88 is the operation. Fields after it are key=value pairs separated by ;, and a receiver splits each on its first = only. Every value is the base64 of a UTF-8 string, which keeps a ; from ever appearing inside one, except the two numeric fields, v and self_repaint, which are written as plain digits. Either ST or BEL may end the sequence; the specification prefers ST and requires a receiver to accept both.
| Operation | Sent by | Meaning |
|---|---|---|
arm | the program | Set this pane’s resume command, replacing any set before. It must have a cmd; one without is ignored. |
clear | the program | Withdraw it, as on a clean exit. Any fields are ignored. |
query | the program | Optional. Asks whether the terminal implements the protocol. |
supported | the terminal | The answer to query: OSC 88 ; supported ; v=N ST, with N the highest version it implements. |
A program may send arm and clear without asking first: a terminal that does not implement the protocol must ignore the whole sequence. One that does should answer query, but no answer means only that support is unknown, and the program must not wait for one indefinitely.
The fields of arm
| Field | Value | Meaning |
|---|---|---|
cmd | base64, required | The program to run, and what the terminal verifies before trusting the rest |
args | base64 | The rest of the command line, appended after cmd |
self_repaint | 0 or 1 | 1: the program redraws its own screen, so the terminal should not restore the pane’s old contents as well. Default 0 |
cwd | base64 | The directory to run in; otherwise the pane’s last known working directory |
title | base64 | A title for the restored pane, below OSC 0 and 2 in priority |
v | digits | The protocol version, 1 by default |
A receiver ignores keys it does not know, so that later versions can add fields; a change that is not backward compatible must raise v. args is a single string, and the specification does not say how it is split into separate arguments.
For example, to have htop -d 10 started again in /home/alice, with cmd the base64 of htop, args of -d 10, cwd of /home/alice, and self_repaint=1 because htop draws its whole screen itself:
ESC ] 88 ; arm ; cmd=aHRvcA== ; args=LWQgMTA= ; cwd=L2hvbWUvYWxpY2U= ; self_repaint=1 ESC \
without the spaces, which are there only to make it readable, and ESC ] 88 ; clear ESC \ when it exits normally.
Security
The terminal will later run what was armed, so the specification is mostly about keeping text that merely passes through the terminal, a file being catted, a log, a page of man, from arming a command. That kind of escape-sequence injection is the threat it sets out to stop; a program that can already run code in the pane is out of scope, since it can do worse than arm a command. A terminal must:
- not run a resumed command without a check that defeats injection. The recommended check is to confirm, before keeping an
arm, that a live process in the pane has anargv[0]whose basename is the basename ofcmd; acatprinting forged bytes cannot claim another program’s name. Another check is allowed if it proves the same thing. - run only
cmdas the program, withargsstrictly as its arguments, so that the unverifiedargscan never change which program runs. - show the resume to the user, and let them undo it.
- and should let the user turn resuming off, for every program or for particular ones.
Open questions
The specification lists what may still change before version 1 is final:
- whether to add a
patchoperation that updates single fields, such ascwdas the program changes directory, instead ofarmreplacing everything; - whether a program should be able to fix
cwdso that the terminal may not substitute its own, more recent idea of it; - whether
queryshould be answered in the style of DECRQM instead of with an OSC.
The number 88 itself is proposed, not settled: the specification found no terminal using OSC 88, and asks for the number to be coordinated through the community registry at terminfo.dev.