Skip to main content
ansicode

OSC 133 — Semantic prompt marks (FinalTerm A / B / C / D)

Tag shell prompt-start / command-start / output-start / command-end so the terminal can jump between prompts, fold output, and decorate exit codes.

Byte forms

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

\\x1b[\x1b]133;A\x07 (prompt start) \x1b]133;B\x07 (command start) \x1b]133;C\x07 (output start) \x1b]133;D;<exit>\x07 (command end)
\\033[\033]133;A\007 / \033]133;B\007 / \033]133;C\007 / \033]133;D;0\007
\\e[\e]133;A\a / \e]133;B\a / \e]133;C\a / \e]133;D;0\a
ESC [ESC ] 133 ; A BEL etc.
hex1b 5d 31 33 33 3b 41 07 / ...3b 42 07 / ...3b 43 07 / ...3b 44 ... 07

Description

FinalTerm-defined **shell integration** protocol now widely adopted by Kitty, WezTerm, Ghostty, iTerm2, Warp, VS Code's terminal, and (partially) Windows Terminal. Four mark codes carve a shell session into structured blocks: - **`OSC 133 ; A ST`** — prompt start (emitted just before `PS1` renders). - **`OSC 133 ; B ST`** — command start (between prompt and the user's input). - **`OSC 133 ; C ST`** — output start (after pressing Enter; before the command's stdout/stderr begins). - **`OSC 133 ; D [ ; <exit-code> ] ST`** — command end (after the command exits; optional numeric exit code). The terminal turns these into UX: **jump to previous / next prompt** (kitty `kitten select-prompt`, iTerm2 ⌘↑/⌘↓, WezTerm `ActivateCommandPalette`), **fold a single command's output** (iTerm2, WezTerm), **decorate the prompt gutter** with the exit code (red triangle / green tick — kitty, iTerm2, Ghostty), and **scroll one command at a time** instead of one screen at a time. Most modern shell-integration plugins (`atuin`, `starship`'s wrappers, the bash/zsh hooks shipped with kitty / wezterm / iTerm2) wire these automatically — `__prompt_command` emits A, the `PS1` ends with B, the `DEBUG`/`preexec` hook emits C, and `precmd` emits D with `$?`. Sub-parameters used in practice: `aid=<unique>` (used by Warp / kitty to disambiguate concurrent shells), `cl=m` on `A` (the 'multi-line prompt' hint), `k=i`/`k=r` on `B` (input vs. continuation). The protocol is opt-in — emitting these into a terminal that doesn't recognise them just dropps the bytes; emit them unconditionally.

Spec citation: FinalTerm Semantic Prompts / xterm-ctlseqs (OSC 133)

Parameters

A / B / C / DMark type: A prompt-start, B command-start, C output-start, D command-end. Each carves a structural boundary the terminal can navigate to.
exit-codeOptional integer after `D;` — the just-finished command's `$?`. Used to decorate the prompt gutter with success / failure indicators.

Examples

bash
# zsh/bash shell-integration sketch (real impls handle PS1 specially):\nPS1='\[\e]133;A\a\]\u@\h \W $ \[\e]133;B\a\]'\npreexec() { printf '\033]133;C\007'; }\nprecmd()  { printf '\033]133;D;%d\007' "$?"; }
python
# Manually frame a command exec inside a Python REPL:\nimport sys, subprocess\nsys.stdout.write('\x1b]133;C\x07')                  # output starts\nrc = subprocess.run(['ls']).returncode\nsys.stdout.write(f'\x1b]133;D;{rc}\x07')             # command ends with exit code
go
fmt.Print("\x1b]133;A\x07")          // before prompt\nfmt.Print("$ \x1b]133;B\x07")        // command waiting\n// … run command, capture rc …\nfmt.Printf("\x1b]133;D;%d\x07", rc)
javascript
// Node REPL wrapping a child:\nprocess.stdout.write('\x1b]133;C\x07')\nconst child = spawn('npm', ['test'])\nchild.on('close', code => process.stdout.write(`\x1b]133;D;${code}\x07`))
c
printf("\x1b]133;A\x07");   /* prompt-start */\nprintf("%s$ ", cwd);\nprintf("\x1b]133;B\x07");   /* command-start */\n/* … fork+exec, wait … */\nprintf("\x1b]133;D;%d\x07", WEXITSTATUS(status));

Terminal support

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

Related sequences

In the family cookbook

OSC cookbook · 5. Shell prompt marks — `OSC 133` (FinalTerm A / B / C / D)