Appearance
Dependency graph
Matrix package dependencies are normal npm dependencies. The Matrix-specific twist is the two parallel stores the Host maintains: a system store and a global store, both populated at install time.
Two parallel stores
hivecast install (seedBundledHostPackages in projects/matrix-3/packages/hivecast/bin/hivecast.mjs) writes every bundled package to both:
<host-home>/packages/system/node_modules/@open-matrix/...
<host-home>/packages/global/node_modules/@open-matrix/...Why two:
| Store | Purpose |
|---|---|
system/ | Packages the system runtime can mount during early bootstrap, before any other runtime is up. Read-only from a runtime's perspective. |
global/ | Packages available to user-installed runtimes via matrix up @open-matrix/foo. Writable: mx install adds packages here. |
The system store is fixed at install time and refreshed by hivecast seed. The global store may be modified at runtime through subsequent installs.
Normal npm dependency resolution
Within either store, npm resolution is standard. A package's package.json declares dependencies; pnpm install (or npm install) inside the store resolves and writes a lockfile. No Matrix-side custom resolver.
When a package depends on another @open-matrix/* package, the dependency is resolved through the configured registry for the @open-matrix scope (registry.hivecast.ai for cloud, the local store for offline).
Cross-package mount visibility
Important distinction: dependency satisfaction is independent of mount visibility.
@open-matrix/chat depends on @open-matrix/core
↓
npm install resolves
↓
<host-home>/packages/global/node_modules/@open-matrix/chat
<host-home>/packages/global/node_modules/@open-matrix/core
↓
chat runtime starts (matrix up @open-matrix/chat)
↓
ChatActor mounts at "chat"
(CoreActor mounts only if @open-matrix/core declares an autoStart component)Installing a dependency does not auto-mount its actors. Mounting requires:
- The dependency package declares components in its
matrix.jsonwithautoStart: true, AND - Some runtime is started that loads that package as its entrypoint.
A purely-library dependency (no components[]) is never visible in system.registry.
Bundled vs. installed dependencies
Some Matrix packages bundle their dependencies to avoid resolution at install time on the consumer side:
| Approach | Used when |
|---|---|
| Plain dependency | Most packages — reduce duplicate disk usage. |
Bundled (bundleDependencies) | The hivecast wrapper bundles every Matrix package it ships into its own dist/node_modules/. This is what makes a fresh hivecast install work without network access. |
The hivecast wrapper's dist/node_modules/ is the source for seedBundledHostPackages; whatever is bundled there ends up in the local package stores.
Peer dependencies
Standard npm peers apply. Peers are commonly used in Matrix to declare compatibility with @open-matrix/core without forcing a specific version:
json
{
"peerDependencies": {
"@open-matrix/core": "^1"
}
}The consumer must install a satisfying @open-matrix/core version themselves. The bundled store usually has one already.
Diamond dependencies
If two packages both depend on @open-matrix/core at compatible ranges, npm/pnpm resolves to a single shared install. If the ranges are incompatible, npm/pnpm puts the conflicting version in a nested node_modules/:
node_modules/
├── @open-matrix/foo/ (depends on @open-matrix/core@^1)
├── @open-matrix/bar/
│ └── node_modules/@open-matrix/core/ (depends on @open-matrix/core@^2 — separate copy)
└── @open-matrix/core/ (resolved version, satisfies foo)Two copies of @open-matrix/core in the same Host means two distinct module identities. Actors from the inner copy do not share class identity with actors from the outer copy. This can break instanceof checks. Avoid it: keep Matrix package versions aligned.
See also
Source:
projects/matrix-3/packages/hivecast/bin/hivecast.mjs:205-233. Standard npm/pnpm semantics for everything else.