# timg: terminal image and video viewer with sixel, kitty and iTerm2 support

> A C++ viewer that shows images at full resolution when your terminal speaks Sixel, the kitty graphics protocol or the iTerm2 protocol, and falls back to colored block characters when it does not.

**hzeller/timg** — A terminal image and video viewer.

- Repository: https://github.com/hzeller/timg
- Stars: 2,762 · Forks: 90
- Language: C++
- License: GPL-2.0
- Published: 2026-10-06 · Updated: 2026-10-06 · Language: en
- Canonical page: https://hysenlabs.com/projects/hzeller-timg

## Full resolution graphics or colored blocks, chosen for you

timg's pitch in one line is that it uses the graphic capabilities of your terminal, naming Sixel, kitty and iTerm2, and falls back to 24-bit color and Unicode character blocks when those are unavailable. That fallback is what makes it a general tool rather than a demo for one terminal. Half blocks present pixels with accurate color, quarter blocks trade a little color accuracy for twice the spatial resolution, and those modes need only UTF-8 and 24-bit color, which is most modern terminals.

The decision is made for you by default. The synopsis puts it as pixelation 'h' for half blocks, 'q' for quarter blocks, 'k' for kitty graphics, 'i' for iTerm2 graphics and 's' for sixel graphics, with auto-detection of graphics and quarter blocks as the fallback. Override it with `-p`. If you are on kitty, iTerm2 or wezterm, or on a terminal implementing the sixel protocol, you get full resolution instead.

The README's framing of when to reach for it is worth quoting in spirit because it sets honest expectations: it is useful for a quick visual check without leaving your shell, sometimes it is the only option when your terminal is connected remotely over ssh, and if you do not need the resolution, block characters are enough. Icons typically fit pixel-perfect; larger images are scaled down to match the available resolution.

## Reading the synopsis, which is the real documentation

The README embeds the full option synopsis in an untagged fence, and it is dense enough to be worth reading rather than skimming. This is the head of it:

```
usage: timg [options] <image/video> [<image/video>...]
Options (most common first):
        -p<pixelation> : Pixelation: 'h' = half blocks    'q' = quarter blocks
                                     'k' = kitty graphics 'i' = iTerm2 graphics
                                     's' = sixel graphics
                         Default: Auto-detect graphics, otherwise 'quarter'.
        --grid=<cols>[x<rows>] : Arrange images in a grid ("contact sheet").
        -C, --center   : Center image horizontally in available cell.
        -f<filelist>   : Read newline-separated list of image files to show.
```

Several things fall out of that. The command takes any number of filenames and shows them one per page, or in a grid when you pass `--grid`, which is the mode you want for browsing a directory of screenshots. A title can be printed above each image, and the format string accepts %f for the full filename, %b for the basename, %w and %h for width and height, and %D for the internal decoder used, which is genuinely useful when you want to know whether something was decoded as an image or a video frame.

Two file-list options exist because relative paths are ambiguous in this context. `-f` treats relative filenames as relative to the current directory, and `-F` treats them as relative to the directory containing the list file. Both may be given more than once, so you can compose several lists.

There is also an explicit decision to be told not to guess. `-V` goes straight to the video subsystem without probing image decoding first, which the synopsis recommends when streaming video from stdin, and `-I` does the opposite and disables video decoding entirely. For a tool whose whole job is guessing what a file is, having flags to remove the guesswork is a well-judged feature.

## Graphics protocol quirks the releases had to work around

The three releases in the project's history are all maintenance work, and reading them is the fastest way to learn where timg is actually fragile.

Version 1.6.3, published 2025-09-27, is described as a maintenance release with no new features. It removes a call to a deprecated function in ffmpeg for easier compilation on modern systems, and fixes a crash in terminal background color detection that can happen over a slow ssh connection. That second fix is telling: the failure mode is a slow network link, which is exactly the situation timg is designed for.

Version 1.6.2, published 2025-05-11, is the interesting one. It states that various terminals with Sixel support have different subtle and incompatible ways of treating cursor placement and dealing with newlines, and adds an environment variable called TIMG_SIXEL_NEWLINE_WORKAROUND so you can choose a behaviour when it cannot be auto-detected. It also adds more ways to detect terminals and debug the process. Auto-detection being insufficient is the honest admission here, and the presence of a manual override is the right response.

Version 1.6.1, published 2025-01-02, fixes an animation bug where the same image ID was used twice in kitty terminals, in an animation followed by a static image. Three releases, three platforms, and each fix is specific to one of them.

## Video, alpha handling, output geometry and threading

Beyond the pixelation choice there is a set of options that determine how timg behaves in a pipeline rather than in front of a person.

Alpha is handled explicitly, which is more than most terminal viewers do. `-b` sets the background color behind the alpha channel, accepting a color name, an #rrggbb value, 'auto' for the terminal background color, or 'none', and it defaults to 'auto'. `-B` sets the checkerboard pattern color used on alpha, and `--pattern-size` scales that pattern as an integer factor. There is also `--auto-crop`, which crops away same-colored pixels around the image, with an optional pre-crop width to remove an uneven border first.

Geometry is in character cells, not pixels. `-g<w>x<h>` takes a partial geometry, leaving out one value and deriving the other from the terminal size, and the default derived from terminal size is 160x50. `-C` centers horizontally in the available cell, and `-W` scales to fit width even if that exceeds the height, which is what you want for a wide screenshot. `-U` allows upscaling, optionally only in integer steps, which matters for small icons.

Two options point at performance on constrained machines. `--threads=<n>` runs image decoding in parallel, and `--compress[=level]` applies only to the kitty and iTerm2 modes, trading more CPU for less bandwidth over a slow link. `-o<outfile>` writes to a file instead of stdout, and the README notes that redirecting output to a file lets you `cat` it later, and that even `less -R` is happy with it. Combined with `-E` to leave the cursor visible, these make the tool scriptable in a way that a GUI viewer is not.

## Where to get it, and what a packaged build might leave out

The README points at timg.sh for binaries, and the release notes for 1.6.3 add the caveat that matters: the distributed app-image is a very bare-bones version with few dependencies, and for full timg with videos, PDFs and SVG support you should compile it yourself or get it via your OS distribution. That distinction decides whether a packaged build is right for you, and it is easy to miss.

The build system is CMake, and the tree shows a conventional C++ layout: CMakeLists.txt at the root, a cmake/ directory for modules, src/ for the code, third_party/ for vendored dependencies, man/ for the manual page, scripts/ for helper scripts, and a shell.nix for Nix users. There is a .clang-format and an .editorconfig, so formatting is enforced rather than argued about.

Format support is broader than the badge list suggests, and the release note mentioning PDFs and SVG alongside video implies those decoders are compiled in for full builds. The topic tags cover the terminal protocol side of it: sixel, sixel-graphics, kitty-terminal, iterm2, xterm, imagemagick, unicode-art and ascii-art. Licence is GPL-2.0, with the LICENSE file at the root.

The repository has 36 open issues and the last push was on 2026-08-05, with the most recent release tag from 2025-09-27. That gap is normal for a working utility, but it does mean features listed in a blog post about timg may not exist yet in a release.

## Conclusion

timg is the tool to install if you spend your day over ssh and want to check whether an image is what you think it is without opening a viewer on the far end. The graphics protocol support means it does not degrade to a toy on a modern terminal, and the block character fallback is good enough for a sanity check when it does. What to verify first is your terminal's protocol, because the pixelation mode is chosen automatically and can be wrong, and version 1.6.2 added the TIMG_SIXEL_NEWLINE_WORKAROUND environment variable precisely because Sixel terminals disagree subtly about cursor placement and newlines in ways that could not always be auto-detected. Second, check where your packaged binary came from: the release notes for 1.6.3 warn that the distributed app-image is a bare-bones build with few dependencies, and that a full timg with video, PDF and SVG support needs compiling yourself or installing from your OS distribution. Given the last push was on 2026-08-05 and the newest release is 1.6.3 from 2025-09-27, this is a mature, slow-moving utility where the code is more interesting than the changelog.

## FAQ

### What is the best terminal image viewer for Linux?

timg is a strong candidate for that description and its own README does not claim otherwise. It uses Sixel, the kitty graphics protocol or the iTerm2 graphics protocol for full resolution where the terminal supports them, and falls back to 24-bit color half or quarter block characters where it does not. It also plays videos and animated GIFs, and version 1.6.3 was published on 2025-09-27.

### How can I display an image in the terminal?

Pass the filename to timg, which auto-detects your terminal's graphics support and picks a pixelation mode, falling back to quarter blocks. Use `-p` to force a mode such as `-pk` for kitty graphics, `-pi` for iTerm2 or `-ps` for sixel, and `--grid=<cols>[x<rows>]` to arrange several images as a contact sheet.

### My Sixel images are broken or offset in my terminal, what can I do?

Terminals with Sixel support treat cursor placement and newlines in subtly different ways, which version 1.6.2 of timg describes as incompatible between implementations. It added the TIMG_SIXEL_NEWLINE_WORKAROUND environment variable so you can pick a behaviour when it cannot be auto-detected, and more verbose terminal detection for debugging.

### Does a packaged timg binary support video and PDF files?

Not necessarily. The notes for release 1.6.3 say the distributed app-image is a very bare-bones version with few dependencies, and that for full timg with videos, PDFs and SVG support you should compile it yourself or install via your OS distribution.

## Sources

- [hzeller/timg on GitHub](https://github.com/hzeller/timg)
- [Issues](https://github.com/hzeller/timg/issues)
- [License: GPL-2.0](https://github.com/hzeller/timg/blob/main/LICENSE)
- [README](https://github.com/hzeller/timg/blob/main/README.md)
- [Releases](https://github.com/hzeller/timg/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/hzeller-timg
