Home › Rust › Rust async (Tokio) .claude/rules file
Rust async (Tokio) .claude/rules file
A path-scoped Claude Code rules file for async Rust on Tokio: no blocking, cancellation safety, locks, and tasks.
Claude Code (CLAUDE.md)Rust
How to use
Save this as .claude/rules/rust-async.md in your repository root, commit it, and your agent will pick it up automatically. Edit the commands to match your project.
Note: Review and test before use. Provided as is, without warranty. See Terms.
.claude/rules/rust-async.mdDownload ---
paths:
- "src/**/*.rs"
- "crates/**/*.rs"
---
# Async Rust with Tokio
- Never block the runtime: no `std::thread::sleep`, blocking file/network I/O, or heavy CPU loops inside async fns. Use `tokio::time::sleep`, `tokio::fs`, async clients, or `tokio::task::spawn_blocking` for CPU/sync work.
- Don't hold a `std::sync::Mutex` guard across `.await`. Use `tokio::sync::Mutex` only when the lock must span awaits; otherwise restructure to drop the guard first.
- Prefer message passing (`mpsc`, `oneshot`, `watch`, `broadcast`) for shared state owned by one task.
- Spawned tasks: keep the `JoinHandle` or use a `JoinSet`; handle `JoinError` (panics). Use `tokio_util::sync::CancellationToken` for shutdown.
- `select!` branches must be cancellation-safe; don't put non-cancel-safe futures (partial reads into a local buffer) directly in a loop'd `select!`.
- Put timeouts on all network calls (`tokio::time::timeout`).
- `Send` errors: usually a non-Send value (`Rc`, `RefCell`, a std guard) lives across an `.await`; scope it in a block instead of switching to a local runtime.
- `#[tokio::main]` only in binaries; libraries don't pick the runtime.
- Tests: `#[tokio::test]`, and `tokio::time::pause()` for time-based logic.
Verify with `cargo clippy -- -D warnings` (watch for `await_holding_lock`) and `cargo test`.