skills/rust/SKILL.md
Robust Rust patterns for file-backed data, parsing, persistence, FFI boundaries, and system integration. Use when writing Rust that handles file formats, subprocess integration, PID/process management, Serde serialization, or UniFFI boundaries. Covers UTF-8 safety, atomic writes, state machines, and defensive error handling.
npx skillsauth add petekp/agent-skills rustInstall 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.
Patterns for building reliable Rust systems that handle file-backed data, external process integration, and cross-language boundaries.
Conservative by Default: Inputs from files, subprocesses, and external systems are untrusted.
Canonical Model Ownership: When Rust is the source of truth, maintain separate representations:
| Layer | Purpose | Characteristics |
|-------|---------|-----------------|
| Internal domain | Business logic | Expressive enums, rich types |
| FFI DTOs | Cross-language boundary | Flat, stable, String-heavy |
| File format | Persistence | Versioned, round-trippable |
| External input | Validation boundary | Strictly validated, never trusted |
Safe Rust Only: None of these patterns require unsafe. Use ecosystem crates for safe abstractions.
Load the relevant reference when working in that domain:
| Domain | Reference | When to Load | |--------|-----------|--------------| | Data Modeling | references/data-modeling.md | Serde patterns, UniFFI, strong types, versioned schemas | | File I/O | references/file-io.md | Atomic writes, concurrency control, file watching | | Process Integration | references/process-integration.md | PID verification, subprocess handling, timestamps | | Text & Parsing | references/text-and-parsing.md | UTF-8 safety, path normalization, state machines | | Testing | references/testing.md | Round-trip tests, fuzz testing, Clippy lints |
Libraries (public API): Use thiserror with granular error types per operation:
// File operations have their own error type
#[derive(thiserror::Error, Debug)]
pub enum ReadError {
#[error("failed to read {path}")]
Io { path: PathBuf, #[source] source: std::io::Error },
#[error("parse error at line {line}: {message}")]
Parse { line: usize, message: String },
}
// Subprocess operations have their own error type
#[derive(thiserror::Error, Debug)]
pub enum SubprocessError {
#[error("failed to spawn process")]
Spawn(#[source] std::io::Error),
#[error("process exited with {code:?}: {stderr}")]
NonZeroExit { code: Option<i32>, stderr: String },
#[error("output not valid UTF-8")]
InvalidUtf8(#[source] std::str::Utf8Error),
#[error("timed out after {0:?}")]
Timeout(std::time::Duration),
}
Applications (internal/binary): Use anyhow for context-rich errors:
use anyhow::{Context, Result};
fn load_config(path: &Path) -> Result<Config> {
let content = std::fs::read_to_string(path)
.with_context(|| format!("failed to read config from {}", path.display()))?;
// ...
}
Errors degrade functionality, not crash. But log when being lenient:
match parse_metadata(&line) {
Ok(meta) => entries.push(meta),
Err(e) => {
tracing::warn!("skipping malformed entry at line {}: {}", line_num, e);
// Continue processing other entries
}
}
std::sync::LazyLock for static regex (Rust 1.80+)#[serde(deny_unknown_fields)] for strict external input.chars() or graphemes, not byte slicingsync_all() before renamesaturating_sub for time arithmeticcargo clippy -- -D warnings and cargo fmt before commit#[from] without adding context (loses which file failed)&s[..N] (panics on char boundaries)unsafe (not needed for these patterns)| Bug | Pattern | Reference |
|-----|---------|-----------|
| PID reuse "ghost sessions" | Store + verify process start time | process-integration.md |
| Timestamp unit mismatch (sec vs ms) | Normalize on read | process-integration.md |
| UTF-8 panic on truncation | Use .chars().take(n) | text-and-parsing.md |
| Lost updates under concurrency | Lock spans full read-modify-write | file-io.md |
| Corrupt file on power loss | sync_all() before rename | file-io.md |
| Silent metadata corruption | Anchor updates to heading lines | text-and-parsing.md |
| Old data breaks new code | #[serde(default)] + alias | data-modeling.md |
When modifying these systems, verify:
Schema / Serde
Option + #[serde(default)]alias (read) or rename (write)#[serde(deny_unknown_fields)]Concurrency
Mutex<T>, not thread_local!Robustness
Quality
cargo clippy -- -D warnings passescargo fmt --check passesunsafe blocks (unless justified and audited)development
Compile a plain-language task into a concise, auditable Codex or Claude Code `/goal`, or explain why a normal prompt fits better. Use when the user asks to draft, formulate, rewrite, tighten, or create a goal for multi-step work that needs a durable objective, transcript-visible proof, constraints, bounded stop conditions, host-aware operation, and risk-based review depth.
tools
Expert Unix and macOS systems engineer for shell scripting, system administration, command-line tools, launchd, Homebrew, networking, and low-level system tasks. Use when the user asks about Unix commands, shell scripts, macOS system configuration, process management, or troubleshooting system issues.
testing
Apply professional typography principles to create readable, hierarchical, and aesthetically refined interfaces. Use when setting type scales, choosing fonts, adjusting spacing, designing text-heavy layouts, implementing dark mode typography, or when asked about readability, font pairing, line height, measure, typographic hierarchy, variable fonts, font loading, or OpenType features.
development
Create visual parameter tuning panels for iterative adjustment of animations, layouts, colors, typography, physics, or any numeric/visual values. Use when the user asks to "create a tuning panel", "add parameter controls", "build a debug panel", "tweak parameters visually", "fine-tune values", "dial in the settings", or "adjust parameters interactively". Also triggers on mentions of "leva", "dat.GUI", or "tweakpane".