CSI scrolling and margins¶
Status: Standard (SU/SD), DEC (margins), xterm (scrollback controls).
Scrolling moves rows within the scrolling region, which defaults to the whole screen. Only text scrolled off the top of the primary screen's region enters scrollback, and only when the region is the full screen in most emulators.
Scroll commands¶
| Name | Sequence | Default | Effect |
|---|---|---|---|
| SU | CSI Ps S |
1 | Scroll region up Ps rows; blank rows enter at the bottom |
| SD | CSI Ps T |
1 | Scroll region down Ps rows; blank rows enter at the top |
| IND | ESC D |
Cursor down; scrolls at the bottom margin | |
| RI | ESC M |
Cursor up; scrolls at the top margin | |
| NEL | ESC E |
Like CR LF | |
| LF, VT, FF | 0x0a, 0x0b, 0x0c |
Cursor down; scroll at the bottom margin; CR too if LNM (CSI 20 h) |
CSI Ps T with five parameters is xterm's mouse highlight-tracking
initiator (XTHIMOUSE), and CSI > Ps T resets title-mode features.
Parsers must dispatch on the parameter count and private marker.
Vertical margins: DECSTBM¶
CSI Pt ; Pb r set top and bottom margins (1-based, inclusive)
CSI r reset to the full screen
Setting margins moves the cursor to the home position (respecting origin
mode). A region of fewer than two rows is rejected. Applications use DECSTBM
to keep a status line fixed while output scrolls above it; DECRQSS with
r reads it back.
Horizontal margins: DECSLRM¶
Status: DEC (VT420), opt-in.
CSI ? 69 h DECLRMM: enable left/right margin mode
CSI Pl ; Pr s DECSLRM: set left and right margins
CSI ? 69 l disable; `CSI s` reverts to SCOSC
Support exists in xterm, WezTerm, Ghostty, foot, Contour, and Windows
Terminal; VTE, Alacritty, and xterm.js do not implement it (xterm.js
documents it as unsupported). Because CSI s changes meaning, applications
must check ?69 support with DECRQM before enabling it.
Scrollback¶
Scrollback is outside every standard. Emulator conventions:
| Control | Meaning | Status |
|---|---|---|
CSI 3 J |
Clear scrollback | xterm |
?1049 |
Alternate screen, which has no scrollback | xterm |
?1007 |
Alternate scroll: wheel sends arrow keys on the alternate screen | xterm |
?1010 |
Scroll to bottom on output | xterm |
?1011 |
Scroll to bottom on key press | xterm |
CSI ? Ps ; … t, Ps = 14 |
Reserved by xterm for scrollback size reports; not implemented | |
CSI Ps + T |
Unscroll: move Ps rows from scrollback back onto the screen, pushing the region down; the inverse of SU into scrollback (kitty 0.20.2+, mintty 3.5.2+); CSI Ps T without the intermediate stays SD |
Extension |
When the scrolling region is smaller than the screen, rows scrolled off its top are discarded, not archived. Terminals differ when the region starts at row 1 but ends above the bottom; xterm archives, several others do not. Applications that want output preserved should leave the region at the full screen.
Reverse wraparound¶
?45 (xterm reverseWrap) lets BS at column 1 move to the end of the
previous row. Off by default; used by shells that redraw long prompts.
Probe¶
printf '\033[5;10r'; seq 1 30; printf '\033[r' # only rows 5-10 scroll
tools/query decrqss r # DECRQSS: expect ^[P1$r5;10r^[\ before the reset
tools/query mode 69 # DECRQM: 1/2 supported, 0 unknown
Sources¶
- ECMA-48 §8.3.147, §8.3.113
- VT510 DECSTBM, DECSLRM
- XTerm Control Sequences
- xterm.js supported sequences
- kitty, Unscrolling the screen
Compatibility¶
Choose terminals
| Feature / stable ID | Alacritty | Apple Terminal | ConPTY (conhost) | Contour | DomTerm | foot | Ghostty | iTerm2 | kitty | Konsole | mintty | mlterm | PuTTY | Revenant | RLogin | st | tmux | rxvt-unicode | VTE | wayst | WezTerm | Windows Terminal | xterm | xterm.js |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
SU/SDcsi-su-sd-scroll |
SupportedImported · unverified | SupportedImported · unverified | Unknown | SupportedImported · unverified | Unknown | SupportedImported · unverified | SupportedImported · unverified | SupportedImported · unverified | SupportedImported · unverified | SupportedImported · unverified | Unknown | Unknown | SupportedImported · unverified | Unknown | Unknown | Unknown | SupportedImported · unverified | Unknown | SupportedImported · unverified | Unknown | SupportedImported · unverified | SupportedImported · unverified | SupportedImported · unverified | SupportedImported · unverified |
DECSTBMcsi-decstbm |
SupportedImported · unverified | SupportedImported · unverified | Unknown | SupportedImported · unverified | Unknown | SupportedImported · unverified | SupportedImported · unverified | SupportedImported · unverified | SupportedImported · unverified | SupportedImported · unverified | Unknown | Unknown | SupportedImported · unverified | Unknown | Unknown | Unknown | SupportedImported · unverified | Unknown | SupportedImported · unverified | Unknown | SupportedImported · unverified | SupportedImported · unverified | SupportedImported · unverified | SupportedImported · unverified |
DECSLRM / ?69csi-decslrm |
Unknown | Unknown | Unknown | SupportedImported · unverified | Unknown | SupportedImported · unverified | SupportedImported · unverified | SupportedImported · unverified | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | SupportedImported · unverified | SupportedImported · unverified | SupportedImported · unverified | UnsupportedImported · unverified |
1007 alternate scrolldec-mode-1007-alternate-scroll |
SupportedImported · unverified | Unknown | Unknown | Unknown | Unknown | SupportedImported · unverified | SupportedImported · unverified | SupportedImported · unverified | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | SupportedImported · unverified | Unknown | SupportedImported · unverified | SupportedImported · unverified | SupportedImported · unverified | SupportedImported · unverified |
?45 reverse wrapdec-mode-45-reverse-wrap |
Unknown | Unknown | Unknown | SupportedImported · unverified | Unknown | Unknown | SupportedImported · unverified | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | SupportedImported · unverified | Unknown | SupportedImported · unverified | SupportedImported · unverified |
SL shift leftcsi-sl |
Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown |
SR shift rightcsi-sr |
Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown |
SU scroll upcsi-su |
Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown |
SD scroll downcsi-sd |
Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown |
Unscroll (CSI + T)csi-plus-t-unscroll |
Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Supported | Unknown | Supported | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown |