webgpu game engine
- fast by default
- instant iteration
- runs anywhere
Five demos are built and served at dylanebert.com/shallot. Each links to its source at the version it was built from.
| demo | play | code |
|---|---|---|
| Collapse | play | code |
| Roads | play | code |
| Sandbox | play | code |
| Visualization | play | code |
| Voxel | play | code |
All you need is bun:
bun create shallot my-game
cd my-game
bun install
bunx shallot devbunx shallot dev runs the project with hot reload, and bunx shallot build ships it as a web bundle. bunx shallot build --target windows|mac|linux --release downloads a prebuilt shell for that version from GitHub Releases, so no Rust toolchain is needed on a hit. A debug build, or any miss (404, offline, checksum mismatch, a source checkout), silently falls back to compiling the Rust window host from source, which needs the Rust toolchain plus that target's system dependencies (see from source).
A project is plain data plus code: a shallot.json manifest, a .scene file, and TypeScript plugins you edit in your IDE.
bunx shallot verify boots the project in a headless browser and exits 0 or nonzero, a check you, an agent, or CI can run to catch a project that no longer boots or renders. It drives a real browser through the optional playwright peer, so install that once per project: bun add -d playwright && bunx playwright install chromium.
The source is the reference: every public export carries a JSDoc contract. There's no docs site to drift from it, and two files carry the consumer surface:
packages/shallot/AGENTS.md— the consumer contract: commands, the ECS and plugin conventions, the GPU, render, physics, and testing rules. Ships in the npm package.examples/AGENTS.md— the examples index: one line per entry, so you grep for the problem you have. The recipes section ships in the npm package as well.
Written for coding agents first, readable by hand. Both files move in the same commit as the code they describe, so there's no generated layer to fall behind.
Examples live under examples/, indexed by examples/AGENTS.md:
recipes/— one minimal project per problem: first-person character, physics playground, import a model, day-night sky, and more.showcase/— full projects rather than one concept each, several under real-device gates:collapse,roads,sandbox,visualization,voxel.gym/— machine-verdict scenarios: the real-device test and benchmark tier.flows/— ejected standalone apps for behavior a unit test can't reach (survive-reload,ui-containment,no-walls,blank), driven bybun run flows.
Run a recipe standalone:
bunx shallot dev examples/recipes/orbit-cameraA new project starts from bun create shallot <name> — the scaffold is the single source, so there's no in-repo starter copy.
Working on the engine itself needs the full toolchain:
- bun
- rust with the
wasm32-unknown-unknowntarget (rustup target add wasm32-unknown-unknown) wasm-optfrom binaryen, optional: the build falls back to copying the unoptimized wasm
git clone https://github.com/dylanebert/shallot
cd shallot
bun install
bun run buildbuild compiles the audio wasm kernel (packages/shallot/rust/audio) and the native window host (packages/shallot/rust/window). The tumble physics kernel is a committed wasm artifact: rebuild it with bun run --cwd packages/shallot scripts/build-tumble-kernel.ts after touching rust/tumble.
shallot build --target <platform> compiles the Rust window host from the crate source shipped in the npm package. You need Rust plus per-target system dependencies:
| target | system webview | portable (CEF) |
|---|---|---|
| mac | Xcode Command Line Tools | same, plus a CEF runtime download on first build (or set CEF_PATH) |
| linux | WebKitGTK dev headers (no usable WebGPU; use --portable) |
libx11-dev (X11 dev headers to link the CEF shell), plus CEF runtime download on first build (or CEF_PATH) |
| windows | cross-compiled via cargo-xwin (cargo install cargo-xwin; no local Windows toolchain needed) |
Visual Studio with the C++ workload incl. ATL, from WSL only (the build bridges to the Windows host) |
Portable builds bundle the Chromium runtime (CEF) instead of the system webview. The CEF runtime auto-downloads on first build unless CEF_PATH points to a local copy. Release builds download a prebuilt shell when one exists for the installed version; debug builds and any release miss always compile from source.
packages/shallot/— the engine. published as@dylanebert/shallotpackages/create-shallot/—bun create shallotscaffoldpackages/vscode-shallot/— VS Code extensionexamples/— example projects against the engineevals/— agent-agnostic eval suite
run from the repo root.
bun run test # unit tests over packages/shallot, scripts, evals, showcase/visualization/test (bun-webgpu)
bun bench # GPU benchmarks
bun check # read-only: tsc + biome + eslint + repo checks + scene-format report
bun run format # biome + scene formatter
bun run build # rust artifactsEngine-internal layout, the full command table, and the rules index are in AGENTS.md; the conventions themselves are path-scoped under .claude/rules/.
bun check and bun run test are the gate before pushing. The by-path slow suites, the invitation-only PR policy, and where to file an issue are in CONTRIBUTING.md.
MIT