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
yes
GNU screen
yes

Related sequences

In the family cookbook

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