Skip to content

Installed source

"Installed source" is the opposite of folder-backed. The runtime loads code from a copy under the Host's package store, separate from your repo checkout. This is what production looks like; it's also what mx install and hivecast install produce.

Where installed packages live

mx install resolves the package store from the current Host home and writes packages under node_modules/:

<MATRIX_HOME>/
├── host.json
├── packages/
│   ├── system/
│   │   └── node_modules/
│   │       ├── @open-matrix/
│   │       │   ├── system/
│   │       │   ├── system-gateway-http/
│   │       │   ├── host-control/
│   │       │   └── ...
│   └── global/
│       └── node_modules/
│           ├── @open-matrix/
│           │   ├── chat/
│           │   ├── director/
│           │   └── ...
└── ...

packages/system/ holds packages the Host needs to function (the "system" set). packages/global/ holds user-installable packages (chat, director, flowpad, smithers, etc.). Both stores are populated on first install.

hivecast install seeds both (packages/hivecast/bin/hivecast.mjs:205-216):

ts
function seedBundledHostPackages(matrixHome) {
  const systemNodeModules = join(matrixHome, "packages", "system", "node_modules");
  const globalNodeModules = join(matrixHome, "packages", "global", "node_modules");
  for (const packageName of listBundledPackageNames()) {
    copyBundledPackageToStore(packageName, systemNodeModules);
    copyBundledPackageToStore(packageName, globalNodeModules);
  }
}

How a runtime resolves an installed package

Host Service up accepts either a directory path or a package name (packages/host-service/src/cli.ts:resolvePackageTarget):

  • Directory path → folder-backed (see Folder-backed source).
  • Package name → look it up in the global store, then the system store. If found, that directory is the packageDir.
bash
matrix up @open-matrix/chat --home /tmp/matrix-home
# resolves to /tmp/matrix-home/packages/global/node_modules/@open-matrix/chat

The runtime record under <host-home>/runtimes/<runtimeId>.json captures the resolved absolute path.

Two ways to populate installed source

  1. From the registry (production):

    bash
    matrix install @open-matrix/chat --home /tmp/matrix-home

    Downloads the published tarball from the configured npm-compatible registry and writes it into the package store. See Installing → Install from registry.

  2. From a local folder (development):

    bash
    matrix install /abs/path/to/projects/matrix-3/packages/<my-pkg> \
      --home /tmp/matrix-home --force

    Copies the local folder into the package store. Same end state — the runtime sees an installed copy, not your live source. See Installing → Install from local folder.

Why use installed source over folder-backed?

Use installed source whenUse folder-backed when
Verifying behavior of the published artifactIterating on source
Running install lifecycle hooks (validate, migrate, seed, verify)Iterating on source
Testing dependency resolution (the package's package.json:dependencies)Iterating on source
Producing a Host that mirrors production layout for screenshots / reproducible bug reportsIterating on source

Iteration cost

Folder-backed: edit → pnpm build → restart. ~1 second.

Installed source: edit → pnpm buildhivecast operator refresh-host-package --package @open-matrix/<my-pkg> --home <home> --restart → runtime restart. Several seconds. Use this only when the install path matters.

Removing an installed package

bash
matrix uninstall @open-matrix/chat --home /tmp/matrix-home

Source: packages/mx-cli/src/commands/uninstall.ts. Removes the package directory from <host-home>/packages/global/node_modules/. Does not touch runtime records — hivecast down first if a runtime is supervising it.

See also

Source: projects/matrix-3/packages/mx-cli/src/commands/install.ts writes packages into the store; packages/hivecast/bin/hivecast.mjs:205-216 seeds the bundled set on first install.