The Weekly Learning Plan
A calendar-shaped version of the roadmap, for people who prefer a schedule to a checklist. Sixteen weeks at roughly 8–12 hours per week — evenings and one weekend session.
Adjust freely. The only rule that matters is the one from the teaching method: do not move on until the current behavior can be inspected and explained. A week that ends with working code you cannot explain is a week you will repay with interest in week 11.
The Shape of the Course
W0 ▓ Warm-up + mental model no code
W1-3 ▓▓▓ Section 1: PTYs and processes M1-M3
W4-8 ▓▓▓▓▓ Section 2: the terminal core M4-M6
W9-11 ▓▓▓ Section 3: the graphical frontend M7-M8
W12-14 ▓▓▓ Section 4: the multiplexer M9-M12
W15 ▓ Section 5: architecture M13
W16 ▓ Compatibility + capstone M14
Sections 3 and 4 are independent — both depend only on Section 2. If multiplexers interest you more than fonts, swap weeks 9–11 with 12–14.
Week 0: Orientation
| Session | Work | Output |
|---|---|---|
| 1 (2h) | The Hitchhiker's Guide | Understanding why terminals are like this |
| 2 (2h) | The Warm-Up, exercises 1–7 | warmup.md with predictions |
| 3 (2h) | The Warm-Up, exercises 8–13 + debrief | The debrief answered |
| 4 (2h) | Milestone 0; set up the workspace | answers-m0.md, committed |
Gate: you can define TTY, PTY, line discipline, emulator, shell, and multiplexer without using any of the other five in the definition.
Tip: Commit
answers-m0.mdeven though it is wrong in places. You re-answer the same twelve questions at the capstone, and the diff is the most direct measure of what you learned.
Weeks 1–3: Section 1 — The PTY Laboratory
Week 1 — Raw mode and the first PTY
| Session | Work | Milestone |
|---|---|---|
| 1 | TTY and PTY + fds, fork & exec | — |
| 2 | termios & the line discipline | — |
| 3 | Lab 1: the byte inspector | M1 |
| 4 | Lab 1 challenges: split sequences, bracketed paste, terminal queries | — |
Gate: every key decoded; stty -a identical before and after; the terminal restored on panic.
Week 2 — Sessions, job control, and spawning a shell
| Session | Work | Milestone |
|---|---|---|
| 1 | Sessions, process groups & the controlling terminal — read this twice | — |
| 2 | Lab 2: the PTY shell runner | M2 |
| 3 | Lab 2 experiment: remove TIOCSCTTY and observe; then the forkpty diff | — |
| 4 | Lab 4 experiments 1–4 | — |
Gate: vim and top run inside your runner; no "no job control in this shell"; you can recite
the spawn syscall list with each one's failure mode.
Warning: Week 2 is where people fall behind, because job control is genuinely harder than it looks and the failure modes are misleading. Budget the extra evening. If Ctrl+C does nothing, the answer is in that chapter's failure-mode table.
Week 3 — The event loop
| Session | Work | Milestone |
|---|---|---|
| 1 | Signals, window size & the child + I/O multiplexing | — |
| 2 | Lab 3: the poll loop | M3 |
| 3 | Lab 3 challenge: port to nix/rustix and diff the two versions | — |
| 4 | Lab 4 experiments 5–7; Lab 5: the recorder | — |
Gate: resize propagates to vim; yes does not freeze anything; a recorded session replays
deterministically; all seven experiments written up with predictions.
Weeks 4–8: Section 2 — The Terminal Core
The longest stretch, and the one that most rewards patience.
Week 4 — The parser
| Session | Work | Milestone |
|---|---|---|
| 1 | Separation of concerns + the parser state machine | — |
| 2 | Lab 6: the state machine | M4 |
| 3 | Lab 6: the split-input test over the whole corpus; the tracing wrapper | — |
| 4 | Lab 6: cargo fuzz, ≥10 minutes clean; commit the corpus | — |
Gate: feeding any recording one byte at a time produces an identical action stream. This is non-negotiable — everything after it assumes the property holds.
Week 5 — The screen
| Session | Work | Milestone |
|---|---|---|
| 1 | The screen model | — |
| 2 | Lab 7: grid, cursor, pending wrap | M5 |
| 3 | Lab 7: scrolling, erase-with-background, damage tracking | — |
| 4 | The CSI catalog blocks 1–2, with tests | — |
Gate: mini-term run --cols 10 -- printf '0123456789' reports col=9 pending_wrap=true.
Week 6 — Sequences and color
| Session | Work | Milestone |
|---|---|---|
| 1 | CSI catalog blocks 3–5 (insert/delete, save/restore, tabs) | — |
| 2 | SGR and color + implementation | — |
| 3 | Lab 8: mini-term | M6 |
| 4 | Lab 8: golden tests; record the ten-case corpus | — |
Gate: ten golden cases; deterministic across ten runs; the four required PTY integration tests.
Week 7 — Unicode
| Session | Work | Milestone |
|---|---|---|
| 1 | UTF-8, widths & graphemes | — |
| 2 | Lab 9: the decoder, by hand | — |
| 3 | Lab 9: wide characters, the spacer invariant, combining marks | — |
| 4 | Lab 9: the cross-terminal width comparison experiment | — |
Gate: the spacer property test passes over 20,000 random operations.
Week 8 — Modes, regions, and strings
| Session | Work | Milestone |
|---|---|---|
| 1 | Modes + OSC and string sequences | — |
| 2 | Lab 10: scroll regions, alt screen | — |
| 3 | Lab 11: OSC, mouse, bracketed paste | — |
| 4 | Lab 11 challenge: the security test suite | — |
Gate: vim, less, and top render correctly under mini-term. You now have a terminal
emulator — it simply has no window.
Weeks 9–11: Section 3 — The Graphical Frontend
Week 9 — Pixels
| Session | Work | Milestone |
|---|---|---|
| 1 | Choosing the stack + fonts and rasterization | — |
| 2 | The font-metrics experiment; a window with a red rectangle | — |
| 3 | Lab 12: the renderer | M7 |
| 4 | Lab 12: the glyph atlas, damage tracking, the resize path | — |
Gate: a shell in a window; vim and top work; idle CPU ~0%; yes does not freeze the UI.
Week 10 — Input
| Session | Work | Milestone |
|---|---|---|
| 1 | Input encoding + the key encoding table | — |
| 2 | Lab 13: the encoder | M8 |
| 3 | Lab 13: mouse, paste, focus; reset-on-exit | — |
| 4 | Lab 13: the xterm comparison experiment; classify every difference | — |
Gate: every table row unit-tested; Alt+B works in bash; pasting into vim does not staircase.
Week 11 — Interaction and the trace
| Session | Work | Milestone |
|---|---|---|
| 1 | Rendering and damage; the damage benchmark | — |
| 2 | Lab 14: selection and clipboard | — |
| 3 | Lab 14: scrollback rendering and its six interaction rules | — |
| 4 | Trace a keystroke — reproduce all 14 steps from your own logs | — |
Gate: you can produce the debug log for one keystroke and explain every line.
Weeks 12–14: Section 4 — The Multiplexer
Week 12 — Sessions and panes
| Session | Work | Milestone |
|---|---|---|
| 1 | Why a server process; the lsof experiment on real tmux | — |
| 2 | Lab 15: N sessions | M9 |
| 3 | Panes and layout | — |
| 4 | Lab 16: the layout tree | M10 |
Gate: the tiling property test over 1,000 random trees; a hidden top still current after 60s.
Week 13 — Client and server
| Session | Work | Milestone |
|---|---|---|
| 1 | The protocol | — |
| 2 | Lab 17: daemonize, socket, framing | M11 |
| 3 | Lab 17: the client; prefix parsing | — |
| 4 | Lab 17: the kill -9 test and the lsof experiment | — |
Gate: kill -9 on the client leaves shells running, proven with ps.
Week 14 — Attach, detach, copy mode
| Session | Work | Milestone |
|---|---|---|
| 1 | Lab 18: detach/attach | M12 |
| 2 | Lab 18: multi-client resize policy; the state-vs-replay timing experiment | — |
| 3 | Input routing and copy mode | — |
| 4 | Lab 19: copy mode | — |
Gate: two clients attached at different sizes, both working; reattach after 5 minutes is instant and correct.
Week 15: Section 5 — Architecture
| Session | Work | Milestone |
|---|---|---|
| 1 | Crate boundaries; run the audit — expect failures | — |
| 2 | Lab 20: fix the audit; wasm32 | M13 |
| 3 | Embedding scenarios; build the headless simulator | — |
| 4 | The boundary-defense document; the break-a-boundary experiment | — |
Gate: the audit passes in CI; four consumers of one unmodified core; wasm32 builds.
Tip: Do the audit on day one of week 15, before reading the fixes. The list of failures is the week's syllabus, and it is more instructive than any chapter.
Week 16: Compatibility and the Capstone
| Session | Work | Milestone |
|---|---|---|
| 1 | Interactive compatibility: run all eleven programs, build the matrix | M14 |
| 2 | Fix the top three findings; add a regression golden case for each | — |
| 3 | Capstone steps 1–3: integration, demo.sh, the full-stack trace | — |
| 4 | Capstone steps 4–8: the write-up and the rubric | — |
Gate: the demonstration runs end to end; the write-up is done; you have scored yourself honestly.
Compressed Schedules
Eight weeks (~20 h/week)
Double up. Sections 1 and 2 stay at full length — they are the foundation and compressing them is false economy. Compress Sections 3–5 instead.
W1 Warm-up + M0 + Section 1 weeks 1-2
W2 Section 1 week 3 + Section 2 week 4
W3 Section 2 weeks 5-6
W4 Section 2 weeks 7-8
W5 Section 3 (all)
W6 Section 4 weeks 12-13
W7 Section 4 week 14 + Section 5
W8 Compatibility + capstone
"I only care about X"
| Goal | Minimum path |
|---|---|
| Understand PTYs and job control | W0, W1–3. Stop. That is a complete, satisfying unit. |
| Write a VT parser | W0, W1 (Lab 1 only), W4–5 |
| Build a headless terminal for testing | W0, W1–3, W4–6 |
| Build a multiplexer | W0, W1–3, W4–6, W12–14 (skip the GUI entirely) |
| Build a GUI terminal | W0, W1–3, W4–8, W9–11 |
Sections 3 and 4 are genuinely optional relative to each other. Section 5 assumes you did at least two of Sections 3, 4, and the CLI.
Keeping Yourself Honest
Weekly, ten minutes:
- Did I write predictions before every experiment this week?
- Can I explain everything I built, or only run it?
- Are the tests still green, including last week's?
- Did I commit? (The git history is a capstone deliverable.)
-
Did I add a crate I was told to avoid? Check
Cargo.lock.
At every section gate: re-read that section's "Section Profile" table and check each row against what you can actually do.
When You Fall Behind
You will. The three common causes and their fixes:
| Cause | Symptom | Fix |
|---|---|---|
| Job control (week 2) | Ctrl+C does nothing; bash complains | Slow down. Do experiment 5 with ps open in a second window until the TPGID changes are boring. |
| The screen model (week 5) | Off-by-ones everywhere; vim draws garbage | You skipped boundary tests. Add the normal/boundary/degenerate trio for every sequence. |
| Fonts (week 9) | Text looks wrong and you cannot say why | Do the font-metrics experiment. Print the numbers. Baselines are arithmetic, not taste. |
And the meta-fix: the schedule is not the point. Sixteen weeks is an estimate for a person with a job. If week 5 takes three weeks because you actually understood pending wrap, that is the plan working.