ICH — Insert Character (CSI 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.
Byte forms
Every common string-literal form so you can paste-and-search either direction.
\x1b[Pn@\033[Pn@\e[Pn@ESC [ Pn @1b 5b <Pn> 40Description
Insert Character. Final byte @ (0x40) shifts the cursor position and every cell to its right within the current line rightward by Pn cells (default 1); cells that fall off the right edge are discarded and the Pn-wide gap at the cursor is filled with blanks (SP, 0x20) carrying the current SGR background. The cursor itself does not move. ICH is the primitive vim insert mode emits per typed character — vim could redraw the whole line for every keystroke, but using ICH keeps screen updates O(1) per character. Pair with DCH (\x1b[Pn P) to delete the same way. ICH is bounded by the right margin (DECSTBM column-margins, if set); cells past the right margin are NOT shifted into. The terminfo capability is ich1 (Pn=1) or ich (parameterised).
Spec citation: ECMA-48 §8.3.64 (ICH)
Examples
# Move cursor to column 5, insert 3 cells, then type 'xyz' (it lands at col 5).\nprintf 'Hello world\033[5G\033[3@xyz'import sys; sys.stdout.write('\x1b[3@') # open a 3-cell gap at the cursorfmt.Print("\x1b[3@")process.stdout.write('\x1b[3@')printf("\x1b[3@");Used in
Real-world tools that emit this sequence — anchors the bytes to commands you've already used.
- vim insert-mode `i` / `I` / `a` primitivesvim emits ICH for in-row character insertion when `'insertmode'` redraws are partial — the row's trailing content shifts right, the inserted character takes the cursor cell. `:set verbose=15` shows `<Esc>[<N>@` patterns during fast typing
- bash readline `quoted-insert` (Ctrl-V)readline's `quoted-insert` binding inserts a literal control character at the cursor with an ICH preceding the byte write — preserves the line-tail's column positions for in-line edits without falling back to a full-line redraw
- zsh ZLE `self-insert` widgetzsh's line editor emits ICH when `INSERT_MODE` is on and the cursor is not at end-of-line — the line tail right-shifts cleanly with a single CSI byte rather than a row-redraw of the full content
- less / more search-marker highlight insertionless ≥ 633 inserts a `>` search-marker at the cursor with ICH before applying the highlight SGR — keeps the row's existing content layout intact while the marker visually pushes everything one cell right within the search hit
- ncurses `insch()` / `winsch()`ncurses' `insch()` maps to `\x1b[1@` (ICH defaulting to 1) on terminals advertising the `ich1` cap, or a parameterised `\x1b[<N>@` via `ich` on others — visible in `infocmp xterm-256color | grep ich`
Frequently asked
Short answers to the questions developers actually search for this sequence.
- What's the difference between ICH (
\x1b[5@) and IL (\x1b[5L)? - ICH (Insert Character — final byte
@, 0x40) insertsPnblank cells *in the current row at the cursor*, shifting the row's trailing content right byPn; cells pushed past the right margin are lost. IL (Insert Line — final byteL, 0x4c) insertsPnblank *rows* at the cursor's row, shifting subsequent rows down within the scroll region. ICH is what vim'sidoes for a single character; IL is what vim'sOandodo for blank lines. Pick ICH for in-row edits, IL for row-level insertions. - Where do characters pushed past the right margin go when I run ICH?
- They're discarded — pushed off the row and gone forever. ICH does NOT wrap pushed-off content onto the next row (that would be a line-rewrap, which is a separate concept — see DECAWM
\x1b[?7h). The row's final cells past the right margin are simply truncated. If the cursor is past the right margin when ICH fires (only possible with DECAWM in the post-wrap pending state), the behaviour is implementation-defined — xterm treats it as a no-op, kitty and Ghostty wrap the cursor first then insert.
Terminal support
- xterm
- yes
- Linux console (fbcon)
- yes
- macOS Terminal.app
- yes
- 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
| 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 | partial | yes | yes | yes | yes | yes | yes | yes | yes |
Related sequences
In the family cookbook
CSI cookbook · 6. Insert / delete / cursor shape — IL / DL / ICH / DCH / ECH + DECSCUSR