rust-standards
Skill1 starsChanged 5 months agoMITView on GitHub
Best-practice coding standards for Rust code (manifest: Cargo.toml). Self-contained — covers toolchain/edition, ownership & borrowing, type design, error handling (Result/?, thiserror/anyhow), unsafe, async/concurrency (tokio), security, logging (tracing), clippy/rustfmt, testing, plus a lean axum HTTP service section. Used by the review agents on Rust projects. Do NOT use for other languages.
2 other projects use a version of this.
Adopted by
Most recently taken up by
- rkdxodud-tyk/SKILLStheir own version, first seen Jul 2, 2026
- kimgoetzke/coding-agent-configstheir own version, first seen Apr 30, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- kimgoetzke/coding-agent-configs★ 2same name
- rkdxodud-tyk/SKILLS★ 1same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository19 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- custom-standardsSkill
- agent-code-to-confirmSkill
- agent-to-confirmSkill
- claude-guideline-creationSkill
- skill-creatorSkill
- youtube-to-guidelineSkill
- youtube-transcribeSkill
- fastapi-standardsSkill
- general-standardsSkill
- go-standardsSkill
- java-standardsSkill
- nextjs-standardsSkill
- nodejs-standardsSkill
- python-standardsSkill
- react-standardsSkill
- reviewing-codebasesSkill
- skill-toggleSkill
- typescript-standardsSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
21 rules. About 0 are common, 3 are distinctive, and 18 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
18
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 50
Target: all Rust source — libraries (crates), CLIs, and async/HTTP services.
- Distinctive: line 51
Self-contained: No framework overlay; the async/service section (§11) is part of this document.
- Very specific: line 62
RUST-BASE-2 (MUST): Use Cargo; commit Cargo.lock for binaries/services (libraries may omit it).
- Very specific: line 66
RUST-BASE-4 (SHOULD): Keep the happy path shallow — return early on error with ?/guard clauses rather than deep nesting.
- Distinctive: line 78
RUST-OWN-3 (SHOULD): Keep lifetimes implicit where elision allows.
- Very specific: line 92
MUST NOT encode absence/▸failure as sentinel values (-1, empty string, 0).
- Very specific: line 95
RUST-TYPE-4 (SHOULD): Prefer iterators and combinators (map/filter/collect) over manual index loops.
- Very specific: line 97
RUST-TYPE-5 (SHOULD): Keep the public API minimal — items are private by default.
- Very specific: line 105
MUST NOT ignore a Result (#[must_use] — enforce unused_must_use).
- Very specific: line 106
RUST-ERR-2 (MUST NOT): Use .unwrap() / .expect() / panic!
- Very specific: line 112
RUST-ERR-4 (SHOULD): Add context as errors cross layers (thiserror variants or anyhow::Context) — don't discard the source.
- Very specific: line 137
RUST-SAFE-1 (SHOULD): Add #![forbid(unsafe_code)] (or #![deny(unsafe_code)]) to crates that don't need unsafe.
- Very specific: line 168
RUST-SEC-4 (SHOULD): Use vetted crypto crates (argon2/bcrypt for password hashing) and a CSPRNG (rand's OsRng / getrandom) for tokens and …
- Very specific: line 175
RUST-LOG-1 (MUST): Use the tracing crate for structured, async-aware logging and spans.
- Very specific: line 176
MUST NOT use println!/eprintln!
- Very specific: line 179
RUST-LOG-3 (SHOULD): Use spans to carry request/trace context for correlation.
- Very specific: line 196
RUST-TEST-1 (MUST): Test with the built-in framework (cargo test): unit tests in a #[cfg(test)] mod tests, integration tests under tests/.
- Very specific: line 201
RUST-TEST-3 (SHOULD): Follow the test pyramid — many fast unit tests, fewer integration, few end-to-end.
- Very specific: line 217
RUST-API-2 (MUST): Use typed extractors (Json<T>, Path<T>, Query<T>, State<T>) and share state via State (an Arc-wrapped app state) — MUST …
- Very specific: line 224
RUST-API-4 (SHOULD): Default auth scheme is stateless JWT bearer (token in Authorization: Bearer), verified in a tower middleware/extractor.
- Very specific: line 241
RUST-DOC-1 (SHOULD): Write /// doc comments on public items (what it does, params, errors, panics), with runnable doctest examples where …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Rust Coding Standard (v1.0)
Status: Locked v1.0. Same RFC-2119 constraint language,
RUST-AREA-Nrule-ID format, and severity mapping as the rest of the suite. Likego.md, Rust is a self-contained standard: it covers the language and a lean async/HTTP-service section (§11), rather than deferring to a separate framework overlay. Where it sets API/auth/logging defaults it stays consistent withnodejs.md/fastapi.md/go.md/java.mdso a polyglot codebase behaves the same way.On adoption this becomes
.claude/skills/rust-standards/SKILL.md+references/*.md.
Toolchain verified current as of 2026-06-13 (via Context7 + crates.io): Rust 1.96.x (edition 2024), clippy/rustfmt (rustup components), tokio 1.52.x, axum 0.8.x, serde 1.x, thiserror 2.x, anyhow 1.x, sqlx 0.9.x, tracing 0.1.x. Rules are written version-agnostically; these are reference points, not pins.
How to read this document
Constraint language (RFC 2119)
- MUST / MUST NOT — hard requirement; a violation is a blocking issue.
- SHOULD / SHOULD NOT — strong recommendation; deviate only with a written
// Justification:. - MAY — optional.
Rule IDs
Stable RUST-AREA-NUMBER (e.g. RUST-ERR-3). The reviewer MUST cite the rule ID. Never renumber.
Severity mapping
| This document says… | Reviewer severity | Gate |
MUST/MUST NOT affecting safety (unsafe/panics) / security | Critical | Blocks merge |
MUST/MUST NOT elsewhere | Critical / Warning (by impact) | Blocks if it risks correctness |
SHOULD without justification | Warning | Should fix |
MAY / stylistic | Suggestion | Nice to have |
Scope & Assumptions
- Target: all Rust source — libraries (crates), CLIs, and async/HTTP services.
- Self-contained. No framework overlay; the async/service section (§11) is part of this document.
- Safe Rust by default.
unsafeis the rare, justified exception (§5), not a tool of convenience. - Custom overrides: the project's
custom-standardsskill overrides this document on conflict.
1. Toolchain, Edition & Cargo
- RUST-BASE-1 (MUST): Build on stable Rust with the current edition (2024) declared in
Cargo.toml. Declare a MSRV (rust-version) and keep CI on it. Nightly only with a written justification for a specific feature. - RUST-BASE-2 (MUST): Use Cargo; commit
Cargo.lockfor binaries/services (libraries may omit it). Keep dependencies minimal and audited; pin via the lockfile. - RUST-BASE-3 (MUST): Code MUST be
rustfmt-clean (cargo fmt --checkin CI). Formatting is not reviewed by hand. - RUST-BASE-4 (SHOULD): Keep the happy path shallow — return early on error with
?/guard clauses rather than deep nesting.
2. Ownership & Borrowing
- RUST-OWN-1 (SHOULD): Borrow rather than clone. Take
&T/&mut T(or&str/&[T]) in function signatures; don't.clone()to dodge the borrow checker. An intentional clone carries a// Justification:or an obvious reason. - RUST-OWN-2 (SHOULD): Accept the most general borrowed type (
&strover&String,&[T]over&Vec<T>,impl AsRef<Path>over&PathBuf) so callers aren't forced to allocate. - RUST-OWN-3 (SHOULD): Keep lifetimes implicit where elision allows; introduce explicit lifetimes only when the compiler requires them. Don't over-annotate.
- RUST-OWN-4 (SHOULD NOT): Reach for
Rc/RefCell(orArc<Mutex<…>>) to escape ownership design when restructuring data flow would remove the need. Shared interior mutability is a deliberate choice, not a default.
3. Types & API Design
- RUST-TYPE-1 (SHOULD): Make illegal states unrepresentable — model variants with
enums and match exhaustively; use newtypes (struct UserId(u64)) over bare primitives for identifiers and units (avoid primitive obsession). - RUST-TYPE-2 (SHOULD): Return
Option<T>for "absent,"Result<T, E>for "fallible." MUST NOT encode absence/▸failure as sentinel values (-1, empty string,0). - RUST-TYPE-3 (SHOULD): Derive standard traits where they make sense (
Debugalmost always;Clone,PartialEq,Eq,Hashas needed). Public types SHOULD implementDebug. - RUST-TYPE-4 (SHOULD): Prefer iterators and combinators (
map/filter/collect) over manual index loops; they're clearer and bounds-check-free. - RUST-TYPE-5 (SHOULD): Keep the public API minimal — items are private by default; expose
pubonly what callers need. Use#[non_exhaustive]on public enums/structs likely to grow.
4. Error Handling
- RUST-ERR-1 (MUST): Model fallible operations with
Result<T, E>and propagate with?. MUST NOT ignore aResult(#[must_use]— enforceunused_must_use). - RUST-ERR-2 (MUST NOT): Use
.unwrap()/.expect()/panic!on recoverable errors in library or service code paths. They're acceptable only in tests, examples,main()startup wiring, or a genuinely-unreachable invariant documented withexpect("reason"). - RUST-ERR-3 (SHOULD): Libraries define typed errors with
thiserror(deriveError, implementstd::error::Error, preserve#[source]). Binaries/services MAY useanyhowfor opaque, context-rich errors (.context("...")). - RUST-ERR-4 (SHOULD): Add context as errors cross layers (
thiserrorvariants oranyhow::Context) — don't discard the source. MUST NOT stringify-and-lose the underlying error. - RUST-ERR-5 (SHOULD NOT): Convert errors to panics at layer boundaries to "simplify" signatures.
Return the
Result; let the top decide.
// ✅ RUST-ERR-1/3/4: typed error, `?`, preserved source
#[derive(Debug, thiserror::Error)]
pub enum LoadError {
#[error("user {0} not found")]
NotFound(String),
#[error("database error")]
Db(#[from] sqlx::Error), // source preserved
}
pub async fn load_user(pool: &sqlx::PgPool, id: &str) -> Result<User, LoadError> {
let user = fetch(pool, id).await?; // `?` propagates Db
user.ok_or_else(|| LoadError::NotFound(id.into()))
}5. Unsafe Code
- RUST-SAFE-1 (SHOULD): Add
#]) to crates that don't needunsafe. Most application/service code should never writeunsafe. - RUST-SAFE-2 (MUST): Where
unsafeis unavoidable, keep each block minimal, wrap it in a safe abstraction, and document the invariants with a// SAFETY:comment explaining why it's sound. Unreviewed/undocumentedunsafeis a blocking issue.
6. Concurrency & Async
- RUST-CONC-1 (SHOULD): Let the type system enforce thread-safety — share state via
Arc, guard mutation withMutex/RwLock(or message-passing channels). The compiler'sSend/Syncchecks are the safety net; don't bypass them withunsafe. - RUST-CONC-2 (MUST): Pick one async runtime —
tokiois the default — and use its primitives consistently. MUST NOT block the async executor: never call blocking I/O orstd::thread::sleepin anasync fn; use async equivalents ortokio::task::spawn_blocking. - RUST-CONC-3 (MUST NOT): Hold a
std::sync::Mutexguard across an.awaitpoint — usetokio::sync::Mutexwhen a lock must span awaits, or restructure to drop the guard first. - RUST-CONC-4 (SHOULD): Propagate cancellation via the runtime; ensure spawned tasks have a
clear join/shutdown path. Don't
spawnand forget — handle theJoinHandleor tie it to shutdown.
7. Security
- RUST-SEC-1 (MUST NOT): Build SQL by string concatenation. Use parameterized/bound queries
(e.g.
sqlxbind parameters —RUST-API-6). - RUST-SEC-2 (MUST NOT): Hard-code secrets. Load credentials/keys from environment or a secret
manager; zero sensitive buffers (
zeroize) where it matters; never commit them. - RUST-SEC-3 (MUST): Audit dependencies with
cargo audit(RustSec advisory DB) in CI; keep crates patched. Vet new dependencies — every crate is supply-chain surface. - RUST-SEC-4 (SHOULD): Use vetted crypto crates (
argon2/bcryptfor password hashing) and a CSPRNG (rand'sOsRng/getrandom) for tokens and salts — never a non-cryptographic RNG.
8. Logging & Observability
- RUST-LOG-1 (MUST): Use the
tracingcrate for structured, async-aware logging and spans. MUST NOT useprintln!/eprintln!for application logging in production code. - RUST-LOG-2 (MUST): Emit structured fields with a level, and MUST NOT log secrets, tokens, or
PII. (Consistent with
NODE-LOG-2.) - RUST-LOG-3 (SHOULD): Use spans to carry request/trace context for correlation; expose
health/readiness for services. (Consistent with
NODE-LOG-3.)
9. Tooling & Linting
- RUST-LINT-1 (MUST):
cargo clippyMUST pass in CI with warnings denied (cargo clippy -- -D warnings). Don't blanket-#[allow(...)]; suppress a single lint inline with a justified#[allow(clippy::...)] // reason. - RUST-LINT-2 (MUST): The build MUST be warning-clean (
#![deny(warnings)]in CI orRUSTFLAGS=-Dwarnings). Treat compiler warnings as errors.
10. Testing
- RUST-TEST-1 (MUST): Test with the built-in framework (
cargo test): unit tests in a#[cfg(test)] mod tests, integration tests undertests/. New or changed behavior ships with tests; changed logic with no test is insufficient coverage. - RUST-TEST-2 (MUST): Tests are deterministic and isolated — no real external network in unit tests, no order dependency, no shared mutable global state.
- RUST-TEST-3 (SHOULD): Follow the test pyramid — many fast unit tests, fewer integration, few
end-to-end. Target ≥ 80% coverage on changed code (not whole-repo) via
cargo llvm-cov(or tarpaulin); coverage is a floor, not the goal. (Consistent withNODE-TEST-3/PY-TEST-4.) - RUST-TEST-4 (SHOULD): Name tests by behavior; use doctests (
///examples that compile and run) for public-API usage.unwrap/expectare fine inside tests (RUST-ERR-2exempts tests).
11. Async HTTP Services & APIs
Cross-platform consistency: these mirror
nodejs.md/fastapi.md/go.md/java.mdso auth, versioning, and the data layer behave the same across the stack.
- RUST-API-1 (SHOULD): Build async HTTP services on
axum(overtokio+tower/hyper) — the idiomatic modern default. Othertower-based frameworks (e.g.actix-web) are sanctioned where a clear need justifies them. - RUST-API-2 (MUST): Use typed extractors (
Json<T>,Path<T>,Query<T>,State<T>) and share state viaState(anArc-wrapped app state) — MUST NOT use global mutable statics. - RUST-API-3 (MUST): Validate and treat all request input as untrusted — deserialize into typed
structs (
serde), validate fields, and reject malformed input with the right 4xx.validator(derive-based field constraints) is the recommended default validation crate (recommended not mandated) — the Rust counterpart to Zod (TS-TYPE-2) / Bean Validation (JAVA-SPRING-4) / Pydantic. Set request timeouts/body limits (viatowerlayers). - RUST-API-4 (SHOULD): Default auth scheme is stateless JWT bearer (token in
Authorization: Bearer), verified in atowermiddleware/extractor; check authorization (roles/scopes), not just authentication. Sanctioned alternatives by context: httpOnly session cookies (browser-first) or an external IdP / OAuth2 provider. (Consistent withNODE-NEST-14/FASTAPI-SEC-1/GO-API-4/JAVA-SPRING-8.) - RUST-API-5 (SHOULD): Version public APIs with URI versioning
/v1in the route path. (Consistent withNODE-NEST-15/FASTAPI-DOC-2/GO-API-5.) - RUST-API-6 (SHOULD): Access the database through a repository abstraction with
sqlx(compile-time-checked, async, bound parameters —RUST-SEC-1) or a vetted alternative (SeaORM/Diesel); run schema changes through versioned migrations (sqlx migrate). Keep raw queries out of handlers. (Consistent with the repo-layer + migrations default inNODE-NEST-16/FASTAPI-STRUCT-5/GO-API-6/JAVA-SPRING-7.)
12. Documentation
- RUST-DOC-1 (SHOULD): Write
///doc comments on public items (what it does, params, errors, panics), with runnable doctest examples where useful. A crate has a//!crate-level doc.
Resolved Decisions (v1.0)
| # | Question | Decision | Rule(s) |
| 1 | Web framework | axum default (on tokio+tower+hyper); actix-web sanctioned. Matches GO-API-1 / JAVA-SPRING-11 named-default+sanctioned-alternative | RUST-API-1 |
| 2 | App error crate | thiserror for libraries / anyhow for binaries — the established Rust library-vs-application convention; named per-context, not collapsed | RUST-ERR-3 |
| 3 | DB / ORM | sqlx recommended default (compile-time-checked, bound params); SeaORM/Diesel sanctioned. Recommended not mandated, but bound params + repo boundary + migrations required. Matches GO-API-6 / FASTAPI-STRUCT-5 | RUST-API-6, RUST-SEC-1 |
| 4 | Validation | validator recommended default boundary-validation crate (recommended not mandated) — the Rust counterpart to Zod / Bean Validation / Pydantic | RUST-API-3 |
Toolchain reference (verified 2026-06-13): Rust 1.96.x (edition 2024), tokio 1.52.x, axum 0.8.x, serde 1.x, thiserror 2.x, anyhow 1.x, sqlx 0.9.x, validator 0.20.x, tracing 0.1.x.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

