Skip to main content
14.03.2026

Terminal Graphics Protocols: Kitty, Sixel, iTerm2, and Beyond

Terminal Graphics Protocols

Quick Reference:

# Kitty - display image
kitty +kitten icat image.png

# Sixel - using img2sixel
img2sixel image.png

# iTerm2 - using imgcat
imgcat image.png

# Check terminal capabilities
echo $TERM
printf '\e[>q'  # Query terminal type

Terminals have evolved far beyond text. Modern terminal emulators can display images, render plots, and show previews directly in your workflow. But with multiple competing protocols, choosing the right one matters.

Why Terminal Graphics?

For DevOps and SRE teams, terminal graphics enable:

  • Monitoring dashboards rendered directly in tmux
  • Log visualization without leaving the terminal
  • Image previews in file managers like ranger or lf
  • Plot rendering from Python/R scripts
  • Documentation with embedded diagrams

The Major Protocols

Kitty Graphics Protocol

The most capable modern protocol, developed for the Kitty terminal.

Supported by: Kitty, WezTerm, Konsole (partial), Ghostty

Capabilities:

  • True color images (24-bit)
  • Animation support
  • Image placement at any position
  • Virtual image placements (reference same image multiple times)
  • Unicode placeholders for text reflow
# Display image with kitty
kitty +kitten icat photo.png

# With specific dimensions
kitty +kitten icat --place 80x24@0x0 photo.png

# Transfer and display programmatically
printf '\e_Gf=100,t=d,a=T;%s\e\\' "$(base64 < image.png)"

Pros:

  • Most feature-rich protocol
  • Efficient binary transfer
  • Great tmux integration (with passthrough)

Cons:

  • Limited terminal support outside Kitty ecosystem
  • Complex escape sequence format

Sixel

The oldest graphics protocol, dating back to DEC terminals in the 1980s.

Supported by: xterm, mlterm, mintty, foot, WezTerm, Contour

Capabilities:

  • Palette-based images (up to 256 colors typically)
  • Works over SSH without special handling
  • Broad terminal support
# Install img2sixel
apt install libsixel-bin  # Debian/Ubuntu
brew install libsixel     # macOS

# Display image
img2sixel image.png

# With width limit
img2sixel -w 800 image.png

# From ImageMagick
convert image.png sixel:-

Pros:

  • Widest terminal compatibility
  • Works over SSH naturally
  • Simple integration

Cons:

  • Limited color palette
  • No animation
  • Can be slow for large images

iTerm2 Inline Images

Apple-focused protocol used by iTerm2 and compatible terminals.

Supported by: iTerm2, Hyper, VSCode terminal, WezTerm

Capabilities:

  • True color images
  • File downloads
  • Custom dimensions
  • Inline rendering
# Using imgcat (included with iTerm2)
imgcat image.png

# With dimensions
imgcat -W 500px image.png

# The escape sequence format
printf '\e]1337;File=inline=1;width=auto;height=auto:%s\a' \
  "$(base64 < image.png)"

Pros:

  • Native macOS integration
  • Simple format
  • Supports file metadata

Cons:

  • Primarily macOS-focused
  • Limited Linux support

tmux Passthrough

Not a graphics protocol itself, but essential for using graphics inside tmux.

# Enable passthrough in tmux.conf
set -g allow-passthrough on

# For Kitty graphics in tmux
kitty +kitten icat --transfer-mode=stream image.png

# Or set the option globally
set -gq allow-passthrough all

Modern terminals handle passthrough differently:

Terminal Passthrough Support
Kitty Full (stream mode)
WezTerm Full
iTerm2 Partial
Ghostty Full

Comparison Table

Feature Kitty Sixel iTerm2
Color depth 24-bit 256 colors 24-bit
Animation Yes No No
tmux support Stream mode Limited Partial
SSH friendly Needs setup Yes Needs setup
Terminal support Growing Widest macOS-focused
Performance Excellent Good Good

Detection and Fallback

Detect terminal capabilities at runtime:

#!/bin/bash
# detect-graphics.sh

detect_graphics_protocol() {
    case "$TERM" in
        xterm-kitty|kitty*)
            echo "kitty"
            ;;
        *)
            # Check for Sixel support
            if printf '\e[?2;1;0S' && read -t 1 -s -d 'S' response; then
                echo "sixel"
            # Check for iTerm2
            elif [[ "$TERM_PROGRAM" == "iTerm.app" ]]; then
                echo "iterm2"
            else
                echo "none"
            fi
            ;;
    esac
}

display_image() {
    local file="$1"
    case "$(detect_graphics_protocol)" in
        kitty)
            kitty +kitten icat "$file"
            ;;
        sixel)
            img2sixel "$file"
            ;;
        iterm2)
            imgcat "$file"
            ;;
        *)
            echo "[Image: $file]"
            ;;
    esac
}

Practical Use Cases

1. File Manager Integration

Configure ranger to use terminal graphics:

# ~/.config/ranger/rc.conf
set preview_images true
set preview_images_method kitty  # or sixel, iterm2

For lf file manager:

# ~/.config/lf/lfrc
set previewer ~/.config/lf/previewer.sh
set cleaner ~/.config/lf/cleaner.sh

2. Python Plotting

Display matplotlib plots directly in terminal:

import matplotlib.pyplot as plt
import matplotlib
matplotlib.use('module://matplotlib-backend-kitty')

plt.plot([1, 2, 3], [1, 4, 9])
plt.show()  # Renders in terminal

For Sixel:

matplotlib.use('module://sixel')

3. Monitoring Dashboards

Render Grafana panels in tmux:

#!/bin/bash
# grafana-terminal.sh

GRAFANA_URL="http://grafana:3000"
PANEL_ID="2"

# Fetch panel as PNG and display
curl -s "$GRAFANA_URL/render/d-solo/abc123?panelId=$PANEL_ID&width=800&height=400" \
    | kitty +kitten icat --stdin=yes

4. Git Diff with Images

Display image diffs in git:

# ~/.gitconfig
[diff "image"]
    textconv = kitty +kitten icat --place 40x20@0x0

SSH Considerations

Graphics protocols behave differently over SSH:

Sixel works naturally - escape sequences pass through unchanged.

Kitty requires file transfer setup:

# On remote, use stream transfer
kitty +kitten icat --transfer-mode=stream image.png

# Or set up kitty's SSH integration
kitty +kitten ssh user@host

iTerm2 needs tmux integration or imgcat wrapper scripts on the remote.

Performance Tips

  1. Resize images before display - terminals struggle with multi-megabyte images

    convert large.png -resize 800x600 - | kitty +kitten icat
    
  2. Use appropriate protocol - Sixel for compatibility, Kitty for features

  3. Cache rendered output - especially for frequently-viewed images

  4. Set size limits - prevent runaway image rendering

    # In kitty.conf
    image_max_width 1920
    image_max_height 1080
    

Troubleshooting

Images not displaying

Check terminal support:

# For Kitty
echo -e '\e_Gi=1,a=q\e\\'

# For Sixel (should show colored blocks)
printf '\ePq#0;2;0;0;0#1;2;100;100;100#1~@-#0~@-\e\\'

tmux breaks graphics

Enable passthrough:

tmux set -g allow-passthrough on
# Then reconnect to session

SSH garbles images

For Kitty, use the SSH kitten:

kitty +kitten ssh user@host

For Sixel, ensure TERM is set correctly:

TERM=xterm-256color ssh user@host

Conclusion

For most DevOps workflows:

  • Use Kitty protocol if you control your terminal environment (best features, tmux support)
  • Use Sixel for maximum compatibility, especially over SSH
  • Use iTerm2 if you're macOS-only

The trend is toward Kitty protocol adoption, with WezTerm, Ghostty, and Konsole adding support. But Sixel remains the safe fallback for heterogeneous environments.


Building terminal-based monitoring tools? Akmatori agents render incident timelines and metrics directly in your terminal workflow.

Automate incident response and prevent on-call burnout with AI-driven agents!