Semantic Prompt Marks (OSC 133)

Mark the boundaries between prompt, input, and output so the terminal can navigate, select, and time commands.

  1. 0x1B
    ESC
  2. 0x5D
    ]
  3. 0x31 0x33 0x33
    133
  4. 0x3B
    ;
  5. ____
    c
  6. 0x3B
    ;
  7. ____
    ...
  8. 0x1B
    ESC
  9. 0x5C
    \

OSC 133 is the semantic prompt protocol. Shell integration scripts emit these marks around prompts, user input, and command output so the terminal emulator knows the structure of the shell session. With those marks in hand the terminal can offer features like jump to previous prompt, select the previous command's output, and per-command runtime tracking.

The protocol was pioneered as Per Bothner's semantic prompts proposal and is widely supported (iTerm2, Wezterm, Kitty, and now Wintty). Each command starts with a single-letter c selector that names the boundary, followed by an optional payload of key=value options.

Commands

cWintty action nameMeaning
Afresh_line_new_promptStart a fresh line, begin a new prompt.
Bend_prompt_start_inputEnd of prompt, start of user input. Terminates at C/P.
Cend_input_start_outputEnd of input, start of command output.
Dend_commandEnd of the running command (optionally with exit status).
Iend_prompt_start_input_terminate_eolLike B, but input is terminated by end-of-line.
Lfresh_lineInsert a fresh line if not already at column 1.
Nnew_commandSame as A. Wintty never implicitly closes a command.
Pprompt_startExplicit prompt start. Optional after A or N.

The terminal uses these marks to attach a semantic content tag (prompt, input, output) to every cell as text is written, which is what enables features like "select the previous command's output".

Options

Most commands accept a trailing semicolon-separated list of options:

OptionTypeUsed byMeaning
aidstringA, B, C, D, I, N, PApplication identifier; pairs related marks.
clenumA, NCursor-movement class for click-to-move: line, m, v, w.
kcharA, N, PPrompt kind: i initial, r right-side, c continuation, s secondary.
errstringDHuman-readable error message.
redrawenumA, NKitty extension: 0 no redraw, 1 full redraw, last (Ghostty/Wintty extension) only last line.
special_keyboolA, NParsed but unused: shell binds a special key for click-to-move-cursor.
click_eventsenumA, N1 absolute click coordinates, 2 coordinates relative to the prompt area. 0 is rejected.
cmdlinestringCThe command line, $'...'-decoded. Parser-level only.
cmdline_urlstringCThe command line, URL-percent-decoded. Parser-level only.

The D (end command) command additionally takes a bare positional integer before any key=value options to report the exit status, for example OSC 133;D;1;aid=abc ST.

Examples

Mark a prompt, the user's input, command output, and the result:

# Right before printing PS1:
printf '\033]133;A\033\\'
# After PS1, just before reading input:
printf '\033]133;B\033\\'
# After the user pressed enter, before the command runs:
printf '\033]133;C\033\\'
# After the command finishes, with exit code 0:
printf '\033]133;D;0\033\\'

Annotate the prompt as a continuation prompt:

printf '\033]133;P;k=c\033\\'

Behavior in Wintty

Wintty implements OSC 133 against the spec with the following notes:

  • The cl option is parsed for all four values (line, m, v, w) and is stored on the screen's semantic prompt state. The shell can also request SGR mouse events with click_events, which takes priority over cl for click-to-move-cursor support. click_events is not a boolean: 1 asks for absolute click coordinates and 2 asks for coordinates relative to the prompt area. click_events=0 is not a valid value and is discarded, leaving cl in charge.
  • The special_key option is parsed and validated but nothing reads it, so binding a special key for click-to-move-cursor has no effect today.
  • The redraw option recognizes 0, 1, and the Wintty/Ghostty extension last (Bash-only behavior: redraw only the last line of the prompt on resize).
  • The cmdline and cmdline_url decoders exist and are correct: the first decodes as if it were a Bash $'...'-quoted string, the second is URL-percent-decoded. Nothing in the terminal calls them, though, so this is true of the parser rather than of a running session. Shipping a command line on C is harmless but is not recorded anywhere.
  • The N command is handled exactly like A. The spec allows N to first terminate an open command with a matching aid, but Wintty does no explicit command tracking, so there is nothing to terminate and nothing is closed.
  • The aid option is parsed and then goes nowhere. The semantic prompt command is not encodable for the C API (its C type is void), so no embedding application can read aid, and Wintty itself does not use it for command tracking.

Tip

Shells usually do not emit OSC 133 out of the box. Wintty ships shell integration scripts that inject the marks at the right points for Bash, Zsh, Fish, PowerShell, cmd, and Elvish. Nushell is the exception: its script only wraps ssh and sudo and emits no OSC 133 at all, so prompt marks, jump-to-prompt, and per-command timing do not work under Nushell. For every other shell, make sure shell integration is enabled.

See also