CNL / CPL — Cursor next / previous line
Move the cursor to column 1 of the line N below (CNL) or above (CPL).
Byte forms
Every common string-literal form so you can paste-and-search either direction.
\x1b[NE (down N lines, col 1) \x1b[NF (up)\033[E / \033[F\e[E / \e[FESC [ N E / F1b 5b <N> 45 / 46Description
Two ECMA-48 cursor-positioning primitives that fold "move vertically N rows" and "snap column to 1" into a single round-trip. Final byte E = CNL (Cursor Next Line, ECMA-48 §8.3.13) — move N rows down + column 1. Final byte F = CPL (Cursor Previous Line, §8.3.27) — move N rows up + column 1. Both default to N=1 if omitted (\x1b[E = "next line, column 1"). The key contrast with CUU / CUD (\x1b[NA / \x1b[NB, see cursor-move) is column behaviour: CUU and CUD preserve the current column; CNL and CPL force column 1 as part of the same move, so a redraw loop becomes \x1b[1F\x1b[K<text> (back to start of previous line + erase + write) instead of the three-token \x1b[1A\r\x1b[K<text>.
Portability — every VT100-conformant emulator supports CNL / CPL: xterm, iTerm2, kitty, alacritty, wezterm, gnome-terminal, Konsole, Ghostty, Windows Terminal, ConPTY 1809+, Linux console. Both predate VT220 — they go back to the VT100 spec — so even minimal emulators have them. Out-of-range values clamp at the visible region boundary: CNL past the bottom row stops there without auto-scrolling (unlike a literal LF + CR at the bottom row which *would* scroll the screen up by one), CPL past the top stops at row 1. DECSTBM scrolling regions are respected: CNL will not move past the region's bottom margin and CPL will not move above its top margin, which is the property that makes them safer than \r\n in a redrawing TUI inside a scroll region. terminfo capability names are cnl / cpl but most terminal entries leave them empty — programs that want the behaviour emit the bytes directly rather than going through the terminfo layer.
No "close" — these are stateless cursor moves, not toggles. The non-scrolling behaviour at the region edge is what makes them load-bearing in TUIs: a multi-line progress indicator that needs to redraw line N back to line 1 can issue \x1b[<N>F\x1b[J (up N lines + erase to end of screen) without any risk of triggering a scroll, even if the user resized the terminal between draws. When the absolute row matters (not just a relative jump), cursor-position (CUP, \x1b[r;cH) is more robust because it doesn't depend on knowing the current row. The compound \x1b[1E\x1b[K (next line + erase to end of line) is the spec-correct alternative to \r\n\x1b[K when the writer is inside a scroll region or a raw-mode TTY where \r semantics might surprise. Related: cursor-move (CUU / CUD / CUF / CUB — moves that preserve the orthogonal axis), cursor-position (CUP — absolute row+column), cursor-column (CHA — column-only counterpart with the same "no line feed" property).
Spec citation: ECMA-48 §8.3.13 (CNL) / §8.3.27 (CPL)
Examples
printf 'top\n\033[2Ebottom-of-3rd-line-below\n'import sys; sys.stdout.write('\x1b[3E')fmt.Print("\x1b[3E")process.stdout.write('\x1b[3E')printf("\x1b[3E");Used in
Real-world tools that emit this sequence — anchors the bytes to commands you've already used.
- vim / neovim `j` / `k` movement in operator-pending pre-stepVim's operator-pending mode (`d`, `y`, `c` then motion) for line-wise operators like `dj` / `yk` emits `\x1b[<n>E` (CNL) or `\x1b[<n>F` (CPL) to position the cursor before applying — `:set verbose=15` then `dj` shows the CNL/CPL in the verbose log distinct from CUD `\x1b[<n>B` used for `<n>j`
- less line-scroll via `j` / `↓``less` redraws on per-line scroll by emitting CNL `\x1b[E` for the cursor advance + ED `\x1b[J` for partial-screen clear, instead of a full repaint — `script -c 'less /etc/passwd' /tmp/log && strings /tmp/log | grep '\x1b\[E'` after some `j` keypresses
- tmux copy-mode-vi line movementtmux copy-mode (`prefix [`) with `mode-keys vi` rebinds `j`/`k` to CNL/CPL for cross-pane consistent cursor advancement — `tmux show-options -g mode-keys` shows the binding, trace pane output with `tmux pipe-pane -o 'cat > /tmp/p.log'` then scroll
- ncurses `wgetnstr()` line-wrap behaviourCurses input function `wgetnstr(WINDOW *, char *, int n)` reads a length-bounded string; when the user types past the visible window, the redraw uses CNL `\x1b[1E` to move to next row plus `wclrtoeol()` (which is EL `\x1b[K`) — `infocmp xterm | grep -E 'nel|cnl'` confirms the `nel` cap maps to CNL
- GNU readline `next-history` / `previous-history`Bound to `↓` / `↑` by default; recalling history with multi-line entries uses CNL / CPL to advance to the next visual row of the recalled command — `bind -p | grep -E 'next-history|previous-history'` shows the binding, trace via `READLINE_DEBUG=trace`
Frequently asked
Short answers to the questions developers actually search for this sequence.
- What's the difference between
\x1b[Fand\r\x1b[A— both go up one line to column 1? - Two differences that matter inside TUIs. (1) Round-trip cost: CPL is one CSI sequence,
\r\x1b[Ais two (a C0 control + a CSI). On a slow serial line or under tmux's input throttling, the extra byte and the intermediate state-machine entry sometimes show up as a visible flicker. (2) Scroll-region behaviour: both forms respect DECSTBM and clamp at the region's top margin, so they're equivalent there. The real win for CPL is composability —\x1b[5Fjumps 5 rows up + column 1 in one move, whereas the\r\x1b[5Aform still needs the explicit\r. For a single-row jump either is fine; for multi-row redraw loops prefer CNL / CPL. - Will
\x1b[Eat the bottom row scroll the screen the way\ndoes? - No — CNL clamps at the bottom of the current scrolling region (full screen if DECSTBM hasn't restricted it) without auto-scrolling. A bare
\nat the same position emits LF, which the terminal handles as "down one line, scroll if needed" — that's how a shell appends a new prompt line at the bottom of the screen. CNL's no-scroll behaviour is exactly why TUIs that redraw a multi-line panel use\x1b[<N>F\x1b[J(up N + erase to end of screen) instead of\r\nrepeated — you stay parked at the panel origin even if the user resized the terminal between draws.
Terminal support
- xterm
- yes
- Linux console (fbcon)
- yes
- macOS Terminal.app
- yes
- iTerm2
- yes
- Windows Terminal
- yes
- cmd.exe / ConPTY
- yes
- 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 | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes |
Related sequences
In the family cookbook
CSI cookbook · 2. Cursor movement — CUU / CUD / CUF / CUB + CUP + CHA / VPA