From beagle-rust
Reviews Rust code for ownership, borrowing, lifetimes, error handling, trait design, unsafe usage, and common mistakes in .rs files. Covers 2021 edition idioms and borrow checker issues.
npx claudepluginhub existential-birds/beagle --plugin beagle-rustThis skill uses the workspace's default tool permissions.
Follow this sequence to avoid false positives and catch edition-specific issues:
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
Follow this sequence to avoid false positives and catch edition-specific issues:
Cargo.toml — Note the Rust edition (2018, 2021, 2024) and MSRV if set. This determines which patterns apply. Check workspace structure if present.Report findings as:
[FILE:LINE] ISSUE_TITLE
Severity: Critical | Major | Minor | Informational
Description of the issue and why it matters.
| Issue Type | Reference |
|---|---|
| Ownership transfers, borrowing, lifetimes, clone traps, iterators | references/ownership-borrowing.md |
| Result/Option handling, thiserror, anyhow, error context | references/error-handling.md |
| Async pitfalls, Send/Sync bounds, runtime blocking | references/async-concurrency.md |
| Unsafe code, API design, derive patterns, clippy patterns | references/common-mistakes.md |
For development guidance on performance, pointer types, type state, clippy config, iterators, generics, and documentation, use the
beagle-rust:rust-best-practicesskill.
.clone() to silence the borrow checker (hiding design issues).clone() inside loops — prefer .cloned() or .copied() on iterators'static when shorter lifetime works)&str preferred over String, &[T] over Vec<T> in function parametersimpl AsRef<T> or Into<T> used for flexible API parametersCell, RefCell, Mutex) used only when shared mutation is genuinely neededCopy and are passed by valueCow<'_, T> used when ownership is ambiguous.collect() — pass iterators directly when the consumer accepts them.sum() preferred over .fold() for summation (compiler optimizes better)_or_else variants used when fallbacks involve allocationResult<T, E> used for recoverable errors, not panic!/unwrap/expect#[error("...")] or manual Display)? operator used with proper From implementations or .map_err()unwrap() / expect() only in tests, examples, or provably-safe contextsanyhow used in applications, thiserror in libraries (or clear rationale for alternatives)_or_else variants used when fallbacks involve allocation (ok_or_else, unwrap_or_else)let-else used for early returns on failure (let Ok(x) = expr else { return ... })inspect_err used for error logging, map_err for error transformationderive macros appropriate for the type (Clone, Debug, PartialEq used correctly)struct UserId(Uuid) not bare Uuid)From/Into implementations are lossless and infallible; TryFrom for fallible conversionsSend + Sync bounds verified for types shared across threadsunsafe blocks have safety comments explaining invariantsunsafe is minimal — only the truly unsafe operation is inside the blockunsafe trait implementations justify why the contract is upheldPascalCase, functions/methods snake_case, constants SCREAMING_SNAKE_CASEsnake_caseis_, has_, can_ prefixes for boolean-returning methodsself (not &mut self) for chaining///)#[must_use] on functions where ignoring the return value is likely a bug#[expect(clippy::...)] preferred over #[allow(...)] for lint suppressionDetailed guidance:
beagle-rust:rust-best-practicesskill (references/performance.md)
&str over String, &[T] over Vec<T>)collect() type is specified or inferableVec::with_capacity() used when size is known.to_string() / .to_owned() chains.collect() when passing iterators directly works.sum() preferred over .fold() for summationimpl Trait) used over dynamic (dyn Trait) unless flexibility requiredDetailed guidance:
beagle-rust:rust-best-practicesskill (references/clippy-config.md)
Cargo.toml ([workspace.lints.clippy] or [lints.clippy])#[expect(clippy::lint)] used over #[allow(...)] — warns when suppression becomes staleredundant_clone, large_enum_variant, needless_collect, perf groupcargo clippy --all-targets --all-features -- -D warnings passesmissing_docs, broken_intra_doc_links)Detailed guidance:
beagle-rust:rust-best-practicesskill (references/type-state-pattern.md)
PhantomData<State> used for zero-cost compile-time state machines (not runtime enums/booleans)self and return new state type (prevents reuse of old state)unsafe code with unsound invariants or undefined behaviorunwrap() on user input or external data in production codeArc<Mutex<...>> without weak referencesreturn err equivalent).clone() masking ownership design issues in hot pathsSend/Sync bounds on types used across threadspanic! for recoverable errors in library code'static lifetimes hiding API design issuesString parameter where &str or impl AsRef<str> would workCargo.toml#[must_use] or #[non_exhaustive]beagle-rust:rust-best-practices skillThese are acceptable Rust patterns — reporting them wastes developer time:
.clone() in tests — Clarity over performance in test codeunwrap() in tests and examples — Acceptable where panicking on failure is intentionalBox<dyn Error> in simple binaries — Not every application needs custom error typesString fields in structs — Owned data in structs is correct; &str fields require lifetime parameters#[allow(dead_code)] during development — Common during iterationtodo!() / unimplemented!() in new code — Valid placeholder during active development.expect("reason") with clear message — Self-documenting and acceptable for invariantsuse super::* in test modules — Standard pattern for #[cfg(test)] modulestype Result<T> = std::result::Result<T, MyError> is idiomaticimpl Trait in return position — Zero-cost abstraction, standard patterncollect::<Vec<_>>() is idiomatic when type inference needs help_ prefix for intentionally unused variables — Compiler convention#[expect(clippy::...)] with justification — Self-cleaning lint suppressionArc::clone(&arc) — Explicit Arc cloning is idiomatic and recommendedstd::sync::Mutex for short critical sections in async — Tokio docs recommend thisfor loops over iterators — When early exit or side effects are neededOnly flag these issues when the specific conditions apply:
| Issue | Flag ONLY IF |
|---|---|
| Missing error context | Error crosses module boundary without context |
Unnecessary .clone() | In hot path or repeated call, not test/setup code |
| Missing doc comments | Item is pub and not in a #[cfg(test)] module |
unwrap() usage | In production code path, not test/example/provably-safe |
Missing Send + Sync | Type is actually shared across thread/task boundaries |
| Overly broad lifetime | A shorter lifetime would work AND the API is public |
Missing #[must_use] | Function returns a value that callers commonly ignore |
Stale #[allow] suppression | Should be #[expect] for self-cleaning lint management |
Missing Copy derive | Type is ≤24 bytes with all-Copy fields and used frequently |
Load and follow beagle-rust:review-verification-protocol before reporting any issue.