4.2 KiB
type, status, created, updated, tags, sources
| type | status | created | updated | tags | sources | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| article | published | 2026-10-17 | 2026-10-17 |
|
|
Terminal file managers in 2026: what viexp should learn from them
TL;DR — Ranger defined the interaction vocabulary; yazi proved a Rust rewrite can be both faster and more extensible; nnn and lf showed that scripts-as-APIs beat embedded interpreters for Linux users; joshuto and hunter showed how scope and toolchain choices kill projects. viexp takes ranger's UX, yazi's architecture patterns, and an extension model that starts declarative and grows to scripts, then Lua.
Introduction
Before writing viexp we studied nine terminal file managers (ranger, yazi, nnn, lf, joshuto, felix, hunter, vifm, broot, mc). This article condenses the four research notes above into the product decisions behind viexp. Full data lives in the linked research notes.
The three eras
- The blueprint (ranger, 2009–). Miller columns, vim keys,
:bulkrename, rifle opener rules,--choosefile. Still the most feature-complete — and still slow for structural reasons: a synchronous Python loop that stats every file inline,statvfson every frame (4–10 s j/k lag on network mounts, issue #1025), ~1 s interpreter startup, and an image preview stack built on an abandoned X11 tool (ueberzug). - The reaction (nnn, lf, vifm, 2015–). Minimalism and Unix philosophy. nnn fits in 150 KiB with zero config and extends through executables; lf keeps the UI responsive with async I/O and pushes previews to an external script; vifm goes the opposite way and makes config a programming language. Each proves a point: speed is a feature; process contracts are a complete extension API; but none ships native graphics, so preview ecosystems fragmented into incompatible script zoos.
- The synthesis (yazi, broot, 2023–). yazi is what happens when you take ranger's UX and
rebuild it on tokio + ratatui: paged preloading (only visible rows get work), prioritized
worker pools, three cancellation mechanisms, protocol auto-detection (kitty/iterm2/sixel/
ueberzug++/chafa), TOML config with
prepend_/append_merge, and Lua plugins through the same dispatch tables as built-ins. broot rethinks navigation itself around an interruptible, composable tree search.
The five decisions viexp takes from this
| # | Decision | Source | ADR |
|---|---|---|---|
| 1 | ratatui + crossterm UI, single-threaded actor fed by background workers | yazi, felix | ADR-001 |
| 2 | Extension model in three phases: TOML rules → external script contract → Lua | yazi tables, nnn/lf contracts, joshuto's failure | ADR-002 |
| 3 | Every file-type module (image/video/audio/pdf/djvu/epub/md) is a registry entry with a runtime enabled switch; cargo features only trim binaries |
yazi, Cargo book | ADR-003 |
| 4 | Image protocol chain: kitty → iterm2 → sixel → ueberzug++ → chafa/halfblocks, detected at runtime | yazi-adapter | ADR-004 |
| 5 | Async adopted gradually: sync core first, threads for previews, tokio for the full pipeline | lf (threads suffice) → yazi (tokio) | ADR-005 |
What we deliberately do not copy
- Full ranger parity in one release — the joshuto trap (5 config files, half-built command line, 14-month release gap). viexp ships a narrow polished core first.
- Nightly Rust or linked C media frameworks — the hunter trap. Stable toolchain; media via
spawned
ffmpeg/ffprobeprocesses. - A bespoke config DSL — the lf trap. TOML now, Lua later, never a private language.
- GPL-linked crates in the binary (
epubcrate) — spawned GPL tools (pdftoppm,ddjvu, ueberzug++) are fine; statically linked GPL is not.
Conclusions
The market gap viexp aims at: ranger's ergonomics with yazi-grade speed, a script-first extension model (Lua last, not first), and documentation-driven module replaceability — built as a learning project that teaches Rust and technical English at 20 hours per sprint.
Sources
See the four linked research notes; each ends with its own verified source list.