developing-reef
Architecture and coding conventions for changing Reef itself. Use before modifying Reef runtime architecture, `App` state, tabs/panels, rendering code, input dispatch, background work, git/file-tree/diff/graph loading, performance-sensitive paths, or when the user asks about "how Reef is structured", "render blocking", "heavy tasks", "new tab", "new feature architecture", or "project conventions". Pair with `testing-reef` whenever adding or changing tests.
Developing Reef
Use this skill as the project onboarding guide for non-test Reef changes. Reef is a minimal single-process Rust TUI: UI must stay responsive, and expensive host work must not run from render.
Core Architecture Rules
- Keep
ui::*::renderon cached state only. Do not call git, filesystem walks, diff generation, syntax highlighting, or long formatting from render. - Treat input handlers as intent dispatchers. They may update cheap UI state (selection, scroll, hover, active tab) and request work, but must not do blocking host work.
- Route expensive work through the background task coordinator in
src/tasks.rs; merge results only fromApp::tick. - Prefer stale cached UI over blocking. Show old data plus loading/stale/error status instead of waiting during tab switches or hover/mouse movement.
- Use generation tokens for async results. Late results from older requests must not overwrite newer selections or newer snapshots.
- Keep each tab/panel independently refreshable. Adding a feature should not require another tab to render before data can update.
Runtime Data Flow
- User input mutates cheap UI state or calls an
Apprequest method such asrefresh_status,load_diff, orload_preview. - The request method marks an
AsyncState, increments its generation, and sends a worker request throughTaskCoordinator. - Workers do git/filesystem/diff/highlight work off the render path and send
WorkerResult. App::tickdrains results, accepts only matching generations, updates snapshots/state, and schedules follow-up work when needed.- Render reads the latest state and status flags. It must never be required for progress beyond drawing.
Read references/runtime-architecture.md before changing src/app.rs, src/tasks.rs, src/input.rs, or any tab/panel render path.
File/Module Habits
src/app.rsowns state orchestration: tab state, snapshot fields, async state, result merging, and command side effects.src/tasks.rsowns background worker definitions and should stay free of UI concerns.src/ui/**owns rendering and local panel command dispatch; keep it pure except transient hit-test registration.src/input.rsowns key/mouse routing; useApp::set_active_tabinstead of assigningactive_tabdirectly.src/file_tree.rsowns tree structure and preview data types; updating Git decorations must not rebuild the tree unless structure changed.src/git/**owns direct git2 operations and pure graph algorithms. Open repositories inside workers withGitRepo::open_at.
Adding or Changing Features
- For a new tab or expensive panel, define: UI state, cached data snapshot,
AsyncState, worker request/result, request method, result merge path, and render fallback for stale/loading/error. - For a cheap UI-only feature, keep it local and synchronous, but verify it never calls host I/O through helpers.
- For actions that move HEAD/refs or change index/worktree, mark the affected snapshots stale and let
tickrefresh them. - For selections that load content, request async work immediately and rely on generations to drop stale responses.
- Keep user-facing behavior stable when possible; avoid broad rewrites of keybindings, file layout, or visual style while solving performance/architecture issues.
Testing Expectations
- Use
$testing-reefbefore adding or modifying tests. - Add unit tests for pure helpers and state transitions when practical.
- Update snapshot tests only when rendered text/layout intentionally changes.
- For async UI behavior, tests should wait for
tickto consume worker results instead of assuming synchronous state. - Run at least focused tests for touched areas; for architecture changes prefer
cargo check,cargo test --lib, relevant integration/snapshot tests,cargo fmt --all -- --check, and clippy with-D warnings.