a workshop log. tutorials, snippets, libraries — straight from the wall.
Before the first line of code, the wall must be primed. Every workshop begins with the same five minutes — a deliberate act that transforms a blank machine into a place where work happens.
Pin your toolchain. Configure the editor. Stand up the project skeleton in a single command, every time, the same way. Boredom is a feature here. Surprises during setup become bugs you ship later.
# prime the wall — once per project
set -euo pipefail
cargo new --lib p9r
cd p9r
echo '[toolchain]' > rust-toolchain.toml
echo 'channel = "stable"' >> rust-toolchain.toml
cargo add anyhow tracing
cargo add --dev pretty_assertions
git init && git add . && \
git commit -m "first tag on the wall"
Threads are spray cans. Each one paints in parallel; if they collide on the same pixel, the wall smears. The job of the developer is to choreograph that paint without tying the cans together.
Channels over locks when you can. Bounded queues over unbounded ones, always. Cancellation as a first-class concern, never a postscript. The patterns below show three primitives that compose into almost any concurrent system.
use tokio::sync::{mpsc, broadcast};
use tokio_util::sync::CancellationToken;
pub async fn spawn_crew(
n: usize,
cancel: CancellationToken,
) -> mpsc::Sender<Job> {
let (tx, mut rx) = mpsc::channel(256);
for id in 0..n {
let cancel = cancel.clone();
tokio::spawn(async move {
loop {
tokio::select! {
_ = cancel.cancelled() => break,
Some(job) = rx.recv() => {
job.run(id).await;
}
}
}
});
}
tx
}
A library is not done when it compiles. It is done when a stranger can install it, run an example, and read the changelog without writing to you. The seams between local craft and public art are the docs.
Versions are promises. The README is the gallery placard. The changelog is the receipt. Treat them as production code — diff them in PRs, fail CI when they drift from reality.
name: release
on:
push:
tags: ['v*']
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: verify changelog
run: ./scripts/check-changelog.sh
- name: test readme example
run: cargo test --doc
- name: publish
run: cargo publish
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO }}
Four small open libraries from the workshop. Drag, swipe, or shift+wheel to walk the wall.
Tiny templating engine for shell-friendly text. Zero deps, single file, fits in a gist.
Rust · 600 LOC v0.4.2Async retry policies with jitter. Drop-in middleware for tower and reqwest stacks.
Rust · async · tower v1.2.0Generate release notes from conventional commits. One binary, two flags, fast enough for hooks.
Rust · clap · git2 v0.9.1Markdown to terminal renderer with theme support. Pipes pretty into less, cat, fzf.
Rust · pulldown · ANSI v0.6.0Macro-free dependency injection for plain structs. Compile-time wiring, no runtime registry.
Rust · proc-macro v0.3.4Tests run. The repo is the studio. Keep both clean enough to invite a stranger in.
Pin the dependencies you trust. Replace the ones you don't. Write the ones nobody else has.
A good error message is a small mural — it tells the reader exactly where the wall ends.
Ship a crate the size of a sticker. Compose it with others. Avoid the temptation of frameworks.