The definitive guide to using tmux-256color on macOS
UPDATE: macOS 14 (Sonoma) updated its bundled ncurses version to
6.0. This version ships with a tmux-256color entry by default, so
the workaround below is no longer needed.
macOS ships with an old and very out-of-date version of ncurses (5.7). This
version does not contain a terminfo entry for tmux-256color, the preferred
TERM value when using tmux.
If you installed tmux via Homebrew or MacPorts, then you will also have a
newer version of ncurses (6.X) present on your system installed by your package
manager. This is the version of ncurses that tmux itself was built against,
which is why you can use
set -s default-terminal tmux-256color
in your .tmux.conf without any errors. However, as soon as you try to use any
application linked against macOS’s version of ncurses (such as man or ls -G), you will notice that things no longer work.
The solution is to get the tmux-256color terminfo entry from the newer
version of ncurses into macOS’s terminfo database. First, create a copy of the
current tmux-256color terminfo entry from the version of curses installed by
your package manager:
# MacPorts
$ /opt/local/bin/infocmp -x tmux-256color > ~/tmux-256color.src
# Homebrew
$ /usr/local/opt/ncurses/bin/infocmp -x tmux-256color > ~/tmux-256color.src
Now, modify the tmux-256color.src file to change the pairs value from
65536 to 32767. This must be done because of a bug in ncurses 5.7 that
interprets pairs#65536 as pairs#01.
Before:
pairs#0x10000
or
pairs#65536
After:
pairs#32767
Prior to macOS Catalina, it was possible to install this new terminfo entry
directly into the system database /usr/share/terminfo. However, as of
Catalina we can no longer do this since the root volume (of which
/usr/share/terminfo is a part) is read-only. There are, apparently,
workarounds to make the root volume writable, so if you want to go that route
you can. Instead, we can install the terminfo entry to a local database under
$HOME:
$ /usr/bin/tic -x -o $HOME/.local/share/terminfo tmux-256color.src
Be sure to explicitly use /usr/bin/tic to ensure that the entry is compiled
with the builtin ncurses. This will install the terminfo database entry under
$HOME/.local/share/terminfo. ncurses uses the TERMINFO_DIRS environment
variable to specify a location to search for terminfo entries when not found in
the primary database (see man 5 terminfo). We can take advantage of this to
have the macOS 5.7 version of ncurses search in a directory of our choice when
it doesn’t find tmux-256color under /usr/share/terminfo, while the 6.X
version provided by the package manager will still use its own version2.
Simply set the TERMINFO_DIRS environment variable in your shell startup file
(e.g. .bashrc, .zshrc, etc.) to use that directory (note that we append
this value to the existing value, if any, similar to how we append values to
$PATH):
$ export TERMINFO_DIRS=$TERMINFO_DIRS:$HOME/.local/share/terminfo
After that, you should be able to correctly use tmux-256color as your TERM
variable. You can check that everything is working by running a few programs
that make use of ncurses and terminal colors, such as htop, man, ls -G,
etc.
-
An earlier version of this article installed the terminfo entry into
$HOME/.terminfo, which is a suboptimal solution as even the updated 6.X version of ncurses would use the terminfo entry with reduced colors. The use ofTERMINFO_DIRSwas suggested to me by Carlo Cabrera, and provides the best of both worlds. Thanks Carlo for the tip! ↩︎