Claude Code (Claude Code) can be a practical pair programmer for Rust if you treat it like a junior engineer with strong compiler reading skills: give it explicit build and lint commands, keep changes small, and review every diff. This guide shows how to configure a Rust project, run a safe edit-test loop, and avoid the usual borrow checker traps. It covers CLAUDE.md, common prompts, verification, and parallel agent use.
Where Claude Code helps most in a Rust codebase
Rust’s compiler already encodes many correctness rules, and Claude Code can read those diagnostics directly. That makes it useful for ownership and lifetime fixes, trait implementations, and refactors that must satisfy the borrow checker. The agent also handles cargo workspace conventions well when the workspace layout is described in CLAUDE.md. In practice, the biggest wins come from using plan mode for anything larger than a mechanical change: ask for a plan before edits so the agent proposes a strategy instead of patching compiler errors one by one. This pairs well with clippy and rustfmt, because you can require the agent to keep the code lint-clean and formatted as part of its definition of done.
Configuring CLAUDE.md for a cargo workspace
The highest-leverage file is CLAUDE.md in the repository root. Keep it short, factual, and specific to this project. Avoid general advice; write the commands the agent should run and the rules it must follow. For a Rust workspace, include the workspace-wide build, test, lint, and format commands, the crate layout, error-handling conventions, and explicit bans on common shortcuts like unnecessary clone or unsafe. If you use cargo aliases or a Makefile, put those commands in CLAUDE.md rather than expecting the agent to infer them.
# CLAUDE.md
## Commands
- Build: `cargo build --workspace`
- Test: `cargo test --workspace`
- Lint: `cargo clippy --workspace --all-targets -- -D warnings`
- Format check: `cargo fmt --all -- --check`
- Run API: `cargo run -p api`
## Rules
- Always run `cargo test --workspace` after code changes.
- Run `cargo clippy --workspace --all-targets -- -D warnings` before marking work done.
- Do not add `clone()`, `Rc<RefCell<...>>`, or `unsafe` just to satisfy the borrow checker.
- Prefer returning `Result<T, anyhow::Error>` in binaries and `thiserror` enums in library crates.
- Keep async functions `Send`-safe when used with `tokio::spawn`.
## Layout
- `crates/core/`: shared domain types and pure logic, no I/O.
- `crates/api/`: HTTP handlers and routing.
- `crates/cli/`: command parsing and entry points.
With this file in place, start claude in the repo root and point it at the task. For broader workflow advice, the practical checklist includes useful pre- and post-edit steps.
A safe edit-test loop for Rust changes
Use a tight loop: plan, edit one small step, run the tests, review the diff. For anything beyond a mechanical rename or a single function change, ask the agent to describe its plan first and wait for your approval. This is where plan mode helps: it lets the agent reason about ownership and lifetimes before touching code. Then keep each prompt scoped to one function, one type, or one crate so a bad change is easy to isolate. After each step, ask for cargo test --workspace and cargo clippy --workspace --all-targets -- -D warnings, and read the diff yourself before accepting. Do not chain several fixes in one turn unless the first fix is proven.
Example prompts for typical Rust work:
- Add a
FromStrimplementation forTaskStatusthat rejects unknown input with a clearanyhow::Error. After implementing, runcargo test -p coreand show the output. - Refactor
handle_messageto remove the two.clone()calls without changing behavior. Then runcargo check --workspaceand explain the ownership changes. - Update
Cargo.tomldependencies to the latest semver-compatible versions in all workspace crates. Fix any breaking API changes and runcargo test --workspace. - Write unit tests for
parse_inputcovering empty input, invalid UTF-8, trailing commas, and a valid record. Use#[cfg(test)]and the existing test module. - Run
cargo clippy --workspace --all-targets -- -D warningsand fix every warning. Keep the fixes minimal and list each change you made.
Common Rust tasks and traps with the agent
Typical strong tasks include implementing From/TryFrom, deriving Serialize/Deserialize, adding error types, splitting a module into files, converting a synchronous function to async, writing tests from existing examples, and fixing straightforward clippy lints. The agent is also decent at explaining a borrow error when you paste the compiler output.
The risky areas are exactly where Rust’s rules are strict. The agent may add .clone() or wrap values in Rc<RefCell<_>> to make a borrow error disappear, which hides a design problem. It may propose 'static lifetimes or Box::leak when a shorter lifetime or a different ownership pattern would do. It occasionally adds unsafe without enough justification, especially around FFI or self-referential structs. It can also over-refactor: a simple change to satisfy clippy may turn into a trait extraction or a module rewrite. In workspaces, it may edit the wrong crate or add a dependency to the root when it belongs in a specific member. Always review the diff for these patterns and reject them explicitly.
Making cargo test and clippy part of acceptance
Make verification part of every prompt, not an afterthought. Ask the agent to run the commands and paste the output, and treat any red output as a failed step. For Rust, the minimum bar is cargo check --workspace for a fast compile, then cargo test --workspace, then clippy with warnings denied, then cargo fmt --all -- --check. Do not accept a change that passes tests but triggers new clippy warnings.
| Verification step | Rust command | Why it matters |
|---|---|---|
| Fast compile | cargo check --workspace | Catches type, trait, and borrow errors without full codegen |
| Unit and integration tests | cargo test --workspace | Confirms behavior and catches regressions |
| Lint gate | cargo clippy --workspace --all-targets -- -D warnings | Enforces idiomatic Rust and catches subtle bugs |
| Format check | cargo fmt --all -- --check | Prevents style-only diffs and keeps review focused |
For tricky lifetime or ownership fixes, ask the agent to first reproduce the exact compiler error, then propose a minimal patch. If the patch adds clone or changes a function signature, have it justify why. Running the commands locally before merging is still the final check.
Parallel agents on one Rust project with AgentVera
For larger Rust refactors, AgentVera runs several CLI agents in parallel, each in its own git worktree, so two agents cannot overwrite each other’s Cargo.toml or source files. Because each worktree builds independently, cargo check and cargo test do not collide on target/. When an agent finishes, a second model reviews the diff and links findings to file:line, which catches missed clippy warnings or suspicious unsafe. Checkpoints let you undo a bad borrow checker workaround instantly, and token caps prevent agents from spending too long chasing a single lifetime error.
Wrap-up: keep Rust checks non-negotiable
Claude Code becomes reliable on Rust when you stop treating it as an oracle and start treating it as an agent with a strict definition of done: compile, test, clippy, fmt. Put those commands in CLAUDE.md, keep each prompt to one verified step, and reject ownership shortcuts. That cadence, plus a quick diff review, turns the borrow checker from a source of agent thrash into a safety net.