The atoll CLI
@atolljs/cli scaffolds pools, shared-memory contracts, and worker-rendered islands — and audits the setup. Source-level generator: it writes readable files into your project, nothing it emits is a runtime dependency.
Experimental. The command grammar and generated code are still evolving — expect breaking changes between minor releases. Bugs and feedback: github.com/jwhenry3/atolljs/issues.
Run it
npx @atolljs/cli <command>
# or, once installed: atoll <command>Requires Node ≥ 22.18 — the bin ships as TypeScript and runs under Node's native type stripping, so there's no build step. The generated app code runs on Node ≥ 20 and in browsers.
atoll new <dir>
Scaffold a fresh app — a Vite shell with COOP/COEP headers already set, a worker-rendered counter island, and a hardened .npmrc:
atoll new my-app --framework react # react | vue | solid | svelte | node
atoll new my-api --framework node # tsx Node service with a pooled worker--pm npm picks the install command. Angular apps scaffold through the Angular CLI instead — ng new, then atoll init.
atoll init
Wire Atoll into an existing project: writes the supply-chain .npmrc (min-release-age=7, ignore-scripts), installs the @atolljs/* packages your detected framework needs, and generates a working spine — src/atoll/app.memory.ts, app.worker.ts, and a typed app.ts client.
atoll add [framework] <kind> [variant] [name]
Generate a piece into the current project. The leading framework word overrides project detection — atoll add react island facade counter. Kinds without a framework scope run anywhere:
| kind | generates |
|---|---|
worker | pooled worker + typed client (any host) — + framework bindings on UI projects |
memory | a *.memory.ts shared-memory contract module |
island | worker-rendered UI — facade (contract + lazy import) or mono variant |
service | nestjs — @AtollService class facade + registerPool module + worker entry |
method | nestjs — @AtollTask method-level offload on an existing service |
module | nestjs — registerPool boundary module + worker entry |
housed | nestjs — route subtree served entirely inside workers (+ gateway wiring) |
route | nextjs — app/api/<name>/ route pool — task or client variant |
component | nextjs — 'use client' component bound to a pool via hooks |
instrumentation | nextjs — server bootstrap that warms route pools at boot |
Variants resolve as a positional (add island facade counter), --variant, an interactive pick, or the first listed non-interactively. A new worker wires the lone *.memory.ts in its directory automatically — --memory <name> pins one, --no-memory opts out.
atoll doctor [--fix]
Audits the setup — each check maps to an invariant in these docs:
- Node ≥ 22.18 for the CLI bin, ≥ 20 for the runtime it generates
@atolljs/*dependencies present and a lockfile committed.npmrcsupply-chain policy —--fixwrites it- worker entries bundler-detectable — every
new Worker(must takenew URL('./x.worker.ts', import.meta.url)inline so the bundler can see it - COOP/COEP headers in the Vite config — the SharedArrayBuffer gate (skipped for Node projects)
Flags & behavior
--yes / -y | accept every default — implied when there's no TTY |
--force | overwrite existing files (they're never touched otherwise) |
--no-install | write files but skip the dependency install |
--dir <path> | output directory for add (default src/atoll/) |
Missing answers prompt interactively. The bootstrap install runs once with --min-release-age=0 — the just-written .npmrc would otherwise block the brand-new packages it installs; the policy governs every install after that.