ttyscan queries a terminal emulator for its type, size and capabilities, creating a
curses-compatible terminfo(5) file entry if necessary, and exports any corrected values of
TERM, COLORTERM, LINES, COLUMNS, and optionally TERMCAP environment variables.
ncurses does not support XTGETTCAP, and so terminfo(5) files for some terminals must be deployed to remote systems by system operators in some circumstances.
Curses programs fail to start until those files are deployed or an alternate TERM is exported.
All kinds of errors and warnings may be raised until this is done, some examples:
$ tmux attach missing or unsuitable terminal: xterm-kitty $ irssi setupterm() failed for TERM=xterm-kitty: 0 Can't initialize screen handling. $ htop Error opening terminal: xterm-kitty. $ python -c 'import curses;curses.setupterm()' Traceback (most recent call last): File "<string>", line 1, in <module> _curses.error: setupterm: could not find terminal $ git log -p WARNING: terminal is not fully functional Press RETURN to continue
ttyscan creates the missing terminfo(5) file using the XTGETTCAP (DCS +q) terminal query
protocol when supported, and suggests a new TERMINFO environment value for export, allowing
legacy calls to curses of setupterm(3) to succeed:
$ ttyscan -vft
ttyscan: probing terminal via XTGETTCAP ...
ttyscan: size via dual CPR: 28x100
ttyscan: XTGETTCAP supported, terminal: rio; received 198 caps (11 bool, 5 num, 178 str) in 4ms
ttyscan: writing /home/jq/.config/ttyscan/terminfo/r/rio
export COLORTERM=truecolor
export TERM=rio
export LINES=28
export COLUMNS=100
export TERMINFO=/home/jq/.config/ttyscan/terminfo
export TERMCAP='rio|XTGETTCAP-discovered terminal::am::ut::hs::km::5i::mi::ms::NP::xn::Co#256::co#80::it#8::li#24::pa#32767::ac=``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~::bl=^G::mb=\E[5m::md=\E[1m::bt=\E[Z::vi=\E[?25l::cl=\E[H\E[2J::ve=\E[?12l\E[?25h::cr=\r::cs=\E[%i%p1%d;%p2%dr::le=\b::DO=\E[%p1%dB::do=\n::nd=\E[C::cm=\E[%i%p1%d;%p2%dH::up=\E[A::vs=\E[?12;25h::dC=\E[P::mh=\E[2m::dl=\E[M::ds=\E]2;^G::ec=\E[%p1%dX::cd=\E[J::ce=\E[K::cb=\E[1K::vb=\E[?5h$<100/>\E[?5l::fs=^G::ho=\E[H::ch=\E[%i%p1%dG::ta=\t::st=\EH::al=\E[L::sf=\n::mk=\E[8m::is=\E[!p\E[?3;4l\E[4l\E>::K2=\EOE::kb=^?::kB=\E[Z::kl=\EOD::kd=\EOB::kr=\EOC::ku=\EOA::kD=\E[3~::@7=\EOF::@8=\EOM::k1=\EOP::k0=\E[21~::F1=\E[23~::F2=\E[24~::k2=\EOQ::k3=\EOR::k4=\EOS::k5=\E[15~::k6=\E[17~::k7=\E[18~::k8=\E[19~::k9=\E[20~::kh=\EOH::kI=\E[2~::kH=\E[1;2B::kN=\E[6~::kP=\E[5~::ps=\E[i::pf=\E[4i::po=\E[5i::op=\E[39;49m::rp=%p1%c\E[%p2%{1}%-%db::mr=\E[7m::sr=\EM::ZR=\E[23m::ae=\E(B::te=\E[?1049l\E[23;0;0t::ei=\E[4l::ke=\E[?1l\E>::se=\E[27m::ue=\E[24m::r1=\Ec\E]104^G::r2=\E[!p\E[?3;4l\E[4l\E>::sa=%?%p9%t\E(0%e\E(B%;\E[0%?%p6%t;1%;%?%p5%t;2%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m::me=\E(B\E[m::ZH=\E[3m::as=\E(0::ti=\E[?1049h\E[22;0;0t::im=\E[4h::ks=\E[?1h\E=::so=\E[7m::us=\E[4m::ct=\E[3g::ts=\E]2;::cv=\E[%i%p1%dd:'
$ eval `ttyscan`
$ echo $TERM, $TERMINFO
rio, /home/jquast/.config/ttyscan/terminfo
$ file -b $TERMINFO/r/rio
Compiled terminfo entry "rio"
$ python -c 'import curses;curses.setupterm()'; echo $?
0
usage: ttyscan [-h] [-v] [-f] [-t] Export terminal capabilities discovered via XTGETTCAP options: -h, --help show this help message and exit -v, --verbose Print diagnostic information to stderr -f, --force Force export of all values even if unchanged -t, --termcap Also export TERMCAP value --version show program's version number and exit
ttyscan saves a terminfo(5) file to $XDG_CONFIG_HOME/ttyscan/terminfo or
~/.config/ttyscan/terminfo, and does not re-query or re-create it when it already exists from
previous executions, unless --force argument is used.
Typical total execution time is under 200ms. The default query timeout can be changed by
environment value TTYSCAN_QUERY_TIMEOUT=1.0 (float), in seconds. If timeout is reached, terminal
response may "bleed" into subsequent programs, (like a shell prompt).
After receiving the initial response, a secondary drain phase collects any remaining XTGETTCAP
replies, controlled by TTYSCAN_DRAIN_TIMEOUT=0.2 (float). Increase this value if some
capabilities are intermittently missing, particularly over high-latency SSH connections.
pip install ttyscanttyscan requires Python3.6+.
ttyscan.py is a stand-alone python file, it does not require pip to install, you can copy this
single file directly from source and execute it from source, eg. python ~/bin/ttyscan.py
Naturally, transferring your $HOME/.terminfo folder to a remote machine is the best solution.
However, enterprise systems, bastion hosts, cloud systems, web consoles, hypervisors, radio, and serial ports can be challenging places or protocol layers through which to deploy terminfo files.
Some workarounds include exporting a generally-compatible TERM=xterm-256color or xterm with
sometimes minor corruption of screen output, missed interpretation of keyboard input such as
backspace or delete, or a small reduction of features such as italic or underlined text or number of
colors.
And so this tool is not often needed except for the very serious terminal connoisseur.
It serves as a demonstration: that a full terminal capability database can be transferred using XTGETTCAP for many modern terminals. My hope is that ncurses and setupterm(3) could negotiate with full XTGETTCAP support at some point in the future, and that this utility is not commonly used or required!
At time of this writing (May 2026), the ucs-detect dataset of 42 terminals shows three categories
of support for XTGETTCAP:
Full
XTGETTCAPcapability support: contour, foot, ghostty, kitty, rio, and wezterm transmit their complete terminfo boolean, numeric, and string capabilities via XTGETTCAP.ttyscan produces terminfo files for only these terminals. ttyscan may also discover a preferred
TERMfromTN, andCOLORTERM=truecolorfromRGB.Partial
XTGETTCAPcapability support: XTerm, iterm2, mlterm, AbsoluteTelnet/SSH, GNOME Terminal, LXTerminal, terminator, termit, and xfce4-terminal report onlyTN,Co, andRGB.ttyscan may only discover preferred
TERMfromTN, andCOLORTERM=truecolorfromRGB.XTerm supports only keyboard sequences in addition to
TN,Co, andRGB. It does not report all capabilities, and so a terminfo(5) entry cannot be built. However,TERM=xterm-256colorandTERM=xtermare the most ubiquitous terminal name, you should be just fine.No Support: alacritty (refuses: alacritty/vte#98), bobcat, cmd.exe, Extraterm, Hyper, Konsole (requested: KDE#507017), linux fbdev, mintty, rxvt-unicode, screen, securecrt, st, Tabby, Terminal.exe (planned: microsoft/terminal#17735), terminology, tmux (passthrough: tmux/tmux#3755), libvterm, VS Code (xterm.js, proposal: xtermjs/xterm.js#4107), weston-terminal, and zutty.
Non-Compliant: ConEmu, cool-retro-term, Apple Terminal, PuTTY, QTerminal: When a terminal emulator does not support XTGETTCAP, it should silently consume VT100 Mode DCS queries without answer.
However, some non-compliant terminals display XTGETTCAP query output, eg.
+q544e+q524742+q636f6c6f7273+q626c696e6b+..visually: QTerminal, cool-retro-term, and qtermwidget (fixed upstream), PuTTY, ConEmu.exe, and Apple's Terminal.app all fail to parse DCS queries, displaying raw sequence output.
ttyscan uses the following,
XTGETTCAPfieldTNis used to correctTERMwhen unmatched.XTGETTCAPfieldRGBis used to correctCOLORTERMwhen unmatched.- all capability strings, keyboard and screen, when provided by
XTGETTCAP. - DEC Private Mode 2048 (In-Band Resize) to determine the window size
- Or failing that, using Cursor Position Report sequence like done in XTerm's resize.c
- DECRQSS (Request Setting Selection) to probe truecolor support when
RGBis unavailable, by setting and querying a 24-bit background color
The difference of Full and Partial XTGETTCAP support is best described by foot:
XTGETTCAPis an escape sequence initially introduced by XTerm, and also implemented (and extended, to some degree) by Kitty.Applications using this feature do not need to use the classic, file-based, terminfo definition.
XTerm's implementation (as of XTerm-370) only supports querying key (as in keyboard keys) capabilities, and three custom capabilities:
TN- terminal nameCo- number of colors (alias for the colors capability)RGB- number of bits per color channel (different semantics from the RGB capability in file-based terminfo definitions!).Kitty has extended this, and also supports querying all integer and string capabilities.
Foot supports this, and extends it even further, to also include boolean capabilities. This means foot's entire terminfo can be queried via
XTGETTCAP.
Further, all of TERM, COLORTERM, LINES, or COLUMNS may not be transmitted by all
software or protocols, some examples:
- ssh does not forward
COLORTERMunless configured usingSendEnvin ssh_config(5) andAcceptEnvin sshd_config(5). - serial does not forward any;
TERMis defined by host agetty(8) configuration, for example. - rlogin can forward all but
COLORTERM. - telnet can forward all, but IAC NAWS and NEW-ENVIRON capability varies by software.
- websocket cannot forward any without customization, often used in-browser.
ttyscan detects when these variables are unset or do not match values and re-exports the corrected values when they differ.