Skip to content

Scaffold a package

The first stage of the lifecycle is creating a package directory. The mx CLI ships six scaffold commands; choose the one that matches the shape you want.

The six scaffold commands

From projects/matrix-3/packages/mx-cli/src/index.ts:53-112:

CommandWhat it produces
mx initEmpty package skeleton: matrix.json, src/index.ts, tests/, examples/, skills/. No actor classes yet.
mx actor <name>Headless service package containing one MatrixActor subclass with accepts/emits declared.
mx element <name>Browser custom element package extending MatrixActorHtmlElement.
mx actor-element <name>Hybrid: paired headless actor + browser element in one package.
mx cqrs <name>Package with split command/query actors (CQRS pattern).
mx webapp <name>Browser web app with shell pattern, federation, and Vite build.

All scaffolds share the same option style:

bash
mx <verb> <name> [--out <path>]
mx init [--name <name>] [--version <version>] [--description <text>] [-y/--yes]

--out overrides the output directory; the default is ./<name> for actor/element/actor-element/cqrs/webapp, and the current directory for init.

mx init — the empty skeleton

bash
mkdir my-package && cd my-package
mx init -y --name my-package --version 0.1.0

What it writes (packages/mx-cli/src/commands/init.ts:71-124):

my-package/
├── matrix.json          ← name, version, description, runtime, components: [], permissions
├── src/
│   └── index.ts         ← `export {};`
├── tests/
│   └── package.spec.ts  ← node:test scaffold
├── examples/            ← empty
└── skills/              ← empty

The generated matrix.json is exactly:

json
{
  "name": "my-package",
  "version": "0.1.0",
  "description": "",
  "runtime": { "language": "typescript", "entry": "dist/index.js" },
  "components": [],
  "permissions": { "fsPolicy": "none" }
}

Without -y, mx init prompts for name, version, and description interactively (init.ts:50-69).

mx actor <name> — one headless actor

bash
mx actor user-store

Produces (packages/mx-cli/src/commands/actor.ts:85-149):

user-store/
├── matrix.json                ← components[]: { type: "UserStoreActor", mount: "user-store", ... }
├── package.json
├── tsconfig.json
├── src/
│   ├── UserStoreActor.ts      ← MatrixActor subclass with getStatus / statusChanged
│   └── index.ts               ← re-exports the class
├── tests/
│   └── user-store.spec.ts     ← node:test verifying accepts has getStatus
├── skills/
│   └── user-store.skill.md
└── examples/
    └── get-status.mxq

The seed actor includes static accepts, static emits, and an onGetStatus() handler. Replace these with your real ops.

mx element <name> — a browser custom element

mx element scaffolds a package that exports a MatrixActorHtmlElement subclass intended to register as <mx-<name>> in the browser. Use this when the package's value is a UI element rather than a headless actor.

mx actor-element <name> — paired actor + element

The Matrix vertical-slice rule (CLAUDE.md Rule 2) says every user-facing function ships both a backend actor and a browser UI component. mx actor-element produces both in one package, wired so the element binds to the actor at mount time.

mx cqrs <name> — split command/query actors

Use mx cqrs for a package whose write surface and read surface should be different actors with different mounts. The scaffold places two actor classes under src/ and registers them in matrix.json as two separate components.

mx webapp <name> — full web app

Use mx webapp for a package whose primary surface is a Vite-built browser app with shell-style federation. Generates:

  • vite.config.ts for the build
  • index.html and src/ with the shell pattern
  • matrix.json with a webapp block
  • An appName slug derived from <name>

This is the most opinionated scaffold; expect to read its generated README to see the federation conventions used.

After the scaffold

  1. cd <name>
  2. Edit the generated source.
  3. pnpm install (the workspace already has all the deps).
  4. pnpm build (calls the package's own build script).
  5. pnpm test to verify the seed test passes.
  6. mx run . --env dev for the deployless inner loop.

See also

Source: projects/matrix-3/packages/mx-cli/src/commands/ contains the actor.ts, element.ts, actor-element.ts, cqrs.ts, webapp.ts, and init.ts implementations of each scaffold.