Skip to content

What is a Runtime Host?

In docker-for-actors terms, the Host is the substrate's docker-engine. It does five things:

  1. Owns one local NATS bus (either a sibling nats-server it manages, or a pre-existing external NATS at a configured URL).
  2. Spawns runtimes as child processes. A runtime is a Node process that hosts one or more Matrix packages — a substrate for actors, not "the runtime for one specific package."
  3. Records their lifecycle in <host-home>/runtimes/<id>/runtime.json files so they survive Host restarts.
  4. Recovers auto-start runtimes after a Host crash, including parse-and-skip over corrupt records.
  5. Exposes a control interface over NATS (host.control mailbox) and over a CLI (matrix status, matrix runtimes, matrix up, matrix down).

The implementation is MatrixHostService in projects/matrix-3/packages/host-service/src/matrix-host-service.ts. The public CLI is projects/matrix-3/packages/host-service/src/cli.ts.

Multi-package runtimes (target shape)

A package's matrix.json declares an isolation level; the Host honors it when accepting deployments:

runtime.isolationWhat it isWhen to useCost
sharedCo-tenanted in any compatible runtime; one Node process, one V8 heapTrusted first-party; control-plane services; lightweight utilities~free per additional package
processOwn Node process; no co-tenancyUntrusted third-party; native deps; independent crash domain~50-100 MB per package
workerNode worker thread inside a host runtime; separate V8 isolate, shared OS processSemi-trusted; CPU-bound work~5-15 MB + startup latency
vmvm.runInContext sandbox in same process; same heap, separated globalThisTrusted-but-buggy; limit blast-radius; not a security boundarymarginal

Default when absent: process (preserves today's one-package-per-runtime behavior; no breaking change).

Status: target state — ships with P1.40-a. Today the codebase implements one package per runtime. The substrate target shape is multi-package runtimes per P1.40. When P1.40-a lands, default-runtime grouping co-tenants shared packages by substrate role (CONTROL-PLANE, USER-APPS); a fresh Host comes up with ~4 runtimes instead of 12.

What a Host does NOT do

The Host is intentionally narrow. The full constraint set lives in projects/matrix-3/packages/docs/content/architecture/host-service-boundary-rule.md.

The Host does NOTWhyWhere it lives instead
Instantiate MatrixActor or MatrixRuntime in its own processIsolation. One bad actor cannot crash the supervisor.inside spawned runtime processes
Implement HTTP, REST, or browser routingHTTP is one transport, not a Host concern.@open-matrix/system-gateway-http
Implement OAuth, sessions, or device approvalAuth is product policy, not supervision.@open-matrix/system-auth
Render UISupervisors do not have UIs.@open-matrix/matrix-web, @open-matrix/matrix-edge
Hold credentials beyond the local NATS handshakeFactotum (system.factotum) owns credentials.system.factotum package
Know about specific packages by nameGeneric. The Host does not import chat, director, etc.the supervised package itself
Serve inventory questions over HTTPInventory is bus authority.system.runtimes, system.registry, system.devices

A Host that grows any of these duties is broken. The hivecast.deb installer and the default hivecast install set ship the gateway, auth, web, and edge packages as supervised runtimes; they are not part of the Host.

What a Host owns

A Host owns the contents of its home directory, which defaults to ~/.matrix on Linux and macOS, %USERPROFILE%\.matrix on Windows, or /var/lib/hivecast on a .deb-installed Linux service. See Filesystem layout for the complete inventory. Quick map:

<host-home>/
  host.json                         host config (single source of truth)
  host.status.json                  current Host status (atomic-written)
  host.pid                          supervisor pid
  runtimes/<id>/runtime.json        per-runtime durable record
  runtime-env/<id>.environment.json per-runtime env file (transport, mounts)
  logs/                             host stdout/stderr + nats logs
  logs/runtimes/<id>/{stdout,stderr}.log
  packages/system/node_modules/     system package store (seeded)
  packages/global/node_modules/     user-installed package store
  bin/nats-server[.exe]             bundled NATS binary
  nats/host-default/                JetStream data dir + nats-server.conf
  credentials/hivecast-install.json install identity (always present)
  credentials/hivecast-link.json    Device Link record (only when linked)
  instances/<instanceId>/           per-DeploymentInstance state directory
                                    (target state — P1.42)

Status: target state — instances/<instanceId>/ directory. Today instance state collides under runtimes/<runtimeId>/ because each runtime hosts one package. P1.42 introduces DeploymentInstance as a first-class registry citizen with its own state dir. See P1.42.

A minimal Host run

bash
node projects/matrix-3/packages/host-service/dist/cli.js init    --home /tmp/h
node projects/matrix-3/packages/host-service/dist/cli.js start   --home /tmp/h --port 0
node projects/matrix-3/packages/host-service/dist/cli.js status  --home /tmp/h
node projects/matrix-3/packages/host-service/dist/cli.js runtimes --home /tmp/h
node projects/matrix-3/packages/host-service/dist/cli.js stop    --home /tmp/h

In production this is wrapped by hivecast install / hivecast start / hivecast stop, which additionally seeds the system package store, supervises NATS as an independent sibling process, and starts the default runtime set (see projects/matrix-3/packages/hivecast/bin/hivecast.mjs:28-39).

See also

Source: the boundary rule is the architectural constraint; the code is the truth. See host-service-boundary-rule.md and matrix-host-service.ts:58-1056.