← Back to Skills Marketplace
iliaal

ia-rust-systems

by Ilia Alshanetsky · GitHub ↗ · v3.0.3 · MIT-0
cross-platform ✓ Security Clean
153
Downloads
0
Stars
0
Active Installs
6
Versions
Install in OpenClaw
/install compound-eng-rust-systems
Description
Rust patterns for CLI tools, backend services, and general application code. Use when working with Rust, Cargo workspaces, axum/tokio services, clap CLIs, as...
README (SKILL.md)

Rust Systems & Services

Covers modern application-layer Rust (edition 2024): CLIs, web services, libraries. Not no_std/embedded.

Tooling

Tool Purpose
cargo Build, dep management, script runner
clippy Lint (cargo clippy --workspace --all-targets -- -D warnings)
rustfmt Formatter (cargo fmt --all)
cargo-nextest Test runner, noticeably faster than cargo test, better isolation
cargo-deny License + advisory + duplicate-dep checks
cargo-machete Find unused dependencies
  • Pin rust-toolchain.toml per repo so every contributor and CI uses the same compiler.
  • cargo update -p \x3Ccrate> for single-package upgrades. cargo update rewrites everything — avoid in PR diffs.
  • Cargo.lock goes in version control for binaries and libraries (modern guidance; reproducibility wins).

Workspaces

Multi-crate projects use a workspace with layered crates. Dependencies point inward only.

Cargo.toml                  # [workspace] members + [workspace.dependencies]
crates/
  protocol/    # Shared types, no deps on other workspace crates
  storage/     # Persistence, depends on protocol
  service/    # Business logic, depends on protocol + storage
  cli/        # Binary, depends on everything
  • Centralize versions in [workspace.dependencies], reference as foo = { workspace = true } in members.

  • Keep the leaf-most crate (protocol / types) dependency-free so every other crate can depend on it without cycles.

  • Feature flags belong on the crate that introduces the dependency, not re-exported through the workspace root.

  • Library crates expose one stable facade: a thin lib.rs with a //! module doc comment stating purpose, followed by pub use re-exports of the public surface. Consumers learn one import path per concept; internal module layout can be reorganized without breaking callers.

  • Feature gates must error, never silently degrade. If runtime config requests a capability the binary wasn't compiled with (e.g. device = "gpu" on a non-CUDA build), fail at startup with a clear error. Silent fallback produces different behavior from what the operator configured, often without anyone noticing.

  • Centralize lints at the workspace root with [workspace.lints.*]. Every member crate inherits the same ruleset — no drift between crates, no per-crate #![deny(...)] stacks. Example:

    [workspace.lints.rust]
    unsafe_code = "warn"
    missing_docs = "warn"
    
    [workspace.lints.clippy]
    all = { level = "warn", priority = -1 }
    pedantic = { level = "warn", priority = -1 }
    nursery = { level = "warn", priority = -1 }
    module_name_repetitions = "allow"
    must_use_candidate = "allow"
    

    Each member crate opts in with [lints] workspace = true in its own Cargo.toml. Changing a lint in one place updates every crate.

Build Profiles

When tuning Cargo build profiles (release LTO, release-dbg symbols, release-min for distributable binaries) or adding dev-machine speedups (mold linker, target-cpu=native, share-generics), load build-profiles.md.

Error Handling

Split by crate role:

  • Libraries / lower crates: define typed errors with thiserror. Consumers can pattern-match.
  • Binaries / top-level crates: use anyhow::Result with .context("what was being attempted"). Human-readable error chains.
  • Never return Box\x3Cdyn Error> from library APIs — it erases variant information.
  • Use ? liberally. Never .unwrap() or .expect() outside tests and main. An expect("...") is acceptable only when the invariant is provably upheld and the message explains why.
  • Convert at boundaries: #[from] on thiserror variants for auto-conversion; .map_err(MyError::from) when explicit.
  • bail!("...") / ensure!(cond, "...") in application code for early exits.
  • Prefer Result\x3CT, E> over panics for any recoverable error. Panics are for programmer bugs (broken invariants), not runtime failures.
  • #[must_use] on fallible APIs: annotate functions returning Result or newtype-wrapped results that callers frequently ignore. Catches let _ = validate(x); at compile time instead of shipping a silently-dropped error.

Ownership Discipline

  • Take &str over &String, &[T] over &Vec\x3CT> in function signatures — accepts more call sites for free.

  • Return owned (String, Vec\x3CT>) from constructors and public APIs. Borrow in hot paths where lifetimes are obvious.

  • Reach for Arc\x3CT> only when sharing across threads. Single-threaded sharing uses Rc\x3CT> or references.

  • Cow\x3C'_, str> when a function sometimes allocates and sometimes borrows (e.g. normalization).

  • Lifetime elision handles 90% of cases. If you're writing 'a in more than one signature, reconsider whether that type should own its data instead.

  • bytes::Bytes for zero-copy slicing of shared immutable buffers — network parsers, frame decoders, protocol handlers. BytesMut for building buffers that split_to / split_off into Bytes without reallocation. Prefer Bytes over Arc\x3CVec\x3Cu8>> when slicing is the dominant access pattern.

  • Reduce hot-path heap allocations with stack-or-inline collections when the typical size is small and known:

    • smallvec::SmallVec\x3C[T; N]> — inline for ≤N items, spills to heap beyond. Good for "usually 1-8 items" cases like parsed tag lists, lookup keys, small event batches.
    • arrayvec::ArrayVec\x3CT, CAP> — fixed capacity, never heap-allocates. Returns an error when full. Good for bounded message buffers or per-request scratch space.
    • String interning for repeatedly-seen strings (enum-like values parsed from config, tenant IDs, route keys): dashmap::DashMap\x3CString, &'static str> with Box::leak on miss gives &'static str comparisons without per-call allocations.

    These are optimizations — profile first. Vec/String on a cold path isn't the bottleneck.

Async with Tokio

  • Default runtime: #[tokio::main] with features = ["full"] for apps; features = ["rt", "macros", "sync"] for libraries that need to stay slim.
  • tokio::spawn for independent tasks. JoinSet for a dynamic group you'll await together with cancellation.
  • tokio::select! for racing futures (timeouts, cancellation, first-wins).
  • Never block the runtime: tokio::task::spawn_blocking for sync CPU work or blocking I/O libs.
  • tokio::sync::Mutex only when the guard must be held across .await. Otherwise std::sync::Mutex is faster.
  • tokio::sync::RwLock when reads dominate writes (config snapshots, route tables, hot caches). Many readers proceed in parallel; Mutex serializes them. For snapshot-swap semantics (rarely-updated config), arc-swap::ArcSwap is faster still — no lock on the read path.
  • Cancellation: CancellationToken (from tokio-util) propagates shutdown. Long-running tasks must check it.
  • Backpressure via bounded mpsc channels — unbounded channels hide memory growth until OOM.
  • Semaphore for hard concurrency limits on spawn paths that don't fit a channel model (e.g. "at most 50 concurrent outbound HTTP calls"). let _permit = sem.acquire().await?; inside the task; dropping the permit releases the slot. Pair with Arc\x3CSemaphore> shared across spawners.
  • Don't mix async runtimes. Pick tokio and stick with it; async-std and smol don't interop cleanly.

CLI Tools (clap)

  • Use the derive API: #[derive(Parser)] + #[derive(Subcommand)]. Less boilerplate, types drive the help text.
  • One enum Commands variant per subcommand; flatten shared flags into a #[command(flatten)] struct CommonArgs.
  • --json flag on query commands for agent/pipe consumption. Emit via serde_json::to_string(&value)?.
  • Exit codes: 0 success, 1 for errors main returned, 2 for argparse (clap handles this), reserve 3+ for domain meanings documented in --help.
  • Provide --version automatically via #[command(version)].

See cli-tools.md for config layering, logging setup, progress reporting, and shell completions.

HTTP Services (axum)

  • Framework default: axum (tokio-native, tower middleware, extractor-based handlers). Pick actix-web only if an existing codebase uses it.
  • Handlers return Result\x3Cimpl IntoResponse, AppError>. Implement IntoResponse for AppError to centralize error → status mapping.
  • Validate input at the boundary: axum::extract::Json\x3CT> where T: Deserialize + Validate (use validator crate). Internal services trust input was validated.
  • Share state via State\x3CArc\x3CAppState>> — not globals, not lazy_static.
  • Middleware via tower::ServiceBuilder: tracing → timeout → auth → CORS → handler. Order matters.
  • Resilience layer stack (outbound HTTP clients and shared services): ServiceBuilder::new().layer(TimeoutLayer).layer(RateLimitLayer).layer(ConcurrencyLimitLayer).layer(LoadShedLayer).layer(RetryLayer).service(client). Name each layer explicitly — LoadShedLayer sheds excess load, ConcurrencyLimitLayer caps in-flight requests, RateLimitLayer bounds request rate, RetryLayer retries classified transient errors. Combining LoadShedLayer + ConcurrencyLimitLayer produces proper backpressure instead of unbounded queueing.

See axum-service.md for project layout, extractors, error types, graceful shutdown, and OpenAPI generation.

Concurrency

Workload Approach
Independent async I/O tokio::spawn + JoinSet or futures::join!
Data-parallel CPU work rayon with par_iter
Shared mutable state across threads Arc\x3CMutex\x3CT>> or Arc\x3CRwLock\x3CT>>, smallest scope possible
Single-producer pipelines tokio::sync::mpsc (async) or std::sync::mpsc (sync)
Broadcast / fan-out tokio::sync::broadcast

rayon and tokio coexist — use tokio::task::spawn_blocking to call a rayon pool from async code. Never call .block_on() from inside a tokio task; it deadlocks the runtime.

Testing

  • Built-in #[test]. Prefer cargo nextest run --workspace over cargo test — it runs tests in parallel processes with proper isolation.
  • Unit tests live in mod tests { ... } at the bottom of the file (access to private items).
  • Integration tests in tests/ directory. One file per public surface area.
  • #[tokio::test] for async tests. Add flavor = "multi_thread" when the code under test spawns tasks.
  • rstest for parametrized tests and fixtures. proptest / quickcheck for property-based tests on pure logic.
  • insta for snapshot testing CLI output, serialization, large structs. Review diffs with cargo insta review.
  • assert_cmd + predicates for CLI integration tests (invokes the binary, asserts on stdout/stderr/exit code).
  • Assert on error variants with matches!: assert!(matches!(result.unwrap_err(), MyError::Validation(_))). Cleaner than match arms when the test only cares whether the error is the right kind, and doesn't force updates when unrelated variants are added.
  • Coverage: cargo llvm-cov --workspace --html. Target 70%+ on application code, higher on library crates.
  • Fuzzing for parsers: cargo fuzz + libfuzzer-sys on any code that parses untrusted input (file formats, protocols, query languages). A short nightly fuzz run surfaces the panics and UB that unit tests miss.

For generic test discipline (anti-patterns, mock rules, rationalization resistance), see the ia-writing-tests skill.

Unsafe Discipline

  • Default: no unsafe. If clippy flags it, don't #[allow] it — refactor.
  • Every unsafe block gets a // SAFETY: comment above it explaining why each invariant holds. No comment = reviewer rejects.
  • Keep unsafe blocks minimal — wrap in a safe abstraction at module boundary, mark the module pub(crate).
  • Use miri (cargo +nightly miri test) on any crate containing unsafe or raw pointer arithmetic — catches UB that optimizers mask.
  • Prefer bytemuck, zerocopy, bytes over hand-rolled transmutes for zero-copy patterns.

Production Resilience

When productionizing a service (config validation, /health + /ready endpoints, graceful shutdown, retries/timeouts/jitter, connection pools, diagnostic secret redaction), load production-resilience.md.

Observability

For logging (tracing + tracing-subscriber with init recipe), #[instrument] spans, correlation IDs, metrics, and distributed tracing patterns, load observability.md. Never use println! or log:: in new code.

CI

General CI design lives with the ia-infrastructure-engineer agent. For Rust-specific callouts (rustsec/audit-check, cargo-llvm-cov, Swatinem/rust-cache, taiki-e/install-action, matrix coverage guidance, doc-test step), load ci-pipeline.md.

Discipline

  • Simplicity first — every change as simple as possible, impact minimal code.
  • Only touch what's necessary — avoid unrelated changes in a PR.
  • No #[allow(clippy::...)] as a shortcut — fix the underlying issue. Document exceptions with a rationale.
  • Before adding a trait or generic, verify it's used in 3+ places. Otherwise a concrete type is clearer.
  • Verify: see Verify section — pass all checks with zero warnings before declaring done.

Verify

  • cargo fmt --all -- --check passes with zero diffs
  • cargo clippy --workspace --all-targets --all-features -- -D warnings passes
  • cargo nextest run --workspace (or cargo test --workspace) passes with zero failures
  • cargo deny check passes (licenses, advisories, duplicates) for any crate going to production
  • No new unsafe without // SAFETY: comment

References

  • cli-tools.md — clap patterns, config layering, tracing setup, progress, shell completions
  • axum-service.md — project layout, extractors, error types, graceful shutdown, testing
  • build-profiles.md — release/release-dbg/release-min profiles, mold linker, dev compile speedups
  • ci-pipeline.md — Rust-specific CI steps (cargo audit, llvm-cov, rust-cache, matrix strategy, doc tests)
  • production-resilience.md — fail-fast config, health/ready endpoints, graceful shutdown, retries, timeouts, connection pools
  • observability.md — tracing init recipe, span instrumentation, correlation IDs, metrics, distributed tracing
Usage Guidance
This skill is documentation-only and appears coherent for Rust service/CLI work; it doesn't ask for credentials or install anything. Two practical cautions before enabling or running suggestions from it: (1) the skill will operate against Rust files/Cargo.toml in your repo (declared paths), so if your repository contains secrets in source files, those could be read — review repository contents before giving the agent access; (2) some recommended developer actions (e.g., `cargo sqlx prepare` or CI steps) may require environment variables like DATABASE_URL or network access if you actually run them — do not provide secrets to the agent unless you trust the workflow. Also note the skill's source/homepage are unknown; that lowers provenance but does not make the content incoherent.
Capability Analysis
Type: OpenClaw Skill Name: compound-eng-rust-systems Version: 3.0.3 The skill bundle is a comprehensive and high-quality guide for modern Rust systems development, covering tooling, workspaces, async concurrency, and web services. It promotes security best practices by recommending tools like cargo-deny, cargo-audit, and miri, and contains no evidence of malicious intent, data exfiltration, or prompt injection.
Capability Tags
cryptorequires-sensitive-credentials
Capability Assessment
Purpose & Capability
Name/description match the content: the skill is a collection of Rust patterns and references for CLIs and services. It does not declare or require unrelated binaries, secrets, or config paths. The only minor provenance note: the source/homepage are unknown, but that does not contradict the declared purpose.
Instruction Scope
SKILL.md and the reference files are documentation and coding patterns. The declared paths ('**/*.rs,**/Cargo.toml') indicate the agent may read Rust source and Cargo.toml files in a repo, which is appropriate for a code-style/assist skill. The instructions do not direct the agent to read unrelated system files, secrets, or transmit data to external endpoints.
Install Mechanism
There is no install spec (instruction-only). Nothing is downloaded or written to disk by the skill itself, which is the lowest-risk install model.
Credentials
The skill declares no required environment variables or credentials. It references common environment concepts (e.g., DATABASE_URL for sqlx compile-time checks) in documentation context only; those references are proportional to the subject matter and are not requests for secrets.
Persistence & Privilege
always=false and user-invocable=true (defaults). The skill does not request persistent presence or modify other skills or system-wide settings.
How to Use
  1. Make sure OpenClaw is installed (local or Docker)
  2. Run the install command in chat: /install compound-eng-rust-systems
  3. After installation, invoke the skill by name or use /compound-eng-rust-systems
  4. Provide required inputs per the skill's parameter spec and get structured output
Version History
v3.0.4
v3.0.4
v3.0.3
v3.0.3
v3.0.2
v3.0.2
v3.0.1
v3.0.1
v3.0.0
v3.0.0
v2.56.1
v2.56.1
v2.56.0
v2.56.0
Metadata
Slug compound-eng-rust-systems
Version 3.0.3
License MIT-0
All-time Installs 0
Active Installs 0
Total Versions 6
Frequently Asked Questions

What is ia-rust-systems?

Rust patterns for CLI tools, backend services, and general application code. Use when working with Rust, Cargo workspaces, axum/tokio services, clap CLIs, as... It is an AI Agent Skill for Claude Code / OpenClaw, with 153 downloads so far.

How do I install ia-rust-systems?

Run "/install compound-eng-rust-systems" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.

Is ia-rust-systems free?

Yes, ia-rust-systems is completely free, licensed under MIT-0. You can download, install and use it at no cost.

Which platforms does ia-rust-systems support?

ia-rust-systems is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).

Who created ia-rust-systems?

It is built and maintained by Ilia Alshanetsky (@iliaal); the current version is v3.0.3.

💬 Comments