This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Plz read README.md.
cargo build --release # Build
cargo test # Run all tests
cargo clippy # Lint
cargo fmt --check # Format check
cargo bench # Run all benchmarks (Criterion)
cargo bench --bench ui_rendering
cargo bench --bench diff_parsing
cargo bench --bench symbol_searchThis project is Building/Development for 5 Principles.
- Write tests before implementation. No feature is complete without passing tests.
- Use
instafor snapshot testing. always use inline-snapshot. - Use
assert_cmd+predicatesfor integration tests that exercise the binary end-to-end. - Prefer scenario-based tests that simulate real user workflows (e.g., "load PR → navigate to file → jump to comment") over isolated unit tests of internal helpers.
- Snapshot tests are the primary regression safety net. When changing rendering or API response parsing, always update or add snapshots.
- Use
serial_test(#[serial]) when tests share mutable global state or filesystem resources.
- Every change must pass all three gates before being considered complete:
cargo clippy -- -D warnings— zero warnings, treated as errorscargo test— all tests greencargo check— no compilation errors
- If a change introduces a Clippy warning, fix it immediately in the same change — never suppress with
#[allow(...)]unless there is a documented, unavoidable reason. - CI failures are blocking. Do not proceed with further work until all three gates pass locally.
- When refactoring, run all three gates after each logical step, not just at the end.
- This app handles PRs with 6,000+ files and 300,000+ lines. Performance is a user-facing feature.
- Use string interning (
lasso::Rodeo) for repeated diff line strings to reduce allocations. - Use
smallvecfor stack-allocated small collections where heap allocation is avoidable. - Use compile-time perfect hash maps (
phf) for static lookup tables (e.g., language detection, capture-to-scope mapping). - Pre-compute and cache syntax-highlighted diffs in
DiffCache— never re-highlight on every render. - Benchmark before and after performance-sensitive changes using Criterion (
benches/). The CI alerts on 150%+ regression. - Prefer
&strborrows overStringclones. Avoid unnecessary.clone()and.to_string(). - Use
tokioasync tasks with cancellation tokens for background data loading — never block the UI thread.
- All screen/mode transitions go through
AppStateenum (17 states). Never use ad-hoc boolean flags to track "which screen am I on." - Data loading lifecycle is modeled as
DataStateenum (Loading→Loaded→Error). Never useOption<Data>+is_loading: boolseparately. - AI Rally transitions flow through
RallyStateenum withRallyEvent-driven transitions. Each state has explicit allowed transitions — invalid transitions are compile-time or runtime errors. - Input modes are modeled as
InputModeenum variants with associated data (context, original code, etc.). - When adding a new feature that introduces a new mode or screen, add a variant to the appropriate state enum and handle it exhaustively in match arms. The compiler enforces completeness.
- Pause/resume is
PauseStateenum (Running→PauseRequested→Paused→Running), not a boolean toggle.
- Empty states are first-class: no PRs, no files, no comments, no diff content — all must render gracefully.
- Unicode and CJK text: use
unicode-widthfor display width calculation. Never assume 1 byte = 1 character = 1 column. - Large inputs: test with 1,000+ line diffs and 5,000+ line patches. Benchmark suites cover 100/500/1000/5000 line scenarios.
- Network failures:
DataState::Errormust display actionable messages. Retry mechanism uses atomic flags. - Concurrent state: file watcher events can arrive during any state. AI Rally commands can arrive while rendering. Handle via channels with non-blocking receives.
- Platform differences: binary runs on Linux, macOS, Windows. Terminal behavior varies — use crossterm abstractions, never raw ANSI escapes.