TERM strings

A certain piece of very misleading advice is often given online to users having problems with the way certain command-line applications are displaying in their terminals. This is to suggest that the user change the value of their TERM environment variable from within the shell, doing something like this:

$ TERM=xterm-256color

This misinformation sometimes extends to suggesting that users put the forced TERM change into their shell startup scripts. The reason this is such a bad idea is that it forces your shell to assume what your terminal is, and thereby disregards the initial terminal identity string sent by the emulator. This leads to a lot of confusion when one day you need to connect with a very different terminal emulator.

Accounting for differences

All terminal emulators are not created equal. Certainly, not all of them are xterm(1), although many other terminal emulators do a decent but not comprehensive job of copying it. The value of the TERM environment variable is used by the system running the shell to determine what the terminal connecting to it can and cannot do, what control codes to send to the program to use those features, and how the shell should understand the input of certain key codes, such as the Home and End keys. These things in particular are common causes of frustration for new users who turn out to be using a forced TERM string.

Instead, focus on these two guidelines for setting TERM:

  1. Avoid setting TERM from within the shell, especially in your startup scripts like .bashrc or .bash_profile. If that ever seems like the answer, then you are probably asking the wrong question! The terminal identification string should always be sent by the terminal emulator you are using; if you do need to change it, then change it in the settings for the emulator.

  2. Always use an appropriate TERM string that accurately describes what your choice of terminal emulator can and cannot display. Don’t make an rxvt(1) terminal identify itself as xterm; don’t make a linux console identify itself as vt100; and don’t make an xterm(1) compiled without 256 color support refer to itself as xterm-256color.

In particular, note that sometimes for compatibility reasons, the default terminal identification used by an emulator is given as something generic like xterm, when in fact a more accurate or comprehensive terminal identity file is more than likely available for your particular choice of terminal emulator with a little searching.

An example that surprises a lot of people is the availability of the putty terminal identity file, when the application defaults to presenting itself as an imperfect xterm(1) emulator.

Configuring your emulator’s string

Before you change your terminal string in its settings, check whether the default it uses is already the correct one, with one of these:

$ echo $TERM
$ tset -q

Most builds of rxvt(1), for example, should already use the correct TERM string by default, such as rxvt-unicode-256color for builds with 256 colors and Unicode support.

Where to configure which TERM string your terminal uses will vary depending on the application. For xterm(1), your .Xresources file should contain a definition like the below:

XTerm*termName: xterm-256color

For rxvt(1), the syntax is similar:

URxvt*termName: rxvt-unicode-256color

Other GTK and Qt emulators sometimes include the setting somewhere in their preferences. Look for mentions of xterm, a common fallback default.

For Windows PuTTY, it’s configurable under the ”’Connections > Data”’ section:

Setting the terminal string in PuTTY

More detail about configuring PuTTY for connecting to modern systems can be found in my article on configuring PuTTY.

Testing your TERM string

On Linux systems, an easy way to test the terminal capabilities (particularly effects like colors and reverse video) is using the msgcat(1) utility:

$ msgcat --color=test

This will output a large number of tests of various features to the terminal, so that you can check their appearance is what you expect.

Finding appropriate terminfo(5) definitions

On Linux systems, the capabilities and behavior of various terminal types is described using terminfo(5) files, usually installed as part of the ncurses package. These files are often installed in /lib/terminfo or /usr/share/terminfo, in subdirectories by first letter.

In order to use a particular TERM string, an appropriate file must exist in one of these directories. On Debian-derived systems, a large collection of terminal types can be installed to the system with the ncurses-term package.

For example, the following variants of the rxvt terminal emulator are all available:

$ cd /usr/share/terminfo/r
$ ls rxvt*
rxvt-16color  rxvt-256color  rxvt-88color  rxvt-color  rxvt-cygwin
rxvt-cygwin-native  rxvt+pcfkeys  rxvt-unicode-256color  rxvt-xpm 

Private and custom terminfo(5) files

If you connect to a system that doesn’t have a terminfo(5) definition to match the TERM definition for your particular terminal, you might get a message similar to this on login:

setterm: rxvt-unicode-256color: unknown terminal type
tput: unknown terminal "rxvt-unicode-256color"
$

If you’re not able to install the appropriate terminal definition system-wide, one technique is to use a private .terminfo directory in your home directory containing the definitions you need:

$ cd ~/.terminfo
$ find
.
./x
./x/xterm-256color
./x/xterm
./r
./r/rxvt-256color
./r/rxvt-unicode-256color
./r/rxvt
./s
./s/screen
./s/screen-256color
./p
./p/putty-256color
./p/putty

You can copy this to your home directory on the servers you manage with a tool like scp:

$ scp -r .terminfo server:

TERM and multiplexers

Terminal multiplexers like screen(1) and tmux(1) are special cases, and they cause perhaps the most confusion to people when inaccurate TERM strings are used. The tmux FAQ even opens by saying that most of the display problems reported by people are due to incorrect TERM settings, and a good portion of the codebase in both multiplexers is dedicated to negotiating the differences between terminal capacities.

This is because they are “terminals within terminals”, and provide their own functionality only within the bounds of what the outer terminal can do. In addition to this, they have their own type for terminals within them; both of them use screen and its variants, such as screen-256color.

It’s therefore very important to check that both the outer and inner definitions for TERM are correct. In .screenrc it usually suffices to use a line like the following:

term screen

Or in .tmux.conf:

set-option -g default-terminal screen

If the outer terminals you use consistently have 256 color capabilities, you may choose to use the screen-256color variant instead.

If you follow all of these guidelines, your terminal experience will be much smoother, as your terminal and your system will understand each other that much better. You may find that this fixes a lot of struggles with interactive tools like vim(1), for one thing, because if the application is able to divine things like the available color space directly from terminal information files, it saves you from having to include nasty hacks on the t_Co variable in your .vimrc.

18 thoughts on “TERM strings

  1. Pingback: Mac - OSX - Admin system - Environment variables | Pearltrees

  2. Nice topic.

    In the past, I had lots of problems when SSHing into a remote machine that assumes some default terminal settings incompatible with the machine I am connecting from. This would often result in my fancy zsh prompt to look completely garbled. What would be the best strategy to convey the right $TERM value upon connecting to a remote host?

      • I typically use an xterm-256color terminal emulator. However, unfortunately I do not remember the TERM string of the machines I had access to in the past (maybe one was vt100?!). I just recall that setting TERM to a new value fixed it.

          • Excellent tip, I use Emacs key bindings for moving in bash, but I was curious why it does not work. I was connecting to old machines with non-256 terminfo definitions! Thanks :-)

  3. Sometimes you just need to. gnome-terminal on Ubuntu for example defaults to “xterm”, despite having full color capabilities, and doesn’t give you any place to configure the TERM variable (to my knowledge, i poked around all over the GUI, it may be changeable with some hidden gconf setting).

    • It’s true that it’s occasionally necessary if the terminal emulator doesn’t provide a way to change it. I recall the reason I abandoned gnome-terminal was partly due to this problem and its occasional incompatibilities.

      There’s a good answer on AskUbuntu that explains the problem has more to do with hardcoded settings in VTE.

      A compromise there that I used to use is to detect xterm in a conditional in a startup script, and force a TERM of xterm-256color that way, but even that is problematic. Personally, I’d suggest changing your terminal emulator.

        • I’ve never used Unity. You could give urxvt(1) a go. It’s ugly by default, though it can definitely be fixed with a .Xresources file. Very sparing in resources if you use the urxvtd daemon.

          • Well, it seems like it has transparency support, so i’ll just have to dedicate some time to set it up just right and i’ll be set.

      • I realize the irony but I’m still using gnome-terminal and setting TERM manually by doing:

        if [ "$COLORTERM" == "gnome-terminal" ] && [ "$TERM" == "xterm" ]; then
            export TERM="xterm-256color"
        fi
        

        This way I’m only doing the bad thing if it’s gnome-terminal.

  4. Thanks for sharing. This was helpful.

    In the article, you mention and link to “my article on configuring PuTTY” … it links to the screenshot you have in this article instead. Just wanted to give you a heads-up on that. Thanks!

  5. Thanks for the information!

    It got me on the right track to fix the problem. I have created this very simple one-liner the transfer the appropriate terminfo data to remote servers:

    infocmp | ssh <HOSTNAME> 'TMP=`mktemp` && cat > $TMP; tic -o .terminfo/ "$TMP" && rm "$TMP"';
    

    Unofortunately tic(1) doesn’t accept input from stdin, so I need to use a temp file.

  6. Pingback: BASH history articles | kossboss

Leave a Reply

Your email address will not be published. Required fields are marked *

You can use Markdown if you want.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>