{
  "id": "rust-crate",
  "type": "loadout",
  "title": "Rust crate rules",
  "summary": "Rust rules for agents: typed errors instead of unwrap, clippy -D warnings, fmt and tests as the done-gate, no unsafe without a SAFETY note, no surprise MSRV bumps.",
  "description": "Agents write plausible Rust that compiles after a few rounds, often by cloning everything, unwrapping on input and sprinkling allow attributes over clippy. This loadout sets the habits Rust reviewers expect: typed error enums with source(), anyhow only in binaries, cargo fmt, clippy with -D warnings and tests before reporting, unsafe only with approval and a SAFETY comment, and no edition, MSRV or major dependency bumps on the side. The skill's error example is compiled and tested by the verifier.\n",
  "highlights": [
    "Done-gate: cargo fmt --check, clippy -D warnings, cargo test",
    "Typed error enums; no unwrap or panic on input-driven paths",
    "unsafe only with approval and a SAFETY comment",
    "No MSRV, edition or major version bumps as a side effect",
    "Stop and explain after two rounds against the borrow checker"
  ],
  "version": "1.0.0",
  "license": "MIT",
  "author": {
    "name": "Agent Loadout",
    "url": "https://loadout.jnw-it.com"
  },
  "credits": [
    {
      "title": "The Rust Programming Language: recoverable errors with Result",
      "url": "https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html"
    },
    {
      "title": "Rust API Guidelines",
      "url": "https://rust-lang.github.io/api-guidelines/"
    },
    {
      "title": "Clippy documentation",
      "url": "https://doc.rust-lang.org/clippy/"
    }
  ],
  "categories": [
    "workflow"
  ],
  "stacks": [
    "rust",
    "cargo"
  ],
  "files": [
    {
      "path": "AGENTS.md",
      "role": "instructions",
      "description": "Rust rules for errors, safety, dependencies and style.",
      "skill": null,
      "agent": null,
      "install_to": {
        "claude-code": "AGENTS.md",
        "codex": "AGENTS.md",
        "cursor": "AGENTS.md",
        "gemini-cli": "AGENTS.md",
        "antigravity-cli": "AGENTS.md",
        "copilot": "AGENTS.md"
      },
      "raw_url": "https://loadout.jnw-it.com/raw/rust-crate/1.0.0/AGENTS.md",
      "raw_latest_url": "https://loadout.jnw-it.com/raw/rust-crate/latest/AGENTS.md",
      "bytes": 1960,
      "lang": "markdown",
      "content": "# AGENTS.md: Rust crate\n\nRust project built with Cargo. Read `Cargo.toml` for the edition and `rust-version` (MSRV) before using newer features.\n\n## Commands\n- Build: `cargo build`. Tests: `cargo test` (add `--all-features` if the crate has features).\n- Format: `cargo fmt --all -- --check`. Lint: `cargo clippy --all-targets --all-features -- -D warnings`.\n- Docs: `cargo doc --no-deps`. Dependency advisories, if installed: `cargo deny check` or `cargo audit`.\n- Done means: fmt clean, clippy with no warnings, tests green. Do not silence a lint with `#[allow]` without a comment why.\n\n## Errors\n- Library code returns `Result<T, E>` with a typed error enum; no `unwrap()`, `expect()` or `panic!` on input-driven paths.\n  `expect(\"reason\")` is fine for true invariants, with the reason saying why it cannot fail.\n- Binaries may use `anyhow` for context (`.context(\"reading config\")`). Libraries should not expose `anyhow::Error`.\n- Use `?` to propagate. Add context at boundaries, not at every call.\n\n## Safety and dependencies\n- `unsafe` only with the human's approval and a `// SAFETY:` comment explaining the invariant. Prefer `#![forbid(unsafe_code)]`.\n- Add dependencies with `cargo add <crate>`; check it is maintained and widely used. Keep default features off when you\n  only need a small part (`cargo add <crate> --no-default-features --features ...`).\n- Never bump the MSRV, edition or a major dependency version as a side effect of another change.\n\n## Style\n- Borrow instead of clone; clone only where ownership is genuinely needed, and not to quiet the borrow checker.\n  If you fight the borrow checker for more than two attempts, stop and explain the ownership problem.\n- Prefer iterators and `match` over index loops and nested `if let`. Keep functions short; name types after the domain.\n- Public items get doc comments with an example where it helps; doc tests run with `cargo test`.\n- Use the `rust-change` skill for any non-trivial change.\n"
    },
    {
      "path": "CLAUDE.md",
      "role": "adapter",
      "description": "Imports AGENTS.md for Claude Code.",
      "skill": null,
      "agent": "claude-code",
      "install_to": {
        "claude-code": "CLAUDE.md",
        "codex": null,
        "cursor": null,
        "gemini-cli": null,
        "antigravity-cli": null,
        "copilot": null
      },
      "raw_url": "https://loadout.jnw-it.com/raw/rust-crate/1.0.0/CLAUDE.md",
      "raw_latest_url": "https://loadout.jnw-it.com/raw/rust-crate/latest/CLAUDE.md",
      "bytes": 358,
      "lang": "markdown",
      "content": "# CLAUDE.md\n\n@AGENTS.md\n\n## Claude Code notes\n- Skills from this loadout live in `.claude/skills/`: `rust-change`. Use them when their description matches the task.\n- Follow AGENTS.md above; where this file and AGENTS.md disagree, AGENTS.md wins.\n\n<!-- From the Agent Loadout \"Rust crate rules\" v1.0.0 — https://loadout.jnw-it.com/loadouts/rust-crate/ -->\n"
    },
    {
      "path": "GEMINI.md",
      "role": "adapter",
      "description": "Imports AGENTS.md for Gemini CLI.",
      "skill": null,
      "agent": "gemini-cli",
      "install_to": {
        "claude-code": null,
        "codex": null,
        "cursor": null,
        "gemini-cli": "GEMINI.md",
        "antigravity-cli": null,
        "copilot": null
      },
      "raw_url": "https://loadout.jnw-it.com/raw/rust-crate/1.0.0/GEMINI.md",
      "raw_latest_url": "https://loadout.jnw-it.com/raw/rust-crate/latest/GEMINI.md",
      "bytes": 359,
      "lang": "markdown",
      "content": "# GEMINI.md\n\n@./AGENTS.md\n\n## Gemini CLI notes\n- Skills from this loadout live in `.agents/skills/`: `rust-change`. Use them when their description matches the task.\n- Follow AGENTS.md above; where this file and AGENTS.md disagree, AGENTS.md wins.\n\n<!-- From the Agent Loadout \"Rust crate rules\" v1.0.0 — https://loadout.jnw-it.com/loadouts/rust-crate/ -->\n"
    },
    {
      "path": "skills/rust-change/SKILL.md",
      "role": "skill",
      "description": "Reviewable Rust change with the three gates.",
      "skill": "rust-change",
      "agent": null,
      "install_to": {
        "claude-code": ".claude/skills/rust-change/SKILL.md",
        "codex": ".agents/skills/rust-change/SKILL.md",
        "cursor": ".agents/skills/rust-change/SKILL.md",
        "gemini-cli": ".agents/skills/rust-change/SKILL.md",
        "antigravity-cli": ".agents/skills/rust-change/SKILL.md",
        "copilot": ".agents/skills/rust-change/SKILL.md"
      },
      "raw_url": "https://loadout.jnw-it.com/raw/rust-crate/1.0.0/skills/rust-change/SKILL.md",
      "raw_latest_url": "https://loadout.jnw-it.com/raw/rust-crate/latest/skills/rust-change/SKILL.md",
      "bytes": 1000,
      "lang": "markdown",
      "content": "---\nname: rust-change\ndescription: Make a reviewable Rust change with typed errors, a failing test first for bugs, and fmt, clippy -D warnings and tests before reporting. Use for any non-trivial change to a Rust crate.\n---\n\n# Rust change\n\n1. Read the module and its tests. Run `cargo test` once first so you know the baseline.\n2. For a bug: write a failing test that reproduces it before touching the code.\n3. Model errors as an enum like `references/errors.rs`: one variant per failure the caller can act on, `Display` written\n   for humans, `source()` returning the underlying error. `thiserror` is fine if the crate already uses it.\n4. Make the change. Keep public API changes out unless asked; if unavoidable, list them in your report.\n5. Run, in order: `cargo fmt --all`, `cargo clippy --all-targets --all-features -- -D warnings`, `cargo test`.\n   Fix every clippy warning you introduced. Do not add `#[allow(...)]` to pass.\n6. Report: what changed, tests added, and the three command results.\n"
    },
    {
      "path": "skills/rust-change/references/errors.rs",
      "role": "reference",
      "description": "Typed error enum with Display, source() and tests.",
      "skill": "rust-change",
      "agent": null,
      "install_to": {
        "claude-code": ".claude/skills/rust-change/references/errors.rs",
        "codex": ".agents/skills/rust-change/references/errors.rs",
        "cursor": ".agents/skills/rust-change/references/errors.rs",
        "gemini-cli": ".agents/skills/rust-change/references/errors.rs",
        "antigravity-cli": ".agents/skills/rust-change/references/errors.rs",
        "copilot": ".agents/skills/rust-change/references/errors.rs"
      },
      "raw_url": "https://loadout.jnw-it.com/raw/rust-crate/1.0.0/skills/rust-change/references/errors.rs",
      "raw_latest_url": "https://loadout.jnw-it.com/raw/rust-crate/latest/skills/rust-change/references/errors.rs",
      "bytes": 2676,
      "lang": "markdown",
      "content": "//! Typed error pattern without extra dependencies. Callers can match on the variant; humans get a clear message.\n//! When copying, change `fixture_crate::errors` in the doc test to your crate and module path.\n\nuse std::fmt;\nuse std::num::ParseIntError;\n\n#[derive(Debug, PartialEq)]\npub enum ConfigError {\n    /// A required key is missing.\n    Missing(&'static str),\n    /// A value could not be parsed.\n    BadNumber { key: &'static str, source: ParseIntError },\n    /// A value is outside the allowed range.\n    OutOfRange { key: &'static str, value: u32, max: u32 },\n}\n\nimpl fmt::Display for ConfigError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self {\n            Self::Missing(key) => write!(f, \"missing required setting `{key}`\"),\n            Self::BadNumber { key, .. } => write!(f, \"setting `{key}` is not a whole number\"),\n            Self::OutOfRange { key, value, max } => write!(f, \"setting `{key}` is {value}, the maximum is {max}\"),\n        }\n    }\n}\n\nimpl std::error::Error for ConfigError {\n    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {\n        match self {\n            Self::BadNumber { source, .. } => Some(source),\n            _ => None,\n        }\n    }\n}\n\n/// Reads the worker count from `key=value` lines.\n///\n/// ```\n/// # use fixture_crate::errors::workers;\n/// assert_eq!(workers(\"workers=4\"), Ok(4));\n/// ```\npub fn workers(config: &str) -> Result<u32, ConfigError> {\n    const KEY: &str = \"workers\";\n    const MAX: u32 = 64;\n    let raw = config\n        .lines()\n        .filter_map(|line| line.split_once('='))\n        .find(|(k, _)| k.trim() == KEY)\n        .map(|(_, v)| v.trim())\n        .ok_or(ConfigError::Missing(KEY))?;\n    let value: u32 = raw.parse().map_err(|source| ConfigError::BadNumber { key: KEY, source })?;\n    if value > MAX {\n        return Err(ConfigError::OutOfRange { key: KEY, value, max: MAX });\n    }\n    Ok(value)\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use std::error::Error;\n\n    #[test]\n    fn reads_value() {\n        assert_eq!(workers(\"name=x\\nworkers = 8\\n\"), Ok(8));\n    }\n\n    #[test]\n    fn missing_key() {\n        assert_eq!(workers(\"name=x\"), Err(ConfigError::Missing(\"workers\")));\n    }\n\n    #[test]\n    fn bad_number_keeps_source() {\n        let err = workers(\"workers=lots\").unwrap_err();\n        assert!(matches!(err, ConfigError::BadNumber { .. }));\n        assert!(err.source().is_some());\n        assert_eq!(err.to_string(), \"setting `workers` is not a whole number\");\n    }\n\n    #[test]\n    fn out_of_range() {\n        assert_eq!(workers(\"workers=100\"), Err(ConfigError::OutOfRange { key: \"workers\", value: 100, max: 64 }));\n    }\n}\n"
    }
  ],
  "requires": {
    "tools": [
      "cargo"
    ],
    "env": [],
    "mcp": []
  },
  "tested": {
    "status": "untested",
    "last_run": null,
    "fixture": null,
    "per_agent": {
      "claude-code": "untested",
      "codex": "untested",
      "cursor": "untested",
      "gemini-cli": "untested",
      "antigravity-cli": "untested",
      "copilot": "untested"
    }
  },
  "security": {
    "scanned": true,
    "scanner": "intake-precheck/1",
    "verdict": "clean",
    "network": true,
    "scripts": [],
    "notes": "cargo add and cargo build download crates from crates.io. The example code makes no network calls."
  },
  "featured": false,
  "deprecated": false,
  "last_checked": "2026-10-17",
  "published": "2026-10-17",
  "updated": "2026-10-17",
  "compatibility": {
    "claude-code": "native",
    "codex": "native",
    "cursor": "native",
    "gemini-cli": "native",
    "antigravity-cli": "native",
    "copilot": "native"
  },
  "counts": {
    "rules": 1,
    "skills": 1,
    "mcp": 0
  },
  "url": "https://loadout.jnw-it.com/loadouts/rust-crate/",
  "api_url": "https://loadout.jnw-it.com/api/loadouts/rust-crate.json",
  "verification": {
    "level": "verified-install",
    "status": "verified",
    "label": "Verified install",
    "verified": true,
    "checked_at": "2026-10-17T08:09:30Z",
    "commit": "03c1b9839c40eb1e44c0a2877baaa3978a96895c",
    "content_current": true,
    "agent_tests": "not-run",
    "counts": {
      "pass": 9,
      "fail": 0,
      "skip": 0,
      "not_applicable": 1
    },
    "meaning": "Level 1: automated checks on the files (parse, install paths, MCP config, safety scan, references, size, licence, starter build). No AI agent was run.",
    "checks": [
      {
        "id": "listing",
        "name": "Listing",
        "status": "pass",
        "summary": "Schema valid; 5 files declared, none missing or extra",
        "details": [
          "tested.status: untested (agent tests are separate from Level 1)"
        ]
      },
      {
        "id": "parse",
        "name": "Files parse",
        "status": "pass",
        "summary": "All 5 files parse; front matter valid",
        "details": []
      },
      {
        "id": "adapters",
        "name": "Adapters",
        "status": "pass",
        "summary": "CLAUDE.md and GEMINI.md import AGENTS.md and are up to date",
        "details": [
          "CLAUDE.md: matches the generator",
          "GEMINI.md: matches the generator"
        ]
      },
      {
        "id": "install-paths",
        "name": "Install paths",
        "status": "pass",
        "summary": "Correct paths for all 6 agents; layouts re-discovered",
        "details": [
          "Claude Code: 4 files, 1 skill in .claude/skills/",
          "Codex CLI: 3 files, 1 skill in .agents/skills/",
          "Cursor: 3 files, 1 skill in .agents/skills/",
          "Gemini CLI: 4 files, 1 skill in .agents/skills/",
          "Antigravity CLI: 3 files, 1 skill in .agents/skills/",
          "GitHub Copilot: 3 files, 1 skill in .agents/skills/"
        ]
      },
      {
        "id": "mcp",
        "name": "MCP config",
        "status": "n/a",
        "summary": "No MCP servers in this loadout",
        "details": []
      },
      {
        "id": "safety",
        "name": "Safety scan",
        "status": "pass",
        "summary": "Clean: no credentials, risky shell or hidden text",
        "details": [
          "Scanner intake-precheck/1: verdict clean; network no (listing says yes)"
        ]
      },
      {
        "id": "references",
        "name": "References",
        "status": "pass",
        "summary": "1 reference between files resolves for every agent",
        "details": []
      },
      {
        "id": "size",
        "name": "Size limits",
        "status": "pass",
        "summary": "5 files, 6.2 KB total; largest skills/rust-change/references/errors.rs 2.6 KB",
        "details": [
          "Limits: 30 files, 32 KB per file, 128 KB total, 500 lines per skill or rule"
        ]
      },
      {
        "id": "licence",
        "name": "Licence",
        "status": "pass",
        "summary": "MIT, by Agent Loadout; text in the repository LICENSE",
        "details": []
      },
      {
        "id": "starter-build",
        "name": "Starter build",
        "status": "pass",
        "summary": "The rust-change skill's typed error example compiles in a crate with forbid(unsafe_code) and its unit and doc tests pass offline; rustfmt and clippy -D warnings run where installed",
        "details": [
          "Applied 7 loadout files at every agent's paths",
          "✓ place the example module: cp .agents/skills/rust-change/references/errors.rs src/errors.rs",
          "✓ cargo test (unit and doc tests): cargo test --offline --quiet",
          "✓ cargo fmt --check (if rustfmt is installed): bash -c if cargo fmt --version >/dev/null 2>&1; then cargo fmt --all -- --check && echo fmt ok; else echo 'fmt ok (rustfmt not installed, skipped)'; fi",
          "✓ cargo clippy -D warnings (if clippy is installed): bash -c if cargo clippy --version >/dev/null 2>&1; then cargo clippy --offline --all-targets -- -D warnings && echo clippy ok; else echo 'clippy ok (clippy not installed, skipped)'; fi",
          "Covers: Typed error enum with Display and source(); no unwrap on input paths",
          "Covers: Unit tests and a doc test run with cargo test",
          "Covers: forbid(unsafe_code) at the crate root",
          "Covers: fmt and clippy -D warnings as gates (on CI runners that ship them)"
        ]
      }
    ]
  },
  "install": {
    "claude-code": {
      "files": [
        {
          "path": "AGENTS.md",
          "target": "AGENTS.md",
          "raw_url": "https://loadout.jnw-it.com/raw/rust-crate/1.0.0/AGENTS.md",
          "role": "instructions"
        },
        {
          "path": "CLAUDE.md",
          "target": "CLAUDE.md",
          "raw_url": "https://loadout.jnw-it.com/raw/rust-crate/1.0.0/CLAUDE.md",
          "role": "adapter"
        },
        {
          "path": "skills/rust-change/SKILL.md",
          "target": ".claude/skills/rust-change/SKILL.md",
          "raw_url": "https://loadout.jnw-it.com/raw/rust-crate/1.0.0/skills/rust-change/SKILL.md",
          "role": "skill"
        },
        {
          "path": "skills/rust-change/references/errors.rs",
          "target": ".claude/skills/rust-change/references/errors.rs",
          "raw_url": "https://loadout.jnw-it.com/raw/rust-crate/1.0.0/skills/rust-change/references/errors.rs",
          "role": "reference"
        }
      ],
      "manual_steps": [],
      "zip_url": "https://loadout.jnw-it.com/download/rust-crate/claude-code.zip"
    },
    "codex": {
      "files": [
        {
          "path": "AGENTS.md",
          "target": "AGENTS.md",
          "raw_url": "https://loadout.jnw-it.com/raw/rust-crate/1.0.0/AGENTS.md",
          "role": "instructions"
        },
        {
          "path": "skills/rust-change/SKILL.md",
          "target": ".agents/skills/rust-change/SKILL.md",
          "raw_url": "https://loadout.jnw-it.com/raw/rust-crate/1.0.0/skills/rust-change/SKILL.md",
          "role": "skill"
        },
        {
          "path": "skills/rust-change/references/errors.rs",
          "target": ".agents/skills/rust-change/references/errors.rs",
          "raw_url": "https://loadout.jnw-it.com/raw/rust-crate/1.0.0/skills/rust-change/references/errors.rs",
          "role": "reference"
        }
      ],
      "manual_steps": [],
      "zip_url": "https://loadout.jnw-it.com/download/rust-crate/codex.zip"
    },
    "cursor": {
      "files": [
        {
          "path": "AGENTS.md",
          "target": "AGENTS.md",
          "raw_url": "https://loadout.jnw-it.com/raw/rust-crate/1.0.0/AGENTS.md",
          "role": "instructions"
        },
        {
          "path": "skills/rust-change/SKILL.md",
          "target": ".agents/skills/rust-change/SKILL.md",
          "raw_url": "https://loadout.jnw-it.com/raw/rust-crate/1.0.0/skills/rust-change/SKILL.md",
          "role": "skill"
        },
        {
          "path": "skills/rust-change/references/errors.rs",
          "target": ".agents/skills/rust-change/references/errors.rs",
          "raw_url": "https://loadout.jnw-it.com/raw/rust-crate/1.0.0/skills/rust-change/references/errors.rs",
          "role": "reference"
        }
      ],
      "manual_steps": [],
      "zip_url": "https://loadout.jnw-it.com/download/rust-crate/cursor.zip"
    },
    "gemini-cli": {
      "files": [
        {
          "path": "AGENTS.md",
          "target": "AGENTS.md",
          "raw_url": "https://loadout.jnw-it.com/raw/rust-crate/1.0.0/AGENTS.md",
          "role": "instructions"
        },
        {
          "path": "GEMINI.md",
          "target": "GEMINI.md",
          "raw_url": "https://loadout.jnw-it.com/raw/rust-crate/1.0.0/GEMINI.md",
          "role": "adapter"
        },
        {
          "path": "skills/rust-change/SKILL.md",
          "target": ".agents/skills/rust-change/SKILL.md",
          "raw_url": "https://loadout.jnw-it.com/raw/rust-crate/1.0.0/skills/rust-change/SKILL.md",
          "role": "skill"
        },
        {
          "path": "skills/rust-change/references/errors.rs",
          "target": ".agents/skills/rust-change/references/errors.rs",
          "raw_url": "https://loadout.jnw-it.com/raw/rust-crate/1.0.0/skills/rust-change/references/errors.rs",
          "role": "reference"
        }
      ],
      "manual_steps": [],
      "zip_url": "https://loadout.jnw-it.com/download/rust-crate/gemini-cli.zip"
    },
    "antigravity-cli": {
      "files": [
        {
          "path": "AGENTS.md",
          "target": "AGENTS.md",
          "raw_url": "https://loadout.jnw-it.com/raw/rust-crate/1.0.0/AGENTS.md",
          "role": "instructions"
        },
        {
          "path": "skills/rust-change/SKILL.md",
          "target": ".agents/skills/rust-change/SKILL.md",
          "raw_url": "https://loadout.jnw-it.com/raw/rust-crate/1.0.0/skills/rust-change/SKILL.md",
          "role": "skill"
        },
        {
          "path": "skills/rust-change/references/errors.rs",
          "target": ".agents/skills/rust-change/references/errors.rs",
          "raw_url": "https://loadout.jnw-it.com/raw/rust-crate/1.0.0/skills/rust-change/references/errors.rs",
          "role": "reference"
        }
      ],
      "manual_steps": [],
      "zip_url": "https://loadout.jnw-it.com/download/rust-crate/antigravity-cli.zip"
    },
    "copilot": {
      "files": [
        {
          "path": "AGENTS.md",
          "target": "AGENTS.md",
          "raw_url": "https://loadout.jnw-it.com/raw/rust-crate/1.0.0/AGENTS.md",
          "role": "instructions"
        },
        {
          "path": "skills/rust-change/SKILL.md",
          "target": ".agents/skills/rust-change/SKILL.md",
          "raw_url": "https://loadout.jnw-it.com/raw/rust-crate/1.0.0/skills/rust-change/SKILL.md",
          "role": "skill"
        },
        {
          "path": "skills/rust-change/references/errors.rs",
          "target": ".agents/skills/rust-change/references/errors.rs",
          "raw_url": "https://loadout.jnw-it.com/raw/rust-crate/1.0.0/skills/rust-change/references/errors.rs",
          "role": "reference"
        }
      ],
      "manual_steps": [],
      "zip_url": "https://loadout.jnw-it.com/download/rust-crate/copilot.zip"
    }
  },
  "source_zip_url": "https://loadout.jnw-it.com/download/rust-crate/source.zip"
}