DECOM ?6 — Origin mode (clip cursor addressing to scroll region)
Make the cursor's row/column origin (1,1) be the top-left of the DECSTBM region instead of the screen.
Byte forms
Every common string-literal form so you can paste-and-search either direction.
\x1b[?6h (origin = region) \x1b[?6l (origin = screen)\033[?6h / \033[?6l\e[?6h / \e[?6lESC [ ? 6 h / l1b 5b 3f 36 68 / 6cDescription
Origin Mode. With DECSTBM (\x1b[T;Br) you carve out a scrolling region; DECOM controls whether subsequent cursor-position commands (\x1b[r;c H CUP, \x1b[6n DSR-CPR, etc.) address the region as if its top-left were (1,1) (?6h set) or the full screen (?6l reset, default). With ?6h set: \x1b[1;1H moves to the region's top-left, the cursor cannot leave the region, and DSR-CPR reports relative coordinates. Used in full-screen forms-style TUIs that want a fixed status bar at row 1 of the screen while the body — a sub-rectangle from row 2 to row N-1 — behaves as if it were the whole canvas. Note: DECOM is one of the two state bits saved/restored by DECSC (\x1b7) / DECRC (\x1b8).
Spec citation: xterm-ctlseqs (DECOM, Private mode 6)
Examples
printf '\033[2;23r\033[?6h\033[1;1H' # region = rows 2..23; origin mode on; CUP to its top-leftimport sys; sys.stdout.write('\x1b[?6h')fmt.Print("\x1b[?6h")process.stdout.write('\x1b[?6h')printf("\x1b[?6h");Used in
Real-world tools that emit this sequence — anchors the bytes to commands you've already used.
- vim / neovim window splits + `:set scrollbind`Vim splits set per-window DECSTBM scroll regions; with `scrollbind` enabled, the sync logic uses `\x1b[?6h` for the duration of cross-window cursor moves so coordinates are window-local — disable via `:set noscrollbind` and the DECOM emit disappears (`:set verbosefile=/tmp/v.log verbose=15`)
- neovim floating-window scroll regionsFloating windows created with `nvim_open_win()` each get a private DECSTBM region; when content scrolls in a float, neovim emits `\x1b[<top>;<bot>r\x1b[?6h<draw>\x1b[?6l\x1b[r` to scope coords — visible by setting `relativenumber` on a float and tracing with `--log-level=trace`
- tmux pane scroll-region setuptmux uses per-pane DECSTBM regions; for status-line panes (`set -g status-position bottom`) the body region is `\x1b[1;<rows-1>r` and DECOM `\x1b[?6h` lets the inner app treat its top-left as `\x1b[1;1H` — tmux ≥ 3.2 negotiates DECOM through to the pane via `allow-passthrough on`
- ncurses `setscrreg()` + `wsetscrreg()`Curses calls that set per-window scroll regions translate to terminfo `csr` (`\x1b[<top>;<bot>r`); some implementations also flip DECOM via the `om` boolean capability when the application requests window-relative coordinates — `infocmp -1 xterm | grep -E 'csr|om'`
- less status line preservation via `?6h`+CUP composite`less ≥ 600` with `-N` (line numbers) keeps a fixed status row at top; the redraw cycle on `j`/`k` emits `\x1b[<top>;<bot>r\x1b[?6h\x1b[<rel>;1H<content>\x1b[?6l` so per-frame CUP coords stay relative to the body region — observable via `script -c 'less -N file' /tmp/log && strings /tmp/log | grep -E '\?6h|\[r'`
Frequently asked
Short answers to the questions developers actually search for this sequence.
- When should I use DECOM
\x1b[?6h(origin mode)? - Only inside applications that set a DECSTBM scroll region AND want all subsequent cursor-positioning sequences to be relative to the region's top-left instead of the screen's. The classic use case is a fixed status line: set the region to rows 2–24 with
\x1b[2;24r, enable\x1b[?6h, and now\x1b[1;1Hlands at row 2 (top of region) without your code having to know the status-line offset. Most modern TUI authors avoid?6hentirely and just bias coordinates in application code — it's one less stateful mode to track across signal handlers and crash paths. If you do use it, pair set/reset with the region's lifecycle and emit\x1b[?6l\x1b[rtogether when returning to defaults, since DECSTBM reset does NOT clear DECOM. - Why does
\x1b[1;1Hland at row R+1 instead of row 1 after I set a scroll region? - DECOM
?6his active. Origin mode rebases all subsequent CUP / HVP / CHA / VPA coordinates to be relative to the top of the current DECSTBM scroll region — so\x1b[1;1Hafter\x1b[<top>;<bot>r\x1b[?6hlands at row<top>, column 1, NOT row 1, column 1. Two fixes: (a) explicitly disable origin mode with\x1b[?6lbefore the move if you need absolute coords, or (b) compute the absolute target as<top> + relative_row - 1. Note that\x1b[r(reset region to full-screen) does NOT clear?6hon any modern terminal — DECOM persists across DECSTBM reset, and the symptom hides until you set a new region.
Terminal support
- xterm
- yes
- Linux console (fbcon)
- yes
- macOS Terminal.app
- yes
- iTerm2
- yes
- Windows Terminal
- partial
- cmd.exe / ConPTY
- no
- kitty
- yes
- alacritty
- yes
- WezTerm
- yes
- Ghostty
- yes
- GNOME Terminal
- yes
- Konsole
- yes
- tmux
- yes
- GNU screen
- yes
| xterm | Linux console (fbcon) | macOS Terminal.app | iTerm2 | Windows Terminal | cmd.exe / ConPTY | kitty | alacritty | WezTerm | Ghostty | GNOME Terminal | Konsole | tmux | GNU screen |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| yes | yes | yes | yes | partial | no | yes | yes | yes | yes | yes | yes | yes | yes |