Skip to content

Commit 24128f7

Browse files
stevenpollackclaude
andcommitted
docs: add project CLAUDE.md with dev-harness notes
Document the exact feedback loop (make check, cargo check/clippy, fmt quirks), the compiler-enforced clippy bans (no unwrap/expect/panic; forbid(missing_docs) in asyncgit), and gotchas (insta snapshots, CHANGELOG requirement, no unused deps) so contributors and AI agents get deterministic feedback when authoring changes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BMQxBdr5f3B3jmDtdvGtTu
1 parent 685cca9 commit 24128f7

1 file changed

Lines changed: 58 additions & 0 deletions

File tree

CLAUDE.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# gitui — working notes for Claude
2+
3+
gitui is a Rust TUI git client. Cargo **workspace**: root crate `gitui` (the `src/` TUI binary) +
4+
members `asyncgit` (git logic over `git2`/`gix`), `filetreelist`, `git2-hooks`, `git2-testing`,
5+
`scopetime`. MSRV **1.88** (`Cargo.toml` `rust-version`, `.clippy.toml` `msrv`, CI matrix — keep
6+
all three in sync if ever bumped).
7+
8+
## Feedback loop (run these — the reviewer here does not read Rust, so tooling IS the review)
9+
10+
- **Fast inner loop while editing:** `cargo check -p asyncgit` (backend) / `cargo check` (whole
11+
workspace). Never iterate with `--release` — LTO + `opt-level="z"` makes it very slow.
12+
- **Format before every check:** `cargo fmt`. Formatting is unusual (`rustfmt.toml`:
13+
`max_width = 70`, `hard_tabs = true`) — hand-written code almost never matches, and
14+
`cargo fmt -- --check` is a CI gate.
15+
- **Full gate before declaring done / committing:** `make check`
16+
= `fmt` (`cargo fmt -- --check`) + `clippy` (`cargo clippy --workspace --all-features`) +
17+
`test` (`cargo nextest run --workspace`) + `sort` (`tombi format --check`) + `deny`
18+
(`cargo deny check`). CI calls the same `make` targets, so green locally ≈ green CI.
19+
- **Subset fallback** if a tool is missing: `cargo fmt -- --check` +
20+
`cargo clippy --workspace --all-features` + `cargo test --workspace` (plain `cargo test` works;
21+
it just also runs doctests that nextest skips).
22+
- **Run a single crate's tests:** `cargo test -p asyncgit <name_filter>`.
23+
24+
Required tooling: `cargo-nextest`, `cargo-deny`, `tombi` (installed via mise), plus `python`,
25+
`gpgsm`/`gpg`, `openssl`, `perl`, a C compiler (vendored OpenSSL + bundled libgit2 build from
26+
source on first compile — the first build is slow, later ones are cached).
27+
28+
## Hard rules clippy enforces (these fail the build, not just warn)
29+
30+
Crate roots carry `#![deny(clippy::all, perf, nursery, pedantic, cargo)]` plus bans below.
31+
- **No `unwrap` / `expect` / `panic!` in production code** — use `?`, `ok_or(...)`,
32+
`unwrap_or_default()`, `map_or(...)`. (`unwrap`/`expect` are fine in `#[cfg(test)]` code.)
33+
- `asyncgit` has `#![forbid(missing_docs)]`**every `pub` item needs a `///` doc comment**.
34+
- `#![forbid(unsafe_code)]` in the binary crate.
35+
36+
## Other gotchas
37+
38+
- **UI output is snapshot-tested with `insta`** (`src/snapshots/*.snap`). If you change rendered
39+
output, tests fail with a diff — review and accept via `cargo insta review` / `cargo insta
40+
accept`, then commit the updated `.snap` files. (Install once: `cargo install cargo-insta`.)
41+
- **CHANGELOG.md** must gain an entry under `## Unreleased` (`Added`/`Changed`/`Fixes`) or the CI
42+
`log-test` job fails. Format: Keep-a-Changelog, with issue/PR links.
43+
- Only the `stable` and `1.88` CI rows gate (nightly is `continue-on-error`). `cargo +nightly
44+
udeps` runs in CI but not in `make check`, so **don't add unused dependencies**.
45+
- Production code never shells out to the `git` binary; use `git2`/`gix`. The only
46+
`Command::new("git")` calls live in test helpers (`debug_cmd_print` in `asyncgit/src/sync/mod.rs`).
47+
48+
## Where things live (patterns to copy)
49+
50+
- Sync git ops: `asyncgit/src/sync/<feature>.rs`, re-exported from `asyncgit/src/sync/mod.rs`. Each
51+
op: `pub fn f(repo_path: &RepoPath, ...) -> Result<T> { scope_time!("f"); let repo =
52+
repo(repo_path)?; ... }`. Test helpers (`repo_init`, `debug_cmd_print`) in `sync/mod.rs::tests`.
53+
- Popups (Branches/Submodules/etc.): `src/popups/<name>.rs`, registered in `src/popups/mod.rs` and
54+
the `setup_popups!` macro in `src/app.rs`; opened via an `InternalEvent` in `src/queue.rs`.
55+
- Components implement `Component` + `DrawableComponent` (`src/components/mod.rs`). Non-commit list
56+
views use `VerticalScroll` + `ui::scrolllist::draw_list` (see `src/popups/submodules.rs`).
57+
- Keybindings: `src/keys/key_list.rs` (`KeysList` struct + `Default`). Command/help strings:
58+
`src/strings.rs`.

0 commit comments

Comments
 (0)