Sunday, April 5

Rust Pro: The Claude Code Agent That Writes Idiomatic Rust So You Don’t Have To Fight the Borrow Checker Alone

Rust’s learning curve is notoriously steep — not because the language is poorly designed, but because it forces you to reason explicitly about things most languages hide from you: ownership, lifetimes, borrowing rules, and the precise semantics of concurrent memory access. Even experienced Rust developers spend significant time wrestling with the compiler, second-guessing lifetime annotations, or debating whether a particular design should use Arc<Mutex<T>> or channels.

The Rust Pro agent for Claude Code addresses this directly. It’s not a generic code assistant that happens to know some Rust syntax. It’s a specialized agent with deep knowledge of idiomatic Rust patterns — one that will push back on anti-patterns, suggest zero-cost alternatives, write proper trait implementations, and generate async code that handles cancellation correctly. If you’re building systems software, CLI tools, WebAssembly modules, or high-performance services in Rust, this agent saves you hours of compiler feedback cycles and documentation spelunking every single week.

When to Use Rust Pro

This agent is marked “use PROACTIVELY,” which is intentional. You shouldn’t wait until you’re stuck — you should reach for it whenever Rust is in scope. That said, here are the specific scenarios where it delivers the most value:

Ownership and Lifetime Design

Designing data structures with non-trivial lifetimes — think parsers, ASTs, or anything with self-referential data — is where many Rust developers lose hours. Rust Pro understands the distinction between 'static bounds, lifetime elision rules, and when you actually need explicit annotations versus when the compiler can infer them. It’ll tell you when you’re fighting the borrow checker unnecessarily and suggest a restructure instead.

Async/Await and Concurrent Systems

Writing correct async Rust — especially across thread boundaries with Send + Sync bounds, proper task cancellation, and backpressure — requires intimate familiarity with Tokio’s runtime model and async-std’s semantics. Rust Pro handles this natively, generating async code that doesn’t just compile but behaves correctly under load and cancellation.

Trait System and Generic Programming

Designing a trait hierarchy that’s composable, ergonomic, and avoids object safety pitfalls is genuinely hard. This agent understands when to use generics versus trait objects, how to use associated types versus generic parameters, and when blanket implementations are appropriate versus overly broad.

Error Handling Architecture

Libraries that panic are a liability. Rust Pro enforces proper Result-based error handling throughout, helps you design custom error types with thiserror, and ensures your public API surfaces errors that callers can actually act on.

Performance-Critical Code

When you need to squeeze performance out of hot paths — avoiding allocations, using iterators correctly, writing benchmarks with criterion.rs, or safely dropping into unsafe with documented invariants — Rust Pro has the expertise to guide those decisions with the compiler, not against it.

FFI Boundaries

Interfacing with C libraries or exposing Rust to other languages requires careful handling of raw pointers, memory ownership across FFI boundaries, and null safety. This is an area where unsafe is unavoidable but must be tightly controlled — exactly the kind of work Rust Pro is built for.

Real-World Examples

Scenario: Building a Thread-Safe Cache with Expiry

A developer is building a caching layer for a Tokio-based service and needs a concurrent map with TTL-based expiry.

Developer: I need a concurrent cache with TTL expiry for my Tokio service.
           I'm thinking HashMap wrapped in Arc<Mutex<T>> with a background
           task that sweeps expired entries. Does that work?

Rust Pro: That works but has a few pitfalls. Holding a Mutex across an
          .await point will deadlock since MutexGuard isn't Send — use
          tokio::sync::Mutex if you need async-aware locking, or better,
          restructure to release the lock before awaiting.

          For TTL expiry, a background sweep task is reasonable but you'll
          want to handle cancellation cleanly. Here's an idiomatic approach:

          use std::collections::HashMap;
          use std::time::{Duration, Instant};
          use tokio::sync::RwLock;
          use std::sync::Arc;

          #[derive(Clone)]
          pub struct Cache<K, V> {
              inner: Arc<RwLock<HashMap<K, (V, Instant)>>>,
              ttl: Duration,
          }

          The RwLock here lets multiple readers proceed concurrently —
          better throughput than Mutex for read-heavy workloads.
          The sweep task should receive a CancellationToken from
          tokio_util so it exits cleanly when your service shuts down.
          Want me to generate the full implementation with the eviction
          task and a criterion benchmark?

Scenario: Custom Error Types for a Library

A developer is building a Rust library and wants to know the right way to expose errors to consumers.

Developer: What's the right way to handle errors in a library crate?
           I've been using anyhow but a colleague said that's wrong for libs.

Rust Pro: Your colleague is right. anyhow is for applications — it's
          designed to collect and display errors for end users, not for
          callers to programmatically handle. Libraries should expose
          typed errors so consumers can match on specific variants.

          Use thiserror for the implementation:

          use thiserror::Error;

          #[derive(Debug, Error)]
          pub enum ParseError {
              #[error("unexpected token `{token}` at position {pos}")]
              UnexpectedToken { token: String, pos: usize },

              #[error("unexpected end of input")]
              UnexpectedEof,

              #[error("invalid utf-8 sequence")]
              InvalidUtf8(#[from] std::str::Utf8Error),
          }

          The #[from] attribute generates the From impl automatically.
          Don't use Box<dyn Error> in your public API — it erases type
          information and forces callers to downcast. Keep your error
          enum exhaustive from the start or use #[non_exhaustive] if
          you expect to add variants without breaking semver.

What Makes This Agent Powerful

Type-System-First Reasoning

Rust Pro’s core philosophy is using the type system to encode correctness. It won’t suggest runtime checks where compile-time guarantees are achievable. This leads to code that’s not just safer but faster — zero-cost abstractions mean the type-level guarantees disappear at compile time, leaving optimized machine code.

No Panics in Library Code

This is a hard rule the agent enforces. unwrap() and expect() have their place in application code and tests, but a library that panics is unpredictable. Rust Pro consistently generates Result-returning functions with proper error types, which makes the code composable with the ? operator throughout.

Iterators Over Manual Loops

Rust’s iterator adapters — map, filter, flat_map, fold, chain, and dozens more — are zero-cost and compile to the same machine code as hand-written loops, often better due to LLVM optimization opportunities. Rust Pro defaults to this style, producing code that’s both idiomatic and performant.

Async Code with Cancellation Semantics

Async Rust is notoriously tricky around cancellation — futures being dropped mid-execution is a feature, not a bug, but it requires careful handling. The agent generates async code that handles cancellation explicitly, uses tokio_util::sync::CancellationToken where appropriate, and avoids holding locks across await points.

Unsafe with Documented Invariants

When unsafe is genuinely necessary — SIMD, FFI, performance-critical data structures — Rust Pro doesn’t shy away from it, but it documents the safety invariants clearly with // SAFETY: comments and minimizes the scope of unsafe blocks to the smallest possible footprint.

Complete, Compilable Output

The agent generates complete artifacts: Rust source with doc comments and doctests, Cargo.toml with appropriate feature flags and dependencies, criterion.rs benchmarks for performance-sensitive code, and clippy-compliant code throughout. You get something you can drop into a real project, not a sketch.

How to Install Rust Pro in Claude Code

Installing the Rust Pro agent takes about sixty seconds. Claude Code automatically discovers agent files placed in the .claude/agents/ directory of your project.

First, create the directory if it doesn’t exist:

mkdir -p .claude/agents

Next, create the file .claude/agents/rust-pro.md and paste the following system prompt as its contents:

You are a Rust expert specializing in safe, performant systems programming.

## Focus Areas

- Ownership, borrowing, and lifetime annotations
- Trait design and generic programming
- Async/await with Tokio/async-std
- Safe concurrency with Arc, Mutex, channels
- Error handling with Result and custom errors
- FFI and unsafe code when necessary

## Approach

1. Leverage the type system for correctness
2. Zero-cost abstractions over runtime checks
3. Explicit error handling - no panics in libraries
4. Use iterators over manual loops
5. Minimize unsafe blocks with clear invariants

## Output

- Idiomatic Rust with proper error handling
- Trait implementations with derive macros
- Async code with proper cancellation
- Unit tests and documentation tests
- Benchmarks with criterion.rs
- Cargo.toml with feature flags

Follow clippy lints. Include examples in doc comments.

That’s the entire installation. The next time you open Claude Code in that project, the agent is available. You can invoke it directly in your prompts by referencing it by name, or Claude Code will activate it automatically based on context when you’re working in Rust files.

The agent definition travels with your repository, so committing the .claude/agents/ directory to version control means every developer on the project gets the same consistent Rust expertise built into their workflow.

Practical Next Steps

If you have an existing Rust codebase, a good first exercise is to ask Rust Pro to audit a module for panics in library-facing code, or to review your error type design. These are common issues in Rust codebases that have grown organically, and the agent will surface specific, actionable improvements.

For greenfield projects, start with your Cargo.toml structure and ask Rust Pro to help design the trait hierarchy before you write implementation code. Getting the abstractions right early in Rust saves enormous refactoring effort later — the type system makes certain structural changes expensive once they’re load-bearing.

For async services, describe your concurrency model upfront — number of tasks, shared state requirements, cancellation behavior — and let the agent generate a skeleton that handles the hard parts correctly from the start rather than retrofitting them later.

Agent template sourced from the claude-code-templates open source project (MIT License).

Share.
Leave A Reply