Terminal UI TUI tui

Nvim :help pages, generated from source using the tree-sitter-vimdoc parser.


By default when you run nvim (without --embed or --headless) it starts the builtin "terminal UI" (TUI). This default UI is optional: you can run Nvim as a "headless" server, or you can use a GUI.
Nvim has a client-server architecture: by default when you run nvim, this starts the builtin UI client, which starts a nvim --embed server (child) process that the UI client connects to. After attaching to the server, the UI client calls nvim_set_client_info() (as recommended for all UIs dev-ui) and sets these fields on its channel:
client = {
  attributes = {
    license = 'Apache 2',
    pid = …,
    website = 'https://neovim.io',
  },
  name = 'nvim-tui',
  type = 'ui',
  version = { … },
},
-- Preserved across :restart.
detach = <false if the UI started the server, true after :detach!>,
Nvim guesses the terminal type when it starts (except in --embed and --headless modes). The $TERM environment variable is the primary hint that determines the terminal type.
To display its user interface, Nvim reads a list of "terminal capabilities" from the system terminfo database (or builtin defaults if terminfo is not found). If that information is wrong, the screen may be messed up or keys may not be recognized.
The Unibilium library (used to read terminfo) allows you to override the system terminfo with one in the "$HOME/.terminfo/" directory. Building your own terminfo is usually as simple as running this:
curl -LO https://invisible-island.net/datafiles/current/terminfo.src.gz
gunzip terminfo.src.gz
tic -x terminfo.src
To override the builtin terminfo, set $NVIM_TERMDEFS to a JSON object whose keys correspond to one or more of the fields below, each of which will override its counterpart (if any) in the builtin terminfo. The system terminfo will be skipped entirely: only builtin definitions, plus the $NVIM_TERMDEFS overrides, will be used.
For example, to disable alternate screen, override the "reset the cursor style" sequence, and set the <Home> and <S-Home> sequences:
NVIM_TERMDEFS='{
  "enter_ca_mode": "",
  "exit_ca_mode": "",
  "reset_cursor_style": "\u001b[0 q",
  "key_home": ["\u001bOH", "\u001b[1;2H"]
}' nvim
Be careful when putting escape sequences in strings, as JSON uses unicode escapes like \u001b. For all available fields, see tui-termdefs.
The $TERM environment variable must match the terminal you are using! Otherwise Nvim cannot know what sequences your terminal expects, and weird or sub-optimal behavior will result (scrolling quirks, wrong colors, etc.).
$TERM is also important because it is forwarded by SSH to the remote session, unlike most other environment variables.
For this terminalSet $TERM tobuiltin-terms
ansi(unknown)Y
Ghosttyghostty, xterm-ghosttyY
iTerm (original)iterm, iTerm.appN
iTerm2 (new capabilities)iterm2, iTerm2.appY
Konsolekonsole-256colorN
libvte-basedvte, vte-256colorY
(e.g. GNOME Terminal)(aliases: gnome, gnome-256color)
Linux virtual terminallinux, linux-256colorY
PuTTYputty, putty-256colorY
rxvtrxvt, rxvt-256colorY
screenscreen, screen-256colorY
simple terminal (st)st, st-256colorY
Terminal.appnstermN
tmuxtmux, tmux-256colorY
Windows/ConEmuconemuY
Windows/Cygwin-built NvimcygwinY
Windows/InterixinterixY
Windows/legacy consolewin32conY
Windows/VTP consolevtpconY
xterm or compatiblexterm, xterm-256colorY
Nvim will map $TERM to a builtin entry according to the above table if:
a terminfo database is not available on the system
no terminfo entry found for the current detected terminal
Nvim was built without terminfo support (has('terminfo')==0)
The builtin terminfo is not combined with any external terminfo database, nor can it be used in preference to one. You can thus entirely override any omissions or out-of-date information in the builtin terminfo database by supplying an external one with entries for the terminal type.
For example "TERM=putty-256color" will be mapped to the builtin "putty" entry. See also tui-colors.
Settings depending on terminalterm-dependent-settings
If you want to set terminal-dependent options or mappings, you can do this in your init.vim. Example:

if $TERM =~ '^\(rxvt\|screen\|interix\|putty\)\(-.*\)\?$'
    set notermguicolors
elseif $TERM =~ '^\(tmux\|iterm\|vte\|gnome\)\(-.*\)\?$'
    set termguicolors
elseif $TERM =~ '^\(xterm\)\(-.*\)\?$'
    if $XTERM_VERSION != ''
        set termguicolors
    elseif $KONSOLE_PROFILE_NAME != ''
        set termguicolors
    elseif $VTE_VERSION != ''
        set termguicolors
    else
        set notermguicolors
    endif
elseif $TERM =~ ...
    ... and so forth ...
endif
Where possible, Nvim will use the terminal's ability to set a scroll region in order to redraw faster when a window is scrolled. If the terminal's terminfo description describes an ability to set top and bottom scroll margins, that is used.
This will not speed up scrolling in a window that is not the full width of the terminal. Xterm has an extra ability, not described by terminfo, to set left and right scroll margins as well. If Nvim detects that the terminal is Xterm, it will make use of this ability to speed up scrolling that is not the full width of the terminal.
Historically, terminal emulators could not distinguish between certain control key modifiers and other keys. For example, <C-I> and <Tab> are represented in the same way, as are <Esc> and <C-[>, <CR> and <C-M>, and <NL> and <C-J>.
Modern terminal emulators are able to distinguish between these pairs of keys by encoding control modifiers differently. There are two common but distinct ways of doing this, known as "modifyOtherKeys" and "CSI u". Nvim supports both encoding methods and at startup will tell the terminal emulator that it understands these key encodings. If your terminal emulator supports it then this will allow you to map the key pairs listed above separately. <Tab>
Nvim uses libtermkey to convert terminal escape sequences to key codes. terminfo is used first, and CSI sequences not in terminfo (including extended keys a.k.a. "modifyOtherKeys" or "CSI u") can also be parsed.
For example, when running Nvim in tmux, this makes Nvim leave Insert mode and go to the window below:
tmux send-keys 'Escape' [ 2 7 u 'C-W' j
Where 'Escape' [ 2 7 u is an unambiguous "CSI u" sequence for the <Esc> key.
The kitty keyboard protocol https://sw.kovidgoyal.net/kitty/keyboard-protocol/ is partially supported, including keypad keys in Unicode Private Use Area. For example, this sequence is recognized by Nvim as <C-kEnter>:
CSI 57414 ; 5 u
and can be used differently from <C-CR> in mappings.
At startup Nvim will query your terminal to see if it supports the "CSI u" encoding by writing the sequence
CSI ? u CSI c
If your terminal emulator responds with
CSI ? <flags> u
this means your terminal supports the "CSI u" encoding and Nvim will tell your terminal to enable it by writing the sequence
CSI > 3 u
If your terminal does not support "CSI u" then Nvim will instead enable the "modifyOtherKeys" encoding by writing the sequence
CSI > 4 ; 2 m
The "3" requests the kitty keyboard protocol "progressive enhancement" flags 1 (disambiguate escape codes) and 2 (report event types). Nvim does not request 8 (report all keys as escape codes) nor 16 (report associated text), which are needed to distinguish keys that produce the same text as their unmodified counterpart, such as <S-Space> and <Space>.
When Nvim exits cleanly it will send the corresponding sequence to disable the special key encoding. If Nvim does not exit cleanly then your terminal emulator could be in a bad state. If this happens, simply run "reset".
Nvim uses 256 colours by default, ignoring terminfo for most terminal types, including "linux" (whose virtual terminals have had 256-colour support since 4.8) and anything claiming to be "xterm". Also when $COLORTERM or $TERM contain the string "256".
Nvim similarly assumes that any terminal emulator that sets $COLORTERM to any value, is capable of at least 16-colour operation.
Nvim emits true (24-bit) colours in the terminal, if 'termguicolors' is set.
It uses the "setrgbf" and "setrgbb" terminfo extensions (proposed by Rüdiger Sonderfeld in 2013). If your terminfo definition is missing them, then Nvim will decide whether to add them to your terminfo definition, using the ISO 8613-6:1994/ITU T.416:1993 control sequences for setting RGB colours (but modified to use semicolons instead of colons unless the terminal is known to follow the standard).
Another convention, pioneered in 2016 by tmux, is the "Tc" terminfo extension. If terminfo has this flag, Nvim will add constructed "setrgbf" and "setrgbb" capabilities as if they had been in the terminfo definition.
If terminfo does not (yet) have this flag, Nvim will fall back to $TERM and other environment variables. It will add constructed "setrgbf" and "setrgbb" capabilities in the case of the "rxvt", "linux", "st", "tmux", and "iterm" terminal types, or when Konsole, genuine Xterm, a libvte terminal emulator version 0.36 or later, or a terminal emulator that sets the COLORTERM environment variable to "truecolor" is detected.
Nvim can resize the terminal display on some terminals that implement an extension pioneered by dtterm. terminfo does not have a flag for this extension. So Nvim simply assumes that (all) "dtterm", "xterm", "teraterm", "rxvt" terminal types, and Konsole, are capable of this.
Nvim will adjust the shape of the cursor from a block to a line when in insert mode (or as specified by the 'guicursor' option), on terminals that support it. It uses the same terminfo extensions that were pioneered by tmux for this: "Ss" and "Se". Similarly, if you set the cursor highlight group with blend=100, Nvim hides the cursor through the "cvvis" and "civis" extensions.
If your terminfo definition is missing them, then Nvim will decide whether to add them to your terminfo definition, by looking at $TERM and other environment variables. For the "rxvt", "putty", "linux", "screen", "teraterm", and "iterm" terminal types, or when Konsole, a libvte-based terminal emulator, or genuine Xterm are detected, it will add constructed "Ss" and "Se" capabilities.
Within tmux it may appear that Nvim is not changing the cursor, but in fact it is tmux receiving instructions from Nvim to change the cursor and not knowing what to do in turn. tmux must translate what it receives from Nvim into whatever control sequence is appropriate for the host terminal. It shares a common mechanism with Nvim, of using the "Ss" and "Se" capabilities from terminfo (for the output terminal) if they are present. Unlike Nvim, if they are not in terminfo you must add them by setting "terminal-overrides" in ~/.tmux.conf .
See the tmux(1) manual page for the details of how and what to do in the tmux configuration file. It will look something like:
set -ga terminal-overrides '*:Ss=\E[%p1%d q:Se=\E[ q'
or (alas!) for Konsole 18.07.70 or older, something more complex like:
set -ga terminal-overrides 'xterm*:\E]50;CursorShape=%?%p1%{3}%<%t%{0}%e%{1}%;%d\007'

Window size window-size

[This is about the size of the whole window Vim is using, not a window that is created with the ":split" command.]
On Unix systems, three methods are tried to get the window size:
an ioctl call (TIOCGSIZE or TIOCGWINSZ, depends on your system)
the environment variables "LINES" and "COLUMNS"
from the terminfo entries "lines" and "columns"
If everything fails a default size of 24 lines and 80 columns is assumed. If a window-resize signal is received the size will be set again. If the window size is wrong you can use the 'lines' and 'columns' options to set the correct values. See :mode.

Slow and fast terminals slow-fast-terminal

If you have a slow terminal you may want to reset the 'showcmd' and 'ruler' options. The command characters and cursor positions will not be shown in the status line (which involves a lot of cursor motions and attribute changes for every keypress or movement). If the terminal scrolls very slowly, set the 'scrolljump' to 5 or so. If the cursor is moved off the screen (e.g., with "j") Vim will scroll 5 lines at a time. Another possibility is to reduce the number of lines that Vim uses with the command "z{height}<CR>".
If the characters from the terminal are arriving with more than 1 second between them you might want to set the 'timeout' and/or 'ttimeout' option.
If you are using a color terminal that is slow when displaying lines beyond the end of a buffer, this is because Nvim is drawing the whitespace twice, in two sets of colours and attributes. To prevent this, use this command:
hi NonText cterm=NONE ctermfg=NONE
This draws the spaces with the default colours and attributes, which allows the second pass of drawing to be optimized away. Note: Although in theory the colours of whitespace are immaterial, in practice they change the colours of cursors and selections that cross them. This may have a visible, but minor, effect on some UIs.

Terminfo override tui-termdefs

Below are the available fields in $NVIM_TERMDEFS. For keys of type string[], the first entry is the unshifted variant of the key, and the second entry is the shifted variant.
FieldType
RGBbool
Subool
Tcbool
back_color_erasebool
columnsint
linesint
max_colorsint
carriage_returnstring
change_scroll_regionstring
clear_screenstring
clr_eolstring
clr_eosstring
cursor_addressstring
cursor_downstring
cursor_homestring
cursor_invisiblestring
cursor_leftstring
cursor_normalstring
cursor_rightstring
cursor_upstring
delete_linestring
enter_blink_modestring
enter_bold_modestring
enter_ca_modestring
enter_dim_modestring
enter_italics_modestring
enter_reverse_modestring
enter_secure_modestring
enter_standout_modestring
enter_underline_modestring
erase_charsstring
exit_attribute_modestring
exit_ca_modestring
from_status_linestring
insert_linestring
keypad_localstring
keypad_xmitstring
parm_delete_linestring
parm_down_cursorstring
parm_insert_linestring
parm_left_cursorstring
parm_right_cursorstring
parm_up_cursorstring
set_a_backgroundstring
set_a_foregroundstring
set_attributesstring
set_lr_marginstring
to_status_linestring
enter_strikethrough_modestring
reset_cursor_colorstring
reset_cursor_stylestring
set_cursor_colorstring
set_cursor_stylestring
set_rgb_backgroundstring
set_rgb_foregroundstring
set_underline_stylestring
key_backspacestring
key_btabstring
key_clearstring
key_npagestring
key_ppagestring
key_selectstring
key_begstring[]
key_dcstring[]
key_endstring[]
key_findstring[]
key_homestring[]
key_icstring[]
key_leftstring[]
key_rightstring[]
key_suspendstring[]
key_undostring[]
key_f1string
...string
key_f63string
Main
Commands index
Quick reference