# Start of String, Privacy Message, Application Program Command (SOS, PM, APC)

> Open a control string whose content the terminal itself does not act on.

- **Sequence:** `ESC X Pt ST`
- **ECMA-48:** [§8.3.128 SOS – Start of String, p. 66](https://archive.org/details/ecma-48-5th-edition-june-1991/page/n79/mode/1up)
- **DEC STD 070:** [§3.5.4.3 Character Strings, p. 3-29](https://archive.org/details/bitsavers_decstandar0VideoSystemsReferenceManualDec91_74264381/page/n133/mode/1up)
- **VT510:** [4.2 Control Characters](https://vt100.net/docs/vt510-rm/chapter4.html#S4.2)

Three control strings carry content meant for someone other than the
terminal. Each is closed by [ST](https://control-codes.page/esc/st/index.html.md):

| Opener | 7-bit form | Carries |
| --- | --- | --- |
| SOS, start of string | `ESC X` | a character string for an application to interpret |
| PM, privacy message | `ESC ^` | a privacy message, under some privacy discipline |
| APC, application program command | `ESC _` | commands for an application program |

PM is [ECMA-48 §8.3.94, p. 53](https://archive.org/details/ecma-48-5th-edition-june-1991/page/n66/mode/1up)
and APC [§8.3.2, p. 33](https://archive.org/details/ecma-48-5th-edition-june-1991/page/n46/mode/1up).
ECMA-48 lets an SOS string hold any characters but SOS and ST, where PM's
and APC's, like [DCS](https://control-codes.page/esc/dcs/index.html.md)'s, may hold only printable characters and
the format effectors `BS` to `CR`. DEC STD 070 reserves SOS for future use,
and recommends a terminal treat it as "the start of an unimplemented control
string"
([§3.5.4.3, p. 3-29](https://archive.org/details/bitsavers_decstandar0VideoSystemsReferenceManualDec91_74264381/page/n133/mode/1up)).
The VT510 manual says that after PM or APC it "ignores all following
characters until it receives a SUB, ST, or any other C1 control character",
but lists SOS itself as simply "Ignored". libghostty-vt treats all three
alike, as DEC STD 070 recommends.

None of them is displayed: a string the terminal does not act on is thrown
away whole. CAN, SUB, ESC or a C1 control ends one early, as for any
control string, so an `ESC [` inside an SOS ends the string and starts a
control sequence, though ECMA-48 would have it be part of the string.

Terminal emulators have since found uses for APC: kitty's graphics protocol
travels in `ESC _ G … ST`, which libghostty-vt reads. A terminal that does
not know the protocol throws the same bytes away as an APC it does not
implement.

All three are C1 controls, with single-byte forms `98`, `9E` and `9F` that
libghostty-vt, decoding its input as UTF-8, does not accept.

## Validation

### SOS-1: None is displayed

Input, one step per line:

```text
A
\eXstart of string\e\\
B
\e^privacy message\e\\
C
\e_application command\e\\
D
```

Expected screen:

```text
|ABCD__|
cursor 1,5
reply none
```

### SOS-2: BEL does not end them

Input, one step per line:

```text
A
\e_hi\a   # BEL is part of the string
B         # and so is this
\e\\
C
```

Expected screen:

```text
|AC____|
bell 0
```

### SOS-3: ESC ends one early

Input, one step per line:

```text
A
\eXa      # an SOS
\e[2;2H   # the ESC ends it, and this is a CUP
b
\e\\      # an ST with nothing to end
B
```

Expected screen:

```text
|A_____|
|_bB___|
```

---

This is the Markdown version of <https://control-codes.page/esc/sos/>. 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>.
