terminal-craft · 1:tmux 2:nvim cheatsheets 10/10 + netrw · 2026-08-08
$ whoami

Building tmux and nvim fluency, on purpose, for AI-coding work.

A hands-on record of seven lessons — drilled live, not just read about — aimed at one thing: less friction reviewing and steering AI-generated code, at the keyboard, without breaking flow.

10 / 10 curriculum + 1 reinforcement eli5 teaching method 2 days, real friction included

Why this exists

The keyboard is the bottleneck in AI-coding work — not the model.

Heavy AI-coding sessions mean juggling multiple agents, reviewing long diffs, and jumping around large files fast. None of that is a model problem. It's a terminal-fluency problem — and it's fixable with the same tools that have existed for decades, used properly.

Terminal-Craft is a side project built to close that gap: real muscle memory in tmux for orchestrating concurrent AI-agent sessions, and in nvim for fast, confident editing and review — not a full IDE replacement, just fluency where it counts.

PHASE 1

tmux

Sessions, windows, panes · detach/reattach across real disconnects · layouts for running multiple agents side-by-side.

PHASE 2

nvim

Motions, registers, macros · multi-file navigation · search/replace · basic LSP — editing fluency, deliberately not a full IDE build-out.

PHASE 3

Shell + dotfiles

History, aliases, functions, PATH · why modern CLI tools replace their classic-Unix predecessors · a real Mac-to-Mac migration system.

The method

Every lesson starts with a real scenario, not a command list.

Each lesson opens with a floor question — a concrete situation pulled from actual AI-coding work — then builds the answer one small step at a time, deriving the rule rather than just handing over syntax. Where something genuinely can't be derived (new syntax, a raw keystroke convention), it's taught directly and flagged as such. Every lesson ends with a hands-on drill, done live, not just discussed.

The lessons

All ten, plus what came after.

01

Sessions, windows, panes

Floor questionWhat has to be true, technically, for a running program to survive you closing the terminal window that started it?

Landed: Session = the process container that survives disconnect. Window = a full-screen switchable view, preserved untouched when unfocused. Pane = a simultaneously-visible split of one window. Rule of thumb: needs to survive and be returned to intact → new window. Needs to be seen at the same time, permanently → new pane.

juniorSplit a pane whenever something new comes up — fast, visually satisfying. seniorAsk first: does this need to survive independently, or just be visible at the same time? Splitting wrong doesn't error — it quietly mutates the layout you meant to keep.
Unplanned, but useful A follow-up question pushed past "the session keeps running" into where it actually runs — a real process tree on whichever machine started it. Laptop sleep pauses everything; shutdown kills the whole tmux server. That distinction is the entire reason unattended long jobs need a remote box, not a laptop.
02

Detach / reattach in practice

Floor questionSSH'd into a remote box running a long job in tmux. Wifi drops mid-session — not a clean detach, just gone. Does tmux know you left, and does it care?

Landed: A dropped connection and a clean detach look identical to tmux — it has no concept of "the connection died," only "the attached terminal went away." Reattaching is always the same command regardless of cause, because nothing ever needed special recovery.

juniorReach for attach as the default verb, even when starting something brand new. seniorattach only targets something that already exists. Ask first: does this session exist yet, or am I creating it right now?
03

Layouts for multiple agents

Floor questionRunning two AI agents at once — one per project — watching both, glancing between, sometimes copying between them. Which construct holds each agent, and why?

Landed: The lesson plan gave way to a bigger, more honest question — "I understand window and pane, not session." The real rule: pane = same task, both visible at once. Window = different task, shared blast radius is fine. Session = different enough that a crash in one must never touch the other. Conclusion: one tmux session per project, windows for sub-tasks inside it — the same isolation principle already used for code repos, applied to the terminal.

juniorDefault to "more windows" for anything new. seniorAsk about blast radius: would a crash here be acceptable to also take down that? If no, it's a new session.
Caught live, on-camera Drilling the tiled layout for real, a claim from earlier in the lesson — "4 presets" — turned out to be wrong. Checking tmux list-keys against the actual config showed 5: even-horizontal, even-vertical, main-horizontal, main-vertical, tiled. Corrected on the spot, credited as a real catch, not smoothed over.
04

Motions, registers, macros

Floor questionReviewing a long AI-generated diff — line 40, then 200, then back to 55. How do you move between them without breaking flow?

Landed: Motions are direct-targeting keystrokes (jump to a line, jump to a pattern). Registers are named clipboard slots that fix the one-slot overwrite problem. Macros aren't primarily about saving keystrokes — the real value is guaranteed identical execution on every repeat, so correctness doesn't quietly degrade on repeat nine of fifteen the way manual repetition does.

juniorJustify macros as "saves keystrokes" — true, but doesn't explain why this beats manual repetition specifically. seniorConsistency under repetition is the actual value — AI-code review often means the same fix, applied uniformly, everywhere it's needed.
The hard one The first live attempt exposed a real gap: mode-switching and undo had never been taught, despite being more foundational than anything else in the lesson. A confusion cascade followed — a terminal's own UI chrome was masking vim's mode indicator, and the real signal turned out to be cursor shape, not status text. A genuine "I don't know how to undo this" moment got resolved with one command (u). The session paused there on purpose, and resumed later with mode-switching and undo taught first, from zero.
05

Multi-file navigation

Floor questionOne file calls a function; the function it's actually calling lives in another file and does something unexpected. Check the other file, then come back — without losing your place.

Landed: Split-and-load shows two files at once when you genuinely need both visible. A direct buffer swap replaces what's on screen with no split at all, for a quick look-and-return. The choice between them isn't a fixed rule — it's a judgment call.

juniorSplit every time you need to check another file — works, but clutters the screen. seniorSame question as the pane-vs-window rule from Lesson 3: do I need both visible at once, or am I just hopping over and back?
06

Search / replace

Floor questionThe same variable name is scattered across an entire file and needs to change everywhere. Macros could do it — what's the problem, and is there something more direct?

Landed: A whole-file substitute changes every match with zero per-occurrence navigation — a fundamentally different move from a macro, which still requires walking to each match even once the edit itself is automated. A confirm-each-match variant adds a review step for anything you're not fully sure about — the same shape as reviewing a diff hunk by hunk before staging it.

juniorReach for a macro whenever the same text needs to change everywhere. seniorRecognize "same pattern, everywhere in the file" as its own case — skip navigation entirely, save macros for edits that aren't a pure text swap.
07

Basic LSP

Floor questionJumping to a definition, so far, has meant manually opening a file and eyeballing it. What if the editor actually understood the code's structure instead of just matching text?

Landed: A language server gives real structural understanding — jump-to-definition that's instant and correct, across files, because the tool knows what a symbol actually is. But the sharper insight: a type-checker's silence is not proof of correctness. It caught a real introduced bug instantly — but the file's actual pre-existing bug, a parameter no caller ever passed, was invisible to it the entire time. That's not a flaw in the tool; it's a different, harder problem than type-checking.

juniorTreat "find the definition" as a manual search problem, even with a language server available. seniorReach for the structural jump first — and separately, know exactly what a clean type-check does and doesn't guarantee.
The only real setup, on purpose This was the sole lesson requiring actual configuration — a language server installed, wired into the editor for the first time. Every prior lesson ran on a completely untouched baseline. The one real bug in the practice code was deliberately introduced and confirmed live: the tool caught the fake bug instantly, and never once flagged the real one.
+44 lines the only config change in the tmux/nvim curriculum
08

Shell fundamentals + history

Floor questionYou run a command, then a minute later want to run something almost identical — just tweak one flag. What do you actually do?

Landed: Reverse history search (type a fragment, jump straight to the most recent match) beats counting arrow-key presses. An alias is pure text substitution — no logic, no arguments, only expands at the start of a line. A function is real code — takes arguments, chains commands — for anything an alias can't express. PATH is an ordered, colon-separated list; first match wins, silently, which is why a newer tool can quietly lose to an older one shadowing it. Config files load once, at shell startup — source reapplies changes to a live shell without starting over.

juniorOpen a new terminal every time a config change needs to take effect. seniorReach for source ~/.zshrc first — reload in place, keep your session state.
09

Modern CLI tools

Floor questionls -la and a git-aware listing both show files in a directory. What's actually different about what the modern tool can show — and why?

Landed: One pattern, confirmed four separate times. A git-aware lister queries git per-file because it was built to; plain ls predates git entirely and has no way to ask. A gitignore-aware search tool skips node_modules/ automatically; grep has no concept of a gitignore file. A frecency-ranked directory jumper remembers what you actually use; cd has no memory at all. A structural JSON tool addresses a field by its real path; a text search tool can only pattern-match, and breaks the moment the file is minified onto one line.

juniorModern CLI tools are just faster, nicer-looking versions of the classics. seniorThey add context — version control state, ignore rules, usage history, data structure — that the tools they replace were built before that context existed, and structurally cannot see.
10

Dotfiles as a migration system

Floor questionYour laptop dies tomorrow. Dotfiles get you your editor config back — but every app and package installed over time isn't tracked anywhere. Could you actually list everything, right now?

Landed: A declarative, replayable file beats a name list every time — the same lesson as Lesson 6's search/replace, in a new domain. A package manager's own dump command captures formulae, casks, and taps as real install directives, not just names. But it has a hard blind spot: anything installed through the Mac App Store is structurally invisible to it. Running the App Store's own listing tool surfaced 30 real apps a package-manager-only approach would have silently missed entirely — including apps in daily use.

juniorTreat "dotfiles" as just the config files themselves — gets you a familiar editor, not a working machine. seniorMigration means covering everything a fresh machine needs, including an honest accounting of what has no automatable path at all, instead of pretending that category doesn't exist.
Two ideas, correctly parked Two reasonable scope-creep instincts came up mid-lesson — pruning long-unused apps, and migrating eligible apps to the package manager for consistency. Both got a real look (one confirmed a migration path actually existed) before being deliberately deferred as separate follow-ups, not bundled into the same sitting. Recognizing scope creep in the moment, even when the idea is good, is its own skill.
+1

netrw (file browser)

Floor questionYou're in nvim editing a file and need to open a different file in a sibling directory, but you don't remember the exact filename. :e <path> has been the tool since Lesson 5 for opening files directly — what's the actual limitation when you don't know the filename?

Landed: :e <path> requires the filename already known and typed — no browsing. :Ex (:Explore) opens netrw's directory listing in the current window, and given :sp/:vsp from Lesson 5, netrw's split variants follow the same pattern: :Sex (horizontal) and :Vex (vertical). The honest final insight: netrw isn't a persistent panel — every invocation is a full buffer that replaces or splits the current view, so you see the tree or the code, never both continuously the way a real docked sidebar does.

juniorReach for a file-tree plugin the moment file-browsing comes up, even when a capable built-in already exists. seniorTry the vanilla tool first, and name its actual limitation precisely — no persistent panel — instead of dismissing it or reflexively reaching for a plugin without feeling the real gap.
Right pattern, wrong letters — and no hands-on drill yet First attempt at deriving netrw's split commands from :sp/:vsp got the pattern right (split + explore) but guessed the wrong actual letters — corrected directly to :Sex/:Vex. This lesson was also verbal/conceptual only: done remotely from a phone, so nothing was actually typed into a live nvim session. The derivation and comprehension landed, but the real hands-on drill — opening netrw, navigating, creating/renaming/deleting a scratch file — is still owed.

Reference

Cheatsheets — the commands, without the story.

Every keystroke from every lesson above, kept as living reference docs in the repo and updated as the curriculum grows.

Status

Curriculum complete. Reinforcement is the work now.

All ten lessons are done, hands-on, including the parts that didn't go smoothly. There's no fixed count beyond this — the next addition only happens if a real gap surfaces from actually using tmux, nvim, or the migration system, the same way Lesson 3's biggest insight came from a detour nobody planned. Until then: use it, don't just remember it.