Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Use when writing, modifying, or reviewing Rust code. ALWAYS invoke before Rust edits; covers Microsoft Pragmatic Rust guidance for error handling, API design, performance, and idiomatic patterns.
.claude/skills/majiayu000-rust-best-practices/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-07 | ✗→✓ | ▲ Improved | 24% | 0% |
| case-01 | ✗→✓ | ▲ Improved | 7% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 12% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 23% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 16% | 0% |
Based on Microsoft Pragmatic Rust Guidelines and Rust community standards.
thiserror for Librariesrustuse thiserror::Error; #[derive(Error, Debug)] pub enum MyError { #[error("IO error: {0}")] Io(#[from] std::io::Error), #[error("Parse error at line {line}: {message}")] Parse { line: usize, message: String }, #[error("Not found: {0}")] NotFound(String), }
anyhow for Applicationsrustuse anyhow::{Context, Result}; fn main() -> Result<()> { let config = load_config() .context("Failed to load configuration")?; run_app(config)?; Ok(()) }
rust// ❌ BAD pub fn get_item(index: usize) -> &Item { &self.items[index] // Panics on out-of-bounds } // ✅ GOOD pub fn get_item(&self, index: usize) -> Option<&Item> { self.items.get(index) } // ✅ GOOD - when you need Result pub fn get_item(&self, index: usize) -> Result<&Item, Error> { self.items.get(index).ok_or(Error::NotFound(index)) }
rustpub struct Client { url: String, timeout: Duration, retries: u32, } impl Client { pub fn builder(url: impl Into<String>) -> ClientBuilder { ClientBuilder { url: url.into(), timeout: Duration::from_secs(30), retries: 3, } } } pub struct ClientBuilder { url: String, timeout: Duration, retries: u32, } impl ClientBuilder { pub fn timeout(mut self, timeout: Duration) -> Self { self.timeout = timeout; self } pub fn retries(mut self, retries: u32) -> Self { self.retries = retries; self } pub fn build(self) -> Client { Client { url: self.url, timeout: self.timeout, retries: self.retries, } } }
rust// ❌ BAD - primitive obsession fn create_user(name: String, email: String, age: u32) -> User { ... } // ✅ GOOD - newtype wrappers pub struct Username(String); pub struct Email(String); pub struct Age(u32); impl Email { pub fn new(email: impl Into<String>) -> Result<Self, ValidationError> { let email = email.into(); if email.contains('@') { Ok(Self(email)) } else { Err(ValidationError::InvalidEmail) } } } fn create_user(name: Username, email: Email, age: Age) -> User { ... }
impl Trait for Flexibilityrust// ❌ BAD - overly specific pub fn process(items: Vec<String>) { ... } // ✅ GOOD - accept any iterable pub fn process(items: impl IntoIterator<Item = impl AsRef<str>>) { for item in items { println!("{}", item.as_ref()); } }
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-07 | fail→pass | 13,245 | 9,830 | -26% | 1 | 1 | 0% | 2,342 | 2,907 | +24% | 0 | 0 | — |
case-01 | fail→pass | 14,916 | 13,383 | -10% | 1 | 1 | 0% | 2,677 | 2,862 | +7% | 0 | 0 | — |
case-02 | fail→pass | 19,234 | 15,160 | -21% | 1 | 1 | 0% | 3,856 | 4,337 | +12% | 0 | 0 | — |
case-03 | pass→pass | 14,488 | 16,744 | +16% | 1 | 1 | 0% | 2,289 | 3,720 | +63% | 0 | 0 | — |
case-04 | pass→pass | 9,171 | 7,626 | -17% | 1 | 1 | 0% | 1,742 | 2,479 | +42% | 0 | 0 | — |
case-05 | pass→pass | 13,268 | 11,562 | -13% | 1 | 1 | 0% | 2,547 | 3,152 | +24% | 0 | 0 | — |
case-06 | pass→pass | 14,345 | 8,227 | -43% | 1 | 1 | 0% | 2,584 | 2,542 | -2% | 0 | 0 | — |
case-08 | pass→pass | 15,614 | 8,928 | -43% | 1 | 1 | 0% | 2,639 | 2,652 | +0% | 0 | 0 | — |
case-09 | pass→pass | 10,899 | 11,282 | +4% | 1 | 1 | 0% | 1,984 | 3,134 | +58% | 0 | 0 | — |
case-10 | fail→pass | 11,953 | 9,570 | -20% | 1 | 1 | 0% | 2,188 | 2,701 | +23% | 0 | 0 | — |
case-11 | pass→pass | 13,509 | 8,510 | -37% | 1 | 1 | 0% | 2,468 | 2,558 | +4% | 0 | 0 | — |
case-12 | pass→pass | 7,934 | 5,040 | -36% | 1 | 1 | 0% | 1,361 | 1,916 | +41% | 0 | 0 | — |
case-13 | fail→pass | 12,634 | 8,947 | -29% | 1 | 1 | 0% | 2,183 | 2,524 | +16% | 0 | 0 | — |
case-14 | pass→pass | 11,673 | 6,528 | -44% | 1 | 1 | 0% | 1,886 | 2,107 | +12% | 0 | 0 | — |
case-15 | fail→fail | 13,301 | 8,870 | -33% | 1 | 1 | 0% | 2,428 | 2,583 | +6% | 0 | 0 | — |
case-16 | pass→pass | 12,119 | 9,290 | -23% | 1 | 1 | 0% | 2,172 | 2,790 | +28% | 0 | 0 | — |
case-17 | pass→pass | 13,387 | 6,816 | -49% | 1 | 1 | 0% | 2,454 | 2,317 | -6% | 0 | 0 | — |
case-18 | pass→pass | 11,769 | 8,036 | -32% | 1 | 1 | 0% | 2,042 | 2,539 | +24% | 0 | 0 | — |
case-19 | pass→pass | 13,826 | 9,243 | -33% | 1 | 1 | 0% | 2,303 | 2,777 | +21% | 0 | 0 | — |
case-20 | pass→pass | 8,527 | 5,303 | -38% | 1 | 1 | 0% | 1,502 | 1,904 | +27% | 0 | 0 | — |
case-21 | pass→pass | 11,227 | 12,569 | +12% | 1 | 1 | 0% | 1,951 | 3,377 | +73% | 0 | 0 | — |
case-22 | pass→pass | 9,063 | 7,218 | -20% | 1 | 1 | 0% | 1,614 | 2,291 | +42% | 0 | 0 | — |
case-23 | pass→pass | 8,328 | 5,053 | -39% | 1 | 1 | 0% | 1,444 | 1,923 | +33% | 0 | 0 | — |
case-24 | pass→pass | 3,512 | 2,826 | -20% | 1 | 1 | 0% | 569 | 1,493 | +162% | 0 | 0 | — |
case-25 | fail→pass | 12,436 | 7,267 | -42% | 1 | 1 | 0% | 2,269 | 2,300 | +1% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 25 cases were attempted. The headline lift of +24 percentage points is the difference between those two pass rates over the 25 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.