Unix-like systems include a Terminfo database that describes the capabilities of various terminals. When a program needs to perform terminal operations, it reads the TERM environment variable to identify your terminal type, then queries the Terminfo database to determine available capabilities and how to use them. This affects output formatting, colour handling, cursor movements, and other terminal behaviour.

If things don’t match up, you’ll see weird stuff — keys not working, colours breaking, or your terminal just acting strangely. You generally want to ensure that:

  1. The TERM environment variable is set correctly
  2. The terminfo database includes an entry for your terminal

The latter is particularly important if you’re using a modern terminal program (e.g., Kitty), as these are often not included in standard terminfo databases.

This is normally not an issue on the machine where you install your terminal, as the correct terminfo package is often installed as a dependency. But when you SSH into remote machines, your TERM is passed along and you can run into issues if the terminfo on the remote machine doesn’t include the required entry.

Fixing this isn’t trivial. I SSH into two types of machines: persistent ones that I care about and set up properly, and random boxes I just hop onto occasionally. For the first, I want to set the correct TERM and install Kitty’s terminfo system-wide. For the second, I just want something that works without hassle, like setting TERM to xterm-256color, which works reasonably well with Kitty and is available on any machine.

I used to use a bunch of shell aliases to SSH with different TERM values but I have now discovered a more seamless setup using the SetEnv option in ~/.ssh/config. This directive lets you set environment variables on the remote server. Normally the SSH server must also be configured to accept these environment variables with the AcceptEnv parameter but TERM is an exception to this requirement! The config below lets me set my local TERM to xterm-kitty and use the safe xterm-256color when I SSH to remote machines, except for the few machines that I have ensured can handle xterm-kitty:

Host dev
    HostName my-dev-machine
    SetEnv TERM=xterm-kitty

Host *
    SetEnv TERM=xterm-256color

The order of things in the config matters because SSH processes the config sequentially and stops at the first match for each individual option. This allows you to create a hierarchy from specific to general rules. For example, I have a few additional conveniences configured that are used for all hosts:

Host dev
    HostName my-dev-machine
    SetEnv TERM=xterm-kitty

Host *
    SetEnv TERM=xterm-256color
    ConnectTimeout 10
    ServerAliveInterval 60
    ServerAliveCountMax 3

    Compression yes
    TCPKeepAlive yes

    ControlMaster auto
    ControlPath ~/.ssh/control-%C
    ControlPersist 5m