Agent skill
Rust
Execute these commands after EVERY implementation (see AGENT_AUTOMATION module for full workflow).
Install this agent skill to your Project
npx add-skill https://github.com/hivellm/rulebook/tree/main/templates/skills/languages/rust
SKILL.md
Rust Project Rules
Agent Automation Commands
CRITICAL: Execute these commands after EVERY implementation (see AGENT_AUTOMATION module for full workflow).
# Complete quality check sequence:
cargo fmt --all -- --check # Format check
cargo clippy --workspace --all-targets --all-features -- -D warnings # Lint
cargo test --workspace --all-features # All tests (100% pass)
cargo build --release # Build verification
cargo llvm-cov --all # Coverage (95%+ required)
# Security audit:
cargo audit # Vulnerability scan
cargo outdated # Check outdated deps
Rust Edition and Toolchain
CRITICAL: Always use Rust Edition 2024 with nightly toolchain.
- Edition: 2024
- Toolchain: nightly 1.85+
- Update: Run
rustup update nightlyregularly
Formatting
- Use
rustfmtwith nightly toolchain - Configuration in
rustfmt.tomlor.rustfmt.toml - Always format before committing:
cargo +nightly fmt --all - CI must check formatting:
cargo +nightly fmt --all -- --check
Linting
- Use
clippywith-D warnings(warnings as errors) - Fix all clippy warnings before committing
- Acceptable exceptions must be documented with
#[allow(clippy::...)]and justification - CI must enforce clippy:
cargo clippy --workspace -- -D warnings
Testing
- Location: Tests in
/testsdirectory for integration tests - Unit Tests: In same file as implementation with
#[cfg(test)] - Coverage: Must meet project threshold (default 95%)
- Tools: Use
cargo-nextestfor faster test execution - Async: Use
tokio::testfor async tests with Tokio runtime
Example test structure:
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_feature() {
// Test implementation
}
#[tokio::test]
async fn test_async_feature() {
// Async test implementation
}
}
Test Categories: S2S and Slow Tests
CRITICAL: Tests must be categorized based on execution time and dependencies.
Test Time Limits
- Fast Tests: Must complete in ≤ 10-20 seconds
- Slow Tests: Any test taking > 10-20 seconds must be marked as slow
- S2S Tests: Tests requiring active server/database must be isolated and run on-demand
S2S (Server-to-Server) Tests
Tests that require active servers, databases, or external services must be isolated using Cargo features.
Implementation:
- Create
s2sfeature inCargo.toml:
[features]
default = []
s2s = [] # Enable server-to-server tests
- Mark S2S tests with feature flag:
#[cfg(test)]
mod tests {
use super::*;
// Regular fast test (always runs)
#[test]
fn test_local_computation() {
// Fast test, no external dependencies
}
// S2S test (only runs with --features s2s)
#[cfg(feature = "s2s")]
#[tokio::test]
async fn test_database_connection() {
// Requires active database server
let db = connect_to_database().await?;
// ... test implementation
}
#[cfg(feature = "s2s")]
#[tokio::test]
async fn test_api_integration() {
// Requires active API server
let client = create_api_client().await?;
// ... test implementation
}
}
- Run tests:
# Regular tests (excludes S2S)
cargo test
# Include S2S tests (requires active servers)
cargo test --features s2s
# CI/CD: Run S2S tests only when servers are available
cargo test --features s2s --test-args '--test-threads=1'
Slow Tests
Tests that take > 10-20 seconds must be marked and run separately.
Implementation:
- Create
slowfeature inCargo.toml:
[features]
default = []
slow = [] # Enable slow tests
- Mark slow tests:
#[cfg(test)]
mod tests {
use super::*;
// Fast test (always runs)
#[test]
fn test_quick_operation() {
// Completes in < 1 second
}
// Slow test (only runs with --features slow)
#[cfg(feature = "slow")]
#[test]
fn test_heavy_computation() {
// Takes 30+ seconds
// Heavy processing, large dataset, etc.
}
#[cfg(feature = "slow")]
#[tokio::test]
async fn test_large_file_processing() {
// Processes large files, takes > 20 seconds
}
}
- Run tests:
# Regular tests (excludes slow)
cargo test
# Include slow tests
cargo test --features slow
# Run both S2S and slow tests
cargo test --features s2s,slow
Best Practices
- ✅ Always run fast tests in CI/CD by default
- ✅ Isolate S2S tests - never run them in standard test suite
- ✅ Mark slow tests - prevent CI/CD timeouts
- ✅ Document requirements - specify which servers/services are needed for S2S tests
- ✅ Use timeouts - Set appropriate timeouts for S2S tests:
tokio::time::timeout(Duration::from_secs(30), test_fn).await? - ❌ Never mix fast and slow/S2S tests in same test run
- ❌ Never require external services for standard test suite
- ❌ Never exceed 10-20 seconds for regular tests
Async Programming
CRITICAL: Follow Tokio best practices for async code.
- Runtime: Use Tokio for async runtime
- Blocking: Never block in async context - use
spawn_blockingfor CPU-intensive tasks - Channels: Use
tokio::sync::mpscortokio::sync::broadcastfor async communication - Timeouts: Always set timeouts for network operations:
tokio::time::timeout
Example:
use tokio::time::{timeout, Duration};
async fn fetch_data() -> Result<Data, Error> {
timeout(Duration::from_secs(30), async {
// Network operation
}).await?
}
Dependency Management
CRITICAL: Always verify latest versions before adding dependencies.
Before Adding Any Dependency
-
Check Context7 for latest version:
- Use MCP Context7 tool if available
- Search for the crate documentation
- Verify the latest stable version
- Review breaking changes and migration guides
-
Example Workflow:
Adding tokio → Check crates.io and docs.rs Adding serde → Verify latest version with security updates Adding axum → Check for breaking changes in latest version -
Document Version Choice:
- Note why specific version chosen in
Cargo.tomlcomments - Document any compatibility constraints
- Update CHANGELOG.md with new dependencies
- Note why specific version chosen in
Dependency Guidelines
- ✅ Use latest stable versions
- ✅ Check for security advisories:
cargo audit - ✅ Prefer well-maintained crates (active development, good documentation)
- ✅ Minimize dependency count
- ✅ Use workspace dependencies for monorepos
- ❌ Don't use outdated versions without justification
- ❌ Don't add dependencies without checking latest version
Codespell Configuration
CRITICAL: Use codespell to catch typos in code and documentation.
Install: pip install 'codespell[toml]'
Configuration in pyproject.toml:
[tool.codespell]
skip = "*.lock,*.json,target,node_modules,.git"
ignore-words-list = "crate,ser,deser"
Or run with flags:
codespell \
--skip="*.lock,*.json,target,node_modules,.git" \
--ignore-words-list="crate,ser,deser"
Error Handling
- Use
Result<T, E>for recoverable errors - Use
thiserrorfor custom error types - Use
anyhowfor application-level error handling - Document error conditions in function docs
- Never use
unwrap()orexpect()in production code without justification
Example:
use thiserror::Error;
#[derive(Error, Debug)]
pub enum MyError {
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("Invalid input: {0}")]
InvalidInput(String),
}
pub fn process_data(input: &str) -> Result<Data, MyError> {
// Implementation
}
Documentation
- Public APIs: Must have doc comments (
///) - Examples: Include examples in doc comments
- Modules: Document module purpose with
//! - Unsafe: Always document safety requirements for
unsafecode - Run doctests:
cargo test --doc
Example:
/// Processes the input data and returns a result.
///
/// # Arguments
///
/// * `input` - The input string to process
///
/// # Examples
///
/// ```
/// use mylib::process;
/// let result = process("hello");
/// assert_eq!(result, "HELLO");
/// ```
///
/// # Errors
///
/// Returns `MyError::InvalidInput` if input is empty.
pub fn process(input: &str) -> Result<String, MyError> {
// Implementation
}
Project Structure
project/
├── Cargo.toml # Package manifest
├── Cargo.lock # Dependency lock file (commit this)
├── README.md # Project overview (allowed in root)
├── CHANGELOG.md # Version history (allowed in root)
├── AGENTS.md # AI assistant rules (allowed in root)
├── LICENSE # Project license (allowed in root)
├── CONTRIBUTING.md # Contribution guidelines (allowed in root)
├── CODE_OF_CONDUCT.md # Code of conduct (allowed in root)
├── SECURITY.md # Security policy (allowed in root)
├── src/
│ ├── lib.rs # Library root (for libraries)
│ ├── main.rs # Binary root (for applications)
│ └── ...
├── tests/ # Integration tests
├── examples/ # Example code
├── benches/ # Benchmarks
└── docs/ # Project documentation
CI/CD Requirements
Must include GitHub Actions workflows for:
-
Testing (
rust-test.yml):- Test on ubuntu-latest, windows-latest, macos-latest
- Use
cargo-nextestfor fast test execution - Upload test results
-
Linting (
rust-lint.yml):- Format check:
cargo +nightly fmt --all -- --check - Clippy:
cargo clippy --workspace -- -D warnings - All targets:
cargo clippy --workspace --all-targets -- -D warnings
- Format check:
-
Codespell (
codespell.yml):- Check for typos in code and documentation
- Fail on errors
Crate Publication
Publishing to crates.io
Prerequisites:
- Create account at https://crates.io
- Generate API token:
cargo login - Add
CARGO_TOKENto GitHub repository secrets
Cargo.toml Configuration:
[package]
name = "your-crate-name"
version = "1.0.0"
edition = "2024"
authors = ["Your Name <your.email@example.com>"]
license = "MIT OR Apache-2.0"
description = "A short description of your crate"
documentation = "https://docs.rs/your-crate-name"
homepage = "https://github.com/your-org/your-crate-name"
repository = "https://github.com/your-org/your-crate-name"
readme = "README.md"
keywords = ["your", "keywords", "here"]
categories = ["category"]
exclude = [
".github/",
"tests/",
"benches/",
"examples/",
"*.sh",
]
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
Publishing Workflow:
- Update version in Cargo.toml
- Update CHANGELOG.md
- Run quality checks:
bash
cargo fmt --all cargo clippy --workspace --all-targets -- -D warnings cargo test --all-features cargo doc --no-deps --all-features - Create git tag:
git tag v1.0.0 && git push --tags - GitHub Actions automatically publishes to crates.io
- Or manual publish:
cargo publish
Publishing Checklist:
- ✅ All tests passing (
cargo test --all-features) - ✅ No clippy warnings (
cargo clippy -- -D warnings) - ✅ Code formatted (
cargo fmt --all -- --check) - ✅ Documentation builds (
cargo doc --no-deps) - ✅ Version updated in Cargo.toml
- ✅ CHANGELOG.md updated
- ✅ README.md up to date
- ✅ LICENSE file present
- ✅ Package size < 10MB (check with
cargo package --list) - ✅ Verify with
cargo publish --dry-run
Semantic Versioning:
Follow SemVer strictly:
- MAJOR: Breaking API changes
- MINOR: New features (backwards compatible)
- PATCH: Bug fixes (backwards compatible)
Documentation:
- Use
///for public API documentation - Include examples in doc comments
- Use
#![deny(missing_docs)]for libraries - Test documentation examples with
cargo test --doc
/// Processes the input data and returns a result.
///
/// # Arguments
///
/// * `input` - The input string to process
///
/// # Examples
///
/// ```
/// use your_crate::process;
///
/// let result = process("hello");
/// assert_eq!(result, "HELLO");
/// ```
///
/// # Errors
///
/// Returns an error if the input is empty.
pub fn process(input: &str) -> Result<String, Error> {
// Implementation
}
Didn't find tool you were looking for?