ADR-0008: The Bun workspace runs in Bun¶
Status: Accepted Date: 2026-10-12 Deciders: Alex Nodeland
Context¶
stackr RFC-0003 fixes the Bun workspace at lattice's root and moon's TypeScript tasks, and lattice RFC-0002 the tools. Phase 1 had four things left to decide: what runs the tools, how a package is consumed by another, which tasks a package without code to build or test has, and what version the web packages carry.
The tools' executables start with #!/usr/bin/env node, and moon runs them that way: with no Node.js on the path, vitest failed with exit code 127. .prototools installs moon, uv and Bun, and no Node.js.
Decision¶
- Bun runs every tool, in its own runtime. Each task is
bun x --bun --no-install <tool>:--bunruns a tool's Node.js script in Bun, and--no-installfails rather than fetching a tool thatbun.lockdoesn't hold. Biome,tsc, Vitest, Vite and knip all pass this way with no Node.js installed. clientanduiare consumed as source. Theirexportspoint atsrc/index.ts, and Vite builds them intoappandadmin. So they have nobuildtask, andappandadminhave notesttask until they have code of their own;checkruns whichever oftestandbuilda package has.- A web package's edges are its workspace dependencies.
appandadmindepend onuialone until they useclient, and the root's edges test holds each web package'sdependsOnto itspackage.json, as it holds the Python packages' to theirpyproject.toml. - The web packages are private and carry no version. portalr's one version is its
pyproject.toml's, which release-please moves. - moon edits and installs nothing.
.moon/toolchains.ymlturns off every setting that would install, dedupe, or rewrite apackage.jsonortsconfig.json. proto installs Bun from.prototools, as it installs moon and uv, and moon doesn't take Bun's version from there: when it did, it installed a proto of its own in CI, mid-run, and a concurrentuvshim failed.
Options considered¶
| Option | For | Against |
|---|---|---|
Bun's runtime for every tool, through bun x --bun --no-install (chosen) |
One runtime, at the version .prototools pins, in CI, the dev container and locally |
Vitest and Vite support Bun's runtime less widely than Node.js's |
Node.js in .prototools |
Every tool's documented runtime | A fourth tool to pin and update, for what Bun already runs |
bunfig.toml's [run] bun = true with bun run <tool> |
Shorter commands | With bun run biome, knip didn't count Biome as used |
| The runner's preinstalled Node.js | Nothing to add | Unpinned, and absent elsewhere |
Consequences¶
- Easier: a contributor needs only what
proto useinstalls. - Harder: a tool that breaks under Bun's runtime needs Node.js after all; that would be a new ADR.
- To revisit: phase 2 first proves Vitest's browser mode,
@vitest/browserwith Playwright, underbun x --bun. If it fails, Node.js joins.prototools, with a new ADR.