Skip to main content
ansicode
Terminal

cmd.exe / ConPTY — ANSI escape code support

cmd.exe is the legacy Windows Command Processor shipping in every release since Windows NT 3.1 (1993). It's a shell, not a terminal — when you launch it, Windows hands its stdio to a console host that does the actual rendering: conhost.exe on Windows 10 and earlier, ConPTY (the in-kernel pseudo-console) on Windows 10 1809+ and Windows 11. The historical gap most developers hit is ANSI escape parsing: vintage conhost.exe ignored \x1b[31m and rendered the bytes as literal text. The fix landed in Windows 10 1511 (Nov 2015) behind an opt-in ENABLE_VIRTUAL_TERMINAL_PROCESSING flag passed to SetConsoleMode, became the default for most apps in Windows 10 1709 (Oct 2017), and was rebuilt around ConPTY in 1809 (Oct 2018) so that legacy Win32 console API calls (SetConsoleTextAttribute, WriteConsoleW) are now translated *into* VT bytes on the way out.

In 2026 practice: every supported Windows version parses xterm-ctlseqs by default. The remaining cmd-specific quirks are the BAT-file $E prompt syntax for embedding ESC, the chcp 65001 codepage incantation needed for non-ASCII text, and the ConPTY translation lossiness — Win32-console-only apps don't always survive the round-trip cleanly. cmd.exe itself emits nothing on its own; everything you see colourised in a cmd window came from a child process via VT bytes.

Last updated

Feature support

How this terminal scores against the 15 features tracked in the site-wide support matrix. Click any feature name to see the full row across every terminal.

  • 8 basic colors (30–37 / 40–47)SGR 30–37 foreground, 40–47 background.
    yes
  • Bright (aixterm) colors (90–97 / 100–107)aixterm SGR extension.
    yes
  • 256-color palette (38;5;n / 48;5;n)xterm 256-color extension.
    partial
  • 24-bit truecolor (38;2;r;g;b)16.7M direct RGB. Set $COLORTERM=truecolor.
    partial
  • Italic (SGR 3)Italic text attribute.
    no
  • Styled underlines (4:1–4:5)Curly/dotted/dashed underline styles.
    no
  • Strikethrough (SGR 9)Horizontal line through text.
    no
  • OSC 8 hyperlinksInline clickable URIs.
    no
  • Alt screen (?1049h)Full-screen app buffer.
    partial
  • Mouse tracking (SGR ?1006)Mouse click/drag events.
    partial
  • Bracketed paste (?2004)Pasted text wrapped in ESC[200~/ESC[201~.
    yes
  • Focus events (?1004)ESC[I on focus in, ESC[O on focus out.
    no
  • Sixel graphicsDEC sixel inline raster images.
    no
  • Kitty graphics protocolPNG/RGB inline images, animations.
    no
  • Synchronized output (?2026)Atomic frame updates to avoid tearing.
    no

Sequences that work here

Canonical reference pages for the escape sequences this terminal handles cleanly. Each links to a full page with byte forms, citations, and per-language examples.

Quirks & version notes

Per-terminal caveats you'll want to know before relying on a sequence in production.

ENABLE_VIRTUAL_TERMINAL_PROCESSING — the legacy opt-in flag
Before 1709, console apps had to opt in to VT parsing by calling SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), ENABLE_VIRTUAL_TERMINAL_PROCESSING | ENABLE_PROCESSED_OUTPUT). Python's colorama.just_fix_windows_console() (since v0.4.6) and pwsh.exe's prompt setup do this for you; raw python.exe / node.exe / go run on 1809+ get VT enabled implicitly because ConPTY is in the pipeline. Bare C: #include <windows.h> + SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), 0x0001 | 0x0004). PowerShell: [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 + nothing else needed. If you're shipping a CLI that must work on Win7 / Server 2008 R2, fall back to the colorama-style Win32-API path.
ConPTY translation is lossy — Win32-console quirks survive
Since 1809, every cmd window is fronted by ConPTY: it owns a screen buffer, runs the parser, and emits VT bytes upstream. Legacy programs that still call WriteConsoleOutput or query screen-buffer state through GetConsoleScreenBufferInfo work by ConPTY synthesising responses. Two known lossy cases: (1) WriteConsoleOutput with non-default attributes is approximated to the nearest VT SGR — sub-cell precision is dropped; (2) bracketed-paste mode bytes can leak into apps that didn't request them, because ConPTY can't tell which child process expects which DEC private mode (microsoft/terminal#3866). Workaround: detect ConPTY via IsConsoleHandle + GetConsoleMode returning ENABLE_VIRTUAL_TERMINAL_INPUT and emit only modern VT.
prompt $E[1;31m…$E[0m — embedding ESC in cmd.exe prompts
cmd.exe's prompt builtin expands $E to a literal \x1b byte, so prompt $E[1;31m$P$E[0m$G paints the working-directory prompt red. Set it permanently via setx PROMPT "$E[1;31m$P$E[0m$G". In BAT scripts you can also use for /F %%a in ('echo prompt $E ^| cmd') do set ESC=%%a to capture an ESC byte into a variable. Modern PowerShell users use $PSStyle.Foreground.Red instead; cmd users have no native colour API, only this prompt-substitution trick.
chcp 65001 for UTF-8 — and the EOF gotcha
cmd.exe defaults to the OEM codepage (cp437 in US English locale), so emoji and most non-ASCII text in coloured output render as mojibake. chcp 65001 switches the active codepage to UTF-8; persist it with setx /M PYTHONUTF8 1 (Python) or via Settings → Time & Language → Language & Region → Administrative language settings → Change system locale → Beta: Use Unicode UTF-8 (Windows 10 1903+, machine-wide). The historical EOF gotcha: under cp65001 some C runtime versions read EOF prematurely on getchar() — fixed in MSVC v142+ but still bites mingw-built binaries. SGR escape bytes themselves are codepage-insensitive (they're ASCII), so colour works on any codepage.
Truecolor: yes since 1709, but conhost.exe quantizes to 16
Windows 10 1709+ parses \x1b[38;2;R;G;Bm truecolor SGR. In Windows Terminal you get the actual 24-bit pixel; in legacy conhost.exe (the host you see when you launch cmd directly from C:\Windows\System32\cmd.exe, not via wt.exe) the truecolor value is quantized to the nearest of 16 console-palette colours. Apps that care should query $COLORTERM=truecolor (Windows Terminal sets it; conhost.exe doesn't) or — better — emit 256-indexed colour as the safer baseline. ConPTY on 1809+ passes the truecolor bytes through unchanged; the quantisation happens at the rendering layer above, not in the parser.
$TERM is unset — detect via OS=Windows_NT
cmd.exe doesn't set $TERM — terminfo-based detection (tput colors, infocmp) silently fails. Instead, cross-platform CLIs check process.platform === 'win32' (Node), os.name === 'nt' (Python), runtime.GOOS === "windows" (Go), cfg!(windows) (Rust). For finer-grained "running under Windows Terminal vs raw conhost" detection, look at $WT_SESSION (set by Windows Terminal only) or $TERM_PROGRAM=Windows_Terminal. Bare cmd / conhost has neither, just OS=Windows_NT. Inside WSL the picture flips: there $TERM is set normally by the Linux shell and the Windows host is invisible.

Citations

Other terminals with landing pages