Skip to main content
ansicode

APC — Application Program Command (`ESC _ … ESC \\` / `\x9F … \x9C`)

The string introducer ECMA-48 reserves for application-to-application messages. Modern use: Kitty graphics protocol, VS Code shell integration, Windows Terminal API patches. Sibling to DCS / OSC / PM / SOS.

Byte forms

Every common string-literal form so you can paste-and-search either direction.

\\x1b[\x1b_<body>\x1b\\ (7-bit) \x9f<body>\x9c (8-bit C1)
\\033[\033_<body>\033\\ (7-bit) \237<body>\234 (8-bit C1)
\\e[\e_<body>\e\\
ESC [ESC _ <body> ESC \\ or 0x9F <body> 0x9C
hex1b 5f <body> 1b 5c / 9f <body> 9c

Description

**APC** (*Application Program Command*) is the ECMA-48 string introducer reserved for **application-to-application** messages — bytes the terminal is supposed to pass through transparently to a peer application listening on the same TTY, without interpreting the body itself. The 7-bit form is `\x1b_<body>\x1b\\` (ESC `_` + opaque bytes + ST); the 8-bit C1 form is the single byte `\x9F` introducer + body + single-byte `\x9C` terminator. Sibling to **DCS** (`\x1bP`, device control), **OSC** (`\x1b]`, OS command), **PM** (`\x1b^`, privacy message), **SOS** (`\x1bX`, start of string) — five 'string-shaped' sequence families framed by the same ST. **Why APC matters in 2026.** ECMA-48 originally designed APC for tunneling between an application running on a remote host and a co-resident application on the same terminal (early thin-client / mainframe-frontend setups). That use case is mostly dead, but the byte shape has been **co-opted** as a 'safe escape hatch' for vendor-specific protocols that don't want to step on OSC's user-facing semantics: - **Kitty's graphics protocol** is the headline modern user — Kitty + Konsole + WezTerm + Ghostty + Wayst accept image data via `\x1b_G<key1>=<val1>,<key2>=<val2>,...;<base64-pixels>\x1b\\`. The `G` first-byte after `_` is Kitty's family tag; subsequent emulators that adopted Kitty graphics keep it. (Despite the slug name `dcs-kitty-graphics`, the actual byte sequence is APC, not DCS — the slug predates this clarification.) - **VS Code shell integration** uses APC with a `633;` prefix as a private channel for shell-integration markers that VS Code's terminal doesn't want to advertise via OSC 133. - **Windows Terminal** is experimenting with `\x1b_<JSON>\x1b\\` for terminal-API JSON messages (preview builds, not stable). - **ConPTY pass-through** — Windows ConPTY filters most OSC sequences for security, but historically passed APC through more permissively, so some Windows-side tools route through APC to reach the host terminal unaltered. **Parser rules.** Treat the body as **opaque bytes** until ST is seen at packet boundary. Specifically: ECMA-48 says any 'escape sequence other than ESC \\' inside the body must be ignored by the terminal but preserved when passed through; a strict parser reads bytes into a buffer, scanning for `\x1b` followed immediately by `\\` (the only valid 7-bit ST) or for the single byte `\x9C`. **Naive 'split on ESC' parsers will mis-frame** any body that legitimately contains ESC bytes (Kitty graphics in particular embeds binary data that statistically hits 0x1B). **Security stance.** Because APC is meant to be passed through opaquely, terminals that *do* implement APC dispatch must whitelist the protocols they recognise (Kitty graphics tag `G`, VS Code `633;`, etc.) and silently drop unknown APC bodies — emitting a stranger's APC body to the user would let one application impersonate another. Terminals that *don't* implement any APC protocols (Alacritty, gnome-terminal, macOS Terminal, Linux console) should silently swallow + discard, which they do; treat APC as 'will reach a peer that knows the tag, or vanish completely' — never as a guaranteed-visible channel. **Distinction from DCS / OSC / PM / SOS.** - **DCS** (`\x1bP`) — device control (data targeted at the *terminal* itself: DECRQSS, DECDLD, DECUDK, Sixel, terminfo cap query). - **OSC** (`\x1b]`) — OS command (data targeted at the terminal-as-OS-shim: window title, palette, clipboard, hyperlink, prompt markers — user-facing semantics). - **APC** (`\x1b_`) — application command (data targeted at a *peer application*, not the terminal — the terminal is just a courier). - **PM** (`\x1b^`) — privacy message (similar courier semantics to APC, less adopted in practice; some legacy thin-client gear used it). - **SOS** (`\x1bX`) — start of string (the most generic introducer, no semantic; almost universally unused in 2026). **Common parsing bug** — terminals that implement OSC and DCS but forget APC: they see `\x1b_G...` , don't recognise the introducer, and **emit `_G...`** to the visible screen. Look for stray `_G` runs on broken Kitty-graphics renders to diagnose this. **Coverage** — APC dispatch (i.e. routing the body to a registered handler) is **niche**. **Kitty** + **WezTerm** + **Konsole** + **Ghostty** = partial-to-full (each routes APC `G` to its graphics handler; other APC bodies discarded). **xterm** = partial (recognises APC framing, discards body by default — `apcDispatch` X resource off). **mlterm** + **iTerm2** + **Windows Terminal** = partial (APC framing recognised, vendor-tagged bodies handled, other bodies discarded). **Alacritty** + **gnome-terminal** + **macOS Terminal** + **Linux console** + **cmd / ConPTY** = no-op-but-correct (APC framing recognised, body silently swallowed — no visible artifact). **Modern emulators all do at least the framing correctly** — buggy ones that emit the body literally are limited to very old builds.

Spec citation: ECMA-48 §8.3.2 (APC) / xterm-ctlseqs (APC) / Kitty graphics protocol

Parameters

Introducer (7-bit)ESC + underscore (\x1b 0x5f). The C0-safe form; works under UTF-8.
Introducer (8-bit)Single byte 0x9F. UTF-8 unsafe (continuation byte). Avoid except in known-Latin-1 channels.
TerminatorESC + backslash (\x1b\\, 7-bit ST) or single byte 0x9C (8-bit ST). Either is valid; match the introducer width.
BodyOpaque bytes — terminal must not interpret. Vendor protocols use a first-byte family tag (Kitty 'G', VS Code '633;', ...).

Examples

bash
# Probe whether the terminal accepts a Kitty-graphics APC frame.\n# Empty image (1x1 transparent PNG, base64-tiny) — if rendered, terminal supports Kitty graphics.\nprintf '\\033_Gf=32,s=1,v=1,a=T;AAAAAA==\\033\\\\'\n# Emit a custom APC tag — most terminals will silently swallow.\nprintf '\\033_myapp;hello\\033\\\\'\necho 'still here'   # no visible artifact on any modern terminal
python
import sys\n# Send a Kitty-graphics-style APC frame.\ndef apc(body):\n    sys.stdout.write('\\x1b_' + body + '\\x1b\\\\')\n    sys.stdout.flush()\napc('Gf=32,s=1,v=1,a=T;AAAAAA==')   # Kitty 'G' tag + base64 payload\napc('myapp;state=ready')             # private tag — silently swallowed on non-vendor terminals
go
// Robust APC parser: read until ST at packet boundary, never split on raw ESC.\nfunc readAPC(r *bufio.Reader) ([]byte, error) {\n    var buf bytes.Buffer\n    for {\n        b, err := r.ReadByte()\n        if err != nil { return nil, err }\n        if b == 0x9c { return buf.Bytes(), nil }      // 8-bit ST\n        if b == 0x1b {\n            n, _ := r.ReadByte()\n            if n == '\\\\' { return buf.Bytes(), nil }    // 7-bit ST\n            buf.WriteByte(b); buf.WriteByte(n); continue\n        }\n        buf.WriteByte(b)\n    }\n}
javascript
// Emit APC + listen for response APC from a peer.\nfunction sendAPC(body) {\n  process.stdout.write('\\x1b_' + body + '\\x1b\\\\');\n}\n// Parse incoming APC (collect bytes until ST, never split on raw ESC).\nlet apcBuf = '';\nprocess.stdin.on('data', chunk => {\n  const m = /\\x1b_([^\\x1b]*(?:\\x1b[^\\\\][^\\x1b]*)*)\\x1b\\\\/.exec(apcBuf + chunk.toString('binary'));\n  if (m) console.error('APC body:', m[1]);\n});
c
/* Emit APC with custom vendor tag. */\n#include <stdio.h>\nvoid send_apc(const char* tag, const char* body) {\n    printf(\"\\x1b_%s;%s\\x1b\\\\\", tag, body);\n    fflush(stdout);\n}\n/* Usage: send_apc(\"myapp\", \"hello\");  // silently swallowed on non-vendor terms */

Terminal support

xterm
partial
Linux console (fbcon)
no
macOS Terminal.app
no
iTerm2
partial
Windows Terminal
partial
cmd.exe / ConPTY
no
kitty
yes
alacritty
no
WezTerm
yes
Ghostty
yes
GNOME Terminal
no
Konsole
yes
tmux
no
GNU screen
no

Related sequences

In the family cookbook

ESC cookbook · 6. APC — the modern application-to-application envelope `\x1b_ … \x1b\\`