Files
viexp/docs/research/rust-preview-stack.md
T

4.8 KiB
Raw Blame History

type, status, confidence, created, question, tags
type status confidence created question tags
research analyzed high 2026-10-17 Which Rust crates should render previews (images, PDF, DJVU, EPUB, markdown, media) in a terminal, with what licenses and fallbacks?
research
rust
crates
preview
ratatui

Rust preview stack (October 2026)

Versions verified against crates.io metadata on 2026-10-17.

Concern Crate Why Notes / license
TUI ratatui 0.30 + crossterm 0.29 De-facto standard; 0.30 split into ratatui-core/-widgets facade; yazi & felix use it MIT; MSRV 1.88
Images in TUI ratatui-image 11.1 kitty, sixel, iTerm2, halfblocks + Picker protocol/font detection; lives in the ratatui org MIT
Image decode image 0.25 yazi's choice; jpeg/png/gif/webp/bmp/tiff (+avif feature) MIT/Apache
Resize fast_image_resize 6.1 (SIMD) or image::thumbnail (triangle filter, yazi-style) hot loop MIT/Apache
Sixel encode quantette 0.6 (+ moxcms, palette) yazi's actual sixel pipeline MIT
PDF pdfium-render 0.9 + pdfium binary only mature page→image in-process option pdfium is Apache-2.0 (b redistribute, ~5 MB); spawn pdftoppm as fallback
DJVU djvu-rs 0.43 (pure Rust, render→image) first usable pure-Rust DjVu decoder 6 months old — keep ddjvu fallback
EPUB hand-rolled: zip + quick-xml/html-to-text the epub crate is GPL-3.0 — viral if statically linked avoid the trap
Markdown comrak 0.56 → styled ratatui lines, or termimad (ready-made renderer) termimad = fastest integration (broot uses it) MIT
Syntax highlight syntect 5.3 yazi's choice; regex Sublime syntaxes, no C deps tree-sitter = heavier, per-language grammars
Media metadata spawn ffprobe -print_format json no linking pain; what yazi does ffmpeg-next ties you to system FFmpeg — avoid
Video thumbnail spawn ffmpeg -ss … -vframes 1 -vf scale… (+ attached_pic cover-art fallback) yazi's proven recipe —
Audio (optional in-process) symphonia 0.6 pure-Rust metadata/album art MPL-2.0
MIME infer 0.22 (magic bytes) + xdg-mime 0.4 (extension DB) fast sniffing + correct text/* new_mime_guess unmaintained — avoid
FS events notify 8.2 yazi's watcher CC0
Fuzzy nucleo 0.5 Helix's matcher, library-first MPL-2.0
Config serde + toml 1.1 yazi's set solid
Errors/logs anyhow + thiserror 2.x + tracing boring and correct —
Async tokio 1.x with results marshalled to a single-threaded UI actor yazi's exact architecture; ecosystem is tokio-first start threads-only, adopt tokio in Sprint 8

Image protocol fallback chain (first match wins)

  1. kitty graphics (unicode-placeholder mode) — kitty ≥0.28, Ghostty ← our primary target
  2. iTerm2 inline — WezTerm, iTerm2, Warp, VSCode terminal
  3. sixel — foot, Konsole 22.04+, Windows Terminal ≥1.22, WezTerm, rio
  4. ueberzug++ subprocess — X11 + Wayland (wlroots compositors: sway/hyprland/niri/wayfire); the only option for alacritty; not GNOME/KDE compositors
  5. chafa / halfblocks — works everywhere incl. SSH and tmux
  6. text: filename + size + mime

Terminal facts (Oct 2026): kitty has no sixel by design; alacritty rejected both protocols; tmux needs allow-passthrough on and never passes kitty-old. The daily terminal here is kitty without a multiplexer → tier 1 covers the primary user; tiers 3–5 cover everyone else.

Thumbnail caching (yazi-proven)

Decode once at preview size (max ~600×900, triangle filter) → persist rendered pages/frames to a disk cache dir → keep decoded previews in an in-process LRU → preload neighbors in background. Re-encoding for a protocol is cheap; re-decoding is not.

Risk notes

  • GPL traps: epub crate (static link), ueberzug++ (fine — spawned), pdftoppm (fine — spawned).
  • pdfium must be shipped as a binary (~5 MB/platform) or static-linked via pdfium-render static.
  • djvu-rs is young; config-selectable ddjvu fallback required.
  • ratatui 0.30 subcrate split may cause ecosystem churn in 2026 — pin carefully.

Outcome

Feeds ADR-001, ADR-004 and Sprints 5–8 crate choices.

Sources