Skip to content

Install

Status

The tooling is real and tested (milestone M2), and so is the engine it drives through M3. npm create aosengine is not published to npm yet, so run it from a checkout for now; everything below is verified by CI against this repository.

What you need

RequirementVersionWhy
Node.js>= 24Pinned in .nvmrc; engine-strict=true will refuse older versions
npm>= 11Workspaces and overrides
A WebGPU browserChrome/Edge 121+The renderer. WebGL is a fallback for splat worlds only
Gitany recentcreate-aosengine runs git init for you

Git LFS is not required to run a generated game, and not required to run this repository's tests. It is only needed if you add real binary content of your own.

Nothing else needs installing by hand. jco, componentize-qjs and its native binding arrive with the game's own npm install, and aosengine doctor tells you if one of them did not.

Start a game

sh
npm create aosengine my-game -- --template fps
cd my-game
npm run dev

That is a playable game: walk, shoot, kill three capsules, win. Open http://localhost:5173, then edit src/game.ts and save.

--template third-person gives you the other scaffold, and --third-person is a shorthand for it.

Options

FlagDoes
--template <name>fps (default) or third-person
--third-personshorthand for --template third-person
--title "<text>"human title for the page and the README; defaults to the directory
--no-installskip npm install
--no-gitskip git init
--aamadd the AvatarOS Asset Manager keys to .env.example
--forcewrite into a directory that already has files in it

With no arguments at all, and an interactive terminal, it asks for the directory and the template. In CI — or when an agent runs it — it takes the defaults and never blocks on a question nobody can answer.

The -- before the flags is npm's, not ours: without it npm eats them.

What you get

my-game/
├─ AGENTS.md            the rules, scoped to this game
├─ .env.example         copy to .env.local; VITE_-prefixed keys only
├─ index.html
├─ package.json         dev / build / preview / test
├─ public/              served at the site root
├─ src/
│  ├─ game.ts           the one defineGame call. Start here
│  ├─ assets.json       asset ids to files. The ids are the contract
│  ├─ prefabs.ts        entity templates
│  ├─ hud.ts
│  └─ systems/          one file per behaviour
├─ tests/
└─ vite.config.ts

.aosengine/ and dist/ appear when you build, and both are gitignored.

The commands

The template's npm scripts wrap @aosengine/cli:

CommandDoes
npm run devVite in direct mode; edit src/game.ts and save
npm run dev -- --wasmbuild the component first and serve it, to check parity
npm run buildcomponentize the guest, then vite build
npm run build -- --reportthe same, plus size and timing numbers, with budgets
npm testthe smoke spec, headless
npx aosengine doctorcheck the toolchain; exit code is the number of failures
npx aosengine docswhere the llms*.txt bundles are on this machine

Direct mode is the default because a jco componentize run is about thirty seconds and that is not a dev loop. The two modes share the same guest runtime on purpose, and a parity test hashes both — if they diverge, that is an engine bug, not a configuration difference.

Verify

sh
node --version          # v24.x
npx aosengine doctor    # 0 failures
npm run dev             # http://localhost:5173

doctor checks node, npm, a single three instance, src/assets.json and the files it references, the aos:engine WIT package, jco, componentize-qjs and its native binding for your platform. Every failure prints a copy-pasteable fix. It cannot probe WebGPU from node, so it always prints the Chrome flags and leaves that one to you.

If something is red, Debug with doctor walks through the failures one at a time.

Work on the engine itself

sh
git clone <repo> aosengine
cd aosengine
npm install
npm run check

npm run check is lint, typecheck, unit tests and docs lint. It must be green before you commit. The full command list:

CommandDoes
npm run devPoints you at an example; there is no root dev server
npm run buildtsdown build of every package
npm run typechecktsc -b --noEmit across all project references
npm run lintESLint flat config, type-aware
npm run formatPrettier write (format:check to verify)
npm testvitest, all packages and tests/
npm run docs:apiTypeDoc markdown into docs/api/ (generated)
npm run docs:devVitePress dev server on port 5173, after docs:api
npm run docs:buildVitePress production build, after docs:api
npm run docs:llmsRegenerate llms*.txt
npm run docs:lintDead links, templates, snippets, llms freshness, budgets
npm run checkAll of the above that gate a commit

Because every package declares a development export condition, npm install is the only build step you need before running an example. There is no watch task.

Running create-aosengine from inside a checkout links the generated game back at packages/ with file: dependencies instead of published versions, so an engine change shows up in the game without a publish.

Next