name: rust-development description: Rust development workflow with quality gates, testing, and iteration patterns. Use when developing Rust code, running tests, or iterating on Rust projects. allowed-tools: Read, Edit, Write, Bash, Grep, Glob, Task
Rust Development Workflow
Development patterns for Rust CLI tools and libraries, based on AllBeads and QDOS workflows.
Quality Gates
ALL THREE must pass before commits:
cargo fmt -- --check && cargo clippy -- -D warnings && cargo test
Run frequently during development, not just before commits.
Development Loop
1. Check and Build
# Fast check (no codegen)
cargo check
# Full build
cargo build
# Release build
cargo build --release
2. Run Tests
# All tests
cargo test
# Specific test
cargo test test_name
# With output
cargo test -- --nocapture
# Single-threaded (for tests with shared state)
cargo test -- --test-threads=1
3. Format and Lint
# Format code
cargo fmt
# Check formatting without changing
cargo fmt -- --check
# Lint with warnings as errors
cargo clippy -- -D warnings
# Auto-fix clippy suggestions
cargo clippy --fix --allow-dirty
4. Run the Binary
# Debug build
cargo run -- [args]
# Release build
cargo run --release -- [args]
# With specific features
cargo run --features "feature1,feature2" -- [args]
Project Structure
Standard Rust project layout:
project/
├── Cargo.toml # Package manifest
├── Cargo.lock # Dependency lock
├── src/
│ ├── main.rs # Binary entry point
│ ├── lib.rs # Library root (if both bin and lib)
│ └── module/
│ └── mod.rs
├── tests/ # Integration tests
├── benches/ # Benchmarks
└── examples/ # Example binaries
Error Handling Patterns
Application Errors (use anyhow)
use anyhow::{Context, Result};
fn main() -> Result<()> {
let config = load_config()
.context("Failed to load configuration")?;
Ok(())
}
Library Errors (use thiserror)
use thiserror::Error;
#[derive(Error, Debug)]
pub enum MyError {
#[error("Invalid input: {0}")]
InvalidInput(String),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
}
Dependency Management
# Add dependency
cargo add serde --features derive
# Add dev dependency
cargo add --dev tokio-test
# Update dependencies
cargo update
# Check for outdated
cargo outdated # requires cargo-outdated
Workspace Setup
For multi-crate projects:
# Cargo.toml (workspace root)
[workspace]
members = ["crate1", "crate2"]
resolver = "2"
[workspace.dependencies]
serde = { version = "1.0", features = ["derive"] }
Performance Profiling
# Build with debug info for profiling
cargo build --release
# Time compilation
cargo build --timings
# Check binary size
cargo bloat --release # requires cargo-bloat
Build Performance
Use mold linker (Linux)
Faster linking times:
# .cargo/config.toml
[target.'cfg(target_os = "linux")']
rustflags = ["-C", "link-arg=-fuse-ld=mold"]
Install: sudo apt install mold or brew install mold
Use sccache for caching
Cache compiler artifacts across builds:
cargo install --locked sccache
export RUSTC_WRAPPER=sccache
# Add to shell profile for persistence
echo 'export RUSTC_WRAPPER=sccache' >> ~/.zshrc
Auto-derive macro
Reduce boilerplate for common derives:
macro_rules! auto_derived {
( $( $item:item )+ ) => {
$(
#[derive(Debug, Clone, PartialEq, Eq)]
$item
)+
};
}
// Usage
auto_derived! {
pub struct User {
id: i64,
name: String,
}
pub struct Config {
host: String,
port: u16,
}
}
Add Serialize, Deserialize to the macro if using serde.
Common Patterns
Builder Pattern
pub struct Config {
host: String,
port: u16,
}
impl Config {
pub fn builder() -> ConfigBuilder {
ConfigBuilder::default()
}
}
#[derive(Default)]
pub struct ConfigBuilder {
host: Option<String>,
port: Option<u16>,
}
impl ConfigBuilder {
pub fn host(mut self, host: impl Into<String>) -> Self {
self.host = Some(host.into());
self
}
pub fn port(mut self, port: u16) -> Self {
self.port = Some(port);
self
}
pub fn build(self) -> Result<Config, &'static str> {
Ok(Config {
host: self.host.ok_or("host required")?,
port: self.port.unwrap_or(8080),
})
}
}
Newtype Pattern
pub struct UserId(pub i64);
pub struct Email(String);
impl Email {
pub fn new(s: impl Into<String>) -> Result<Self, &'static str> {
let s = s.into();
if s.contains('@') {
Ok(Self(s))
} else {
Err("invalid email")
}
}
}
IDE Integration
For VS Code with rust-analyzer:
// .vscode/settings.json
{
"rust-analyzer.check.command": "clippy",
"rust-analyzer.cargo.features": "all"
}
Anti-Patterns
DON'T:
- Use
.unwrap()in library code (use?instead) - Ignore clippy warnings
- Skip
cargo fmtbefore commits - Write tests after the fact
DO:
- Write code that passes fmt/clippy on first write
- Use
Result<T, E>for fallible operations - Run tests frequently during development
- Use
#[must_use]for important return values
chat Comments (0)
Sign in to join the discussion and leave a comment.
Skill Details
GitHub Stars
2
GitHub Forks
0
Created
Jan 2026
Last Updated
4个月前
tools
tools automation tools
Related Skills
Build your own?
Join 12,000+ developers contributing to the Claude ecosystem.
No comments yet. Be the first to share your thoughts!