agentsclimarketplace

Rust project standard

Skill VoldemortGin/AI-Coding-Skill-Bible/rust-project-standard

Enforce a strict, model-agnostic, AI-navigable Rust project standard: a Cargo workspace with crate-per-domain deep structure, #![forbid(unsafe_code)] + strict clippy workspace lints + a one-command zero-warning gate (fmt + clippy -D warnings + doc + test + cargo-deny), serde + newtypes at boundaries, trait-based provider seams with a zero-SDK domain crate and a default MockProvider, tracing, figment, include_str! + minijinja prompts, and a CLAUDE.md in every crate. Use whenever starting or scaffolding a Rust project, crate, or workspace; setting up Cargo.toml / clippy / rustfmt / CI; deciding crate or module structure; adding an LLM / embedding / vector-store dependency; wiring providers or adapters; setting up cargo-deny or supply-chain/license checks; or checking an existing Rust project conforms. Apply even when the user only says "start a Rust project", "structure this crate", "add an LLM", or "wire up CI" without naming the standard.From its SKILL.md

Install
npx -y skills add VoldemortGin/AI-Coding-Skill-Bible --skill rust-project-standard

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

3 things to look at

  • skips confirmationTells the agent to proceed without asking first, 1 time: "Apply it by default; don't wait to be asked.".
  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
  • runs commandsInstructs the agent to run 5 commands, including `python scripts/scaffold.py <project_name> --target <dir> --domains ingestion retrieval generation agents` and 4 more.

SKILL.md

10.9 KB, ~2.5k tokens by cl100k_base, as published. Nobody here has run it

Rust Project Standard

This skill is the guiding standard for any Rust work. Apply it by default; don't wait to be asked.

Its spine: trust is placed not in the model, but in the machine-checkable code that constrains it. In Rust most of that scaffold is the compiler — types, ownership, exhaustiveness are enforced at compile time with no type erasure, so there's no runtime type-checker to bolt on (unlike the Python sibling's beartype). The job here is to (a) keep the few escape hatches shut, (b) push every external dependency behind a trait so the model is hot-swappable, (c) organize deep and name-navigable, and (d) mechanize the implicit knowledge a human would otherwise hold — via a zero-warning gate, per-crate contracts, and supply-chain checks. The agent's output ceiling equals the tightness of that loop.

Baseline: edition 2024, pinned toolchain (rust-toolchain.toml), #![forbid(unsafe_code)], strict clippy via workspace lints, serde, thiserror/anyhow, tracing, figment, minijinja, cargo-deny.

When starting a new project

python scripts/scaffold.py <project_name> --target <dir> --domains ingestion retrieval generation agents

This mirrors assets/templates/ into a Cargo workspace (root config + kernel/domain/adapters crates + app binary + a CLAUDE.md per crate + ci.sh + CI + ADR), substitutes __PROJECT__, and creates a crate skeleton per domain (members = ["crates/*", "app"] auto-includes them). When adapting an existing repo, copy from assets/templates/ by hand — only the workspace root, app/Cargo.toml, and CLAUDE.md headers carry the literal name; crate names (kernel/domain/adapters) are project-independent so use paths never depend on the project name.

Then: cargo check, and ./ci.sh (or just check) to verify. ./ci.sh needs cargo install cargo-deny once (CI uses the action).

When working on existing code

Apply the rules below, and verify structural invariants:

python scripts/check_conformance.py <project_root>

It checks the mechanically enforceable invariants (workspace layout, unsafe_code = "forbid", clippy lints configured, domain crate has zero vendor-SDK deps — parsed from its Cargo.toml, cleaner than grep, toolchain/deny/ci files present, a CLAUDE.md in every crate). Everything else is enforced by the gate and by applying the standard.

The non-negotiables

Full rationale in references/standard.md.

  1. The compiler is the static guarantee; keep the escape hatches shut. #![forbid(unsafe_code)] at the workspace level (a hard ban — #[allow] can't override forbid). Strict clippy via [workspace.lints]; the gate runs clippy -- -D warnings, so every warning is fatal. No bolted-on runtime type check — Rust doesn't need one. A crate that genuinely needs unsafe (FFI, SIMD) takes the controlled exit in references/standard.md §2 — isolate it in a dedicated crate that opts out of the workspace lint and drops to deny + per-site // SAFETY:, rather than loosening the workspace.

  2. No silent failures: Result<T, E> + thiserror, not unwrap/expect sprinkled around. unwrap_used/expect_used/panic are clippy-warn (→ error at the gate); escaping needs #[allow(...)] with a reason (the Rust analog of a justified # type: ignore). unwrap/expect are allowed in tests (clippy.toml). Vendor errors normalize at the adapter boundary into domain::ProviderError; program bugs propagate — never swallow.

  3. Boundaries: parse, don't validate — serde + newtypes. Everything crossing a boundary (config, LLM output, tool results, files) deserializes into a strongly-typed struct via serde; encode constraints in newtypes so invalid states are unrepresentable rather than runtime-checked.

  4. Model-agnostic: every external AI dependency behind a trait in domain; SDKs only in adapters. The domain crate has zero vendor-SDK dependencies (the checker parses its Cargo.toml to enforce this); traits stay object-safe (Box<dyn _>). SDKs are optional + feature-gated in adapters and normalized to ProviderError. The composition root (app) is the one place that selects an impl by config and injects it. A deterministic MockProvider is the default (not a test stub) so the binary, tests, and CI run offline with no SDK or key.

  5. Completion = one zero-warning gate, the agent's only correctness judge. ./ci.sh runs cargo fmt --checkclippy -D warningscargo doc (with RUSTDOCFLAGS=-D warnings) → cargo testcargo deny check, under set -euo pipefail. Run it after every change; fix until green; never "looks fine, commit". Pin it with a pre-push hook; CI mirrors it.

  6. cargo-deny is part of the gate. License allow-list (rejects AGPL/GPL/SSPL leaking into the tree), RUSTSEC advisories, and dependency hygiene are checked on every run — this doubles as supply-chain/SCA compliance.

Structure: deep Cargo workspace, crate-per-domain

The depth comes from the workspace, not from one crate with deep modules. "Fix the reranker" should resolve to crates/retrieval/src/reranking/ with no search.

  • Workspace with a crate per bounded context (crates/<domain>/), plus the fixed infra crates and a thin binary:
    • kernel — cross-cutting infra: config (figment, env APP_* + __ nesting), logging (tracing; init once in the binary; library code only emits events; log_provenance + payload-free traces), prompts (include_str! compile-time embed + minijinja strict undefined). Named kernel, not core (which collides with std::core).
    • domain — ports (traits) + models + boundary errors; zero SDK deps.
    • adapters — trait impls; the only crate that may depend on vendor SDKs (feature-gated); MockX defaults.
    • domain crates (ingestion/retrieval/…) depend on domain + kernel, never on adapters or SDKs.
    • app — the binary and composition root; wires concrete adapters by config.
  • A CLAUDE.md in every crate (the layered-context rule applied per directory): the root one is a routing table (hard constraints + where to look); each crate's states its responsibility, dependencies, and local contract. The checker requires one per crate.
  • Go deep: split crates into submodules by sub-capability; names map to paths.

Navigability

Naming-as-path is to navigation what types are to interface contracts — and Cargo workspaces make it crate-level. Group by capability, not by types//utils/. Nest until leaf modules have a single clear responsibility. See references/standard.md.

Principles for AI-touching code (advisory)

Beyond the type system — for any code where a model produces output. Upper-level discipline; not all mechanically checkable.

  • Constrain, don't ask. Push non-negotiable properties (no fabrication, must-cite, no privilege escalation) into deterministic control flow so the model physically cannot violate them — don't rely on the prompt. Synthesize answers from typed values in code; discard model prose on the critical path.
  • Narrow the emission surface. Make the model pick from a typed enum of options or call tools returning a tri-state result; take final values from tool results, not free-form model text. A Rust enum is the natural controlled surface.
  • Guardrails are deterministic, independent, never pluggable. Intent parsing can be swapped; safety decisions are deterministic code re-evaluated from raw input.

Driving AI on big work (advisory)

Treat AI as supervisable labor, not unsupervised autopilot.

  • Decision-first: a numbered, immutable ADR (docs/adr/) before coding — context + chosen option + rejected alternatives and why. Rejected-reasons stop it re-walking excluded paths.
  • TDD red-light first; tests are the immutable spec. Write the failing #[test] (or doc test), then implement to green; never weaken a test to pass.
  • Numbered steps, each independently green; one commit per step through the full gate. No giant diffs.
  • Adversarial independent review. After writing, run a separate, hostile, multi-perspective review prioritizing what tests can't cover (diagrams, docs, tradeoffs).

Scale to project size

The workspace split, per-crate CLAUDE.md, ADRs, and cargo-deny are real overhead — overkill for a 200-line CLI. Present them as triggered, scalable patterns ("the moment you call an LLM/embedding/vector store, put it behind a trait in its own crate"; "split a crate out the moment it takes a second responsibility"), not blanket mandates. A single-crate project with modules + clippy + the gate is a perfectly good small-scale instantiation.

Scale along two axes, not one — size and domain. The standard has a universal spine that holds for any Rust project whether or not it touches AI: #![forbid(unsafe_code)], the zero-warning gate, Result/thiserror (no silent failure), serde + newtypes at boundaries, workspace + deep naming-as-path, cargo-deny, tracing, figment. The rest is an AI-triggered layer that only switches on once the project actually calls an LLM / embedding / vector store: the domain trait seam, MockProvider-as-default, minijinja / include_str! prompts, log_provenance, and the constrain-don't-ask / narrow-the-emission-surface discipline. A pure systems / library / CLI crate that never calls a model should take the spine in full and skip the AI layer outright — bolting MockProvider or prompt-embedding onto such a project is cargo-culting, not conformance.

Resources

  • references/standard.md — the full standard with rationale and complete code for every crate.
  • assets/templates/ — exact workspace boilerplate; __PROJECT__ is the only placeholder. Includes kernel/domain/adapters/app, workspace lints, clippy.toml, deny.toml, ci.sh, GH Actions, a per-crate CLAUDE.md, and docs/adr/.
  • scripts/scaffold.py — generate a conforming workspace.
  • scripts/check_conformance.py — verify structural invariants (incl. domain-zero-SDK and per-crate CLAUDE.md).

What ships with it: 36 files

41.3 KB alongside SKILL.md, 3 of them executable

references/

scripts/

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.