internal/skills/content/rust-guide/SKILL.md
Rust guardrails, patterns, and best practices for AI-assisted development. Use when working with Rust files (.rs), Cargo.toml, or when the user mentions Rust. Provides ownership conventions, error handling with Result/Option, testing standards, and unsafe code guidelines.
npx skillsauth add ar4mirez/samuel rust-guideInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Applies to: Rust 2021 edition+, Systems Programming, CLIs, WebAssembly, APIs
Result<T, E> for all fallible operations; panic! is a bug#[forbid(unsafe_code)]; justify every unsafe block in writingcargo clippy -- -D warnings with zero exceptionsedition = "2021" in Cargo.toml)rust-version (MSRV) in Cargo.toml for all published crates~ for compatible updates in librariesCargo.lock for binaries; omit for librariescargo update weekly for security patchescargo fmt before every commit (no exceptions)cargo clippy -- -D warnings before every commitsnake_case for functions, variables, modules, crate namesPascalCase for types, traits, enums, type parametersSCREAMING_SNAKE_CASE for constants and staticsmatch over if let chainsuse super::* in non-test modules (explicit imports only)Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, DeserializeResult<T, E> for all operations that can failthiserror for library error types, anyhow for application codeString as an error type (create enums or use thiserror)? operator for propagation; avoid manual match on Result when ? sufficesunwrap() is forbidden outside tests and examplesexpect("reason") is allowed only with a comment explaining the invariant#[must_use] on functions returning Result or important valuesCow<'a, str> when a function may or may not allocate'static bounds unless truly needed (e.g., thread spawning, lazy statics)tokio as the async runtime (unless project requires async-std)tokio::time::timeoutArc<T> for shared ownership across threads; never Rc<T> in async codetokio::sync::Mutex over std::sync::Mutex in async contextsmpsc, oneshot, broadcast) over shared mutable statetokio::spawn; propagate errors via JoinHandleselect! branch must handle cancellationmyproject/
├── Cargo.toml
├── Cargo.lock
├── src/
│ ├── main.rs # Entry point, minimal (parse args, call run)
│ ├── lib.rs # Public API and module declarations
│ ├── config.rs # Configuration loading
│ ├── error.rs # Custom error types
│ ├── domain/
│ │ ├── mod.rs
│ │ └── user.rs
│ └── infra/
│ ├── mod.rs
│ ├── db.rs
│ └── http.rs
├── tests/ # Integration tests
│ └── api_test.rs
├── benches/ # Benchmarks (criterion)
│ └── throughput.rs
└── examples/
└── basic_usage.rs
workspace/
├── Cargo.toml # [workspace] members
├── crates/
│ ├── core/ # Domain logic (no I/O)
│ │ ├── Cargo.toml
│ │ └── src/lib.rs
│ ├── api/ # HTTP layer
│ │ ├── Cargo.toml
│ │ └── src/lib.rs
│ └── cli/ # Binary entry point
│ ├── Cargo.toml
│ └── src/main.rs
└── tests/ # Workspace-level integration tests
main.rs should be thin: parse CLI args, build config, call lib.rs entrylib.rs modules (testable without binary)error.rs at crate root defines the crate-level error enumuse thiserror::Error;
#[derive(Error, Debug)]
pub enum StorageError {
#[error("record {id} not found in {table}")]
NotFound { table: &'static str, id: String },
#[error("duplicate key: {0}")]
Conflict(String),
#[error(transparent)]
Database(#[from] sqlx::Error),
#[error(transparent)]
Io(#[from] std::io::Error),
}
use anyhow::{bail, Context, Result};
fn load_config(path: &str) -> Result<Config> {
let raw = std::fs::read_to_string(path)
.with_context(|| format!("reading config from {path}"))?;
let config: Config = toml::from_str(&raw)
.context("parsing TOML config")?;
if config.port == 0 {
bail!("port must be non-zero");
}
Ok(config)
}
// Define From impls via thiserror's #[from], then just use ?
fn create_user(db: &Pool, input: &NewUser) -> Result<User, AppError> {
validate_email(&input.email)?; // ValidationError -> AppError
let user = db.insert(input)?; // sqlx::Error -> AppError
Ok(user)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_valid_email_succeeds() {
let result = Email::parse("[email protected]");
assert!(result.is_ok());
}
#[test]
fn parse_invalid_email_returns_error() {
let err = Email::parse("not-an-email").unwrap_err();
assert!(matches!(err, ValidationError::InvalidEmail(_)));
}
#[test]
fn amount_cannot_be_negative() -> Result<(), Box<dyn std::error::Error>> {
let result = Amount::new(-5);
assert!(result.is_err());
Ok(())
}
}
// tests/api_test.rs
use myproject::app;
#[tokio::test]
async fn health_endpoint_returns_ok() {
let app = app::build_test_app().await;
let resp = app.get("/health").await;
assert_eq!(resp.status(), 200);
}
/// Adds two numbers together.
///
/// # Examples
///
/// ```
/// use mycrate::add;
/// assert_eq!(add(2, 3), 5);
/// ```
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
use proptest::prelude::*;
proptest! {
#[test]
fn roundtrip_serialization(input in "[a-zA-Z0-9]{1,100}") {
let encoded = encode(&input);
let decoded = decode(&encoded)?;
prop_assert_eq!(input, decoded);
}
}
fn rejected_order_cannot_be_shipped()#[cfg(test)] mod tests in the same filetests/ directory#[should_panic(expected = "...")] for panic-testing (rare)assert!(matches!(...)) for enum variant assertionscargo tarpaulin or cargo llvm-cov for coverage#[tokio::test]cargo fmt # Format (non-negotiable)
cargo clippy -- -D warnings # Lint with deny
cargo test # All tests
cargo test --all-features # Test all feature combinations
cargo check # Fast type-check (no codegen)
cargo doc --open # Generate and view docs
cargo audit # Check for vulnerable deps
cargo deny check # License + advisory check
cargo bench # Run benchmarks (criterion)
[package]
name = "myproject"
version = "0.1.0"
edition = "2021"
rust-version = "1.75"
[dependencies]
serde = { version = "1", features = ["derive"] }
thiserror = "2"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
tracing = "0.1"
[dev-dependencies]
proptest = "1"
tokio = { version = "1", features = ["test-util"] }
[profile.release]
lto = true
codegen-units = 1
strip = true
[lints.clippy]
pedantic = { level = "warn", priority = -1 }
unwrap_used = "deny"
expect_used = "warn"
# rustfmt.toml
edition = "2021"
max_width = 100
use_field_init_shorthand = true
rust-version in Cargo.toml for every published cratecargo +1.75.0 checkFor detailed patterns and examples, see:
development
Zig language guardrails, patterns, and best practices for AI-assisted development. Use when working with Zig files (.zig), build.zig, or when the user mentions Zig. Provides comptime patterns, allocator conventions, C interop guidelines, and testing standards specific to this project's coding standards.
tools
WordPress framework guardrails, patterns, and best practices for AI-assisted development. Use when working with WordPress projects, or when the user mentions WordPress. Provides theme development, plugin architecture, REST API, blocks, and security guidelines.
tools
Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs. Use when testing web apps, automating browser interactions, or debugging frontend issues.
tools
Suite of tools for creating elaborate, multi-component web applications using modern frontend technologies (React, Tailwind CSS, shadcn/ui). Use for complex projects requiring state management, routing, or shadcn/ui components - not for simple single-file HTML/JSX pages.