Skip to content

Runtime entrypoints

The runtime entry tells the runner which compiled file to load. The matrix.service.json factory tells the runner which exported function to call once the file is loaded. Together they define how a package becomes a process.

runtime block in matrix.json

json
{
  "runtime": {
    "language": "typescript",
    "entry": "dist/index.js"
  }
}

Required fields:

FieldPurpose
languageThe source language; the validator only checks that it is non-empty (typescript and javascript are the values seen in the live tree)
entryThe relative path inside the package that the runtime imports

Optional fields used by hybrid packages:

FieldPurposeUsed by
browserEntryPath to the compiled browser entry (custom-element registration)Hybrid packages whose actors run in the browser tab
bootstrapEntryPath to the browser bootstrap that connects same-origin NATS-WSHybrid packages
environmentsAllowed run environments (browser, headless-dom, runtime)Documents intent; not enforced by the validator
executionClassCompatibilityAllowed execution classes (shared_host_service, dedicated_process, container, isolate, remote_managed_service)Documents intent; not enforced

Real example, from packages/chat/matrix.json:

json
"runtime": {
  "language": "typescript",
  "entry": "./dist/runtime/index.js",
  "browserEntry": "./dist/browser/register-elements.js",
  "bootstrapEntry": "./dist/browser/bootstrap.js",
  "environments": ["browser", "headless-dom", "runtime"],
  "executionClassCompatibility": [
    "shared_host_service", "dedicated_process",
    "container", "isolate", "remote_managed_service"
  ]
}

Publish-time validation

mx publish runs ensurePublishPreflight (packages/mx-cli/src/commands/publish.ts:49-86) which:

  1. Validates matrix.json against the CLI validator.
  2. Asserts runtime.entry is a non-empty string (MX_MANIFEST_INVALID: runtime.entry is required).
  3. Asserts the file at runtime.entry exists on disk (MX_MANIFEST_INVALID: runtime.entry does not exist (...)).
  4. If a webapp block is declared, asserts the entry HTML exists under webapp.distDir.
  5. Asserts the package declares at least one of: a root actor, a component, a webapp, or a matrix.service.json factory.

In other words: a publishable package always has a real runtime.entry file in dist/. Run pnpm build first.

matrix.service.json — the factory contract

Optional, but required if the package is to be started as a service runtime (rather than as a pure library or pure web app). The shape (packages/mx-cli/src/utils/service-manifest.ts:25-56):

json
{
  "kind": "factory",
  "export": "createStandaloneSystem",
  "instance": {
    "id": "RUNTIME-HOST-SYSTEM",
    "class": "service",
    "rootKind": "package-root",
    "mount": "system",
    "autoStart": true
  },
  "bootstrap": {
    "overrides": { "mode": "standalone-local" }
  }
}

Required fields:

FieldPurpose
kindAlways "factory" today
exportThe named export of runtime.entry to call
instance.idStable runtime id (used in system.runtimes)
instance.classRuntime class label, e.g. "service"
instance.rootKind"package-root" is the live value

Optional bootstrap envelope replaces deprecated top-level overrides/root/transport/auth/http/mount fields. New packages must use bootstrap.*; the deprecated names exist only as back-compat aliases inside the loader.

What the runtime does at startup

mx run . (packages/mx-cli/src/commands/run.ts:251-302) for a package with matrix.service.json:

  1. Loads matrix.service.json and the loaded service manifest.
  2. Loads .matrix/<env>.environment.json.
  3. Imports runtime.entry and resolves export (the factory function).
  4. Calls the factory with a ServiceContext that includes the runtime, environment, root, and overrides.
  5. The factory mounts actors against the bus and returns.

For packages without matrix.service.json but with a webapp block, mx run . --serve runs in standalone webapp mode: it does not call a service factory; instead it mounts a MatrixHttpAssetEndpointActor that serves webapp.distDir/webapp.entry.

Three concrete factory examples

json
// packages/system/matrix.service.json
{
  "kind": "factory",
  "export": "createStandaloneSystem",
  "instance": { "id": "RUNTIME-HOST-SYSTEM", "class": "service",
    "rootKind": "package-root", "mount": "system", "autoStart": true }
}
json
// packages/system-gateway-http/matrix.service.json
{
  "kind": "factory",
  "export": "createStandaloneHttpGateway",
  "instance": { "id": "RUNTIME-HOST-GATEWAY", "class": "service",
    "rootKind": "package-root", "autoStart": true }
}
json
// packages/chat/matrix.service.json
{
  "kind": "factory",
  "export": "createHostManagedChat",
  "instance": { "id": "RUNTIME-HOST-CHAT", "class": "service",
    "rootKind": "package-root", "mount": "chat", "autoStart": true },
  "bootstrap": { "overrides": { "mode": "standalone-local" } }
}

See also

Source: projects/matrix-3/packages/mx-cli/src/utils/service-manifest.ts defines the manifest shape; packages/mx-cli/src/commands/run.ts is the live runner; packages/mx-cli/src/commands/publish.ts is the publish-time gatekeeper.