smol-rust

Installation
SKILL.md

smol

smol is a small, fast, modular async runtime for Rust. The smol crate is a thin facade that re-exports a family of independent [smol-rs] crates (async-executor, async-io, async-channel, async-lock, async-net, async-fs, async-process, blocking, futures-lite). The reactor (async-io, built on polling) wraps epoll / kqueue / event ports / IOCP. Apply these conventions when building async Rust on smol. Current: smol 2.0.2, dual MIT/Apache-2.0. Upstream README/Cargo.toml now set MSRV to Rust 1.85 (crates.io metadata for the already-published 2.0.2 still reports 1.63), so target Rust 1.85+.

Core API (what smol:: gives you)

  • smol::block_on(future) — run a future to completion on the current thread. The entry point for fn main and tests (smol has no required #[main] macro).
  • smol::spawn(future) -> Task<T> — spawn onto smol's built-in global executor. Worker-thread count comes from the SMOL_THREADS env var (default 1). You still need a block_on somewhere to drive progress on the calling thread.
  • Task<T> — a spawned task handle. Dropping a Task cancels it. .await it for the result, or call .detach() to let it run independently. Forgetting this silently cancels work; if the program exits while global tasks are still running, their futures are abandoned and destructors may not run.
  • Executor / LocalExecutor — composable executors when you don't want the global one. ex.spawn(fut), ex.spawn_many(...) for large batches, drive with block_on(ex.run(future)). LocalExecutor runs !Send futures on one thread. See the smol-macros crate for declarative main!/test! macros and multi-threaded Executor setup without proc-macro dependencies.
  • Timer (async-io) — Timer::after(Duration), Timer::at(Instant), Timer::interval(Duration), Timer::interval_at(Instant, Duration), Timer::never(), plus set_after/set_at/set_interval/set_interval_at reset methods and will_fire(). .await a one-shot timer for an Instant; poll an interval timer as a stream. Precision is platform-limited (Windows is roughly 16 ms) and timers may sleep longer, never less.
  • Async<T> — wrap a pollable OS I/O handle (networking types and OS FDs such as TcpStream, UnixStream, timerfd, inotify) to make it async via the reactor. Async::new puts the handle in non-blocking mode; Async::new_nonblocking assumes you already did. async-net provides ready-made TcpStream/TcpListener/UdpSocket/Unix types built on it. Regular files and stdio are not safe/pollable here — use async-fs (or Unblock) for those, not Async. For custom operations prefer read_with/write_with; get_mut and *_with_mut are unsafe because the inner I/O source must not be dropped.
  • unblock(closure) / Unblock<T> (blocking crate) — run blocking or CPU-heavy work on a dedicated thread pool. Unblock::new(std::io::stdout()) adapts blocking I/O (stdio, std::fs::File) into async; unblock(|| expensive()) offloads a closure.
  • Re-exported modules: smol::io, smol::future, smol::stream, smol::pin, smol::ready (from futures-lite); smol::channel (mpmc), smol::lock (Mutex/RwLock/Semaphore/Barrier/OnceCell), smol::net, smol::fs, smol::process (smol::process is omitted on target_os = "espidf").
  • use smol::prelude::*; — brings in Future, Stream, and the extension traits (FutureExt, StreamExt, AsyncReadExt, AsyncWriteExt, AsyncBufReadExt, AsyncSeekExt) so .next(), .read_to_end(), .race(), etc. are in scope.
use smol::{io, net, prelude::*, Unblock};
Installs
28
Repository
avbel/ai-skills
GitHub Stars
2
First Seen
May 25, 2026