Display Images, PDFs, and GIFs Directly in Your Terminal
Introduction
Did you know that modern terminal emulators are capable of displaying many file formats, including images, PDFs and GIFs directly in the terminal? This can be particularly useful when connected to a remote SSH server. Although similar functionality may be achieved using X11 forwarding, this feature is not always enabled on remote servers. In addition, the X11 protocol tends to be quite slow, since it needs to forward the entire graphical user interface (GUI) application, rendering it unpractical for quickly viewing images.
Setup
Many modern terminal emulators support various protocols for visualizing images in the terminal. In this post, we will focus on the iTerm2 and the Kitty terminal emulators, since these are the ones that I use on my Mac and Linux computers, respectively.
iTerm2
In order for iTerm2
to display images, its Utilities Package needs to be installed. This can be done by navigating in the menu bar to iTerm2 > Install Shell Integration
. A popup will open in which the “Also install iTerm2 Utilities” option needs to be selected.
The utilities may then either be installed using local copy or the latest version of the tools may be fetched from a remote repository. I recommend the latter method, which should provide better compatibility with the latest version of iTerm2
. The command automatically pulls a number of useful shell scripts from a remote Git repository, which extend the functionality of iTerm2
. Note that, if preferred, each individual script may be manually installed by simply placing them somewhere in your PATH
. The one that we are interested in is the imgcat
script. Once it has been installed, various image formats (JPG, PNG, etc…), PDF and even animated GIF may be displayed directly in the terminal using
imgcat image.ext
The script comes with a number of command line options that are listed in its help page, accessible with imgcat --help
. Noteworthy flags include -H
and -W
, which configure the height and width of the images, and the -u/--url
with which arbitrary images can be fetched from the internet using a URL.
Tip
Since, by default,
imgcat
preserves the original size of the image–leading to vastly varying sizes of the displayed images–I prefer setting a fixed height of the image (in my case 33% of the terminal window) such that images are displayed using a consistent size. This can be done by passing the-H 33%
flag toimgcat
. I use an alias to overwrite the default behavior:alias imgcat="imgcat -H 33%"
.
Kitty
For the kitty
terminal, this feature is part of a set of extensions–called kittens–many of which provide similar functionality to the iTerm2
utility scripts. The icat
kitten, which can be display images in the terminal, requires the ImageMagick program as a dependency for performing some of the image manipulations. Once, these have been installed, images may be viewing using:
kitten icat image.ext
The icat
kitten
also comes with a number of options which are listed in its help page.
Enabling use through SSH
Viewing images in the terminal becomes an essential feature in the context where GUI applications are not available, as in the case of an SSH connection to a remote server. Thankfully, both the iTerm2
and kitty
protocols work seamlessly even through SSH. All that needs to be done is to also install the iTerm2
imgcat
script (following the procedure described above) or the kitty
terminal on the remote server.
Automatically Dispatching to iTerm2 or Kitty
Note that the iTerm2
and kitty
protocols are not compatible. Therefore, if the iTerm2
terminal emulator was used to SSH into the remote server then the kitten icat
command will not work. Therefore, it would be convenient to configure the shell on the remote server to detect the terminal that was used to SSH and, based on that, automatically dispatch to the appropriate command. This can be achieved by storing the terminal emulator in use in an environment variable on the host and then sending it to the remote server. In the iTerm2
settings enable the Advanced > Experimental Features > Set LC_TERMINAL=iTerm2
option. This will set the LC_TERMINAL
environment variable to iTerm2
whenever a shell is started in iTerm2
.
Now, this environment variable needs to be propagated to the remote server. The iTerm2
documentation states that OpenSSH
passes this environment variable by default to the remote servers. However, this doesn’t seem to be the case for me. In any case, environment variables may be sent explicitly to the remote server by setting the option SendEnv LC_TERMINAL
in the ~/.ssh/config
file. This option can be enabled for all servers using the following wildcard at the top of the configuration:
Host *
SendEnv LC_TERMINAL
Note that in order for this to work, the remote server needs to be configured such that it accepts sent environment variables from the host. Further information on enabling this feature can be found by consulting the
sshd_config
man
pages (see for instance theAcceptEnv
entry).
On the remote server, inside the .bashrc
or .zshrc
, this environment variable may be queried and, accordingly, the icat
command can be dispatched to the appropriate routine:
if [ "$LC_TERMINAL" = "iTerm2" ]; then
alias icat="imgcat -H 33%"
else
alias icat="kitten icat"
fi
Waring: Compatibility with
tmux
Unfortunately, in my case, both of these methods failed inside of
tmux
sessions. For some users, this is resolved by enabling theset -gq allow-passthrough
in thetmux
configuration.
Conclusion
Terminal emulators have come a long way from their initial exclusively text-based input/output modality. Today, they offer a surprising array of features, including the ability to display images, PDFs and GIFs directly within the terminal. This functionality is a game-changer, particularly for remote work, where traditional graphical interfaces may not be available or feasible.