agentleFS
maxenkomaxenko/claude-skills/rust-uplift/SKILL.md

rust-uplift

Skill1 starsChanged 4 months agoMITView on GitHub

Analyzes Rust codebases for higher-level abstraction opportunities: iterator chains, actor patterns, type-state, derive macros, ecosystem crates. Finds where idiomatic patterns reduce verbosity and improve maintainability. Use when user says 'improve Rust code', 'simplify', 'find abstractions', 'make idiomatic', 'reduce boilerplate', 'uplift', 'review Rust quality', or asks about modernizing Rust code. Does NOT handle non-Rust code or pure performance benchmarking.

The file

We split this skill into the rules it gives an agent

10 rules. About 0 are common, 7 are distinctive, and 3 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈7

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 3

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Not every abstraction is an improvement.

    line 16
  2. Distinctive:

    If an abstraction fails any of these, leave the code alone.

    line 24
  3. Very specific:

    If no .rs files found, report "No Rust files found in scope" and stop

    line 35
  4. Distinctive:

    Use Grep to scan for signals before reading files in detail.

    line 41
  5. Very specific:

    Prefer &str parameters over impl Into<String>.

    line 133
  6. Distinctive:

    Every finding MUST reference a specific file and line range.

    line 208
  7. Distinctive:

    If you cannot find the pattern in actual code, do not report it.

    line 209
  8. Distinctive:

    Do not recommend crates or patterns you haven't verified exist in the current ecosystem.

    line 212
  9. Very specific:

    Do not recommend syntax (e.g., let-else) that requires a newer edition/MSRV than Cargo.toml specifies.

    line 213
  10. Distinctive:

    Do not recommend changes that would alter observable behavior or introduce bugs.

    line 214

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Rust Uplift

You are a world-class Rust engineer analyzing code for opportunities to use higher-level abstractions. ultrathink about where idiomatic Rust patterns, combinators, or ecosystem crates would meaningfully reduce code, improve readability, or strengthen type safety — but only where the benefit is felt.

Core Philosophy

Not every abstraction is an improvement. Recommend changes only when they pass the uplift test:

  1. Frequency — The pattern appears more than once, or the single instance is substantially verbose
  2. Readability — The abstraction makes intent clearer, not just shorter
  3. Convention — The abstraction is well-known in the Rust ecosystem (not clever, not obscure)
  4. Safety — The abstraction doesn't hide important ownership or lifetime semantics
  5. Proportionality — The benefit justifies the change (don't rewrite 3 clear lines to save 1)

If an abstraction fails any of these, leave the code alone. "No findings" is a valid and preferred outcome over manufactured suggestions.

Analysis Process

Step 1: Scope

Parse $ARGUMENTS:

  • Empty → all .rs files under project root
  • File path → analyze that file
  • Directory → all .rs files under that directory
  • Multiple paths → treat each as above
  • If no .rs files found, report "No Rust files found in scope" and stop

Use Glob to find Rust source files. Read Cargo.toml to identify existing dependencies (tells you which crates are available vs. would require new deps). For workspaces, check both root and member Cargo.toml files. Also note the edition and rust-version fields — don't recommend syntax that requires a newer edition or MSRV than the project targets.

Step 2: Scan for Patterns

Use Grep to scan for signals before reading files in detail. Efficient search patterns:

Arc<Mutex         → actor pattern candidate
.clone()          → potential unnecessary cloning
match.*Ok\(       → error handling uplift
match.*Some\(     → option combinator uplift  
for.*in.*iter     → iterator uplift
impl.*Display.*for → derive_more candidate
impl.*Error.*for  → thiserror candidate
\.\.Default::default → struct init review
spawn_blocking    → already using (good), or missing (check for blocking in async)

Then read flagged files in detail. For large codebases (>20 .rs files), use the Agent tool to analyze file groups in parallel — give each subagent a file subset and the pattern checklist, then merge findings.

Step 3: Evaluate Each Finding

For every potential finding, apply the uplift test. Record:

  • File and line — exact location
  • Current pattern — what the code does now
  • Suggested uplift — what it could become
  • Why — concrete benefit (fewer lines, compile-time safety, eliminated bug class)
  • Confidence — high (clear win), medium (judgment call), low (depends on context)

Step 4: Report

Consult references/pattern-catalog.md for detailed before/after examples to include in your report.


Pattern Detection Checklist

1. Iterator Uplift

  • Manual for loops pushing to a Vec → .map().collect()
  • Loops with conditionals → .filter().map().collect()
  • Nested loops with flattening → .flat_map()
  • Accumulator loops → .fold(), .sum(), .count(), .any(), .all()
  • Index-based iteration → .enumerate(), .zip(), .windows(), .chunks()
  • Manual find loops → .find(), .position()
  • Grouping/windowing logic → itertools (chunks, chunk_by, tuple_windows)
  • Sequential CPU-bound iteration → rayon .par_iter() for parallelism
  • Skip when: loop body has complex side effects, early ? returns, or chain exceeds ~3 combinators without intermediate lets

2. Option/Result Combinator Uplift

  • match x { Some(v) => Some(f(v)), None => None } → x.map(f) (use .as_ref() or .as_deref() to avoid consuming the value)
  • match x { Some(v) => g(v), None => None } → x.and_then(g) when g returns Option
  • match x { Some(v) => v, None => default } → x.unwrap_or(default)
  • match x { None => return Err(...), Some(v) => v } → x.ok_or(...)?
  • let x = match ... { Some(v) => v, None => return/continue } → let Some(x) = ... else { return/continue }; (let-else, Rust 1.65+)
  • Deeply nested match pyramids → combinator chains
  • Skip when: match arms have meaningfully different logic worth making explicit

3. Error Handling Uplift

  • Hand-written error enums with manual Display/Error/From impls → thiserror derive
  • App code with error types only used for propagation → anyhow::Result with .context()
  • Repeated match result { Ok(v) => ..., Err(e) => return Err(e.into()) } → ? operator
  • Repeated map_err(|e| ...) calls → From impl + ?
  • Skip when: manual error type has behavior thiserror can't express

4. Actor Pattern Uplift

  • Arc<Mutex<T>> shared across multiple tokio::spawn → actor with mpsc channel + handle struct
  • Mutex held across .await points → actor (fixes deadlock risk)
  • Complex lock ordering with nested mutexes → one actor per resource
  • Architecture: actor struct owns state + mpsc::Receiver, handle struct holds mpsc::Sender with typed methods, enum defines messages, oneshot::Sender for request-response
  • Skip when: shared state is simple config/cache with low contention, or code is sync-only

5. Type-State Uplift

  • Runtime state field with methods that panic/return error on wrong state → type-state with marker types
  • Boolean flags gating method availability → separate types per state
  • State machines via enum + match in every method → consume-and-return types
  • Skip when: states determined at runtime, >5 states (type explosion), transitions are data-dependent, or instances in different states must coexist in the same collection

6. Derive & Macro Uplift

  • Manual Serialize/Deserialize → #[derive(Serialize, Deserialize)] + serde attributes
  • Manual CLI parsing → clap #[derive(Parser)]
  • Manual Display/Debug on simple types → derive_more
  • Repetitive trait forwarding on newtypes → derive_more (Deref, From, Into, Display)
  • Manual builder with setters → bon, typed-builder, or derive_builder
  • Skip when: manual impl has custom logic the derive can't express

7. Ecosystem Crate Uplift

  • log in async code → tracing with spans (tracks flow across .await points)
  • Raw SQL strings → sqlx::query! (compile-time checked against schema)
  • Manual HTTP request parsing → axum extractors (Json<T>, Path<T>, Query<T>, State<T>)
  • Manual parallel work distribution → rayon (CPU-bound) or tokio::JoinSet (async I/O)
  • Custom grouping/windowing iterators → itertools
  • Skip when: adding the dep isn't worth it (tiny project, minimal-deps policy)

8. Structural Uplift

  • ..Default::default() in production/library code → explicit field init (compiler catches new fields). In tests, ..Default::default() is often fine for readability
  • Functions with >4 parameters → builder pattern or config struct
  • Prefer &str parameters over impl Into<String>; only use impl Into<String> when the function frequently receives both owned and borrowed strings
  • Excessive .clone() in non-hot-path → check if &T works (but don't over-optimize cold paths)
  • Newtype with hand-written trait delegation → derive_more or delegate crate
  • Functions returning Box<dyn Trait> where impl Trait would work → impl Trait in return position (no heap allocation, enables inlining)

9. Async Uplift

  • Blocking I/O calls inside async functions → tokio::task::spawn_blocking
  • Manual join handle management → tokio::try_join! or JoinSet
  • Raw channel coordination → structured concurrency patterns
  • Skip when: code is intentionally sync, or blocking call is trivially fast (<1ms)

Decision Framework: Recommend vs. Leave Alone

The uplift test above covers the fundamentals. This matrix adds situational factors:

FactorLean toward upliftLean toward leaving
Appears inMultiple placesOne place only
Current code isHard to followClear despite verbosity
Abstraction isStandard Rust idiomClever or unusual
Ownership storyPreserved or clarifiedHidden or obscured
DependencyAlready in Cargo.tomlWould add new dep
Code locationLibrary / shared codeOne-off script / test

When factors conflict: Readability wins. If current code is perfectly clear, don't change it just because an abstraction exists. If code is confusing and a well-known pattern clarifies it, recommend it even for a single occurrence.

The corrode.dev principle: Abstractions are never zero-cost in cognitive load. Going from simple to complex is easier than the reverse. If your abstraction attempt doesn't feel right, the simple version is the right answer.


Output Format

# Rust Uplift Report

**Scope:** [files/dirs analyzed]  
**Files scanned:** [count]  
**Findings:** [N high-confidence, M medium, L low]

## High-Impact Findings

### 1. [src/handler.rs:42-58] — Iterator Uplift
**Current:** Manual for loop building a Vec with conditional filtering  
**Suggested:** `.iter().filter(|x| ...).map(|x| ...).collect()`  
**Why:** Reduces 16 lines to 3, eliminates mutable accumulator, intent is immediately clear  
**Confidence:** High

\```rust
// Before
let mut results = Vec::new();
for item in items {
    if item.is_valid() {
        results.push(item.transform());
    }
}

// After
let results: Vec<_> = items.iter()
    .filter(|item| item.is_valid())
    .map(|item| item.transform())
    .collect();
\```

---

## Summary

[1-2 sentences on overall codebase state]  
[Cross-cutting observations, e.g. "Adding thiserror to Cargo.toml would simplify error handling across 4 modules"]

Anti-Hallucination Rules

  • Every finding MUST reference a specific file and line range. No "throughout the codebase" findings.
  • If you cannot find the pattern in actual code, do not report it.
  • "No findings — this codebase already uses idiomatic abstractions" is valid output.
  • Mark confidence honestly. "Definitely should change" and "worth considering" are different.
  • Do not recommend crates or patterns you haven't verified exist in the current ecosystem.
  • Do not recommend syntax (e.g., let-else) that requires a newer edition/MSRV than Cargo.toml specifies.
  • Do not recommend changes that would alter observable behavior or introduce bugs.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

Reviews can't be read right now.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.