Automated summary
Guides Rust development following official standards, community best practices, and idiomatic patterns from The Rust Book and Rust API Guidelines.
Strengths
- Based on authoritative sources (Rust Book, API Guidelines)
- Covers project structure, error handling, naming conventions, and workflows
- Provides automated workflow triggers for build, test, lint, publish, etc.
Limitations
- Assumes familiarity with Rust syntax and basic concepts
- Does not deeply cover advanced async or unsafe patterns
- Focused on general application/library development, not niche domains
Use this skill when starting a new Rust project or refactoring existing code to follow idiomatic patterns and best practices.
Avoid this skill for highly specialized areas like embedded or WebAssembly without adaptation, or if you need a step-by-step tutorial on Rust fundamentals.
Security analysis
SafeThe skill contains only educational/reference content about Rust coding practices. It does not include any executable commands, network operations, file system modifications, or instructions that could be misused. No tools are declared, so the AI agent will not execute anything. There is no risk of destructive or exfiltrating actions.
No concerns found
How this analysis is madeExamples
Create a new Rust library project following idiomatic project structure with proper error handling, naming conventions, and a basic CLI example.Show me how to implement idiomatic error handling in Rust using Result, thiserror, and anyhow for a simple file reader.What are the available workflows in the Rust skill and how do I trigger them?name: Rust description: Rust development best practices and patterns. USE WHEN writing Rust code, designing Rust projects, working with Cargo, testing, or Rust package development.
Rust Development Best Practices
Purpose
Guide Rust development following official standards, community best practices, and idiomatic patterns from The Rust Book, Rust API Guidelines, and the Rust team's recommendations.
Context Detection
This skill activates when:
- Claude is asked to work on Rust code
- Current directory path or git repository contains
Cargo.toml - User is working with
.rsfiles - Commands like
cargo,rustc, orclippyare mentioned
Workflow Routing
When executing a workflow, output this notification directly:
Running the **WorkflowName** workflow from the **Rust** skill...
| Workflow | Trigger | File |
|----------|---------|------|
| Build | "build rust project", "cargo build", "compile" | workflows/Build.md |
| Test | "run tests", "cargo test", "test coverage" | workflows/Test.md |
| Bench | "benchmark", "cargo bench", "performance test" | workflows/Bench.md |
| Lint | "lint", "clippy", "cargo fmt", "format" | workflows/Lint.md |
| Deps | "dependencies", "cargo add", "update deps" | workflows/Deps.md |
| Error | "error handling", "Result", "thiserror", "anyhow" | workflows/Error.md |
| Workspace | "workspace", "multi-crate", "monorepo" | workflows/Workspace.md |
| Publish | "publish crate", "crates.io", "cargo publish" | workflows/Publish.md |
Core Principles
- Safety first: Leverage Rust's ownership and type system for memory safety
- Zero-cost abstractions: Write high-level code without runtime overhead
- Fearless concurrency: Use Rust's guarantees to write concurrent code safely
- Explicit error handling: Use
ResultandOptiontypes, never panic in libraries - Idiomatic patterns: Follow Rust API Guidelines and community conventions
Standard Project Structure
Binary Application
myapp/
├── Cargo.toml # Project manifest
├── Cargo.lock # Dependency lock file (commit for apps)
├── src/
│ ├── main.rs # Entry point
│ ├── lib.rs # Optional library code
│ └── bin/ # Additional binaries
│ └── helper.rs
├── tests/ # Integration tests
│ └── integration_test.rs
├── benches/ # Benchmarks
│ └── my_bench.rs
├── examples/ # Example code
│ └── basic.rs
└── README.md
Library Crate
mylib/
├── Cargo.toml
├── Cargo.lock # Don't commit for libraries
├── src/
│ ├── lib.rs # Library root
│ └── submodule/
│ └── mod.rs
├── tests/
│ └── integration_test.rs
├── benches/
│ └── benchmark.rs
└── examples/
└── usage.rs
Workspace (Multiple Crates)
myworkspace/
├── Cargo.toml # Workspace manifest
├── Cargo.lock # Shared lock file
├── crates/
│ ├── core/
│ │ ├── Cargo.toml
│ │ └── src/lib.rs
│ ├── cli/
│ │ ├── Cargo.toml
│ │ └── src/main.rs
│ └── api/
│ ├── Cargo.toml
│ └── src/lib.rs
└── README.md
Writing Idiomatic Rust
Naming Conventions
// Types: UpperCamelCase
struct MyStruct;
enum MyEnum { VariantA, VariantB }
trait MyTrait {}
// Functions, variables, modules: snake_case
fn my_function() {}
let my_variable = 42;
mod my_module {}
// Constants, statics: SCREAMING_SNAKE_CASE
const MAX_SIZE: usize = 100;
static GLOBAL_COUNT: AtomicUsize = AtomicUsize::new(0);
// Lifetimes: short lowercase
fn foo<'a, 'b>(x: &'a str, y: &'b str) -> &'a str { x }
Error Handling
use std::fs::File;
use std::io::{self, Read};
// Good: Use Result for recoverable errors
fn read_file(path: &str) -> Result<String, io::Error> {
let mut file = File::open(path)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
Ok(contents)
}
// Good: Use Option for values that might not exist
fn find_user(id: u64) -> Option<User> {
DATABASE.get(&id).cloned()
}
// Bad: Don't use unwrap() in library code
fn bad_read_file(path: &str) -> String {
let mut file = File::open(path).unwrap(); // DON'T DO THIS
// ...
}
// Use thiserror for library errors
use thiserror::Error;
#[derive(Error, Debug)]
pub enum MyError {
#[error("IO error: {0}")]
Io(#[from] io::Error),
#[error("Parse error: {0}")]
Parse(String),
#[error("Not found: {0}")]
NotFound(String),
}
// Use anyhow for application errors
use anyhow::{Context, Result};
fn process_file(path: &str) -> Result<()> {
let contents = std::fs::read_to_string(path)
.context("Failed to read configuration file")?;
let config: Config = serde_json::from_str(&contents)
.context("Failed to parse JSON config")?;
Ok(())
}
Ownership and Borrowing
// Good: Use references when you don't need ownership
fn calculate_length(s: &String) -> usize {
s.len()
}
// Good: Use mutable references for modification
fn append_world(s: &mut String) {
s.push_str(", world!");
}
// Good: Take ownership when you need it
fn consume_string(s: String) -> usize {
s.len()
} // s is dropped here
// Good: Use slices for flexibility
fn first_word(s: &str) -> &str {
let bytes = s.as_bytes();
for (i, &byte) in bytes.iter().enumerate() {
if byte == b' ' {
return &s[..i];
}
}
&s[..]
}
Iterator Patterns
// Good: Use iterators for functional transformations
let numbers: Vec<i32> = vec![1, 2, 3, 4, 5];
let doubled: Vec<i32> = numbers
.iter()
.map(|x| x * 2)
.collect();
let sum: i32 = numbers
.iter()
.filter(|&&x| x % 2 == 0)
.sum();
// Good: Chain iterator methods
let result: Vec<String> = input
.lines()
.map(str::trim)
.filter(|line| !line.is_empty())
.map(|line| line.to_uppercase())
.collect();
// Good: Use iterator adapters
let pairs: Vec<(usize, &i32)> = numbers
.iter()
.enumerate()
.filter(|(i, _)| i % 2 == 0)
.collect();
Cargo Essentials
Cargo.toml Configuration
[package]
name = "myproject"
version = "0.1.0"
edition = "2021" # Use latest edition (2024 coming soon)
rust-version = "1.70" # Minimum supported Rust version (MSRV)
authors = ["Your Name <you@example.com>"]
description = "A short description"
documentation = "https://docs.rs/myproject"
repository = "https://github.com/user/myproject"
license = "MIT OR Apache-2.0"
keywords = ["cli", "tool"]
categories = ["command-line-utilities"]
[dependencies]
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1.0", features = ["full"] }
anyhow = "1.0"
[dev-dependencies]
criterion = "0.7"
proptest = "1.0"
[build-dependencies]
cc = "1.0"
# Profile optimizations
[profile.release]
lto = true # Link-time optimization
codegen-units = 1 # Better optimization
strip = true # Remove debug symbols
opt-level = 3 # Maximum optimization
[profile.dev]
opt-level = 0 # Fast compilation
debug = true
# Workspace dependencies (in workspace root)
[workspace.dependencies]
serde = "1.0"
tokio = "1.0"
Common Commands
# Create new project
cargo new myproject # Binary
cargo new --lib mylib # Library
# Build
cargo build # Debug build
cargo build --release # Release build
cargo build --all-features # With all features
# Run
cargo run # Run binary
cargo run --example basic # Run example
# Test
cargo test # Run all tests
cargo test --doc # Run doc tests
cargo test integration # Run tests matching pattern
# Check without building
cargo check # Fast compile check
cargo clippy # Lint checks
# Format
cargo fmt # Format code
# Documentation
cargo doc --open # Build and open docs
# Dependencies
cargo add serde # Add dependency
cargo update # Update dependencies
cargo tree # Show dependency tree
Testing
Unit Tests
// In same file as code being tested
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_addition() {
assert_eq!(add(2, 2), 4);
}
#[test]
fn test_with_result() -> Result<(), String> {
if add(2, 2) == 4 {
Ok(())
} else {
Err(String::from("Addition failed"))
}
}
#[test]
#[should_panic(expected = "divided by zero")]
fn test_panic() {
divide(10, 0);
}
#[test]
#[ignore] // Skip unless --ignored flag
fn expensive_test() {
// ...
}
}
Integration Tests
// tests/integration_test.rs
use mylib;
#[test]
fn it_works() {
assert_eq!(mylib::add(2, 2), 4);
}
#[test]
fn test_full_workflow() {
let result = mylib::process_data("input.txt");
assert!(result.is_ok());
}
Property-Based Testing
use proptest::prelude::*;
proptest! {
#[test]
fn test_reversing_twice_gives_original(s in ".*") {
let reversed = reverse(&s);
let double_reversed = reverse(&reversed);
prop_assert_eq!(s, double_reversed);
}
#[test]
fn test_addition_commutative(a in 0..1000i32, b in 0..1000i32) {
prop_assert_eq!(a + b, b + a);
}
}
Async Rust with Tokio
use tokio;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Spawn concurrent tasks
let handle = tokio::spawn(async {
// Async work
fetch_data().await
});
let result = handle.await?;
Ok(())
}
async fn fetch_data() -> Result<String, reqwest::Error> {
let response = reqwest::get("https://api.example.com/data")
.await?
.text()
.await?;
Ok(response)
}
// Concurrent execution
use tokio::join;
async fn do_stuff_concurrently() {
let (result1, result2, result3) = join!(
fetch_thing_1(),
fetch_thing_2(),
fetch_thing_3()
);
}
Best Practices Checklist
- [ ] Use
cargo fmtfor consistent formatting - [ ] Run
cargo clippyand fix all warnings - [ ] Add documentation comments (
///) for public APIs - [ ] Write tests for new functionality
- [ ] Use
Resultfor error handling, notpanic!in libraries - [ ] Specify MSRV in
Cargo.toml - [ ] Use workspace dependencies for consistency
- [ ] Enable useful Clippy lints in
Cargo.toml - [ ] Profile release builds for performance
- [ ] Use semantic versioning for releases
Resources
Official Documentation
Error Handling
Testing & Benchmarking
Best Practices
Examples
Example 1: Creating a Rust CLI application
User: "Build a CLI tool to process logs"
→ Initializes project with cargo new
→ Adds clap for argument parsing
→ Implements error handling with anyhow
→ Writes unit tests and integration tests
→ Builds optimized binary with cargo build --release
→ Result: Fast, safe Rust CLI tool
Example 2: Fixing ownership and borrowing issues
User: "Help me fix these borrow checker errors"
→ Analyzes ownership flow in code
→ Identifies unnecessary clones or moves
→ Suggests lifetime annotations where needed
→ Refactors to use references appropriately
→ Explains Rust's ownership rules
→ Result: Clean code that satisfies the borrow checker
Example 3: Optimizing Rust performance
User: "This Rust code is slower than expected"
→ Uses cargo flamegraph to profile
→ Identifies allocations and hot paths
→ Optimizes with iterators and zero-copy operations
→ Adds benchmark tests with criterion
→ Measures improvement
→ Result: Performant Rust code with benchmarks
From the file to a first result
The download contains exactly the content displayed on this page. This copy may differ from the latest version in the source repository.
View the source and supporting filesThis download contains SKILL.md only. Any scripts, references, templates and dependencies are not included. Get the required files from the source, preserving their directory structure, before continuing.
1. Download the file
Download SKILL.mdFrom the root of a test project, save the file as .skill-downloads/rust-development-mmk3nh35/SKILL.md, or use the command below. This folder is for inspecting the skill before installation.
Command for macOS/Linux or WSL: requires a POSIX shell and curl. On Windows without WSL, use the download button and create the folder manually.
mkdir -p '.skill-downloads/rust-development-mmk3nh35' && curl --fail --show-error --location 'https://skills-guides.com/api/skills/rust-development-mmk3nh35/download' --output '.skill-downloads/rust-development-mmk3nh35/SKILL.md.part' && mv '.skill-downloads/rust-development-mmk3nh35/SKILL.md.part' '.skill-downloads/rust-development-mmk3nh35/SKILL.md'2. Check prerequisites
Read SKILL.md before using it. If it references scripts or external services, inspect them and prepare the required access in your test environment.
No recognized prerequisites section in this file. This does not mean it is self-contained: libraries, tools and access requirements may be mentioned elsewhere in the content or source repository.
The platforms on this page are catalog indications. The paths below follow tool documentation; they do not prove this skill has been run in those tools. No minimum tool version is confirmed for this listing.
3. Load the skill
This file does not provide a usable name/description header for this native procedure. It remains available to download and inspect; use the manual method below.
Manual method or another tool: attach SKILL.md to a conversation, or open it in an agent that can read files. Include any required supporting resources. No universal folder is recognized by every tool.
4. Try a first task
Use a short, synthetic input: an API endpoint, a small document or an interface brief. In a new conversation, attach the file or give the agent its path, then adapt this request:
Read .skill-downloads/rust-development-mmk3nh35/SKILL.md and apply its instructions to this example: [describe a test input]. Identify any missing files, dependencies or access. Produce the result requested by the skill without inventing data or running unreviewed scripts.Expected result: output matching the skill instructions, or a precise list of missing prerequisites. A read confirmation alone does not validate a first use. If an external resource is unavailable, that path remains untested.
React Hook Form Best Practices
Development
Master React Hook Form: avoid anti-patterns, manage subscriptions, and handle reset, dirty state, and controlled inputs correctly.
Emotion to Mantine Migration
Development
Migrate Emotion styled-components to Mantine components with style props and CSS modules. Use when converting .styled.tsx files or removing @emotion imports.
Scope Creep Detector
Development
Analyzes git diffs against a stated intent to detect scope creep, unrelated files, broad PRs, and oversized changes, then suggests keep, split, or justify actions.