# viexp Roadmap — Rust + English in 20-hour sprints Method: Josh Kaufman, **"The First 20 Hours"** — rapid skill acquisition. The project is split into isolated 20-hour sprints (~45 min/day for a month each). Every sprint: one Rust sub-skill, one working app increment, one English artifact. The goal of each sprint is to cross the frustration barrier and ship something that runs — not perfect code. **Kaufman's rules, adapted** | Kaufman principle | How this roadmap applies it | |---|---| | Deconstruct the skill | The table below: each sprint = one sub-skill + one app increment | | Learn just enough to self-correct | Per-sprint "Rust focus — the vital 20%": the minimum theory to *read your own compiler errors*. Every error goes to the ErrorJournal with a self-correction cue | | Remove barriers to practice | Sprint 0 sets up the whole environment: toolchain, linters, fast feedback (`bacon`), Gitea board, CI. Never debug your setup during practice time | | Fast feedback loops | `cargo check`/bacon on save, unit tests per session, immediate AI code review of each session's diff (commit → review → fix) | | Quantity over quality | Many small commits, many small drills. Working ugly code beats beautiful unfinished code. No over-engineering before v0.1 | ## Skill deconstruction **Rust sub-skills** (learned in order): cargo & project layout → types & control flow → ownership/borrowing → structs, enums, pattern matching → `Option`/`Result` & `?` → modules & crates → traits & generics → iterators → `Path`/`fs` & error handling (`thiserror`/`anyhow`) → serde/TOML → lifetimes → trait objects & dynamic dispatch → threads & channels → async/await & tokio → process spawning → caching & performance. **App increments** (each demoable): `vls` CLI → 3-pane TUI → navigation & file ops → config & openers → text previews → image previews → document previews → media & async → script plugins → power features → performance → release. **English track**: every commit message, every issue, all docs — English only. One written artifact per sprint. Daily DevLog (3–5 sentences). See [[workflows/english-workflow|English workflow]]. ## Session rhythm (45 min, every day) 1. **5 min** — read yesterday's DevLog + ErrorJournal; `git pull`, `bacon` starts. 2. **30 min** — today's drill or feature slice (one drill = one commit). 3. **10 min** — get the diff reviewed, fix what the reviewer flags, write the DevLog entry. **Frustration rules**: stuck >20 min on one error → ask for a review instead of grinding; never end a session with broken code (revert to green); a slow day is a reading day (Rust Book chapter in English) — log it, no guilt. ## Sprints Legend: 🎯 milestone. Each sprint gets a `docs/sprints/sprint-NN-*.md` note (Sprint template) and a Gitea milestone with issues created from its Definition of Done. --- ### Sprint 0 — Setup & deconstruction (≈6 h, short) - **App deliverable**: empty `viexp` cargo project that compiles, `cargo test` runs one trivial test, CI (Gitea Actions) is green, `bacon` + `clippy` + `rustfmt` wired, Gitea board ready. - **Rust focus**: toolchain mental model — what cargo, rustc, crates.io, `Cargo.toml` are; read your first compiler error on purpose (break a program, fix it). - **English**: README "Status" section + the vault (this roadmap counts). - **DoD**: `cargo bacon` shows check+test on save; first commit pushed; Sprint-1 issues exist. ### Sprint 1 — Rust core via `vls` (20 h) - **App deliverable**: `viexp ls` subcommand — a better `ls`: colored names by type, human-readable sizes, `--sort name|size|mtime`, `--hidden`, `--long`; ≥10 unit tests. - **Rust focus (vital 20%)**: variables & types, functions, `if`/`match`, loops, `Vec`/`String` vs `&str`, structs & enums, `Option`/`Result` + `?`, modules, `#[cfg(test)]`. Rust Book ch. 1–9 (skim 7/8), rustlings `intro→enums`. - **English**: README usage section; article "Why build a file manager in Rust" (draft). - **DoD**: `vls ~/` output beats `ls` for your eyes; clippy clean; tests green. ### Sprint 2 — First TUI (20 h) — the borrow-checker sprint - **App deliverable**: three-pane Miller layout (parent / current / placeholder preview), `j/k/gg/G` cursor movement, `:q` quits, resize-safe redraw, no flicker. - **Rust focus**: **ownership & borrowing in anger** (the state struct owns everything), references vs clones, lifetimes as they appear in ratatui calls, the event-loop pattern (poll event → mutate state → redraw). Rust Book ch. 4, 10.3 (skim), ratatui official docs. - **English**: keymap reference table in docs (precise imperative phrasing). - **DoD**: navigate a 10k-file directory smoothly; panic-free for 15 min of use. ### Sprint 3 — Navigation & file ops (20 h) 🎯 **M1: personal daily driver** - **App deliverable**: enter/leave directories, hidden toggle, sort cycling, `Space`/`V` selection, `yy`/`dd`/`pp` copy/cut/paste, delete → **first-class trash** (freedescompliant) with undo, `:mkdir :touch :rename`, status bar (path, size, free space — **not** per-frame `statvfs`; 1 Hz poll). - **Rust focus**: `Path`/`PathBuf`, `fs::read_dir`/`metadata`, real error handling (`thiserror` for lib-style internals, `anyhow` at main), iterators (`map/filter/sort_by` chains), `Display` impls. - **English**: article "Week one of dogfooding my own file manager". - **DoD**: use viexp instead of ranger for real work for 3 days; log every pain point as an issue. ### Sprint 4 — Config & openers (20 h) - **App deliverable**: `viexp.toml` (defaults, theme colors, sort) + `modules.toml` registry v0 (ADR-003): mime/glob → opener, per-module `enabled`, user rules prepend/append; opener engine (infer + xdg-mime → rule table → `xdg-open` fallback), `r` "open with" menu, `:open_with`. - **Rust focus**: serde derive on enums/structs, `Default` + merge semantics, `HashMap`/ `BTreeMap`, first **trait design** (`Opener`), builder-ish config loading with helpful errors. - **English**: configuration guide draft (reference-style writing). - **DoD**: any file opens with your preferred app from config alone; broken TOML produces a friendly error, not a panic. ### Sprint 5 — Text previews & bulk rename (20 h) - **App deliverable**: preview pane v1 — syntax-highlighted text (syntect) with line numbers and scrolling, directory preview, file metadata panel, zip/tar listing, `:bulkrename` via `$EDITOR` (ranger's killer feature), `n/N` plain search, `:` command history. - **Rust focus**: lifetimes in real signatures, **trait objects** (`Box` registry), advanced iterators, caching keyed by `(path, mtime)`. - **English**: article "How a TUI paints text" (explaining rendering → strongest writing practice). - **DoD**: preview parity with ranger for text/code/archive files. ### Sprint 6 — Image previews (20 h) 🎯 **M2a** - **App deliverable**: image module through the registry; **kitty graphics adapter first** (owner's terminal), chafa/halfblocks floor; thumbnail disk cache + LRU; runtime disable/replace via `modules.toml` proven on images. - **Rust focus**: the `image` crate, decode/resize pipeline, `#[cfg(feature)]` modules, pixel data, spawning helper processes safely. - **English**: article "How terminals display images" (kitty protocol, sixel, ueberzug++ — your best future blog post; research notes already hold the material). - **DoD**: PNG/JPEG/WebP/GIF preview instantly in kitty; `enabled=false` kills it in one line. ### Sprint 7 — Document previews (20 h) 🎯 **M2b: full ranger replacement** - **App deliverable**: PDF (pdfium-render, Apache-2.0), EPUB (hand-rolled zip+XML — **GPL trap avoided**), Markdown (comrak/termimad), DJVU (djvu-rs + `ddjvu` fallback config). All as registry modules, all runtime-disableable. - **Rust focus**: binary data & byte streams, feature-gated crates, error taxonomy design, more trait objects; reading crate docs as a skill. - **English**: module documentation pages (PDF/EPUB/DJVU) in user-guide style. - **DoD**: your entire document library previews; ranger uninstalled. ### Sprint 8 — Media & async (20 h) 🎯 **M2c** - **App deliverable**: video thumbnail (spawn `ffmpeg -ss … -vframes 1`), audio metadata + cover art (`ffprobe` JSON), **background preview pipeline**: std threads + mpsc now, generation-counter cancellation, large-directory pagination; adopt **tokio** for the pipeline by sprint end (ADR-005). - **Rust focus**: `std::thread`, `mpsc`, `Arc`/`Mutex`, then async/await, `tokio::spawn`, `select!`, cancellation patterns. Rust Book ch. 16 + async book chapters (English only!). - **English**: article "Async Rust for a skeptic" — explain threads-vs-tokio in your own words. - **DoD**: 4K-video directory scrolls at full speed; huge directory never blocks input. ### Sprint 9 — Script plugin protocol (20 h) 🎯 **M3a: extensible** - **App deliverable**: freeze the **external plugin contract** (ADR-002 phase 2): previewer argv `(path, w, h, x, y)` + env context + FIFO write-back + `cleaner` hook; documented exit codes & SIGPIPE; opener scripts; `plugins/` dir discovery; two reference plugins (bash: torrent info; python: git repo summary). - **Rust focus**: process spawning & pipes, timeouts, safe command construction (no shell injection), protocol design & semver, integration tests with fixture scripts. - **English**: **plugin author guide** — the sprint's main artifact; write it as if for strangers. - **DoD**: a script written only from the guide (no source peeking) works. ### Sprint 10 — Power features (20 h) 🎯 **M3b: feature parity with your ranger config** - **App deliverable**: tabs, bookmarks + marks, fuzzy finder (nucleo) with **interruptible** search (broot lesson), `:commands` set (`:find :delete :copy…`), `push` key-simulation, shell integration `--choosefile/--choosedir/--selectfile`, cd-on-exit wrapper script, session restore. - **Rust focus**: state machines (modes), Rc-free architecture review, `macro_rules!` for keymap tables, API refactoring under tests. - **English**: article "Vim-style UX patterns in file managers". - **DoD**: your shell rc sources the viexp wrapper; fuzzy find feels instant. ### Sprint 11 — Performance & robustness (20 h) - **App deliverable**: `notify`-based live directory updates, virtual scrolling, startup <50 ms, one-week dogfood with zero panics, `tracing` logs to file, panic hook restores the terminal, criterion benchmarks committed, crash-fix buffer. - **Rust focus**: profiling (`cargo flamegraph`, `perf`), benchmarking (criterion), reading someone else's code (yazi's) for patterns, hardening. - **English**: article "Profiling a TUI app: making viexp start in 40 ms". - **DoD**: benchmark numbers in README; a week of daily use logged. ### Sprint 12 — Release & docs (20 h) 🎯 **M4: v0.1.0 public** - **App deliverable**: `v0.1.0` — cargo-dist release builds, AUR PKGBUILD, Gitea release + changelog, **user guide** (mdBook in-repo), plugin examples gallery, install docs. - **Rust focus**: release engineering, MSRV policy, feature matrix testing, rustdoc comments on the public plugin API. - **English**: the user guide is the largest English artifact of the project; polish it hard. - **DoD**: a stranger installs from AUR and writes a plugin using only the docs. ### Backlog (post-1.0, priority order) Embedded Lua plugins (mlua, ADR-002 phase 3) · sixel/iTerm2/ueberzug++ adapters · DDS-style inter-instance pub/sub · `NNN_FIFO`-style hover event stream · themes gallery · zoxide jump · archive mount/browsing depth. ## Milestones | Milestone | After sprint | Meaning | |---|---|---| | M1 | 3 | daily driver for basic navigation/file ops | | M2a–c | 6–8 | full ranger replacement (images, docs, media) | | M3a–b | 9–10 | extensible by scripts, feature parity | | M4 | 12 | v0.1.0 released publicly | At 45 min/day this is roughly a 12–13 month journey to v0.1.0 — the point is a working product **and** durable skills, in that order, every single sprint. ## Cadence & safety nets - Sprint notes live in `docs/sprints/`; each sprint's DoD becomes Gitea issues (milestone per sprint) — see [[workflows/gitea-workflow|Gitea workflow]]. - If a sprint overruns by >30%, cut scope from the bottom of its DoD — never silently skip tests. - One "buffer week" is allowed between sprints; more than one means the sprint was too big — re-decompose in the retro.