David Says
Claude Code plugin channeling David Tolnay's Rust philosophy. "Let the types do the work."
David reviews your Rust code for ownership fights, error handling anti-patterns, and missed opportunities to use the type system. Precise, quiet, and authoritative.
Available through the Ryde Ventures plugin marketplace.
Installation
# Add the Ryde Ventures marketplace (one-time)
/plugin marketplace add rydeventures/claude-plugins
# Install the plugin
/plugin install david-says@rydeventures-claude-plugins
Quick Start
# Review uncommitted changes (default behavior)
@david
# Review a specific file
@david review src/lib.rs
# Simplify uncommitted changes (applies fixes directly)
@david simplify
# Simplify a specific file
@david simplify src/errors.rs
# Hunt for anti-patterns in your codebase
@david find unnecessary clones in my codebase
# Review an entire directory
@david review all files in src/
# Find error handling issues
@david check if my error types are well-structured
# Audit dependencies
@david review my Cargo.toml dependencies
Modes
| Mode | Command | Behavior |
|---|
| Review | @david | Analyze, give feedback, no changes |
| Simplify | @david simplify | Analyze AND apply fixes directly |
Simplify mode focuses on structural improvements: replacing Box with thiserror, removing unnecessary clones, fixing function signatures to accept references, and adding error context.
What David Looks For
Red Flags
anyhow::Error in library public APIs
.clone() to satisfy the borrow checker
&String / &Vec<T> instead of &str / &[T]
Box<dyn Error> when callers need to match variants
.unwrap() on user-controlled input
- Custom serde impls when attributes suffice
The Rust Way
thiserror for libraries, anyhow for applications
- Borrow when you only read, own when you store
- Accept the most general type (
&str, &[T], &Path)
- Make invalid states unrepresentable with the type system
- Implement std traits (Display, FromStr, From, Default)
- Derive first, attributes second, custom impls last
Example Review
Input: A library function with Box<dyn Error> and unnecessary clones
pub fn process(input: String) -> Result<Output, Box<dyn std::error::Error>> {
let config = load_config()?;
let data = input.clone();
let parsed: Input = serde_json::from_str(&data)?;
Ok(transform(parsed, config))
}
David says:
Overall Assessment
The function signature is too greedy with ownership and too vague with errors. The clone is unnecessary, and callers can't handle failures programmatically.
Critical Issues
Box<dyn Error> in a public function. Callers must downcast to handle errors. Use thiserror.
String parameter when &str suffices. The function only reads the input. Borrowing avoids forcing callers to allocate.
Unnecessary clone on line 3. input is already a String. You can call serde_json::from_str(&input) directly.
Bare ? on load_config(). If this fails, the caller sees the raw IO error with no context about what config file was being loaded.
The Rust Way
#[derive(thiserror::Error, Debug)]
pub enum ProcessError {
#[error("failed to load config")]
Config(#[from] ConfigError),
#[error("invalid input format")]
Parse(#[from] serde_json::Error),
}
pub fn process(input: &str) -> Result<Output, ProcessError> {
let config = load_config()?;
let parsed: Input = serde_json::from_str(input)?;
Ok(transform(parsed, config))
}
What Works
The transformation logic is clean. The separation of config loading and parsing is correct.
Let the types do the work.
Representative Quotes
"anyhow is for applications. thiserror is for libraries."
"The caller shouldn't need to downcast."
"Every dependency is a cost."
"If you're cloning to satisfy the borrow checker, you're modeling ownership wrong."
"The derive handles this."
Knowledge System
David automatically loads relevant knowledge based on the files being reviewed:
| File Pattern | Knowledge |
|---|
| Error types, Result | Error handling patterns |
| Lifetimes, borrows | Ownership and borrowing |
| Serde derives, JSON | Serde attributes and performance |
| Structs, enums, traits | Type design principles |
| Async, tokio, channels | Concurrency patterns |
| Tests | Testing best practices |
| Proc macros, syn, quote | Macro development |
| Cargo.toml | Dependency management |
Philosophy
David's code philosophy centers on: