
Rust Expert
- 6 installs
- 5 repo stars
- Updated August 5, 2026
- bjornmelin/dev-skills
Rust-expert is a Claude Code skill that serves as the default router for core Rust implementation, debugging, review, and toolchain work.
About
Rust-expert is a Claude Code skill that acts as the default router for core Rust engineering, including implementation, debugging, code review, refactors, compiler errors, ownership and lifetimes, traits and generics, async and concurrency, typed errors, and Cargo and toolchain work. It inspects the repo first, loads only the references a task needs, and uses compiler and test feedback as design evidence. A developer uses it for general Rust work and it routes framework-specific tasks to narrower Rust specialists.
- Default Rust engineering router for implementation, debugging, and review
- Covers ownership/lifetimes, traits/generics, async, typed errors, and Cargo/MSRV
- Routes framework-specific tasks to CLI, TUI, Tauri, and web-service specialists
Rust Expert by the numbers
- 6 all-time installs (skills.sh)
- Ranked #90 of 121 Rust skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
rust-expert capabilities & compatibility
Free; uses the Rust toolchain and cargo.
- Capabilities
- rust engineering · code review · refactoring · crate selection
- Use cases
- refactoring · debugging · code review · testing
- Pricing
- Free
What rust-expert says it does
Use this as the default Rust engineering router. Inspect the repo first, load only the references needed for the task, then use compiler/test feedback as design evidence.
Fix the root cause. Avoid silencing Rust with reflexive `.clone()`, `Arc<Mutex<_>>`, broad trait bounds, `unwrap`, or `unsafe`.
If no specialist owns the task, stay in `rust-expert`.
npx skills add https://github.com/bjornmelin/dev-skills --skill rust-expertAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 6 |
|---|---|
| repo stars | ★ 5 |
| Last updated | August 5, 2026 |
| Repository | bjornmelin/dev-skills ↗ |
What it does
Handle core Rust implementation, debugging, review, and toolchain work, routing framework tasks to specialists.
Who is it for?
Rust implementation, debugging, code review, refactors, ownership/async/error design, crate selection, and Cargo/toolchain work.
Skip if: Focused framework or product-surface work when a narrower Rust specialist skill applies.
When should I use this skill?
Rust implementation, compiler errors, ownership/lifetimes, traits/generics, async, typed errors, or Cargo/MSRV decisions.
What you get
Root-cause Rust fixes validated by compiler and test feedback, with correct crate and toolchain decisions.
- root-cause Rust fixes
- crate and toolchain decisions
- verification ladder commands
By the numbers
- 5-step operating model
- 6-line verification ladder
- 3 helper scripts
Files
Rust Expert
Use this as the default Rust engineering router. Inspect the repo first, load only the references needed for the task, then use compiler/test feedback as design evidence.
Operating Model
1. Read the local guidance and manifests first: AGENTS.md, Cargo.toml, Cargo.lock, rust-toolchain.toml, .cargo/config.toml, CI, justfile, mise.toml, and nearby tests. 2. Classify the task before editing: compile failure, implementation, review, refactor, dependency, public API, release, performance, or security. 3. Fix the root cause. Avoid silencing Rust with reflexive .clone(), Arc<Mutex<_>>, broad trait bounds, unwrap, or unsafe. 4. Use repo-native gates first. When command surface is unclear, run scripts/discover-rust-gates.mjs <repo-root>. 5. Research current docs/source when facts can drift: dependency additions or upgrades, version-sensitive APIs, Tauri/plugin support, public API/release decisions, security, unsafe/FFI, or novel crates.
Domain Routing
Use these implicit specialist skills when the task clearly belongs there:
| Signal | Prefer |
|---|---|
| Command-line app, subcommands, flags, config precedence, JSON/stdout contracts | rust-cli-clap |
| Terminal UI, interactive dashboards, Ratatui widgets/layout/events | rust-tui-ratatui |
Tauri v2, src-tauri, commands, capabilities, IPC, updater, mobile layout | rust-tauri-apps |
| HTTP APIs/services, Axum, Tower, Tokio server runtime, DB pools | rust-web-services |
| Broad architecture review or multi-domain Rust planning explicitly requested | rust-mega-eng |
If no specialist owns the task, stay in rust-expert.
Reference Map
Load the smallest needed set:
references/toolchain-cargo.md: editions, MSRV, resolver, lockfiles, features,
workspace policy, verification commands.
references/ownership-async-errors.md: borrow checker, ownership,
lifetimes, async Send, task ownership, typed errors.
references/crate-selection.md: preferred crates, dependency decision rules,
feature hygiene, source-refresh triggers.
references/testing-quality.md: unit/integration/doctest/property/snapshot/
benchmark checks and reviewable test design.
references/performance-security.md: measurement, allocations, unsafe/FFI,
supply chain, cargo-deny/audit, secrets and subprocesses.
Toolchain Policy
Existing repos: preserve detected contracts first. Do not change edition, resolver, rust-version, lockfile policy, or exact toolchain pins unless the task is explicitly a migration or the repo is missing required metadata.
Greenfield defaults:
edition = "2024".- Set
[workspace] resolver = "3"explicitly for virtual workspaces. - Add an explicit
rust-versionand document the policy. - Commit
Cargo.lockby default; for public libraries, also test latest
dependency resolution because consumers use Cargo.toml.
- Avoid exact
rust-toolchain.tomlversion pins unless reproducibility,
nightly, embedded/custom targets, or release policy requires them.
Verification Ladder
Start narrow, then broaden:
cargo check -p <crate>
cargo test -p <crate> <test_name>
cargo fmt --all -- --check
cargo clippy --workspace --all-targets --all-features --locked -- -D warnings
cargo test --workspace --all-targets --all-features --locked
cargo test --doc --workspace --lockedUse cargo nextest run when configured. Add cargo hack, cargo deny, cargo audit, cargo semver-checks, or release tooling only when the repo or change surface warrants it.
Helper Scripts
scripts/discover-rust-gates.mjs [repo-root]: print likely Rust gates.scripts/check-reference-links.mjs <skill-dir...>: validate local skill links.scripts/check-trigger-evals.mjs <skill-dir...>: validate trigger eval JSON.
display_name: Rust Expert
short_description: Core Rust engineering guidance.
default_prompt: Use $rust-expert to implement, debug, review, or refactor Rust code with repo-native verification.
policy:
allow_implicit_invocation: true
metadata:
skill_category: rust
primary_domains:
- core-rust
- cargo
- async
- quality
[
{
"query": "Fix this Rust borrow checker error in the parser without just cloning everything.",
"should_trigger": true,
"reason": "Core Rust compiler and ownership debugging."
},
{
"query": "Review this Rust PR for unsafe, async lifecycle, error handling, and missing tests.",
"should_trigger": true,
"reason": "Core Rust review across cross-cutting concerns."
},
{
"query": "Our Cargo workspace has feature conflicts and MSRV failures after a dependency bump.",
"should_trigger": true,
"reason": "Cargo, feature, and MSRV policy."
},
{
"query": "Write a new CLI with clap subcommands and JSON output.",
"should_trigger": false,
"reason": "Owned by rust-cli-clap."
},
{
"query": "Build a Ratatui dashboard with keyboard navigation.",
"should_trigger": false,
"reason": "Owned by rust-tui-ratatui."
},
{
"query": "Add Tauri v2 commands and capabilities for a desktop app.",
"should_trigger": false,
"reason": "Owned by rust-tauri-apps."
},
{
"query": "Design an Axum API with middleware and sqlx pool handling.",
"should_trigger": false,
"reason": "Owned by rust-web-services."
}
]
Crate Selection
Use existing repo choices first. Add or replace dependencies only when the benefit exceeds API, maintenance, compile-time, feature, license, and supply chain cost.
Research Order
1. Inspect manifests, lockfile, features, MSRV, and current dependency graph. 2. Check official docs and examples for current API shape. 3. Check source/changelog/release notes when behavior or version risk matters. 4. Inspect transitive features with cargo tree -e features. 5. Prefer one canonical crate per capability; remove parallel stacks when doing a deliberate hard cut.
Opinionated Defaults
| Need | Prefer |
|---|---|
| Serialization | serde, serde_json, format-specific serde crates |
| CLI | clap derive; builder for dynamic command construction |
| TUI | ratatui plus crossterm; color-eyre for app reports |
| Desktop/mobile shell | Tauri v2 when webview UI plus Rust backend fits |
| Async runtime | tokio with minimal features; full only when justified |
| HTTP service | axum on Tokio with tower middleware |
| HTTP client | reqwest, prefer rustls when OpenSSL friction matters |
| SQL | sqlx for async SQL and compile-time query checking when feasible |
| Errors | thiserror for library boundaries; anyhow/miette for apps |
| Observability | tracing; binaries install subscribers, libraries emit spans/events |
| Benchmarks | criterion |
| Property tests | proptest |
| Snapshots | insta with reviewable redactions |
| Supply chain | cargo-deny, cargo-audit |
| Public API release | cargo-semver-checks, release-plz |
| Binary distribution | cargo-dist when shipping downloadable artifacts |
Anti-Patterns
| Smell | Better |
|---|---|
| Hand-parsed CLI args | clap typed parser |
anyhow::Error in public library API | concrete thiserror type |
| Library installs global tracing subscriber | library emits tracing; binary installs subscriber |
| SQL built by string concatenation | bind parameters or checked sqlx::query! |
| Broad default features | minimal required feature set |
| Git dependency with no policy | crates.io release or explicit approval |
| Duplicate HTTP/JSON/error stacks | choose one canonical stack |
| Tiny utility crate for stdlib behavior | standard library |
Freshness Triggers
Research live docs/source before relying on:
- new dependencies or major upgrades;
- Tauri plugin/platform support;
- Clap/Ratatui/Tauri current APIs;
- security-sensitive crates;
- MSRV-sensitive dependencies;
- release automation or public API compatibility;
- crates with low maintenance signals or unclear licenses.
Ownership, Async, And Errors
Use this reference when the task involves borrow checker errors, lifetimes, mutability, async Send failures, task lifecycle, error boundaries, or recovery behavior.
Borrow Checker Repair Order
1. Reproduce the exact compiler diagnostic. 2. Read the owning type, caller, and intended invariant. 3. Narrow borrow scopes before changing types. 4. Move behavior onto the owner when mutation authority belongs there. 5. Split data structures when independent fields are being borrowed together. 6. Borrow or move deliberately; clone only when shared ownership or retained values are semantically required.
Avoid:
.clone()just to silence E0382.Arc<Mutex<_>>as a generic Send/Sync fix.RefCellwhere ordinary ownership works.- Public fields that let callers violate invariants.
unsafeto bypass ownership errors.
Async Design
Ask what kind of work this is:
| Work | Prefer |
|---|---|
| I/O-bound concurrency | Tokio when repo already uses it or networking requires it |
| CPU-bound parallelism | rayon, dedicated threads, or spawn_blocking |
| One owner, many messages | channels or actor/task owner |
| Shared immutable config | Arc<T> |
| Shared mutable state | redesign first, then narrow locks if needed |
Rules:
- Do not block the executor with blocking I/O, sleeps, or CPU-heavy loops.
- Do not hold lock guards, borrowed refs, or non-Send values across
.await
unless the architecture explicitly supports it.
- Prefer bounded channels for backpressure.
- Use
JoinSetor owned task groups for related spawned work. - Use
tokio::select!for cancellation, shutdown, timeouts, and races. - Treat dropped channels as expected shutdown signals when appropriate.
Error Boundaries
| Context | Default |
|---|---|
| Public library/module API | typed thiserror enum/struct |
| Application internals | anyhow or miette/color-eyre context |
| CLI/user boundary | stable exit code, kind, operation, message, cause chain |
| Service boundary | typed status/error envelope, no internal leakage |
| Bug/invariant | panic!, assert!, or precise expect message |
Do not use anyhow to erase errors that drive retry behavior, CLI exit codes, JSON contracts, public APIs, or operator remediation.
Recovery Rules
- Invalid input: no retry; return an actionable error.
- Timeout, 503, rate limit: bounded retry with backoff and jitter.
- Invalid config: fail fast.
- Data corruption: stop and surface high-severity error.
- Dependency unavailable: timeout/circuit/fallback only if product semantics
allow degraded behavior.
Performance, Unsafe, And Security
Use this reference when performance, unsafe, FFI, supply chain, secrets, subprocesses, paths, parsing, or untrusted input are in scope.
Performance Order
1. Measure in release mode. 2. Check algorithm and data structure first. 3. Inspect allocation and clone patterns. 4. Check I/O batching and lock contention. 5. Add parallelism/SIMD/unsafe only after identifying a real hotspot.
Useful tools:
cargo bench
cargo flamegraph --bin <binary>
heaptrack ./target/release/<binary>
cargo bloat --release --bin <binary>
cargo tree -e featuresAvoid optimizing debug builds, hiding algorithmic problems with parallelism, or adding unsafe for micro-optimizations without proof.
Unsafe Rules
Every unsafe block or item needs:
- a
SAFETY:comment explaining caller obligations and why they hold; - the smallest possible unsafe scope;
- a safe abstraction around the boundary when possible;
- checks for aliasing, lifetimes, initialization, alignment, thread-safety, and
panic behavior;
- Miri, sanitizer, fuzzing, or targeted tests when risk warrants it.
FFI Rules
- Confirm ABI and
repr(C)layout. - Document ownership transfer and allocation/freeing side.
- Validate nullability before dereference.
- Do not unwind across FFI.
- Convert raw pointers at the boundary.
- Make cleanup explicit when it can fail.
Supply Chain
Prefer maintained crates with clear license, docs, source, CI, and recent activity. Run configured policy tools:
cargo deny check
cargo audit
cargo tree -d
cargo macheteUse cargo-udeps only when nightly is acceptable. Treat build scripts and proc macros as higher-risk code in sensitive environments.
Application Security
Pay extra attention to:
- auth and authorization checks;
- crypto;
- parsers and deserialization of untrusted data;
- filesystem paths and archive extraction;
- subprocess arguments and shell execution;
- network timeouts and TLS;
- secrets in logs/errors;
- temporary files and permissions.
Testing And Quality
Use this reference when adding tests, changing contracts, reviewing quality, or closing out Rust work.
Test Choice
| Risk | Test |
|---|---|
| Pure behavior | unit test near the module |
| Public crate behavior | integration test under tests/ |
| Public examples | doctest |
| CLI contract | stdout, stderr, exit status, and JSON schema assertions |
| Error contract | stable variant/category plus user-facing message boundary |
| Serialization | round-trip, golden, or small snapshot |
| Async/concurrency | deterministic synchronization; avoid sleeps |
| Input space invariant | property test |
| UI/TUI rendering | buffer or backend snapshot |
| Performance | benchmark or profiler evidence |
| Public API compatibility | cargo-semver-checks |
Test Quality Rules
- Name tests by behavior.
- Keep fixtures small and deterministic.
- Test failure paths when introducing a new failure class.
- Do not weaken tests to fit the implementation.
- Assert stable contracts, not full debug strings.
- Avoid sleeping in async tests; use barriers, fake clocks, or explicit
notifications.
- For snapshots, review and redact unstable fields.
- For mocks, test the boundary contract instead of duplicating internals.
Review Checklist
For Rust reviews, findings lead:
- correctness and data loss;
- public API and serialization contracts;
- async lifecycle, cancellation, and backpressure;
- error classification and user/operator messages;
- dependency and feature changes;
- unsafe/FFI invariants;
- test coverage for changed risk.
Report file/line evidence, impact, and a concrete fix direction.
Closeout Commands
Prefer repo-native commands. Common Rust closeout:
cargo fmt --all -- --check
cargo clippy --workspace --all-targets --all-features --locked -- -D warnings
cargo test --workspace --all-targets --all-features --locked
cargo test --doc --workspace --locked
git diff --checkUse narrower commands while iterating; broaden before claiming completion.
Toolchain And Cargo
Use this reference for toolchain policy, workspace structure, feature hygiene, dependency resolution, and verification commands.
Existing Repo Policy
Preserve these contracts unless the user explicitly asks for a migration:
editionrust-version- workspace
resolver rust-toolchain.toml.cargo/config.toml- lockfile policy
- CI matrix and README MSRV policy
Changing any of these can affect dependency resolution and user compatibility. Treat edition/resolver/MSRV changes as migrations with lockfile review and full repo checks.
Greenfield Defaults
Use these defaults for new Rust projects unless the target domain says otherwise:
[package]
edition = "2024"
rust-version = "1.85"For virtual workspaces:
[workspace]
resolver = "3"
members = ["crates/*"]Use rust-version = "1.85" as the Rust 2024 compatibility floor for reusable libraries/tools, then raise it only for chosen APIs/dependencies. For internal apps, current stable is acceptable if documented and CI tracks it.
Lockfiles
Commit Cargo.lock by default for apps, CLIs, services, workspaces, and agent tooling. For published libraries, committing the lockfile is acceptable, but CI should also test latest dependency resolution because downstream users are not bound by the library lockfile.
Avoid upper-bounding dependencies to preserve old Rust compatibility unless a real incompatibility requires it. Prefer rust-version plus resolver 3 and latest-dependency CI.
Features
- Use workspace dependency ownership when possible.
- Keep features additive.
- Disable default features only when you know what stack you are removing.
- Avoid
fullfeature sets unless the task genuinely needs the entire surface. - Test important feature combinations with
cargo hackwhen public crates or
optional stacks are involved.
Useful commands:
cargo metadata --format-version=1
cargo tree -e features
cargo tree -d
cargo hack check --feature-powerset --no-dev-depsVerification Tiers
Focused iteration:
cargo check -p <crate>
cargo test -p <crate> <test_name>Normal closeout:
cargo fmt --all -- --check
cargo clippy --workspace --all-targets --all-features --locked -- -D warnings
cargo test --workspace --all-targets --all-features --lockedPublic API/release:
cargo test --doc --workspace --locked
cargo semver-checks
release-plz update --dry-runSupply-chain/security:
cargo deny check
cargo auditUse repo-native wrappers (just, mise, make, xtask, RTK) when they exist.
#!/usr/bin/env node
import fs from "node:fs";
import path from "node:path";
const roots = process.argv.slice(2);
if (roots.length === 0) {
console.error("Usage: check-reference-links.mjs <skill-dir...>");
process.exit(2);
}
let ok = true;
for (const rootArg of roots) {
const skillDir = path.resolve(rootArg);
if (!isDirectory(skillDir)) {
ok = false;
console.error(`invalid skill directory: ${rootArg}`);
continue;
}
for (const file of listMarkdown(skillDir)) {
const text = fs.readFileSync(file, "utf8");
const relFile = path.relative(skillDir, file);
const patterns = [
/`((?:references|scripts|assets|templates)\/[^`]+)`/g,
/\[[^\]]+\]\(((?:references|scripts|assets|templates)\/[^)]+)\)/g,
];
for (const pattern of patterns) {
for (const match of text.matchAll(pattern)) {
const target = match[1].split("#")[0].split(/\s+/)[0];
const full = path.resolve(skillDir, target);
const insideSkill = full === skillDir || full.startsWith(`${skillDir}${path.sep}`);
if (!insideSkill || !fs.existsSync(full)) {
ok = false;
console.error(`${path.basename(skillDir)}/${relFile}: missing linked file ${target}`);
}
}
}
}
}
if (!ok) process.exit(1);
console.log("skill reference links OK");
function listMarkdown(dir) {
const out = [];
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
const full = path.join(dir, entry.name);
if (entry.isDirectory()) out.push(...listMarkdown(full));
else if (entry.name.endsWith(".md")) out.push(full);
}
return out;
}
function isDirectory(dir) {
try {
return fs.statSync(dir).isDirectory();
} catch {
return false;
}
}
#!/usr/bin/env node
import fs from "node:fs";
import path from "node:path";
const roots = process.argv.slice(2);
if (roots.length === 0) {
console.error("Usage: check-trigger-evals.mjs <skill-dir...>");
process.exit(2);
}
let ok = true;
for (const rootArg of roots) {
const skillDir = path.resolve(rootArg);
const skillName = path.basename(skillDir);
const evalPath = path.join(skillDir, "assets", "trigger-evals.json");
if (!fs.existsSync(evalPath)) {
ok = false;
console.error(`${skillName}: missing assets/trigger-evals.json`);
continue;
}
const skillPath = path.join(skillDir, "SKILL.md");
const openaiPath = path.join(skillDir, "agents", "openai.yaml");
const skillText = fs.existsSync(skillPath) ? fs.readFileSync(skillPath, "utf8") : "";
const openaiText = fs.existsSync(openaiPath) ? fs.readFileSync(openaiPath, "utf8") : "";
const explicitOnly =
/\binvocation:\s*explicit-only\b/.test(skillText) ||
/\ballow_implicit_invocation:\s*false\b/.test(openaiText);
let data;
try {
data = JSON.parse(fs.readFileSync(evalPath, "utf8"));
} catch (error) {
ok = false;
console.error(`${skillName}: invalid JSON: ${error.message}`);
continue;
}
if (!Array.isArray(data) || data.length < 6) {
ok = false;
console.error(`${skillName}: expected at least 6 eval cases`);
continue;
}
const positives = data.filter((item) => item?.should_trigger === true).length;
const negatives = data.filter((item) => item?.should_trigger === false).length;
if (positives < 3 || negatives < 3) {
ok = false;
console.error(`${skillName}: expected at least 3 positive and 3 negative evals`);
}
for (const [index, item] of data.entries()) {
const isObject = typeof item === "object" && item !== null;
if (!isObject) {
ok = false;
console.error(`${skillName}[${index}]: eval item must be an object`);
continue;
}
const query = typeof item.query === "string" ? item.query : "";
const shouldTrigger = item.should_trigger;
const reason = typeof item.reason === "string" ? item.reason : "";
if (query.length < 10) {
ok = false;
console.error(`${skillName}[${index}]: missing realistic query`);
}
if (typeof shouldTrigger !== "boolean") {
ok = false;
console.error(`${skillName}[${index}]: should_trigger must be boolean`);
}
if (reason.length < 8) {
ok = false;
console.error(`${skillName}[${index}]: missing reason`);
}
if (
explicitOnly &&
shouldTrigger === true &&
!query.includes(skillName) &&
!query.includes(`$${skillName}`)
) {
ok = false;
console.error(`${skillName}[${index}]: explicit-only positive eval must name ${skillName}`);
}
}
}
if (!ok) process.exit(1);
console.log("trigger eval fixtures OK");
#!/usr/bin/env node
import fs from "node:fs";
import path from "node:path";
const root = path.resolve(process.argv[2] ?? ".");
const commands = new Set();
const RUN_COMMAND = /(cargo .+|just .+|mise run .+|make .+)/;
if (exists("Cargo.toml")) {
commands.add("cargo fmt --all -- --check");
commands.add("cargo clippy --workspace --all-targets --all-features --locked -- -D warnings");
commands.add("cargo test --workspace --all-targets --all-features --locked");
}
if (exists("nextest.toml") || exists(".config/nextest.toml")) {
commands.add("cargo nextest run --workspace --all-features --locked");
}
if (exists("deny.toml")) commands.add("cargo deny check");
if (exists("rust-toolchain.toml")) commands.add("rustup show active-toolchain");
if (exists("Justfile") || exists("justfile")) addRecipes("just");
if (exists("mise.toml")) commands.add("mise tasks # inspect Rust-related tasks");
if (exists("Makefile")) commands.add("make help # inspect Rust-related targets");
for (const workflow of listFiles(path.join(root, ".github", "workflows"))) {
const text = fs.readFileSync(workflow, "utf8");
const lines = text.split(/\r?\n/);
for (let i = 0; i < lines.length; i += 1) {
const line = lines[i];
const inline = /^\s*(?:-\s*)?run:\s*(cargo .+|just .+|mise run .+|make .+)/.exec(line);
if (inline) {
commands.add(inline[1].trim());
continue;
}
const block = /^(\s*)(?:-\s*)?run:\s*([|>])\s*$/.exec(line);
if (!block) continue;
const baseIndent = block[1].length;
const blockLines = [];
for (let j = i + 1; j < lines.length; j += 1) {
const next = lines[j];
if (next.trim() === "") {
blockLines.push("");
continue;
}
const nextIndent = next.match(/^\s*/)[0].length;
if (nextIndent <= baseIndent) break;
blockLines.push(next.trim());
i = j;
}
const separator = block[2] === "|" ? " && " : " ";
const match = RUN_COMMAND.exec(blockLines.filter(Boolean).join(separator));
if (match) commands.add(match[1].trim());
}
}
console.log([...commands].join("\n") || "No Rust gates discovered. Inspect repo scripts and CI manually.");
function exists(rel) {
return fs.existsSync(path.join(root, rel));
}
function addRecipes(runner) {
const file = exists("Justfile") ? "Justfile" : "justfile";
const text = fs.readFileSync(path.join(root, file), "utf8");
for (const line of text.split(/\r?\n/)) {
const match = /^([a-zA-Z0-9_-]+):/.exec(line);
if (match && /test|check|lint|fmt|verify|clippy|bench|audit|deny/.test(match[1])) {
commands.add(`${runner} ${match[1]}`);
}
}
}
function listFiles(dir) {
if (!fs.existsSync(dir)) return [];
const out = [];
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
const full = path.join(dir, entry.name);
if (entry.isDirectory()) out.push(...listFiles(full));
else out.push(full);
}
return out;
}
Related skills
FAQ
When does rust-expert defer to a specialist?
It routes CLI, TUI, Tauri, web-service, and broad multi-domain architecture tasks to rust-cli-clap, rust-tui-ratatui, rust-tauri-apps, rust-web-services, and rust-mega-eng.
What is its approach to compiler errors?
Fix the root cause and avoid reflexive .clone(), Arc<Mutex<_>>, broad bounds, unwrap, or unsafe.