Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Architecture

Decision history lives in docs/adr/. This file is the current map.

Crate graph

margin (bin) ──► margin-tui ──► margin-core
        │                          ▲
        └──────► margin-vcs ───────┘
CrateRoleMay do I/O?Key contract
margin-coreDiff model, unified-diff parser, intra-line diff, collapse heuristicsNoPure, panic-free on untrusted input, fuzzed (ADR-0003, 0009)
margin-vcsRead-only DiffSource adapters + repository write operationsYes — VCS, files, ghgit2 quarantined; no git2 types in public APIs (ADR-0005, 0019)
margin-tuiElm-architecture UI: AppState, Msg, update, view, themes, keymapTerminal only (review effects → Command)Never imports margin-vcs; view() is pure → snapshot-testable (ADR-0002, 0003)
marginCLI, config, capability-aware Review Session, persistence, watchingYes — runtime shellPager passthrough guarantee; exit codes are API (ADR-0007, 0019, 0022)

Data flow

CLI args + config ─► Review Session ─► DiffSource ─► Changeset ─► AppState
                              │                              ▲          │ view()
                              │     key events ─► Msg ─► update() ─────┘
                              │                       │                 ▼
                              └─ capabilities ◄──── Commands      terminal frame
                                                   │
                              runtime adapters execute effects; results return as Msgs

The model (margin-core)

Changeset → FileDiff (paths, status, mode) → Hunk (@@ ranges) → Line
                                                                 └ intra-line spans

Everything downstream — rendering, search, --json, staging — consumes this model. The parser that builds it from unified diffs is the single most security-sensitive code in the project (stdin is untrusted) and is correspondingly fuzzed and corpus-tested (ADR-0010).

Performance strategy

Parse eagerly (cheap, linear). Highlight and intra-line-diff lazily — only what the current frame requests, cached per file, bounded by a per-frame budget with unfinished work resuming across fill-in frames (ADR-0006, ADR-0026: there is no background warming thread). The input loop never blocks on rendering work.

Budgets (< 50 ms first paint on 100 files; smooth 250k-line scrolling) are enforced in CI by workload completion tests with exact result assertions (crates/margin-core/tests/perf_budgets.rs, crates/margin-tui/tests/perf_budgets.rs) plus the deterministic budget-exhaustion test in highlight.rs. The criterion benches (parse/*, first_frame/*, scroll_frame/*, search_keystroke/* — run with cargo bench -p margin-core / -p margin-tui) are informational observations for local comparison, not gates: shared runners cannot make statistically trustworthy timing decisions.

Where things live

  • margin-core: model.rs (bytes-first changeset model), patch.rs (tolerant unified-diff parser), intraline.rs (word-level emphasis), ansi.rs (escape stripping for pager input)
  • margin-vcs: lib.rs (DiffSource trait + SourceError, write transactions), git.rs (worktree/staged/show/range sources + git2 conversion), files.rs (two-file diffs), gh.rs (PRs via the user’s gh), staging.rs (index writes), discard.rs (recoverable discard + trash + undo)
  • margin-tui: app.rs (AppState/Msg/update, per-layout Row stream), keymap.rs, theme.rs (built-ins + color modes), highlight.rs (budgeted lazy syntax/emphasis cache), runtime.rs (terminal session + panic guard), view/{mod,diff,sidebar,help,split,style}.rs
  • margin: main.rs (clap dispatch, passthrough guarantee), review.rs (Review Session modes, capabilities, effect execution, watching and display), review_state.rs (atomic versioned per-DiffId review state, ADR-0020), config.rs (discovery/merge, color-mode detection)

For agent-oriented operational detail (commands, gotchas, testing playbook), see AGENTS.md.