rtk-tdd — Claude Code skill: Rust TDD and install
This skill enforces a Red-Green-Refactor workflow for Rust and activates on implementation, testing, refactoring, and bug-fixing tasks.
npx skills add rtk-ai/rtk --skill rtk-tdd -a claude-codeWhat rtk-tdd does
rtk-tdd makes the agent follow a defined Rust TDD loop. It puts a test in the same file under #[cfg(test)], runs the focused cargo test command until it fails, adds the smallest implementation, then runs the test again before refactoring. The guidance uses Arrange-Act-Assert, assert_eq!, assert!, Result<()>, #[should_panic], and tempfile::NamedTempFile for filesystem cases.
The skill maps test choices to the code being changed: parsers are checked through their output, validation uses boundary inputs, error paths expect is_err(), and serialization checks a construct-serialize-deserialize roundtrip. The final gate runs cargo fmt --all --check, cargo clippy --all-targets, and cargo test. That matters when the code calls Command::new(), uses direct I/O, or exits from the process, because the guidance points those cases toward parser, pure-logic, or integration tests.
What it helps with
- drive Rust implementation from a failing test
- cover invalid parsing and validation inputs
- test filesystem code with
tempfile::NamedTempFile - verify serialization roundtrips
- run the Rust formatting, lint, and test gate
Example prompts for the agent
- Implement `parse_config` with the TDD loop: add a test under `#[cfg(test)]`, run `cargo test MODULE::tests::test_parse_config_invalid_input`, then write the minimum code to pass it.
- Add a test that rejects `../etc/passwd`, and run `cargo test MODULE::tests::test_validate_path_traversal`.
- Run the final Rust gate with `cargo fmt --all --check`, `cargo clippy --all-targets`, and `cargo test`.
How to install rtk-tdd
1Skills CLI (Vercel)
npx skills add rtk-ai/rtk --skill rtk-tdd -a claude-code2Manually: put the files in place
~/.claude/skills/rtk-tdd/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/rtk-tdd/
1Skills CLI (Vercel)
npx skills add rtk-ai/rtk --skill rtk-tdd -a codex2Manually: put the files in place
.agents/skills/rtk-tdd/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add rtk-ai/rtk --skill rtk-tdd -a cursor2Manually: put the files in place
.cursor/skills/rtk-tdd/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install rtk-ai/rtk rtk-tdd2Manually: put the files in place
.github/skills/rtk-tdd/SKILL.md1Skills CLI (Vercel)
npx skills add rtk-ai/rtk --skill rtk-tdd -a gemini-cli2Platform CLI
gemini skills install https://github.com/rtk-ai/rtk --path .claude/skills/rtk-tddManually: put the files in place
.devin/skills/rtk-tdd/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add rtk-ai/rtk --skill rtk-tdd -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
From the same set4
The whole set →Similar
Questions about rtk-tdd
How do I install rtk-tdd in Claude Code?
Run npx skills add rtk-ai/rtk --skill rtk-tdd -a claude-code, then run npx skills add rtk-ai/rtk --skill rtk-tdd -a claude-code again. The skill file is at ~/.claude/skills/rtk-tdd/SKILL.md.
What does rtk-tdd do?
It makes the agent use Red-Green-Refactor for Rust work: create a failing test, add the minimum production code, then verify and refactor it.
What runs in the final check?
The final gate runs cargo fmt --all --check, cargo clippy --all-targets, and cargo test. All three commands must pass.
Source text
SKILL.md · Apache-2.0
---
name: rtk-tdd
description: >
Enforces TDD (Red-Green-Refactor) for Rust development. Auto-triggers on
implementation, testing, refactoring, and bug fixing tasks. Provides
Rust-idiomatic testing patterns with anyhow/thiserror, cfg(test), and
Arrange-Act-Assert workflow.
allowed-tools:
- Read
- Write
- Edit
- Bash
effort: medium
tags: [tdd, testing, rust, red-green-refactor, rtk]
---
# Rust TDD Workflow
## Three Laws of TDD
1. Do NOT write production code without a failing test
2. Write only enough test to fail (including compilation failure)
3. Write only enough production code to pass the failing test
Cycle: **RED** (test fails) -> **GREEN** (minimum to pass) -> **REFACTOR** (cleanup, cargo test)
## Red-Green-Refactor Steps
```
1. Write test in #[cfg(test)] mod tests of the SAME file
2. cargo test MODULE::tests::test_name -- must FAIL (red)
3. Implement the minimum in the function
4. cargo test MODULE::tests::test_name -- must PASS (green)
5. Refactor if needed, re-run cargo test (still green)
6. cargo fmt && cargo clippy --all-targets && cargo test (final gate)
```
Never skip step 2. If the test passes immediately, it tests nothing.
## Idiomatic Rust Test Patterns
| Pattern | Usage | When |
|---------|-------|------|
| Arrange-Act-Assert | Base structure for every test | Always |
| `assert_eq!` / `assert!` | Direct comparison / booleans | Deterministic values |
| `assert!(result.is_err())` | Error path testing | Invalid inputs |
| `Result<()>` return type | Tests with `?` operator | Fallible functions |
| `#[should_panic]` | Expected panic | Invariants, preconditions |
| `tempfile::NamedTempFile` | File/I/O tests | Filesystem-dependent code |
## Patterns by Code Type
| Code Type | Test Pattern | Example |
|-----------|-------------|---------|
| Pure function (str -> str) | Input literal -> assert output | `assert_eq!(truncate("hello", 3), "...")` |
| Parsing/filtering | Raw string -> filter -> contains/not-contains | `assert!(filter(raw).contains("expected"))` |
| Validation/security | Boundary inputs -> assert bool | `assert!(!is_valid("../etc/passwd"))` |
| Error handling | Bad input -> `is_err()` | `assert!(parse("garbage").is_err())` |
| Struct/enum roundtrip | Construct -> serialize -> deserialize -> eq | `assert_eq!(from_str(to_str(x)), x)` |
## Naming Convention
```
test_{function}_{scenario}
test_{function}_{input_type}
```
Examples: `test_truncate_edge_case`, `test_parse_invalid_input`, `test_filter_empty_string`
## When NOT to Use Pure TDD
- Functions calling `Command::new()` -> test the parser, not the execution
- `std::process::exit()` -> refactor to `Result` first, then test the Result
- Direct I/O (SQLite, network) -> use tempfile/mock or test the pure logic separately
- Main/CLI wiring -> covered by integration/smoke tests
## Pre-Commit Gate
```bash
cargo fmt --all --check
cargo clippy --all-targets
cargo test
```
All 3 must pass. No exceptions. No `#[allow(...)]` without documented justification.
© rtk-ai · Apache-2.0 · rtk-ai/rtk