Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Async Rust

ASecurity

Write correct async Rust — runtime choice, Send and Sync bounds, cancellation safety, blocking work inside async contexts, and shared state across tasks. Use when writing or reviewing async code, when a future is held across an await point, when the user hits a Send bound error on a spawned task, when a runtime stalls or deadlocks, or when the user asks about tokio, select!, or spawn_blocking.

2 stars
0 votes
0 copies
1 views
Added 9/19/2026
developmentrustgobashapiperformance

Works with

cliapi

Security Analysis

A100/100

Pro scans all 3 files and shows the line behind each finding

Scanned 9/19/2026

$npx -y skills add rewrite-rs/skills --skill async-rust --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Async Rust?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Async Rust
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/rewrite-rs-async-rust/badge)](https://www.skillsdirectory.com/skills/rewrite-rs-async-rust)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: async-rust
description: Write correct async Rust — runtime choice, Send and Sync bounds, cancellation safety, blocking work inside async contexts, and shared state across tasks. Use when writing or reviewing async code, when a future is held across an await point, when the user hits a Send bound error on a spawned task, when a runtime stalls or deadlocks, or when the user asks about tokio, select!, or spawn_blocking.
---
# Async Rust

Async Rust fails in three places: an executor thread that gets blocked, a guard
held across an await point, and a future dropped mid-operation. This skill
governs *correctness under concurrency and cancellation* — it does not decide
whether the code should be async in the first place.

## Async is not free concurrency

An `async fn` yields a future that does nothing until polled. Concurrency comes
from the runtime and from combining futures — `join!`, `select!`, `spawn` — not
from the `async` keyword:

```rust,ignore
// Serial: the second fetch starts only after the first completes.
let a = fetch_user(id).await;
let b = fetch_orders(id).await;

// Concurrent: both futures are polled at the same time.
let (a, b) = tokio::join!(fetch_user(id), fetch_orders(id));
```

Every `.await` in a function adds to the size of the generated future, and a
large future is copied on every move — into `Box::pin`, into a `JoinSet`.
Many awaits and large locals mean kilobytes; box the inner future or split
the function once a profile says the moves matter.

## Runtime choice, once, at the top

Pick a runtime, in the overwhelming majority of cases `tokio`, deliberately.
The library rules: stay runtime-agnostic if you can, feature-gate the
integration if you cannot, and never start a runtime inside a library
function (`#[tokio::main]` belongs in a binary or test; a `Runtime::block_on`
there hands the consumer a second, conflicting executor).

## Blocking work in an async context

A CPU-bound loop, a synchronous file or network call, or a compute stretch
without an `.await` inside an `async fn` stalls the executor thread and starves
every other task on it. The fix: `tokio::task::spawn_blocking` for blocking I/O
and short CPU work, a dedicated thread pool (`rayon`) for sustained CPU work,
and never a `std::thread::sleep` inside a task. For a compute loop, yielding
periodically is the weaker fix — it only helps if the chunks are genuinely
small.

## `Send`, `Sync`, and the spawn bound

`tokio::spawn` requires `Send + 'static`: everything held *across* an `.await`
must be `Send` — where `Rc` and `RefCell` fail to compile, and where a
`std::sync::MutexGuard` held across an `.await` becomes a deadlock:

```rust,ignore
// Deadlock waiting to happen: the std guard is held across the await.
let mut guard = state.lock().unwrap();
guard.value = fetch().await;

// Either drop the guard before awaiting…
let value = fetch().await;
state.lock().unwrap().value = value;

// …or use the async-aware mutex when the lock genuinely must span the await.
let mut guard = state.lock().await; // tokio::sync::Mutex
guard.value = fetch().await;
```

Prefer `std::sync::Mutex` unless the lock must span an `.await`, then
`tokio::sync::Mutex` — `clippy::await_holding_lock` catches the common case.

## Cancellation safety

Any future can be dropped at any `.await` point — that is what `select!` and
timeouts do. A future that has consumed input but not yet committed it loses
data when dropped mid-flight. The rule: do the irreversible step in one
non-cancellable piece, or make the operation resumable. The worked cases
live in `CANCELLATION.md`.

## Shared state across tasks

`Arc<Mutex<T>>` for shared mutation, channels for handing work between tasks,
and message passing when the state has one logical owner — a task that owns
its state and is told what to do beats tasks that reach into shared memory.

| Channel | Use for |
|---|---|
| `mpsc` | Many producers to one consumer |
| `oneshot` | A single reply |
| `watch` | The latest value, where missing intermediate values is correct |
| `broadcast` | Every receiver seeing every message, with a bounded backlog |

The choice is semantic, not performance — picking `broadcast` where `watch`
was meant produces a lagging receiver error nobody expected.

Dynamic task groups and their abort semantics are in `CANCELLATION.md`.

## Async in a public API

Prefer `async fn` over `-> impl Future` unless the extra control is needed —
the desugared form additionally promises `Send`-ness (or its absence) in ways
the caller then depends on. In traits, `async fn` still lacks `Send` bound
sugar, and `#[async_trait]` remains the pragmatic choice for object-safe
async traits.

## Deferrals

Error types for timeouts and cancellation are `/rust-errors`; shared-ownership,
`/ownership-not-clone`; public-surface commitments, `/rust-api-design`; the
`Pin` invariants of a manual `Future` impl, `/unsafe-rust`.

## Verification

```bash
cargo clippy --all-targets   # add -- -D warnings only if the repo has no lint config
cargo test
```

The async-relevant lints (`await_holding_lock`, `await_holding_refcell_ref`,
`async_yields_async`) come out of its output, not switched on. Async bugs
are timing-dependent — a passing `cargo test` is weak evidence: where
the repo uses `#[tokio::test]`, cover the changed path with
`#[tokio::test(flavor = "multi_thread", worker_threads = 2)]`.

Attribution

rewrite-rsrewrite-rs
View sourceSee grades on GitHubMore from rewrite-rs →
SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Related Skills

Clean Code

Pragmatic coding standards - concise, direct, no over-engineering, no unnecessary comments

304955 votes

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

285172 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2222 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

10311 votes
View all in development →