with one click
rs
Rust development. NOT for non-Rust code (use go, py, ts, tsx, or sh).
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
Rust development. NOT for non-Rust code (use go, py, ts, tsx, or sh).
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
Development wisdom and workflow rules. NOT for project-specific conventions (those live in CLAUDE.md, edit via wisdom).
The `BUGS.md` open-issues queue — entry format, lifecycle, pruning to diary. NOT for the record-don't-fix policy (that's CLAUDE.md Bug Triage Protocol), NOT for resolved-bug history (use /diary), NOT for feature backlog (use TODO.md/specs).
Terminal demo GIF + MP4 recordings for READMEs and social (asciinema + agg + ffmpeg). NOT for general Makefile targets (use software) or GUI screenshots (use visual).
Go development. NOT for non-Go code (use rs, py, ts, tsx, or sh).
Humanize text: strip AI-isms and add real voice. NOT for drafting new copy (use writing).
Python development. NOT for shell scripting (use sh) or non-Python code.
| name | rs |
| description | Rust development. NOT for non-Rust code (use go, py, ts, tsx, or sh). |
| when_to_use | editing .rs files or writing Rust code |
Requires the software skill's code.md for shared naming, style, and design
rules. Below are Rust-specific additions.
as aliases to rename external typesuse super::, NEVER local use inside function bodies
(exception: tests/main where scoping demands it)use crate:: for absolute pathsArc, the project's main error type, common
wire/record types) gets a top-of-file single-line use so it reads bare
(Arc<str>, not std::sync::Arc<str>). A type used once or twice gets a full
inline path (std::time::Duration, std::sync::atomic::AtomicU64) instead of
a use. Pick the SAME side project-wide: if Arc is used where it's common,
use it everywhere it's common — do NOT scatter bare Arc in some files and
std::sync::Arc::... full paths in others. Reduces import churn + makes every
file read the same way.collect_tx_summaries() not tx_summaries(); nouns ok for new(), from_str()v, k, n in .map(|v| ...))n, k, i, j, x, y, z, m, g, f, h; doubled (kk, vv) for nested/plural; short descriptive (data, msg) fineo, O, I, l (look like 0 or 1)$a, $val, $ty); meaningful names for semantic roles ($state, $key)for x in xs {} over xs.for_each(|x| ...) when the closure adds no clarity.filter().map().unwrap_or() as a disguised if/else — write if/let directly.filter() filters collections; it is NOT a conditional branch.map(), .filter() ok on iterators/collections, NEVER on Option to express control flow#[repr(i16)] enum in codesrc/<module>_test.rs, imported with
#[cfg(test)] mod <module>_test; at the bottom of the source file —
NOT inline #[cfg(test)] mod tests { ... }, NOT in tests/tests/src/<module>_test.rs use crate:: paths, not super::*--test-threads=1 if global state via DashMap/RwLocktests/common/mod.rs.get_host_port_ipv4()std::panic::set_hook(Box::new(|_| std::process::exit(0)));#[command]eyre + color-eyre for new projects; keep anyhow if already presentthiserror for typed errorscolor_eyre::install()? before tracing init.wrap_err("context") not .context() (avoids trait ambiguity)let _ = call_that_returns_result(). Silent drops have caused real correctness bugs. Use ?, if let Err(e) = ..., or fail loud.tracing over logEnvFilter from RUST_LOG for subscriber init#[instrument] on hot-path functions (overhead)main() wraps run() in retry loop with 5s sleepfn main() -> eyre::Result<()> {
color_eyre::install()?;
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.init();
let cli = Cli::parse();
let config = load_config(&cli.config);
loop {
match run(&config) {
Ok(()) => break Ok(()),
Err(e) => {
tracing::error!("crashed: {e:#}, restarting in 5s");
std::thread::sleep(Duration::from_secs(5));
}
}
}
}
.unwrap() in non-test code; use .expect("msg").expect() ok at startup (fail-fast) or on documented invariants; otherwise propagateResult (and the
caller has a retry/backoff/supervisor), ? the error — don't .expect(). A
socket bind, PG connect, etc. can fail TRANSIENTLY; fail-fast-panic is only for
truly unrecoverable config. "It's at startup" is not a reason to panic if
startup is re-entered (e.g. a re-entrant run_main on demote/restart)..expect("msg"): put the REASON in the message; do NOT prefix a // SAFETY:
comment (see Unsafe)..lock().unwrap_or_else(|e| e.into_inner()) to recover poisoncargo +nightly miri test on modules with unsafe blocks; NEVER ship unsafe without a // SAFETY: invariant comment// SAFETY: is RESERVED for justifying unsafe — it documents the
invariants that make an unsafe block sound, and is the audit signal a reader
greps when reviewing unsafe. NEVER put // SAFETY: on SAFE code to justify a
.expect() / panic! / fail-fast / .unwrap(). That dilutes the convention
and is wrong. For a deliberate panic, the reason goes in the .expect("…")
message or a plain // comment — // SAFETY: means "this unsafe is sound", nothing else.serde_json::from_value::<T>(value.clone()) — &Value implements Deserializer, use
T::deserialize(value) (ref, no clone):
let Ok(value) = MyType::deserialize(details) else { continue };
let Some(value) = details.get("count").and_then(|v| v.as_u64()) else { continue };
spawn(async { ... }) — name the coroutine as a function:// WRONG: tokio::spawn(async move { ... });
// RIGHT:
async fn fetch_and_process(client: Client) { ... }
tokio::spawn(fetch_and_process(client));
pub mod flat, no nested mod.rsSerialize/Deserialize on adapter-layer DTOs, not on core domain entitiescargo check fastest for error checking (no codegen)