Render terminal text to beautiful PNG screenshots with full ANSI color support. Built for tmux users who need to share long terminal output as a single image.
English | 简体中文
- ANSI Color Rendering -- Faithfully renders 8/16/256/truecolor ANSI escape sequences including bold, dim, italic, underline, strikethrough, and reverse
- CJK Support -- Correct double-width character alignment with automatic CJK font fallback
- Symbol Fallback -- Automatic fallback for Unicode symbols (e.g.
U+23FA) missing from the primary font, using bitmap-hash tofu detection - Retina / HiDPI -- Default 2x rendering; macOS Preview displays at correct logical size
- Themes -- Built-in One Half Dark and One Half Light color schemes, with
--bg/--fgoverrides - tmux Integration -- One-key screenshot via
capture-panein tmux copy-mode, preserving ANSI colors - Flexible Input -- Reads from stdin pipe or system clipboard automatically
- Clipboard Output -- Copy the rendered PNG directly to the system clipboard
- Config File -- Persistent preferences via
~/.config/tmux-shot/config.toml - Cross-Platform -- macOS (primary) and Linux support
Requires Python 3.10+ and Pillow.
# From PyPI
pip install tmux-shot
# Or with pipx (isolated environment)
pipx install tmux-shot
# From source
git clone https://github.com/Async23/tmux-shot.git
cd tmux-shot
pip install -e .# Screenshot from clipboard, open in Preview
tmux-shot --open
# Pipe any command output
ls --color=always | tmux-shot --open
# Light theme + copy to clipboard
echo "hello world" | tmux-shot --light --clipboardtmux-shot uses tmux capture-pane -e to preserve ANSI escape sequences. The integration requires a helper script tmux-shot-capture that translates copy-mode selection coordinates into capture-pane line ranges.
- Install the helper script to your
$PATH:
# Copy from the project
cp scripts/tmux-shot-capture ~/.local/bin/
chmod +x ~/.local/bin/tmux-shot-capture- Add to
~/.tmux.conf:
# y = copy to clipboard (default)
bind -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "pbcopy"
# Y = screenshot selection (preserving ANSI colors) + copy to clipboard
bind -T copy-mode-vi Y if-shell -F '#{selection_present}' \
'run-shell -b "tmux-shot-capture #{selection_start_y} #{selection_end_y} #{history_size} --open --clipboard" ; \
send-keys -X copy-pipe-and-cancel "pbcopy"' \
'display-message "No selection"'- Reload tmux config:
tmux source ~/.tmux.conf
- Enter copy-mode:
prefix + [(or your custom binding) - Select text with
vand movement keys - Press
Y-- a PNG screenshot is generated, copied to clipboard, and opened in Preview
Y pressed in copy-mode
--> tmux expands #{selection_start_y}, #{selection_end_y}, #{history_size}
--> tmux-shot-capture converts to capture-pane line range
--> tmux capture-pane -e -p -S <start> -E <end> (preserves ANSI)
--> piped to tmux-shot for rendering
--> PNG saved, copied to clipboard, opened in Preview
Why not
copy-pipe? Thecopy-pipecommand sends plain text only, stripping all ANSI escape sequences. By usingcapture-pane -e, we preserve colors, bold, italic, and all other terminal formatting.
# Capture visible pane content
tmux capture-pane -p -e | tmux-shot --open
# Capture with scrollback (last 500 lines)
tmux capture-pane -p -e -S -500 | tmux-shot --openNote: Always use the
-eflag withtmux capture-paneto preserve ANSI escape sequences.
| Option | Default | Description |
|---|---|---|
-o, --output PATH |
/tmp/tmux-shot-<timestamp>.png |
Output file path |
--theme NAME |
one-half-dark |
Color theme (one-half-dark, one-half-light) |
--light |
Shortcut for --theme one-half-light |
|
--font PATH |
Auto-detected | Path to a monospace .ttf/.otf font file |
--font-size N |
16 |
Font size in logical pixels |
--padding N |
20 |
Image padding in logical pixels |
--line-height F |
1.0 |
Line height multiplier |
--scale N |
2 |
HiDPI scale factor (2 = Retina) |
--bg COLOR |
Theme default | Override background color (#rrggbb) |
--fg COLOR |
Theme default | Override foreground color (#rrggbb) |
--open |
false |
Open image in default viewer after rendering |
--clipboard |
false |
Copy image to system clipboard |
--version |
Show version and exit |
Create ~/.config/tmux-shot/config.toml for persistent preferences:
[general]
theme = "one-half-dark"
scale = 2
open = true # always open after rendering
[font]
family = "DejaVuSansM Nerd Font Mono" # path or font name
size = 16
line_height = 1.0
[layout]
padding = 20
tab_width = 8
[output]
directory = "/tmp"
clipboard = falseSettings are resolved in this order (highest priority first):
- CLI arguments --
--font-size 14 - Environment variables --
TMUX_SHOT_FONT_SIZE=14 - Config file --
~/.config/tmux-shot/config.toml - Built-in defaults
| Variable | Description |
|---|---|
TMUX_SHOT_THEME |
Color theme name |
TMUX_SHOT_FONT |
Font file path |
TMUX_SHOT_FONT_SIZE |
Font size |
TMUX_SHOT_PADDING |
Padding |
TMUX_SHOT_SCALE |
Scale factor |
TMUX_SHOT_OUTPUT_DIR |
Output directory |
| Feature | tmux-shot | freeze | silicon | termshot | carbon |
|---|---|---|---|---|---|
| ANSI color parsing | Yes | Yes | No | Yes | No |
| Syntax highlighting | No | Yes | Yes | No | Yes |
| tmux integration | Native | Manual | No | No | No |
| Clipboard in + out | Yes | No | Partial | No | No |
| CJK support | Yes | Partial | Yes | Unknown | Yes |
| Symbol fallback | Yes | No | No | No | No |
| Config file | Yes | Yes | Yes | No | N/A |
| PNG output | Yes | Yes | Yes | Yes | Yes |
| SVG output | No | Yes | No | No | Yes |
| Offline | Yes | Yes | Yes | Yes | No |
| Install | pip | brew/go | cargo | brew/go | Web |
tmux-shot focuses on a niche the others don't cover well:
- tmux-native: purpose-built
capture-paneworkflow -- select and press one key - ANSI + clipboard: parses real terminal escape sequences AND supports clipboard I/O
- CJK-first: double-width character alignment is a first-class feature
- Symbol-aware: bitmap-hash tofu detection with automatic fallback fonts
- Zero config: works immediately with
pip install, no Go/Rust toolchain needed
tmux-shot is structured as a modular Python package:
tmux_shot/
cli.py # CLI entry point and argument parsing
config.py # Config file, env vars, and defaults
input.py # Text acquisition (stdin / clipboard)
ansi.py # ANSI SGR escape sequence parser
layout.py # Character cell layout engine
fonts.py # Font loading with CJK + symbol fallback
renderer.py # Pillow-based image rendering
themes.py # Color scheme definitions
output.py # File save, clipboard copy, preview
See docs/DESIGN.md for the full architecture and rendering pipeline documentation.
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/my-feature) - Make your changes
- Run linting and tests:
ruff check . ruff format --check . pytest
- Submit a pull request
git clone https://github.com/Async23/tmux-shot.git
cd tmux-shot
pip install -e ".[toml]"