CLAUDE.md¶
to match your codebase. -->
Project¶
One-paragraph description of what this crate does and who uses it.
- Language: Rust (edition 2021)
- Framework: Axum / Actix / CLI (clap) / library crate
- Async runtime: Tokio (services only)
- Database: SQLx with PostgreSQL / none
- Tests: built-in
cargo test, integration tests intests/
Commands¶
cargo build— compile all targetscargo test— run all tests (unit + integration)cargo test <name>— run tests matching<name>cargo clippy -- -D warnings— lint; warnings are errorscargo fmt— auto-format;cargo fmt --checkin CIcargo run— run the binary (services read config from the environment)cargo sqlx prepare— refresh offline query metadata (SQLx projects only)
Run cargo fmt && cargo clippy -- -D warnings && cargo test before opening a
PR. CI blocks on all three.
Architecture¶
src/main.rs— entry point; wiring only, no business logic.src/lib.rs— crate root; re-exports the public interface.src/routes/orsrc/handlers/— HTTP layer; thin, delegates downward.src/services/— business logic; no HTTP types.src/repositories/— database access; SQLx compile-time checked queries.src/models/— domain types and row structs.src/errors.rs— one error enum withthiserror;IntoResponseimpl for HTTP.migrations/— SQLx migrations; never edit an applied migration.
Handlers call services, services call repositories. Never skip a layer, and
never let HTTP types leak below routes/.
Error Handling¶
- One unified error type (
AppError) derived withthiserror. All fallible functions returnResult<T, AppError>and propagate with?. - Add context with
anyhow::Contextat the boundary where the error leaves the layer that caused it. - Map error variants to status codes in one place — the
IntoResponseimpl — not in individual handlers.
Conventions¶
- No
unwrap()orexpect()outside tests. Return errors. - No
unsafewithout a// SAFETY:comment and a human reviewer. - Owned types (
String,Vec<T>) in structs and returns; borrows (&str,&[T]) in function parameters. - Derive
Debug, Clone, Serialize, Deserializeon public API types. - Typed IDs, not raw strings:
OrderId(Uuid), notString. tracingfor logging. Noprintln!in library code.- Prefer
mod.rsexporting the public interface; keep implementation in sibling modules.
Testing¶
- Unit tests live in
#[cfg(test)] mod testsat the bottom of each module. - Integration tests live in
tests/<feature>.rsand exercise the public API. - SQLx projects: use
#[sqlx::test]for automatic per-test rollback. - Build test data through constructor functions, not hand-built structs at every call site.
Do NOT¶
- Add dependencies without asking.
Cargo.tomlis reviewed. - Use
.clone()to silence the borrow checker without trying ownership fixes first. - Block the async runtime: no
std::fsor blocking IO inside async contexts — usetokio::fsorspawn_blocking. - Commit
target/orCargo.lockchanges unrelated to your dependency edit.
Available skills¶
/add-endpoint— scaffold a route across handlers, services, and repositories with tests, following the project's layering.
See also¶
- starters/index.md — how this kit was assembled and how to adapt it
- ../../guides/claude-md-guide.md — how to write a good CLAUDE.md