一键导入
rust-workflow
Rust project workflow guidelines. Activate when working with Rust files (.rs), Cargo.toml, Cargo.lock, or Rust-specific tooling.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Rust project workflow guidelines. Activate when working with Rust files (.rs), Cargo.toml, Cargo.lock, or Rust-specific tooling.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Language-agnostic API design patterns covering REST and GraphQL, including resource naming, HTTP methods, status codes, versioning, pagination, filtering, authentication, error handling, and schema design. Activate when working with APIs, REST endpoints, GraphQL schemas, API documentation, OpenAPI/Swagger, JWT, OAuth2, endpoint design, API versioning, rate limiting, or GraphQL resolvers.
Git workflow and commit guidelines. Trigger keywords: git, commit, push, .git, version control. MUST be activated before ANY git commit, push, or version control operation. Includes security scanning for secrets (API keys, tokens, .env files), commit message formatting with HEREDOC, logical commit grouping (docs, test, feat, fix, refactor, chore, build, deps), push behavior rules, safety rules for hooks and force pushes, and CRITICAL safeguards for destructive operations (filter-branch, gc --prune, reset --hard). Activate when user requests committing changes, pushing code, creating commits, rewriting history, or performing any git operations including analyzing uncommitted changes.
Testing workflow patterns and quality standards. Activate when working with tests, test files, test directories, code quality tools, coverage reports, or testing tasks. Includes zero-warnings policy, targeted testing during development, mocking patterns, and best practices across languages.
Ansible automation workflow guidelines. Activate when working with Ansible playbooks, ansible-playbook, inventory files (.yml, .ini), or Ansible-specific patterns.
Claude Code AI-assisted development workflow. Activate when discussing Claude Code usage, AI-assisted coding, prompting strategies, or Claude Code-specific patterns.
Guidelines for containerized projects using Docker, Dockerfile, docker-compose, container, and containerization. Covers multi-stage builds, security, signal handling, entrypoint scripts, and deployment workflows.
| name | rust-workflow |
| description | Rust project workflow guidelines. Activate when working with Rust files (.rs), Cargo.toml, Cargo.lock, or Rust-specific tooling. |
| location | user |
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
| Task | Tool | Command |
|---|---|---|
| Lint | Clippy | cargo clippy |
| Format | rustfmt | cargo fmt |
| Type check | built-in | cargo check |
| Build | cargo | cargo build |
| Test | cargo | cargo test |
| Security | cargo-audit | cargo audit |
| Coverage | cargo-tarpaulin | cargo tarpaulin |
| Docs | rustdoc | cargo doc |
# Check before commit
cargo fmt --check && cargo clippy -- -D warnings && cargo test
# Full validation
cargo fmt && cargo clippy --fix --allow-dirty && cargo test && cargo doc --no-deps
cargo build --release
cargo test --release
All public types MUST implement:
Debug - Required for error messages and debuggingClone - Required unless the type explicitly manages unique resourcesPublic types SHOULD implement:
PartialEq - When equality comparison is meaningfulEq - When PartialEq is reflexive (most cases)Hash - When the type may be used as a keyDefault - When a sensible default exists// Minimal public struct
#[derive(Debug, Clone)]
pub struct Config { /* ... */ }
// Value type (data container)
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct UserId(String);
// With default
#[derive(Debug, Clone, Default, PartialEq)]
pub struct Settings { /* ... */ }
// Serializable types
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct ApiResponse { /* ... */ }
Types representing user-facing values SHOULD implement Display:
use std::fmt;
impl fmt::Display for UserId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
Cargo.lock to version control.gitignore exceptions if using a global ignoreCargo.lock (add to .gitignore)Cargo.lockthiserroruse thiserror::Error;
#[derive(Debug, Error)]
pub enum LibraryError {
#[error("invalid configuration: {0}")]
InvalidConfig(String),
#[error("resource not found: {resource}")]
NotFound { resource: String },
#[error(transparent)]
Io(#[from] std::io::Error),
}
anyhowuse anyhow::{Context, Result};
fn main() -> Result<()> {
let config = load_config()
.context("failed to load configuration")?;
run_app(config)?;
Ok(())
}
.unwrap() in library code (except tests).expect() without a meaningful message? operator for propagation.context() or .with_context().unwrap() in main() for unrecoverable errorsLibraries SHOULD define a Result alias:
pub type Result<T> = std::result::Result<T, LibraryError>;
&T) allowed simultaneously&mut T) at a time// Explicit lifetime when returning borrowed data
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
// Struct containing references
struct Parser<'a> {
input: &'a str,
}
// Clone to avoid borrow issues (acceptable for small types)
let owned = borrowed.to_string();
// Use Cow for flexible ownership
use std::borrow::Cow;
fn process(input: Cow<'_, str>) -> String { /* ... */ }
// Arc/Rc for shared ownership
use std::sync::Arc;
let shared = Arc::new(data);
unsafe blocks&[T] over raw pointers for slicesBox<T> for heap allocationArc<T> or Rc<T> for shared ownershipsrc/
├── lib.rs # Library root (pub mod declarations)
├── main.rs # Binary entry point (optional)
├── config.rs # Single-file module
├── handlers/ # Multi-file module
│ ├── mod.rs # Module root (pub mod + re-exports)
│ ├── auth.rs # Submodule
│ └── api.rs # Submodule
└── utils/
├── mod.rs
└── helpers.rs
// src/handlers/mod.rs
mod auth;
mod api;
// Re-export public items
pub use auth::AuthHandler;
pub use api::{ApiClient, ApiError};
// Keep private implementation details
use auth::internal_helper;
pub only for intentional public APIpub(crate) for crate-internal itemspub(super) for parent-module accesspub(in path) for fine-grained control// src/prelude.rs
pub use crate::config::Config;
pub use crate::error::{Error, Result};
pub use crate::traits::*;
Unit tests MUST be in the same file as the code being tested:
// src/calculator.rs
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_add_positive() {
assert_eq!(add(2, 3), 5);
}
#[test]
fn test_add_negative() {
assert_eq!(add(-1, -1), -2);
}
}
Integration tests MUST be in the tests/ directory:
tests/
├── common/
│ └── mod.rs # Shared test utilities
├── api_tests.rs # Integration test file
└── cli_tests.rs # Another test file
// Use test fixtures
#[test]
fn test_with_fixture() {
let fixture = TestFixture::new();
// test code
}
// Test error conditions
#[test]
fn test_invalid_input() {
let result = parse("");
assert!(result.is_err());
}
// Use should_panic for expected panics
#[test]
#[should_panic(expected = "index out of bounds")]
fn test_panic_condition() {
let v = vec![1, 2, 3];
let _ = v[10];
}
// Run expensive tests only with --ignored
#[test]
#[ignore]
fn expensive_test() { /* ... */ }
// Async tests (with tokio)
#[tokio::test]
async fn async_test() { /* ... */ }
#[ignore] for slow tests/// Calculates the factorial of a number.
///
/// # Arguments
///
/// * `n` - The number to calculate factorial for
///
/// # Returns
///
/// The factorial of `n`, or `None` if overflow occurs.
///
/// # Examples
///
/// ```
/// use mylib::factorial;
/// assert_eq!(factorial(5), Some(120));
/// ```
///
/// # Panics
///
/// This function does not panic.
pub fn factorial(n: u64) -> Option<u64> {
// implementation
}
//! # Authentication Module
//!
//! This module provides authentication and authorization
//! functionality for the application.
//!
//! ## Features
//!
//! - JWT token validation
//! - Role-based access control
//! - Session management
mod jwt;
mod roles;
# Examples for non-trivial functions# Panics if the function can panic# Errors for functions returning Result# Safety for unsafe functions#[doc(hidden)] for public-but-internal itemsExamples in documentation are compiled and run as tests:
/// ```
/// # use mylib::Config; // Hidden setup line
/// let config = Config::default();
/// assert!(config.is_valid());
/// ```
unsafe blocksunsafe in safe abstractionsunsafe for convenience/performance without justification/// Reads a value from the given pointer.
///
/// # Safety
///
/// The caller MUST ensure:
/// - `ptr` is valid and properly aligned
/// - `ptr` points to initialized memory
/// - No other references to this memory exist
pub unsafe fn read_ptr<T>(ptr: *const T) -> T {
// SAFETY: Caller guarantees pointer validity per function contract
unsafe { std::ptr::read(ptr) }
}
pub struct SafeBuffer {
ptr: *mut u8,
len: usize,
}
impl SafeBuffer {
pub fn new(size: usize) -> Self {
let ptr = unsafe {
// SAFETY: size > 0 checked, layout is valid
std::alloc::alloc(std::alloc::Layout::array::<u8>(size).unwrap())
};
Self { ptr, len: size }
}
// Safe public API
pub fn get(&self, index: usize) -> Option<u8> {
if index < self.len {
// SAFETY: bounds checked above
Some(unsafe { *self.ptr.add(index) })
} else {
None
}
}
}
// SAFETY: comment before every unsafe block#[deny(unsafe_op_in_unsafe_fn)]#[derive(Debug, Clone, Default)]
pub struct RequestBuilder {
url: String,
headers: Vec<(String, String)>,
timeout: Option<u64>,
}
impl RequestBuilder {
pub fn new(url: impl Into<String>) -> Self {
Self { url: url.into(), ..Default::default() }
}
pub fn header(mut self, key: &str, value: &str) -> Self {
self.headers.push((key.to_string(), value.to_string()));
self
}
pub fn timeout(mut self, seconds: u64) -> Self {
self.timeout = Some(seconds);
self
}
pub fn build(self) -> Request {
Request { /* ... */ }
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Email(String);
impl Email {
pub fn new(value: &str) -> Result<Self, ValidationError> {
if value.contains('@') {
Ok(Self(value.to_string()))
} else {
Err(ValidationError::InvalidEmail)
}
}
pub fn as_str(&self) -> &str {
&self.0
}
}
pub struct Connection<State> {
inner: TcpStream,
_state: std::marker::PhantomData<State>,
}
pub struct Disconnected;
pub struct Connected;
impl Connection<Disconnected> {
pub fn connect(addr: &str) -> Result<Connection<Connected>, Error> {
let stream = TcpStream::connect(addr)?;
Ok(Connection { inner: stream, _state: std::marker::PhantomData })
}
}
impl Connection<Connected> {
pub fn send(&mut self, data: &[u8]) -> Result<(), Error> { /* ... */ }
}
Add to Cargo.toml or clippy.toml:
# Cargo.toml
[lints.clippy]
pedantic = "warn"
nursery = "warn"
unwrap_used = "deny"
expect_used = "warn"
#[allow(clippy::too_many_arguments)]
fn complex_function(/* many args */) { /* ... */ }
cargo clippy -- -D warnings -D clippy::unwrap_used