Skip to content

Package manifest

matrix.json is the contract between a package and the rest of the system. Host Service, the runner, the gateway, the launcher, the catalog, and hivecast doctor all read it. This page documents every field that is actually wired up today, with cross-references to the running examples in the tree.

Status: target state — single-source matrix.json ships in v1. Today many packages still carry both matrix.json and a sibling matrix.service.json; mx-cli reads matrix.service.json for bootstrap (factory export, root mount), and the package's factory function hardcodes child mount paths in source. The manifest reconciliation in P1.41 absorbs matrix.service.json into matrix.json and moves per-component mount paths into the manifest as relativeMount declarations. The full v1 manifest also gains the runtime.isolation / instance.{defaultMount,factory,singleton} shape from P1.40. Both target-state shapes are documented below alongside what's wired today; pages and call sites use the current shape until the migration lands.

Top-level shape (current)

json
{
  "name": "@open-matrix/<package-name>",
  "version": "0.1.0",
  "description": "...",
  "class": "hybrid",
  "namespace": "...",
  "root": { ... },
  "runtime": { ... },
  "webapp": { ... },
  "components": [ ... ],
  "consumes": [ ... ],
  "config": { ... },
  "permissions": { ... }
}

Target shape (v1, P1.40 + P1.41)

json
{
  "name": "@open-matrix/<package-name>",
  "version": "0.1.0",
  "description": "...",
  "runtime": {
    "language": "typescript",
    "entry": "./dist/runtime/index.js",
    "isolation": "shared"
  },
  "instance": {
    "defaultMount": "chat",
    "factory": "createChatInstance",
    "singleton": false,
    "autoStart": true
  },
  "components": [
    { "type": "ChatRoot", "export": "ChatRootActor", "relativeMount": "" },
    { "type": "ChatPreferences", "export": "ChatPreferencesProxy", "relativeMount": "preferences" }
  ],
  "webapp": { ... },
  "service": { "description": "...", "intentFilters": [ ... ] },
  "permissions": { "fsPolicy": "scoped" },
  "storage": { "stateDir": "<instance-state-dir>/sessions" },
  "state": { "shape": "session-store-v1" }
}

The differences from the current shape:

  • runtime.isolationshared / process / worker / vm. Default when absent is process. The runtime honours the declaration; multiple shared-declared packages can co-tenant in one runtime (P1.40).
  • instance.{defaultMount,factory,singleton} — describes how a DeploymentInstance is created. defaultMount is the root mount when no --instance-name is supplied; factory is the export the runtime calls; singleton is enforced at deploy time (P1.40 / P1.42).
  • components[].relativeMount — every component declares its mount relative to the instance root. relativeMount: "" is the root actor; relativeMount: "preferences" lives at <instance-mount>.preferences. The factory function no longer hardcodes mount paths; it receives a componentMounts map at deploy time (P1.41).
  • matrix.service.json is absorbed and removed. v1 has one manifest file (P1.41).

Not every field is required. The minimum manifest is name + version + at least one of runtime.entry, webapp, or components[]. The richest examples in the tree are chat (hybrid) and director (webapp-only).

Required fields

name

The package name. Must match package.json's name. Convention: @open-matrix/<short-name> for first-party packages, @<vendor>/<name> for third-party.

version

Semver string. Used by system.runtimes and system.catalog to track installed versions.

description

Short human-readable description. Surfaced in hivecast runtimes, the launcher, the catalog, and $introspect.

Runtime block — what to load

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"
  ]
}
FieldWhat it doesRequired?
languageSource language. typescript or javascript.Yes when runtime is present
entryPath the runner imports for headless-side actors. For webapp-only packages this can point at dist/index.html (a sentinel meaning "no JS entry").Yes
browserEntryJS module loaded by the served HTML for component registration.Only when shipping browser components
bootstrapEntryJS module loaded first by the served HTML; sets up transport, host element, root mount.Only when shipping browser components
environmentsWhich environments this package is valid in: browser, headless-dom, runtime. Discovery hint.Optional
executionClassCompatibilityWhich Host execution classes can run this package: shared_host_service, dedicated_process, container, isolate, remote_managed_service. Discovery hint for placement.Optional

The simplest possible runtime block (used by director, flowpad, inference-settings):

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

For these webapp-only packages, entry: "dist/index.html" is a sentinel — the runner sees no JS to import; only the gateway serves the HTML.

Webapp block — when the package has a UI

json
"webapp": {
  "distDir": "./dist/browser",
  "entry": "index.html",
  "appName": "chat",
  "displayName": "Chat",
  "icon": "💬",
  "navOrder": 30,
  "description": "Conversation and agent workspace",
  "shells": ["platform", "edge"],
  "base": "relative",
  "routePrefix": "/apps/chat"
}
FieldMeaning
distDirDirectory served by the gateway. Relative to package root.
entryHTML file inside distDir. Default route serves this.
appNameURL-safe slug. The package is reachable at /apps/<appName>/ (or routePrefix if explicit).
displayNameHuman-readable name shown in the launcher.
iconEmoji or short string for the launcher.
navOrderSort key in the launcher (lower first).
descriptionTooltip / launcher description.
shellsArray of "platform" (matrix-web), "edge" (matrix-edge), or both. Determines which shell lists this app.
baseSet to "relative" to use relative paths in built assets (works behind any prefix).
routePrefixOptional explicit route. Default is /apps/<appName>.

Components block — headless actors

json
"components": [
  {
    "type": "ChatConversationProxy",
    "export": "ChatConversationProxy",
    "mount": "conversation",
    "surface": "headless",
    "autoStart": true
  }
]

Each entry tells the runner: "import the export from runtime.entry, instantiate it, mount it at <package-namespace>.<mount>, and bring it up at startup if autoStart is true."

FieldMeaning
typeClass name (informational; aids debugging).
exportNamed export to import from runtime.entry.
mountMount path under the package namespace.
surfaceheadless (Node-only) or browser (registered as a custom element).
autoStartWhether the runner instantiates this on package boot. Default true is the convention; set false for opt-in actors.

Top-level root — webapp root component

json
"root": {
  "type": "MatrixChatApp",
  "export": "MatrixChatApp",
  "mount": "chat",
  "surface": "browser"
}

Declares the top-level UI component the bootstrap mounts. Only used when the package has a UI bootstrap that defers to a manifest-declared root rather than hard-coding it.

Consumes block — required cross-package contracts

json
"consumes": [
  { "contract": "IChatConversationService", "required": true, "bindingKey": "conversation-service" },
  { "contract": "IChatIdentityService", "required": false, "bindingKey": "identity-service" }
]

Discovery hint for the runtime supervisor: "this package needs an actor implementing IChatConversationService." The supervisor refuses to start the package if required: true contracts cannot be resolved (this is enforcement when the supervisor implements it; today it is largely advisory).

Config block — see Package config contract

json
"config": {
  "schema": "./config/config.schema.json",
  "defaults": "./config/config.defaults.json",
  "envPrefix": "MATRIX_CHAT_",
  "providers": [
    { "kind": "env", "prefix": "MATRIX_CHAT_" },
    { "kind": "file", "env": "MATRIX_CHAT_CONFIG_FILE", "optional": true },
    { "kind": "service", "service": "system.config", "namespace": "@open-matrix/chat", "optional": true }
  ]
}

Detailed on the next page.

Permissions block

json
"permissions": {
  "fsPolicy": "none",
  "network": true,
  "subprocess": false,
  "env": false
}
FieldMeaning
fsPolicy"none", "read", "read-write", or a more granular policy. Required.
networkWhether the package may open outbound network connections.
subprocessWhether the package may spawn child processes.
envWhether the package may read process env vars beyond the configured prefix.

The SDK does not enforce these flags at runtime today — they are declarative for the supervisor. Browser-side packages still execute under the browser sandbox regardless.

class and namespace

json
"class": "hybrid",
"namespace": "chat"

class is one of webapp, headless, or hybrid — informational for tooling (e.g. the launcher decides whether to show a tile). namespace is the bus-namespace prefix the package's components mount under (chat.conversation, chat.security-realm, etc.).

Worked examples

Minimal webapp (projects/matrix-3/packages/director/matrix.json)

json
{
  "name": "@open-matrix/director",
  "version": "0.1.28",
  "description": "Director — Matrix actor hierarchy explorer",
  "runtime": { "language": "typescript", "entry": "dist/index.html" },
  "webapp": {
    "distDir": "dist", "entry": "index.html",
    "appName": "director", "displayName": "Director",
    "icon": "🧭", "navOrder": 20,
    "description": "Matrix actor hierarchy explorer",
    "shells": ["platform", "edge"]
  },
  "components": [],
  "permissions": { "fsPolicy": "none" }
}

Hybrid (projects/matrix-3/packages/chat/matrix.json)

See the Component packaging page for the full chat manifest, which uses every category of field.

See also

Source: projects/matrix-3/packages/{chat,director,flowpad,inference-settings,smithers}/matrix.json (canonical examples).