CSI escape codes — cursor, erase, scroll, position
Control Sequence Introducer. The `ESC [` family minus its SGR sub-set — cursor movement (up / down / forward / back / column / absolute position), erase (line / display), scroll, save / restore, and the handful of CSI sequences for window and cursor reporting.
60 sequences
CSI cookbook — six purposes the family covers
CSI (Control Sequence Introducer) is the largest active corner of the escape-code dialect — over 60 finals doing everything except palette and chrome (those are SGR and OSC). Six stops, top to bottom: the envelope syntax itself, cursor movement, screen / line erase, the round-trip queries terminals answer on stdin, scroll-region and margin setup that TUIs use to carve out fixed regions, and local insert / delete / cursor-shape ops that avoid the cost of a full repaint.
1. The envelope —
\x1b[…<final-byte>Every CSI sequence is
\x1b[(ESC[), an optional **private-marker** (?for DEC private modes,</=/>for xterm-defined variants), zero or more numeric parameters separated by;, and a **final byte** in the\x40–\x7Erange that picks the action. Unlike OSC there's no terminator — the final byte ends the sequence. SGR usesm(\x1b[31m), ED usesJ, EL usesK, CUP (cursor position) usesH, DSR usesn, DA usesc— over 60 finals in active use across ECMA-48 + xterm. Parameters default to 1 or 0 depending on the action; omitted is equivalent to the default, so\x1b[A(move up 1) is identical to\x1b[1A. There's also an 8-bit CSI form\x9b …you'll see in old VT manuals but never in the wild.2. Cursor movement — CUU / CUD / CUF / CUB + CUP + CHA / VPA
The eight cursor primitives every TUI lives on. **CUU / CUD / CUF / CUB** (
\x1b[NA/B/C/D) move the cursor up / down / forward / backward byNcells (default 1) without crossing the screen edge. **CUP** (\x1b[r;cH, aliasf) jumps to absolute rowr, columnc(1-indexed). **CHA** (\x1b[NG) and **VPA** (\x1b[Nd) jump to absolute column / row keeping the other axis. **CNL / CPL** (\x1b[NE/F) move N lines down / up but also reset column to 1 — useful for paragraph-style cursor flow. **SCOSC / SCORC** (\x1b[s/\x1b[u) save / restore one cursor slot — older than DECSC\x1b7/ DECRC\x1b8but identical in effect on every modern emulator.See alsoCUU / CUD / CUF / CUB — Move cursorCUP — Set cursor positionCHA — Cursor horizontal absolute (column)VPA — Vertical line position absolute (CSI d)HVP — Horizontal and vertical position (CSI f, alias of CUP)SCOSC / SCORC — Save / Restore cursor (CSI s / u)CNL / CPL — Cursor next / previous line3. Erase — ED
Jand ELKTwo finals do all the erasing: **
J** for screen, **K** for line. Each takes a parameter selecting the range:0(default) from cursor to end,1from start to cursor,2the whole screen / line, and3forJalso wipes scrollback (xterm extension, supported by most modern emulators). The canonical "clear screen and home" combo every TUI emits on launch is\x1b[2J\x1b[H— erase whole screen, then move cursor to row 1 column 1. **ECH**\x1b[NX(covered in section 6) is the in-place alternative that overwrites N cells with blanks without moving anything else. For partial repaints,\x1b[K(erase to end of line) after a CUP jump is the cheapest way to wipe a row before redrawing it.4. Queries — DA, DA2, DSR, DECRQM
Round-trip queries where the terminal replies back on **stdin** — programs that emit a query must read the response or it leaks into the next user input. **DA**
\x1b[c(Primary Device Attributes) asks "what are you?" — modern emulators reply\x1b[?<id>;<feature>;<feature>cadvertising VT100 / VT200 / VT400 base + supported features (sixel, regis, colour, etc.). **DA2**\x1b[>creturns model + firmware version — useful for distinguishing iTerm2 from kitty from xterm. **DSR**\x1b[6n(cursor position) returns\x1b[r;cR;\x1b[5nreturns terminal-OK status. **DECRQM**\x1b[?<n>$preads whether DEC private modenis currently set / reset / permanent / unsupported (one of0/1/2/3/4in the reply). Use case: feature-detect alt-screen support before emitting\x1b[?1049h.5. Margins & scroll region — DECSTBM
rand DECSLRMs**DECSTBM**
\x1b[<top>;<bottom>rsets the scrolling region to rowstop–bottom(1-indexed, inclusive). Inside this region scroll-up / scroll-down (\x1b[NS/\x1b[NT) and IL / DL only affect those rows; the rest of the screen stays put. The classic use is a stationary status bar at the bottom — set\x1b[1;<screenrows-1>rand the status row never scrolls away. To reset to full-screen scrolling, emit\x1b[rwith no arguments. **DECSLRM**\x1b[<left>;<right>ssets horizontal margins the same way, but only takes effect when DECLRMM (\x1b[?69h) is enabled first — most TUIs skip horizontal margins entirely. Without DECLRMM,\x1b[sis interpreted as SCOSC (save cursor) — a classic mode-confusion trap when porting code between terminals.6. Insert / delete / cursor shape — IL / DL / ICH / DCH / ECH + DECSCUSR
Local edits that don't need a full repaint. **IL**
\x1b[NLinserts N blank lines at the cursor, pushing existing content down (off the scroll region). **DL**\x1b[NMdeletes N lines, pulling content up. **ICH**\x1b[N@and **DCH**\x1b[NPdo the same on the column axis within a single line. **ECH**\x1b[NXerases N cells in place — overwrites with blanks without shifting anything else, the right primitive for clearing a known-width field. **DECSCUSR**\x1b[N qpicks cursor shape:1blinking block (default),2steady block,3blinking underline,4steady underline,5blinking bar,6steady bar — vim'sterminal-modetoggles between2and6to show insert vs normal. Honoured by xterm, kitty, iTerm2, wezterm, alacritty, ghostty, Windows Terminal, gnome-terminal 3.16+, konsole; Linux console ignores.
All sequences in this family
- CUU / CUD / CUF / CUB — Move cursor
\x1b[NA (up; B down, C right, D left)Move the cursor up / down / right / left by N cells.
- CNL / CPL — Cursor next / previous line
\x1b[NE (down N lines, col 1) \x1b[NF (up)Move the cursor to column 1 of the line N below (CNL) or above (CPL).
- CHA — Cursor horizontal absolute (column)
\x1b[NGMove the cursor to column N of the current row (1-indexed).
- CUP — Set cursor position
\x1b[row;colHMove the cursor to absolute row/column (1-indexed).
- ED — Erase in display (\x1b[2J clear screen)
\x1b[NJErase part or all of the screen.
- EL — Erase in line (\x1b[K)
\x1b[NKErase part or all of the current line.
- SU / SD — Scroll up / down
\x1b[NS (scroll up) \x1b[NT (scroll down)Scroll the screen contents up (SU) or down (SD) by N lines without moving the cursor.
- DECSCUSR — Cursor shape
\x1b[N\x20q (N = 0..6)Change the cursor shape: block, underline, or bar (with optional blink).
- DECSTR — Soft terminal reset
\x1b[!pReset DEC private modes and SGR to defaults WITHOUT clearing the screen or scrollback.
- CBT — Cursor Backward Tabulation (CSI Z)
\x1b[NZMove the cursor back N tab stops — the reverse of pressing Tab.
- TBC — Tab Clear (CSI g)
\x1b[g (clear current) \x1b[3g (clear all)Clear one or all tab stops, changing where HT and CBT land.
- DECSTBM — Set Top/Bottom Margins (CSI r)
\x1b[T;BrDefine the vertical scrolling region — rows outside it stay pinned, rows inside scroll.
- SCOSC / SCORC — Save / Restore cursor (CSI s / u)
\x1b[s (save) \x1b[u (restore)CSI-style save (s) and restore (u) of cursor position — distinct from ESC 7 / ESC 8 (DECSC / DECRC).
- CHT — Cursor Forward Tabulation (CSI I)
\x1b[NIAdvance the cursor N tab stops — the parameterized form of pressing Tab.
- DA — Device Attributes (CSI c / CSI > c)
\x1b[c (primary DA) \x1b[>c (secondary DA)Ask the terminal what kind of VT it is — primary (CSI c) returns features, secondary (CSI > c) returns model + firmware.
- DSR — Device Status Report (CSI 5n / CSI 6n)
\x1b[5n (status request) \x1b[6n (cursor pos request)Ask for terminal status (5n) or the current cursor position (6n) — the reverse channel TUIs use to size the terminal.
- DECRQM — Request Mode Status (CSI ? Ps $ p)
\x1b[?Ps$pAsk the terminal whether a specific DEC private mode is enabled — used for feature detection at runtime.
- ICH — Insert Character (CSI Pn @)
\x1b[Pn@Shift the rest of the current line right by N cells and blank-fill the gap — the primitive vim's insert mode is built on.
- DCH — Delete Character (CSI Pn P)
\x1b[PnPDelete N cells at the cursor and shift the rest of the line left to fill the gap — the inverse of ICH.
- IL — Insert Line (CSI Pn L)
\x1b[PnLOpen N blank lines at the cursor row and push subsequent lines down within the scrolling region — vim's 'O' command primitive.
- DL — Delete Line (CSI Pn M)
\x1b[PnMRemove N lines starting at the cursor row and pull subsequent lines up within the scrolling region — vim's 'dd' command primitive.
- ECH — Erase Character (CSI Pn X)
\x1b[PnXErase N cells in place at the cursor — same shape as DCH but the rest of the line does NOT shift left.
- REP — Repeat Preceding Character (CSI Pn b)
\x1b[PnbRepeat the most-recently-emitted printing character N times — a bandwidth-saver for runs of identical glyphs.
- VPA — Vertical line position absolute (CSI d)
\x1b[<row>dMove the cursor to an absolute row, keeping the current column.
- HVP — Horizontal and vertical position (CSI f, alias of CUP)
\x1b[<row>;<col>fMove the cursor to absolute (row, col) — semantically identical to CUP but uses final byte `f` instead of `H`.
- XTWINOPS — Window manipulation (CSI Ps ; Ps ; Ps t)
\x1b[<Ps>t or \x1b[<Ps>;<Pa>;<Pb>txterm's window-manipulation family — resize, minimise, raise/lower, query size, push/pop title.
- DECSED / DECSEL — Selective erase display / line (CSI ? Ps J / CSI ? Ps K)
\x1b[?<Ps>J (DECSED) \x1b[?<Ps>K (DECSEL)Erase only the unprotected cells in the display (DECSED) or current line (DECSEL) — the private-mode siblings of ED / EL.
- SL / SR — Scroll left / right (CSI Ps SP @ / CSI Ps SP A)
\x1b[<Ps> @ (SL) \x1b[<Ps> A (SR)Scroll the screen content left (SL) or right (SR) by Ps columns — the horizontal counterpart of CSI S / CSI T.
- DECSCA — Select character protection attribute (CSI Ps " q)
\x1b[<Ps>"qMark subsequently-written cells as DECSED/DECSEL-protected (Ps=1) or unprotected (Ps=0/2).
- DECSLRM — Set left and right margins (CSI Pl ; Pr s)
\x1b[<Pl>;<Pr>sConstrain horizontal cursor movement + scrolling to columns Pl…Pr — the horizontal counterpart of DECSTBM.
- XTPUSHCOLORS / XTPOPCOLORS / XTREPORTCOLORS — Palette stack (CSI # P / # Q / # R)
\x1b[#P (push) \x1b[#Q (pop) \x1b[#R (report)Save / restore / inspect xterm's ANSI palette via a process-local stack — useful for TUIs that mutate the palette temporarily.
- DECDC / DECIC — Delete / insert column (CSI Pn ' ~ / CSI Pn ' })
\x1b[<Pn>'~ (DECDC) \x1b[<Pn>'} (DECIC)Delete (DECDC) or insert (DECIC) Pn columns at the cursor — the column-oriented counterparts of DL (CSI Pn M) and IL (CSI Pn L).
- XTMODKEYS — Modify keyboard reporting (CSI > Pp ; Pv m)
\x1b[><Pp>;<Pv>mSwitch xterm's modifyKeyboard / modifyCursorKeys / modifyFunctionKeys / modifyOtherKeys resources at runtime — the foundation for Ctrl+letter, Alt+letter disambiguation.
- XTSMTITLE / XTRMTITLE — Set / reset title display modes (CSI > Ps ; … t / T)
\x1b[><Ps>;<Ps>…t (set) \x1b[><Ps>;<Ps>…T (reset)Switch how xterm interprets / returns window-title and icon-name strings — hex vs UTF-8 encoding, truncation, set-vs-query behaviour.
- DECSWBV / DECSMBV — Set warning / margin bell volume (CSI Ps SP t / CSI Ps SP u)
\x1b[<Ps> t (DECSWBV) \x1b[<Ps> u (DECSMBV)Adjust the audio volume of the C0 BEL (DECSWBV) and the right-margin warning bell (DECSMBV) — almost universally ignored by modern emulators.
- SGR / urxvt mouse encoding — Mouse-report wire formats (CSI M / CSI < / CSI)
\x1b[M<Cb><Cx><Cy> (legacy) \x1b[<<Cb>;<Cx>;<Cy>M|m (SGR ?1006) \x1b[<Cb>;<Cx>;<Cy>M (urxvt ?1015)The three on-wire formats a terminal uses to report mouse events: legacy CSI M Cb Cx Cy, modern SGR ?1006, and urxvt ?1015 — what's actually in the input stream after DECSET ?100x enables tracking.
- XTVERSION — Report terminal name and version (CSI > Pp q)
\x1b[>0q (query) reply: \x1bP>|<name> <version>\x1b\\Ask the terminal for a human-readable name + version string — the modern alternative to DECDA for feature detection in tools like Helix, Zellij, Neovim.
- CSI ? Ps n — Private DSR (extended status queries)
\x1b[?<Ps>nDEC private Device Status Reports — extended cursor position (?6 DECXCPR with page), printer / UDK / locator / macro-space / memory-checksum status.
- HPA / HPR / VPR — Position absolute & relative (CSI ` / CSI a / CSI e)
\x1b[<col>` (HPA) \x1b[<n>a (HPR) \x1b[<n>e (VPR)ECMA-48's row/col-preserving cursor moves — HPA (absolute column), HPR (relative column), VPR (relative row) — completing the trio anchored by VPA.
- XTSMGRAPHICS — Sixel / ReGIS / color-register capacity query + set (CSI ? Pi ; Pa ; Pv S)
\x1b[?<Pi>;<Pa>;<Pv>SRead / set the terminal's graphics limits — number of sixel color registers, sixel graphics area, ReGIS area. The standard knob for image-aware TUIs to size their bitmaps.
- DECSASD / DECSSDT — Status display routing & type (CSI Ps $ } / CSI Ps $ ~)
\x1b[<Ps>$} (DECSASD) \x1b[<Ps>$~ (DECSSDT)Pick which display surface (main vs status line) receives subsequent output (DECSASD), and what the status line is for (DECSSDT) — DEC VT320's split-screen status row.
- XTQMODKEYS — Query modifyKeys current value (CSI ? Pp m)
\x1b[?<Pp>mAsk xterm what the current modifyKeyboard / modifyCursorKeys / modifyFunctionKeys / modifyOtherKeys value is — the companion query for XTMODKEYS.
- XTPUSHSGR / XTPOPSGR / XTREPORTSGR — SGR stack (CSI Ps + p / + q / + r)
\x1b[#{ (XTPUSHSGR, alt: CSI Pm + p) \x1b[#} (XTPOPSGR, alt: CSI + q) \x1b[+r (XTREPORTSGR)Save / restore / inspect the current SGR attributes via a stack — the SGR analogue of XTPUSHCOLORS for the palette.
- DECSCPP — Select columns per page (CSI Pn $ |)
\x1b[80$| (80 cols) \x1b[132$| (132 cols)Resize the active page to 80 or 132 columns — the data-side request that DECCOLM expresses as a private mode toggle.
- Secondary DA reply decoder — `CSI > Pp ; Pv ; Pc c` model / firmware / cart
\x1b[>Pp;Pv;PccDecoder reference for the secondary Device Attributes reply — what each Pp model code means and how kitty / wezterm / alacritty / iTerm2 / Ghostty encode their version in Pv.
- XTSAVE / XTRESTORE — Save / restore DEC private mode (`CSI ? Pm s` / `CSI ? Pm r`)
\x1b[?<Pm>s (save) \x1b[?<Pm>r (restore)Stash one or more DEC private mode states on a stack, then restore them later — the foundation tmux / screen / fzf use to safely toggle mouse / alt-screen / paste modes without trampling user prefs.
- DECSCL — Select conformance level (`CSI Pl ; Pc " p`)
\x1b[<Pl>;<Pc>" pChoose VT100 / VT200 / VT300 / VT400 / VT500 conformance level — controls which subset of escape sequences the terminal honours, plus 7-bit vs 8-bit C1 emission. Implicitly performs a hard reset (RIS) first.
- DECSTR side-effects — exactly which modes `\x1b[!p` resets
\x1b[!pReference enumeration of every DEC mode / attribute that DECSTR (soft reset) restores to its default — what gets cleared, what survives, and where xterm vs kitty vs iTerm2 diverge.
- DECRPM decoder — parsing the DECRQM reply (`CSI ? Ps ; Pm $ y`)
\x1b[?<Ps>;<Pm>$y (private) \x1b[<Ps>;<Pm>$y (ANSI)How to read the `CSI ? Ps ; Pm $ y` (and `CSI Ps ; Pm $ y`) reply that DECRQM returns — the `Pm` value tells you whether the mode is set / reset / always-set / always-reset / unrecognised.
- DEC locator suite — DECELR / DECEFR / DECSLE / DECRQLP (mouse / locator events)
\x1b[<Pn>;<Pu>'z \x1b[<Pm>'{ \x1b[<Pt>;<Pl>;<Pb>;<Pr>'w \x1b[<Ps>'|The original DEC pointing-device protocol (predates xterm SGR mouse modes by a decade). Four sequences enable, filter, select, and query locator events; modern interactive UIs use SGR mouse modes (`?1000` + `?1006`) instead.
- DECREQTPARM / DECREPTPARM — Request and report terminal parameters (`CSI Ps x`)
\x1b[<Ps>xVT100-era legacy probe — ask the terminal for its serial-line parameters (parity, bit-count, baud, clock multiplier, flags). Predates DA / DA2 / XTVERSION; almost never the right tool now, but xterm and most modern emulators still answer with synthetic defaults.
- DECCARA / DECRARA — Change / Reverse attributes in rectangular area (`CSI Pt;Pl;Pb;Pr;Ps;… $ r` / `$ t`)
\x1b[<Pt>;<Pl>;<Pb>;<Pr>;<Ps>;…$r (DECCARA) \x1b[<Pt>;<Pl>;<Pb>;<Pr>;<Ps>;…$t (DECRARA)Set or XOR SGR attributes across a rectangle of cells without rewriting any character data — the rectangular-attribute siblings of the copy/fill/erase ops in `dec-rect-ops`.
- DECPS — Play Sound (`CSI Pv ; Pd ; Pn1 [; …] , ~`)
\x1b[<Pv>;<Pd>;<Pn1>[;<Pn2>…],~DEC VT520 musical-tone playback — `Pv` volume, `Pd` duration, then one or more `Pn` MIDI-style note numbers. Niche but implemented by xterm, WezTerm, Ghostty, mlterm; the only ANSI way to make the terminal beep at a specific pitch.
- DECTABSR — Tab Stop Report (`CSI 2 $ w`)
\x1b[2$wAsk the terminal to dump its current horizontal tab stops as a DCS report. Closes the round-trip story: set via HTS (`esc-hts`), clear via TBC (`csi-tbc`), query the current set via DECTABSR.
- DECRQCRA / DECCKSR — Request Checksum of Rectangular Area (`CSI Pi;Pg;Pt;Pl;Pb;Pr*y`)
\x1b[Pi;Pg;Pt;Pl;Pb;Pr*y reply \x1bP<Pi>!~<hex4>\x1b\\Ask the terminal to compute a 16-bit checksum over a rectangle of cells (`CSI Pi;Pg;Pt;Pl;Pb;Pr*y`); reply arrives as DCS DECCKSR (`\x1bP<Pi>!~<hex4>\x1b\\`). The xterm vttest / ConPTY conformance pin.
- DECLL — Load LEDs (`CSI Ps q`, no SP intermediate)
\x1b[Ps qTurn the keyboard's front-panel L1–L4 LEDs on / off (`CSI Ps q`). Surviving in Linux-console terminfo as `KEYBOARD_LED 1/2/3/4` — modern emulators silent no-op except xterm + Linux console.
- DECCRA / DECFRA / DECERA / DECSERA — Copy / Fill / Erase / Selective-erase rectangular area
\x1b[<Pts>;<Pls>;<Pbs>;<Prs>;<Pps>;<Ptd>;<Pld>;<Ppd>$v DECCRA\n\x1b[<Pch>;<Pt>;<Pl>;<Pb>;<Pr>$x DECFRA\n\x1b[<Pt>;<Pl>;<Pb>;<Pr>$z DECERA\n\x1b[<Pt>;<Pl>;<Pb>;<Pr>${ DECSERAThe four content-side rectangle ops missing from the DEC rect family — copy a block, fill it with a glyph, erase to space, or erase only non-protected cells. Pairs with DECCARA / DECRARA (attribute-side) and DECSACE (block-vs-stream toggle).
- DECSACE — Select Attribute Change Extent (`CSI Ps * x`)
\x1b[<Ps>*xToggle whether DECCARA / DECRARA treat their rectangle as a literal cell block (default) or as a stream from start-position to end-position. The content-side rect ops (DECCRA / DECFRA / DECERA / DECSERA) are unaffected.
- CSI Ps i — Media Copy (MC) — printer-on / printer-off / print line
\x1b[0i / \x1b[4i / \x1b[5i / \x1b[?4i / \x1b[?5iECMA-48 §8.3.82 control that historically routed terminal output to an attached printer. Survives today as the 'print screen' hook on xterm/mlterm, the IBM-3270 emulator pass-through, and as private-mode `CSI ? 4 / 5 i` auto-print toggles consumed by `expect`-style automation.
- DECRQDE / DECRPDE — Request / Report Displayed Extent (`CSI " v` / `" w`)
\x1b["v DECRQDE (request)\n\x1b[<Ph>;<Pw>;<Pml>;<Pmt>;<Pmp>"w DECRPDE (reply)VT420+ pagination query — ask the terminal how many rows / columns are currently displayed and where the scroll window sits inside the page memory. Reply tells the host the visible viewport without relying on `tput lines / cols`.