Appearance
Build
A Matrix package builds with whichever tool its package.json:scripts.build runs. The workspace-level orchestrator is pnpm plus Turbo; individual packages call esbuild, tsc, node build.mjs, or vite build depending on the shape.
Top-level commands
From CLAUDE.md Rule 10:
bash
pnpm install # install workspace deps
pnpm build:affected # build only packages whose source or deps changed
pnpm build # build everything (slower, sometimes needed)build:affected uses Turbo's affected-detection. Use it during normal development. Use the full pnpm build after pulling a large batch of changes or when a build cache is corrupt.
Per-package build scripts
Different shapes use different build tools. The patterns in the live tree:
esbuild for headless service packages
json
// packages/system/package.json
"scripts": {
"build": "esbuild src/index.ts --bundle --platform=node --target=node22 --format=esm --outfile=dist/index.js --external:node:* --external:@open-matrix/core ..."
}@open-matrix/system, @matrix/mx-cli, @open-matrix/host-service all use this pattern. esbuild is fast; the externalized dependencies get resolved by the runtime importer.
node build.mjs for hybrid packages
json
// packages/director/package.json
"scripts": { "build": "node build.mjs" }build.mjs typically chains: tsc --noEmit (type check) → vite build (browser assets) → an esbuild call (runtime entry). Look at packages/director/build.mjs and packages/chat/build.mjs for full examples.
vite build for pure web apps
Pure browser apps that lack a service factory may call vite build directly through their build script.
tsc for libraries
Pure libraries (e.g. @open-matrix/core) use tsc to emit dist/ in the layout the rest of the workspace expects.
What gets produced
The runtime entry path declared in matrix.json:runtime.entry must exist after build:
my-package/
├── matrix.json ← runtime.entry: "dist/index.js"
└── dist/
├── index.js ← built artifact
└── ...For a webapp package, webapp.distDir/webapp.entry must also exist. mx publish checks both before letting you publish.
Rebuild before testing
CLAUDE.md "REBUILD BEFORE TESTING": tests use built artifacts. Stale bundles produce false results. The order is always:
bash
pnpm build # produce dist/
pnpm test # tests run against dist/If you change source and skip the build, your test will exercise the old code without telling you.
Rebuild order matters across packages
When you change a workspace-internal dependency, dependents need their own rebuild before you can verify them. pnpm build:affected walks the dependency graph; manual rebuilds follow the same order:
@open-matrix/core- Other libraries that depend on
core mx-cli,host-service,host-control- The package you changed
hivecastwrapper if you changed any of the above and want to re-seed the install
hivecast operator refresh-host-package (from packages/hivecast/bin/hivecast.mjs:73-76) does steps 4 and 5 for you for a single package.
See also
- Local Development → Test
- Local Development → Run in place
- Local Development → Refresh without copying
- Publishing → Versioning
Source:
package.json:scripts.buildper package. Top-level orchestration isturbo.json+package.json:scriptsat the repo root.