From ceej-skills
Use when reviewing a scoped Rust change — uncommitted diff, unpushed commit stack, or open PR. Triggers on phrases like "review this change", "review my diff", "review this PR", "look over what I'm about to push", or "is this ready to merge". Applies the project-review quality lens scoped to the diff and answers four targeted questions (intent match, testing, documentation, completeness). Produces a small number of ranked, highly actionable suggestions.
How this skill is triggered — by the user, by Claude, or both
Slash command
/ceej-skills:rust-change-reviewThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
The change-oriented counterpart to `rust-project-review`. Same standards, but ruthlessly restricted to what the diff actually touches.
The change-oriented counterpart to rust-project-review. Same standards, but ruthlessly restricted to what the diff actually touches.
Core principle: Every finding must cite a file and a line in the diff. "Could use more tests" is not a finding; "src/parser.rs:42-58 adds the empty-header branch but no test covers empty input" is. Project-wide advice is out of scope unless the diff makes an existing problem materially worse.
Establish exactly what is under examination before reviewing anything:
git diff (working tree) and git diff --cached (staged).git log --oneline origin/main..HEAD and git diff origin/main...HEAD for a range, or a single commit hash.gh pr view <number> for the description, gh pr diff <number> for the patch.Always:
Findings land in a single message. Don't fix anything in this pass — review only. Fixes come after the user picks priorities.
The project-review lens, restricted to what the change actually touches. Skip anything the diff doesn't touch — listing irrelevant criteria is noise.
pub items, or is the new surface minimal? Could a pub(crate) work instead?dbg!, eprintln!, commented-out blocks, #[allow(dead_code)], or TODOs without context?/// docs explaining why and when, not just restating the signature? Module-level docs updated if the module's shape changed?UserId(u64), Millis(u64), Email(String))? Stringly-typed parameters that should be enums? NonZeroU32 / NonEmpty<T> / OnceLock opportunities the diff just missed?thiserror with #[source] / #[from] chaining. Binaries: anyhow / eyre with .context() at each call. No Box<dyn Error> in public APIs..unwrap() / .expect() confined to tests, main returning Result, or genuine type-system invariants (with a // SAFETY:-style comment explaining why it can't fail)? New index access (arr[i]) that should be .get() or .chunks()?for i in 0..n, ? over manual match, if let / let else to cut nesting, From / Into / TryFrom for conversions, Default where there's a sensible default, #[must_use] on builders and query results, Display hand-written where it's user-facing..clone() / .to_string() justified? Could it be a borrow, a move, or Cow<'_, T>? Particularly suspect inside hot loops, on large structs, or in trait impls.'static smuggled in to silence a borrow checker complaint.pub intentional, not "the compiler asked for it"? pub(crate) / pub(super) used where appropriate? Re-exports build a clean public façade, not "reach through internal::deeply::nested"?block_on deep in the call stack, no second runtime introduced, Send + 'static bounds only where required, cancel-safe across .await points (no half-mutated state if the future drops).unsafe — every new unsafe block has a // SAFETY: comment justifying the invariants? Safer alternative considered? Default target for personal projects is zero unsafe.Cargo.toml — new dependencies justified and not duplicating something already in the graph? Features documented? [dev-dependencies] separated? MSRV bump intentional if any?cargo audit / cargo deny check (RUSTSEC advisory, license, typosquat)? Any new .unwrap() / index access on an attacker-reachable path? Any hardcoded secret or credentialed URL introduced?Answer each one explicitly in the output, not just implicitly via the suggestion list.
Run these scoped to the changed crate(s), not the whole workspace where possible:
cargo fmt --check — should be clean.cargo clippy --all-targets -- -D warnings on the touched crate. New #[allow(clippy::...)] should carry a comment explaining why.cargo test -p <crate> — including cargo test --doc -p <crate> for any modified public items.cargo doc --no-deps -p <crate> — warning-free, especially if the diff added new public items.If any of these fail or warn on the change, that's a finding, not a footnote. If the change can't be built locally (cross-compile, missing dev deps), say so explicitly rather than silently skipping.
Constructive review is more useful than exhaustive review. The goal is to help the work land cleanly, not to demonstrate rigor.
## Change under review
<One-sentence description + reference to diff / PR / commit range>
## Does it achieve its stated goal?
<Direct answer with evidence from the diff and the commit/PR text>
## Four questions
- **Intent match:** ...
- **Testing:** ...
- **Documentation:** ...
- **Completeness:** ...
## Tooling
- `cargo fmt`: ...
- `cargo clippy`: ...
- `cargo test`: ...
- `cargo doc`: ...
(One line each. "Not run — <reason>" is acceptable when the change can't be built locally.)
## Suggestions (ranked)
**Critical**
1. `<file:line>` — <concrete problem>. <What a successful fix looks like>. <How to evaluate.>
**Important**
1. ...
**Medium**
...
**Polish**
...
## Overall verdict
<One or two sentences. "Ready to merge", "One critical issue, the rest is minor", "Direction is good after X", etc.>
## Recommended next action
<Single concrete step, or "None — this looks ready to land.">
| Don't | Why |
|---|---|
| Review the whole project instead of the diff | Out of scope. Project-wide concerns belong in rust-project-review. |
| Give 10 nits at equal weight | Forces the user to do the prioritization. Top few, then a tail. |
| Vague advice ("needs more tests") | Useless without naming the behavior or the file in the diff. |
| Suggest large refactors unrelated to the goal | The diff has a job. Don't expand its scope to fit your review. |
| Ignore the commit / PR description | The "supposed to do" is the rubric. Without it you're guessing at intent. |
| Manufacture findings to look engaged | If the change is good, saying so is the review. |
| Numeric scores ("7/10") | Feel rigorous, aren't. |
| Recommend rewrites | This is a review pass. Smallest move that improves it. |
| Skip Tooling because "it probably passes" | Run it. A failing clippy lint is a real finding, not a footnote. |
Replace this section with notes for the repository being reviewed. Example shape (from Entropic):
Use the same high standards as rust-project-review, but ruthlessly scoped to the diff and the stated intent of the change.
Guides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.
npx claudepluginhub ceejbot/ceej-skills --plugin ceej-skills