Skip to main content
ansicode

DECSET ?12 — Cursor blink

Enable or disable the blinking attribute of the cursor — independent of cursor shape.

Byte forms

Every common string-literal form so you can paste-and-search either direction.

\\x1b[\x1b[?12h (start blinking) \x1b[?12l (stop blinking)
\\033[\033[?12h / \033[?12l
\\e[\e[?12h / \e[?12l
ESC [ESC [ ? 1 2 h / l
hex1b 5b 3f 31 32 68 / 6c

Description

Toggle the cursor-blink attribute. Distinct from DECSCUSR (\x1b[N SP q), which combines shape AND blink in one parameter: with ?12 you can keep the user's preferred shape (block / bar / underline) and just override whether it blinks. Used by editors that want a steady cursor in normal mode and a blinking one in insert mode WITHOUT touching the user's chosen shape. Reset to terminal default by combining with DECSCUSR \x1b[0 q or DECSTR (\x1b[!p).

Spec citation: xterm-ctlseqs (Private mode 12)

Examples

bash
printf '\033[?12h'   # start blinking\nprintf '\033[?12l'   # stop blinking
python
import sys; sys.stdout.write('\x1b[?12l')
go
fmt.Print("\x1b[?12l")
javascript
process.stdout.write('\x1b[?12l')
c
printf("\x1b[?12l");

Used in

Real-world tools that emit this sequence — anchors the bytes to commands you've already used.

  • vim / neovim `'guicursor'` per-mode blinkvim's `:set guicursor=n-v-c:block-Cursor/lCursor-blinkwait300-blinkon200-blinkoff150,i-ci:ver25-iCursor` emits `\x1b[?12h` on insert-mode entry and `\x1b[?12l` on insert-mode exit — keeps the user's preferred block / bar / underline shape (set via DECSCUSR) while toggling only the blink. neovim ≥ 0.5 honours the same syntax
  • helix editor `cursor-shape` blink modeshelix's `[editor.cursor-shape]` config (`insert = "bar"`, `normal = "block"`) plus `[editor] cursor-blink = true` emits `\x1b[?12h` on focus-gain and `\x1b[?12l` on focus-loss — distinct from kakoune's all-or-nothing approach. Verified by `script -q -c hx /dev/null` and grep-ing `\x1b\[?12`
  • kitty `cursor_blink_interval` configkitty's `cursor_blink_interval 0.5` in `~/.config/kitty/kitty.conf` is enforced *terminal-side* — but apps that emit `\x1b[?12l` (e.g. midnight commander, htop) can override per-application; kitty respects DECSET ?12 from the running process even when the user config sets a non-zero blink. Setting the interval to `0` disables blinking globally
  • Alacritty `cursor.style.blinking` profileAlacritty's `cursor.style.blinking = "On"` in `alacritty.toml` honours `\x1b[?12h` / `\x1b[?12l` from running apps — apps overriding the user's choice for a brief insert-mode flash, then restoring. `cursor.blink_interval = 750` (default) sets the period when blink is active
  • midnight commander (mc) cursor-blink suppressionGNU `mc` emits `\x1b[?12l` on launch and `\x1b[?12h` on exit to suppress blink while the user is in its TUI panels — visible by `script -c 'mc' /dev/null; grep -a '\x1b\[?12' typescript`. Same pattern in `ranger`, `nnn`, `lf` (each shipping a `cursor.blink = false` config knob that translates to the byte sequence)

Frequently asked

Short answers to the questions developers actually search for this sequence.

How do I turn off cursor blinking — \x1b[?12l or DECSCUSR \x1b[<n> q?
Two distinct mechanisms exist, and which one works depends on the terminal. \x1b[?12l (ATT 610 DEC private mode) is the old xterm-compatible toggle for *just* the blink attribute — supported by xterm, foot, gnome-terminal, konsole; unsupported on macOS Terminal and Windows Terminal (silently ignored). DECSCUSR \x1b[<n> q (with even n for non-blinking, odd for blinking — 0/1=blinking block, 2=steady block, 3=blinking underline, 4=steady underline, 5=blinking bar, 6=steady bar) is the modern path supported almost everywhere (xterm, kitty, alacritty, wezterm, ghostty, foot, Windows Terminal, iTerm2, gnome-terminal, konsole). For broadest compatibility emit DECSCUSR with the desired even value (e.g. \x1b[2 q for steady block); for old terminals that only honour ?12, also send \x1b[?12l. They don't conflict.
Why does setting cursor-blink in my TUI leak across into the user's shell?
Both ?12 and DECSCUSR persist across process exit by design — the terminal has no concept of "reset on PID death". You must explicitly restore the prior state in an atexit / defer / trap EXIT handler. The portable restore is \x1b[0 q (DECSCUSR parameter 0 = terminal default — block + whichever blink the user configured), which works on every terminal supporting DECSCUSR. For paranoid round-trip safety, query DECRQSS at startup with \x1bP$q q\x1b\\ to capture the exact n value, save it, and emit \x1b[<saved> q on exit. Common bug: setting \x1b[5 q (blinking bar) for an editor caret, crashing, and leaving the user's bash prompt blinking — survives until they emit a manual reset or restart the terminal.

Terminal support

xterm
yes
Linux console (fbcon)
partial
macOS Terminal.app
partial
iTerm2
yes
Windows Terminal
yes
cmd.exe / ConPTY
partial
kitty
yes
alacritty
yes
WezTerm
yes
Ghostty
yes
GNOME Terminal
yes
Konsole
yes
tmux
yes
GNU screen
yes

Related sequences

In the family cookbook

DEC cookbook · 3. Cursor visibility & blink — `?25`, `?12`