# How Windows Terminal Handles Operating System Commands (OSC): VT Parser Deep Dive

> Discover how Windows Terminal uses its VT parser to process Operating System Commands (OSC) from ESC] sequences to BEL or ESC\ terminators for execution.

- Repository: [Microsoft/terminal](https://github.com/microsoft/terminal)
- Tags: deep-dive
- Published: 2026-02-26

---

**Windows Terminal processes Operating System Commands (OSC) through a dedicated VT parser state machine that detects `ESC]` sequences, accumulates numeric parameters and string payloads until a `BEL` or `ESC\` terminator, then dispatches the parsed data to `IAdaptDispatch` methods for execution.**

Operating System Commands (OSC) are escape sequences that allow applications to interact with the terminal environment, from setting window titles to manipulating the clipboard. In the `microsoft/terminal` repository, **OSC handling** is implemented through a sophisticated state machine architecture in [`src/terminal/parser/stateMachine.cpp`](https://github.com/microsoft/terminal/blob/main/src/terminal/parser/stateMachine.cpp) that parses incoming byte streams and converts them into concrete terminal actions via the `OutputStateMachineEngine` and `AdaptDispatch` layers.

## OSC Sequence Structure and Detection

An OSC sequence follows the format `ESC ] <parameter> ; <string> <terminator>`, where the terminator can be either `BEL` (`\x07` or `\a`) or the two-character string terminator `ESC \` (ST). The parser uses specific helper functions to identify these components:

- **`_isOscIndicator`** in [`stateMachine.cpp`](https://github.com/microsoft/terminal/blob/main/stateMachine.cpp) (lines 272-275) recognizes the `]` character that follows an `ESC` to start an OSC sequence.
- **`_isOscDelimiter`** (lines 85-88) identifies the semicolon that separates the numeric parameter from the string payload.
- **`_isOscTerminator`** (lines 10-13) detects the `BEL` character as a primary termination signal.
- **`_isStringTerminatorIndicator`** (defined in [`ascii.hpp`](https://github.com/microsoft/terminal/blob/main/ascii.hpp)) handles the `ESC \` sequence for standards-compliant termination.

When the parser is in the Escape state and encounters `]`, it transitions to the **OscParam** state via `_EnterOscParam` to begin collecting the OSC action number.

## The State Machine Architecture for OSC Parsing

Windows Terminal implements OSC parsing through three distinct states managed by the `StateMachine` class: **OscParam**, **OscString**, and **OscTermination**. Each state handles specific transitions based on incoming characters.

### Parsing the OSC Parameter

In the **OscParam** state, defined in [`stateMachine.cpp`](https://github.com/microsoft/terminal/blob/main/stateMachine.cpp) (lines 49-73), the parser accumulates numeric characters into the `_oscParameter` buffer:

```cpp
void StateMachine::_EventOscParam(const wchar_t wch) {
    if (_isOscTerminator(wch)) { _ActionOscDispatch(); _EnterGround(); }
    else if (_isEscape(wch))   { _EnterOscTermination(); }
    else if (_isNumericParamValue(wch)) { _ActionOscParam(wch); }
    else if (_isOscDelimiter(wch))      { _EnterOscString(); }
    else                               { _ActionIgnore(); }
}

```

Numeric values build the action code (e.g., `0` for window title, `52` for clipboard). When the parser encounters the delimiter `;`, it transitions to **OscString** via `_EnterOscString`. If it encounters `BEL`, it immediately dispatches the action, while `ESC` triggers a transition to **OscTermination** to handle the `ST` sequence.

### Collecting the String Payload

Once in the **OscString** state (lines 87-105), the parser accumulates all subsequent characters into the `_oscString` buffer:

```cpp
void StateMachine::_EventOscString(const wchar_t wch) {
    if (_isOscTerminator(wch)) { _ActionOscDispatch(); _EnterGround(); }
    else if (_isEscape(wch))   { _EnterOscTermination(); }
    else if (_isOscInvalid(wch)) { _ActionIgnore(); }
    else { _ActionOscPut(wch); }   // store the character in _oscString
}

```

The `_ActionOscPut` method appends valid characters to the string buffer until a terminator is encountered. Invalid C0 control characters are ignored to prevent parser corruption.

### Handling String Terminators

The **OscTermination** state (lines 119-129) manages the standards-compliant `ESC \` string terminator:

```cpp
void StateMachine::_EventOscTermination(const wchar_t wch) {
    if (_isStringTerminatorIndicator(wch)) {
        _ActionOscDispatch(); _EnterGround();
    } else {
        _EnterEscape(); _EventEscape(wch);
    }
}

```

If the character following `ESC` is `\`, the sequence is considered complete and `_ActionOscDispatch` is invoked. Otherwise, the parser treats the `ESC` as the start of a new escape sequence and transitions accordingly.

## Dispatching OSC Actions to the Terminal Engine

Once parsing is complete, `_ActionOscDispatch` (lines 696-702) forwards the accumulated parameter and string to the active engine:

```cpp
void StateMachine::_ActionOscDispatch() {
    _trace.TraceOnAction(L"OscDispatch");
    _trace.DispatchSequenceTrace(_SafeExecute([=]() {
        return _engine->ActionOscDispatch(_oscParameter, _oscString);
    }));
}

```

The `OutputStateMachineEngine::ActionOscDispatch` method in [`OutputStateMachineEngine.cpp`](https://github.com/microsoft/terminal/blob/main/OutputStateMachineEngine.cpp) (lines 750-998) implements a comprehensive switch statement that maps OSC codes to specific terminal operations:

```cpp
bool OutputStateMachineEngine::ActionOscDispatch(const size_t parameter,
                                                const std::wstring_view string) {
    switch (parameter) {
        case OscActionCodes::SetWindowTitle:
        case OscActionCodes::SetIconAndWindowTitle:
        case OscActionCodes::DECSWT_SetWindowTitle:
            _dispatch->SetWindowTitle(string); break;

        case OscActionCodes::SetClipboard:
            std::wstring text; bool query;
            if (_GetOscSetClipboard(string, text, query) && !query)
                _dispatch->SetClipboard(text);
            break;

        case OscActionCodes::Hyperlink:
            // parse "params;URI" and call _dispatch->AddHyperlink() or EndHyperlink()
            break;
            
        // Additional cases for SetColor, ConEmuAction, ITerm2Action, VsCodeAction, etc.
    }
    return true;
}

```

## Concrete OSC Implementations in Windows Terminal

The actual side effects are implemented in [`src/terminal/adapter/adaptDispatch.cpp`](https://github.com/microsoft/terminal/blob/main/src/terminal/adapter/adaptDispatch.cpp). When `SetWindowTitle` is invoked (lines 82-89), it updates the terminal UI:

```cpp
void AdaptDispatch::SetWindowTitle(std::wstring_view title) {
    _api.SetWindowTitle(title);   // Calls the console API to rename the window.
}

```

Supported **OSC codes** include:

- **OSC 0, 1, 2**: Window title manipulation via `SetWindowTitle`.
- **OSC 4, 10, 11**: Color palette queries and modifications using `SetColorTableEntry` and `SetXtermColorResource`.
- **OSC 8**: Hyperlink creation through `AddHyperlink` and `EndHyperlink`, enabling clickable terminal text.
- **OSC 52**: Clipboard integration allowing applications to copy text to the system clipboard via `SetClipboard`.
- **OSC 1337, 133, etc.**: Extended actions for ConEmu, iTerm2, and VS Code integration protocols.

## Practical Examples: Sending OSC Sequences

### Setting Window Titles with OSC 0

From PowerShell, applications can update the window title using:

```powershell

# ESC ] 0 ; My Awesome Terminal BEL

$osc = "`e]0;My Awesome Terminal`a"
[Console]::Write($osc)

```

The parser extracts `parameter = 0` and `string = "My Awesome Terminal"`, then invokes `AdaptDispatch::SetWindowTitle` to update the title bar.

### Clipboard Manipulation via OSC 52

Applications can copy text to the clipboard by sending base64-encoded data:

```bash

# ESC ] 52 ; c ; <base64-payload> BEL

printf '\e]52;c;$(echo -n "Hello, World!" | base64)\a'

```

Windows Terminal decodes the payload and calls `SetClipboard` to place the content on the system clipboard. Note that clipboard reading via OSC 52 is restricted for security reasons.

### Creating Clickable Hyperlinks with OSC 8

Terminal hyperlinks follow the format `ESC ] 8 ; params ; URI BEL`:

```bash

# Open a clickable link to the repository

printf '\e]8;;https://github.com/microsoft/terminal\aClick Here\e]8;;\a\n'

```

The parser interprets `parameter = 8`, extracts the URI from the string payload, and `AdaptDispatch` creates a clickable region in the terminal buffer that opens the URL when activated.

## Summary

- **OSC Detection**: The `StateMachine` class identifies `ESC]` sequences using `_isOscIndicator` and transitions through dedicated parsing states.
- **Parameter Extraction**: The **OscParam** state accumulates numeric action codes, while **OscString** collects the text payload until a terminator is detected.
- **Dual Termination Support**: Windows Terminal accepts both `BEL` (`\a`) and `ESC\` (ST) as valid sequence terminators.
- **Engine Dispatch**: Parsed data flows through `OutputStateMachineEngine::ActionOscDispatch` to map codes to terminal operations.
- **Concrete Actions**: The `IAdaptDispatch` interface in [`adaptDispatch.cpp`](https://github.com/microsoft/terminal/blob/main/adaptDispatch.cpp) implements side effects including window titles, clipboard access, color tables, and hyperlinks.

## Frequently Asked Questions

### What is the difference between OSC and other VT sequences?

**OSC sequences** start with `ESC]` and are used for high-level terminal-environment interactions like setting titles or clipboard contents, whereas **CSI sequences** (Control Sequence Introducer, `ESC[`) control cursor movement and text formatting, and **DCS sequences** (Device Control String) handle device-specific configurations. The parser uses distinct states for each introducer type.

### How does Windows Terminal handle malformed OSC sequences?

Malformed sequences are handled gracefully through the `_ActionIgnore` mechanism in the state machine. If the parser encounters invalid C0 control characters in the **OscString** state, or if termination occurs without proper payload completion, the sequence is discarded without crashing the parser, allowing subsequent valid sequences to process normally.

### Which OSC codes are supported by Windows Terminal?

Windows Terminal supports standard XTerm codes including **OSC 0-2** (window titles), **OSC 4** (color palette), **OSC 8** (hyperlinks), **OSC 10-11** (foreground/background colors), **OSC 52** (clipboard), and extended protocols like **OSC 133** (shell integration), **OSC 1337** (iTerm2 extensions), and **OSC 9** (ConEmu progress notifications). The full dispatch table is implemented in [`OutputStateMachineEngine.cpp`](https://github.com/microsoft/terminal/blob/main/OutputStateMachineEngine.cpp).

### Can OSC sequences be used to read clipboard contents?

While the OSC 52 specification supports clipboard querying via specific parameter flags, Windows Terminal restricts this capability for security reasons. The `ActionOscDispatch` implementation checks the query flag in `_GetOscSetClipboard` and only allows write operations to the clipboard, preventing malicious applications from exfiltrating sensitive data without user consent.