RepoPilotOpen in app →

smol-rs/smol

A small and fast async runtime for Rust

Healthy

Healthy across the board

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 6w ago
  • 7 active contributors
  • Distributed ownership (top contributor 41% of recent commits)
Show all 6 evidence items →
  • Apache-2.0 licensed
  • CI configured
  • No test directory detected

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/smol-rs/smol)](https://repopilot.app/r/smol-rs/smol)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/smol-rs/smol on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: smol-rs/smol

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/smol-rs/smol shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across the board

  • Last commit 6w ago
  • 7 active contributors
  • Distributed ownership (top contributor 41% of recent commits)
  • Apache-2.0 licensed
  • CI configured
  • ⚠ No test directory detected

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live smol-rs/smol repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/smol-rs/smol.

What it runs against: a local clone of smol-rs/smol — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in smol-rs/smol | Confirms the artifact applies here, not a fork | | 2 | License is still Apache-2.0 | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 75 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>smol-rs/smol</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of smol-rs/smol. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/smol-rs/smol.git
#   cd smol
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of smol-rs/smol and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "smol-rs/smol(\\.git)?\\b" \\
  && ok "origin remote is smol-rs/smol" \\
  || miss "origin remote is not smol-rs/smol (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
  && ok "license is Apache-2.0" \\
  || miss "license drift — was Apache-2.0 at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "src/lib.rs" \\
  && ok "src/lib.rs" \\
  || miss "missing critical file: src/lib.rs"
test -f "src/prelude.rs" \\
  && ok "src/prelude.rs" \\
  || miss "missing critical file: src/prelude.rs"
test -f "src/spawn.rs" \\
  && ok "src/spawn.rs" \\
  || miss "missing critical file: src/spawn.rs"
test -f "Cargo.toml" \\
  && ok "Cargo.toml" \\
  || miss "missing critical file: Cargo.toml"
test -f "README.md" \\
  && ok "README.md" \\
  || miss "missing critical file: README.md"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 75 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~45d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/smol-rs/smol"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

smol is a lightweight async runtime for Rust that unifies the async ecosystem by re-exporting smaller, composable crates (async-executor, async-io, async-net, async-fs, etc.) rather than building everything monolithically. It enables you to write async/await code with minimal dependencies and fast compilation, targeting developers who want tokio-like capabilities without tokio's size or complexity. Single-crate facade structure: src/lib.rs re-exports from subcrates (async-channel, async-executor, async-fs, async-io, async-lock, async-net, async-process, async-task, blocking, futures-lite, polling). src/prelude.rs provides convenient imports. src/spawn.rs likely wraps executor functionality. examples/ directory contains 20+ runnable demos (tcp-server.rs, websocket-client.rs, hyper-server.rs, etc.). No internal business logic—entirely a composition layer.

👥Who it's for

Rust developers building async applications (networking, file I/O, concurrent tasks) who prioritize small binary size, fast compile times, and lean dependency trees. Also developers integrating with tokio-based libraries via the async-compat adapter, and contributors exploring or building composable async infrastructure crates.

🌱Maturity & risk

Production-ready and actively maintained. Current version is 2.0.2 (as of the Cargo.toml), with comprehensive CI via GitHub Actions (ci.yml, release.yml), solid test coverage via dev-dependencies (anyhow, tokio for testing), and a structured changelog. The MSRV is Rust 1.85, indicating serious version support discipline. Last commit data not visible, but the organized CI/CD and dependency structure signal a mature, stable project.

Low risk overall. The project explicitly depends on ~8 well-maintained smol-rs ecosystem crates (async-executor, async-io, async-net, etc.) rather than building from scratch, reducing surface area. Single logical maintainer risk is mitigated by a community organization (smol-rs). No exotic dependencies—all are standard async Rust libraries with clear governance. The main risk is that it's a thin wrapper, so if an underlying subcrate breaks, smol is affected; monitor smol-rs/* repositories closely.

Active areas of work

The repo is in maintenance/stable mode at v2.0.2. Specific active work is not visible from the file list alone, but the presence of release.yml suggests active release workflows, and ci.yml indicates continuous integration. The examples cover modern protocols (WebSockets, TLS, HTTP/2 via hyper) and platform features (linux-inotify.rs, windows-uds.rs), suggesting ongoing breadth improvements.

🚀Get running

git clone https://github.com/smol-rs/smol.git
cd smol
cargo build
cargo test
cargo run --example tcp-server

Daily commands:

cargo run --example tcp-server
cargo run --example http-client
cargo run --example websocket-server
``` Select any example from the examples/ directory. For tests: ```bash
cargo test

🗺️Map of the codebase

  • src/lib.rs — Main library entry point that re-exports the async runtime and all public APIs; every contributor must understand the module structure and what's being exposed.
  • src/prelude.rs — Defines the prelude module with commonly-used traits and types; essential for understanding the public API surface.
  • src/spawn.rs — Core spawning abstraction for async tasks; critical for understanding how smol executes concurrent work.
  • Cargo.toml — Defines all dependencies (async-executor, async-io, async-fs, async-net, etc.); contributors must understand the dependency graph and MSRV policy.
  • README.md — Documents the runtime's purpose, examples, and design philosophy; essential context for any contribution.
  • examples/tcp-server.rs — Canonical example showing core async I/O and spawning patterns; reference implementation for contributors.
  • CHANGELOG.md — Version history and breaking changes; critical for release management and understanding API stability.

🧩Components & responsibilities

  • async-executor (Rust, parking_lot locks, crossbeam-deque) — Multi-threaded work-stealing scheduler for spawned tasks; manages thread pool and task queues.
    • Failure mode: Deadlock if user code causes circular waits; panic in executor thread aborts entire runtime.
  • async-io (epoll (Linux), kqueue (macOS/BSD), IOCP (Windows), Polling (other)) — Wraps OS I/O multiplexing (epoll/kqueue/IOCP); notifies executor when I/O is ready.
    • Failure mode: System-level I/O errors propagate to tasks; file descriptor leaks if not closed properly.
  • async-net (std::net, async-io, tokio-compat if needed) — Async TCP/UDP socket abstractions; wraps std::net with async-io integration.
    • Failure mode: Socket errors (ECONNREFUSED, timeout) returned as Result to caller; half-open connections may hang.
  • async-fs (blocking crate, std::fs) — Async file I/O using the blocking crate; dispatches to thread pool to avoid executor blocking.
    • Failure mode: Exhausted blocking thread pool causes file operations to queue; disk errors propagated as I/O Result.
  • blocking crate — Manages a thread pool for

🛠️How to make changes

Add a new async example

  1. Create a new .rs file in examples/ that uses smol, async-io/async-net for I/O, and spawn() for concurrency (examples/my-example.rs)
  2. Use the prelude pattern: use smol::prelude::*; and import specific async crates as needed (examples/my-example.rs)
  3. Call smol::block_on() or use #[smol_macros::main] to run your async main function (examples/my-example.rs)

Expose a new async API from smol

  1. Add the upstream crate to [dependencies] in Cargo.toml (e.g., async-something = "X.Y.Z") (Cargo.toml)
  2. Re-export the public types/functions in src/lib.rs using pub use statements (src/lib.rs)
  3. If commonly used, also add to src/prelude.rs so users get it with one import (src/prelude.rs)
  4. Document with examples in README.md and optionally add an example file (README.md)
  5. Update CHANGELOG.md with the new feature and version bump (CHANGELOG.md)

Update the runtime for a new platform or OS

  1. Check conditional dependencies in Cargo.toml for platform-specific async-process features (Cargo.toml)
  2. If adding platform-specific examples (e.g., linux-inotify.rs, windows-uds.rs), create in examples/ (examples/my-platform.rs)
  3. Ensure async-io and async-net cover the new platform's I/O abstractions (Cargo.toml)

🔧Why these technologies

  • async-executor (1.5.0) — Provides the core multi-threaded task scheduler; smol re-exports this as the main executor.
  • async-io (2.1.0) — Low-level I/O multiplexing (epoll/kqueue/IOCP); foundation for all async I/O operations.
  • async-net (2.0.0) — Async TCP/UDP networking abstractions built on async-io; enables non-blocking socket I/O.
  • async-fs (2.0.0) — Async file I/O using the blocking crate under the hood; prevents blocking the executor.
  • async-channel (2.0.0) — Lock-free channels for inter-task communication; core concurrency primitive.
  • futures-lite (2.0.0) — Minimal future utilities and stream adapters; lightweight alternative to futures crate.
  • blocking (1.3.0) — Thread pool for CPU-bound blocking work; keeps async executor responsive.

⚖️Trade-offs already made

  • Re-export pattern instead of wrapper types

    • Why: Reduces code duplication and compilation time; users get battle-tested crates directly.
    • Consequence: smol is thin and composable but not a walled garden; users see upstream crate APIs directly.
  • Single-threaded executor option via async-executor

    • Why: Flexibility for embedded/WASM; zero synchronization overhead for single-threaded workloads.
    • Consequence: Users must choose or configure thread count; not automatic tuning.
  • Blocking crate for file I/O and CPU-bound work

    • Why: Prevents executor starvation from blocking system calls; transparent to users.
    • Consequence: Small overhead per blocking operation; thread pool memory usage.
  • No built-in macros; smol-macros is separate

    • Why: Keeps smol fast to compile and proc-macro-free; easier to iterate on macros.
    • Consequence: Users need extra dependency for #[smol::main]; more boilerplate without it.

🚫Non-goals (don't propose these)

  • Does not provide built-in HTTP framework; users choose hyper, async-h1, or similar.
  • Does not include TLS out of the box; examples show async-tls or rustls integration.
  • Not a database driver; works with async database crates like sqlx.
  • Does not handle process spawning on espidf targets (conditional dep in Cargo.toml).
  • Not a replacement for tokio; designed for smaller, composable async applications.
  • Does not provide async equivalents for all stdlib APIs; delegates to async-fs, async-net, etc.

🪤Traps & gotchas

No critical gotchas; the project is deliberately simple. Minor caveat: async-process is conditionally compiled (excluded on ESPidf target), so spawn_blocking for child processes only works on standard platforms. Note: The project is not a full async runtime like tokio; it's a composition layer—users must understand that actual executor scheduling comes from async-executor and I/O multiplexing from polling/async-io. No async runtime is started automatically; you must call smol::block_on() or integrate with an executor explicitly (see examples).

🏗️Architecture

  • tokio-rs/tokio — Direct alternative async runtime; monolithic, feature-rich, widely adopted; smol is lighter and more modular by design
  • async-rs/async-std — Competing lightweight async runtime with standard library-like APIs; smol's composition strategy is philosophically different (wrapper vs. standalone)
  • smol-rs/async-executor — Core subcrate providing task scheduling; where smol's executor logic lives and where significant optimization work happens
  • smol-rs/async-io — Core subcrate providing I/O multiplexing abstraction; the portable layer wrapping epoll/kqueue/wepoll that powers network and file operations in smol
  • smol-rs/smol-macros — Companion crate providing #[smol::main] macro and pre-configured executor setups to reduce boilerplate (mentioned in README)

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add MSRV validation CI workflow

The Cargo.toml specifies rust-version = "1.85" and README.md mentions an "MSRV Policy" section, but there's no CI workflow in .github/workflows/ to validate that the crate actually compiles on the minimum supported Rust version. This prevents accidental MSRV regressions during development.

  • [ ] Create .github/workflows/msrv.yml that runs cargo +1.85 check and cargo +1.85 test on all supported platforms
  • [ ] Add a step to verify against all feature combinations using cargo-hack or similar
  • [ ] Update CHANGELOG.md to document the new MSRV validation process
  • [ ] Test the workflow locally before submitting

Create platform-specific integration tests in tests/ directory

The examples/ directory has platform-specific examples (linux-inotify.rs, linux-timerfd.rs, unix-signal.rs, windows-uds.rs), but there are no corresponding tests in a tests/ directory. These platform-specific features lack automated test coverage and could regress silently.

  • [ ] Create tests/ directory structure with tests/platform/ subdirectories
  • [ ] Add tests/platform/linux_inotify.rs with basic integration tests for inotify functionality
  • [ ] Add tests/platform/unix_signal.rs with signal handling tests for Unix systems
  • [ ] Add tests/platform/windows_uds.rs with UDS tests for Windows
  • [ ] Ensure tests use appropriate #[cfg(target_os = "...")] guards matching dev-dependencies in Cargo.toml
  • [ ] Update CI workflow to run platform-specific tests only on relevant OS runners

Add comprehensive feature documentation to src/lib.rs

The src/lib.rs file re-exports smaller async crates as mentioned in README.md, but lacks documentation explaining what each re-exported dependency provides and when to use which component. This makes it harder for new users to understand the runtime's architecture.

  • [ ] Document each major re-export in src/lib.rs with examples (async-executor, async-io, async-fs, async-net, async-channel, async-lock)
  • [ ] Add a module-level doc comment explaining the overall architecture and how components work together
  • [ ] Include examples showing common patterns like spawning tasks, file I/O, and networking
  • [ ] Reference the examples/ directory from relevant doc sections
  • [ ] Ensure doc tests compile by running cargo test --doc

🌿Good first issues

  • Add a documented example showing how to use smol with tokio libraries via async-compat (similar to examples/hyper-server.rs but explicitly calling async_compat wrappers); this fills the gap between the README mention of async-compat and no concrete demo.
  • Write a comparison table in the README documenting when to use smol vs. tokio vs. async-std (download sizes, compile times, MSRV, feature set) to help users make an informed choice—the repo implies 'small and fast' but doesn't quantify it.
  • Add integration tests in a tests/ directory covering the main subcrate re-exports (e.g., verify async-executor::block_on, async-net::TcpStream, async-fs::File all work correctly when imported from smol prelude) to catch re-export regressions early.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 4af083b — Update async-tungstenite requirement from 0.33 to 0.34 (#373) (dependabot[bot])
  • 5bbe7eb — Update scraper requirement from 0.25 to 0.26 (#374) (dependabot[bot])
  • 38e96d7 — Update async-tungstenite requirement from 0.32 to 0.33 (#372) (dependabot[bot])
  • 5590f33 — Update async-native-tls requirement from 0.5 to 0.6 (#371) (dependabot[bot])
  • e9c4bf6 — Update MSRV in readme (taiki-e)
  • 9d27afe — Update signal-hook requirement from 0.3 to 0.4 (#363) (dependabot[bot])
  • 325490c — Migrate to Rust 2021 (taiki-e)
  • 13df7f3 — Bump MSRV to 1.85 (taiki-e)
  • 920ae6c — chore: improve code comments clarity (xibeiyoumian)
  • 5abe211 — Update async-tungstenite requirement from 0.31 to 0.32 (#358) (dependabot[bot])

🔒Security observations

The smol async runtime codebase demonstrates good security practices overall. It is a legitimate, well-maintained open-source project with no critical vulnerabilities identified. Minor concerns include example TLS files in version control (standard for examples but worth noting) and the absence of automated dependency vulnerability scanning in the visible CI/CD configuration. The codebase itself does not expose injection risks, hardcoded secrets, or misconfigured infrastructure. Dependencies are from reputable async ecosystem projects maintained by established open-source authors.

  • Medium · TLS Certificate and Private Key in Examples — examples/certificate.pem, examples/identity.pfx. The repository contains example TLS certificate (certificate.pem) and identity key (identity.pfx) files in the examples directory. While these are clearly marked as examples and not production credentials, storing certificate and key material in version control is a security anti-pattern that could be misconstrued or accidentally misused. Fix: Consider generating these files dynamically in example code or documenting that these are self-signed test certificates for development only. Add comments in code examples explaining they should never be used in production.
  • Low · Permissive Dependency Version Specifications — Cargo.toml - dependencies section. Several dependencies use loose version constraints (e.g., '2.0.0', '1.5.0' without explicit upper bounds). While this allows minor/patch updates, it could introduce unexpected breaking changes if a dependency's major version is bumped in a minor release due to semver violations in upstream crates. Fix: Consider using caret (^) or tilde (~) version specifications for better control. Regularly audit dependencies with 'cargo audit' and use 'cargo deny' for additional security checks.
  • Low · Missing Security Audit Configuration — CI/CD configuration (.github/workflows/). The repository does not appear to have a cargo-audit or cargo-deny configuration visible in the file structure. This means potential security vulnerabilities in dependencies may not be automatically detected in CI/CD. Fix: Add 'cargo audit' step to CI/CD pipeline (.github/workflows/ci.yml) to automatically scan for known vulnerabilities in dependencies on each commit.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · smol-rs/smol — RepoPilot