Extensions

Install and Manage Extensions

Learn where a self-hosted instance loads extensions from, and how to install, reload, update, and remove them.
Preview
Extensions are in preview and can change in breaking ways between releases. Use them in non-production environments only. See Stability. Written for Monospace 1.0.0, @monospace/cli 0.2 and @monospace/extension-kit 0.3.

Overview

Monospace is self-hosted. Installing an extension means placing its built directory in your instance's install location, the directory Engine scans for extensions. An instance is a running Monospace deployment. There is no install API, no upload in Studio, and no marketplace.

Installing, reloading, updating, and removing work the same way for every extension, whatever its entry types. Every installed extension is available to every workspace on the instance. What an entry type needs after installation is covered in its own section. For data connector extensions, see Manage Data Sources.

Choose the Install Location

Engine reads extensions from the directory in MONOSPACE_EXTENSIONS__INSTALL_LOCATION. The default is ./extensions, resolved against Engine's working directory.

VariableDefaultEffect
MONOSPACE_EXTENSIONS__INSTALL_LOCATION./extensionsDirectory Engine scans for installed extensions
MONOSPACE_EXTENSIONS__AUTO_RELOADfalseWatches the install location and reloads changed extensions without a restart

Each subdirectory of the install location that contains a manifest.json is one installed extension. The CLI names it <namespace>__<name> after the extension id, but Engine reads the id from the manifest, not the directory name:

extensions/
extensions/
└── example__artic/
    ├── manifest.json
    └── example/
        └── artic-connector.js
RuleBehavior
Missing or unreadable install locationEngine starts with no extensions installed and logs that none were loaded
Subdirectory with an invalid manifestSkipped with a warning. Other extensions still load
Two subdirectories with the same extension idThe first in sorted directory order loads; the other is skipped
Two extensions with the same entry idThe entry from the first extension in sorted directory order loads. The later extension loads without that entry, and Engine logs skipping provider declared in installed bundle
Symlinked subdirectoryNot loaded. Place a real directory in the install location

See Extension Config and Manifest for the layout rules.

Run Monospace in Docker

The Monospace image runs Engine from /monospace, so the default install location inside the container is /monospace/extensions. The quick-start compose file mounts the named volume extensions_data there, which keeps installed extensions across restarts. To install extensions you build on this machine, replace that volume with a bind mount of a host directory.

Create the directory next to your docker-compose.yaml first:

terminal
mkdir extensions

Creating it yourself makes your user its owner, instead of leaving it to Docker. A CLI run without write access to the install location fails: with extension.install_dir_unusable when it can't inspect or create the install directory, and with extension.install_failed when copying the build into it fails.

In the monospace service, swap the named volume for the bind mount the quick-start file lists, and uncomment automatic reloading:

docker-compose.yaml
  monospace:
    volumes:
      - keys_data:/keys:ro
      - uploads_data:/monospace/uploads
      # - extensions_data:/monospace/extensions
      - ./extensions:/monospace/extensions
    environment:
      MONOSPACE_EXTENSIONS__AUTO_RELOAD: "true"
SettingWhy
./extensions:/monospace/extensionsPoint monospace extension build --install-to at ./extensions on the host, and Engine sees the build in its install location
Readable filesThe container runs as user 65532, so that user must be able to read every file and enter every directory (e.g., 644 files and 755 directories)
MONOSPACE_EXTENSIONS__AUTO_RELOADLoads new and changed extensions without restarting the container

Restart the stack with docker compose up -d to apply the change. On macOS, changes made on the host through a bind mount can miss the container. If a new install doesn't load, run docker compose restart monospace.

Reload Extensions Automatically

Engine scans the install location once at startup. With MONOSPACE_EXTENSIONS__AUTO_RELOAD set to true, it also watches the location and rescans once changed files have been quiet for 500 ms.

At startup, Engine logs watching installed bundles directory for changes when the watcher runs. The install location must exist when Engine starts. If it doesn't, Engine logs failed to watch installed bundles directory; bundle hot reloading is inactive, and only a restart picks up extensions.

The CLI's install summary ends with Restart the engine to load it, unless it runs with MONOSPACE_EXTENSIONS__AUTO_RELOAD=true. With automatic reloading on, no restart is needed, except after a data connector build that changes its query capabilities. See Update an Extension.

Install an Extension

Build the extension and install it in one step with --install-to, from the extension project's root:

npm run build -- --install-to ../monospace/extensions

The build script is the one monospace extension create scaffolds; it runs monospace extension build. ../monospace/extensions is the install location on the host, here the directory mounted into the container. The CLI writes the build to <install-to>/<namespace>__<name>/ and replaces a previous install of the same extension whole. See Install a Build for the rules.

To install an extension someone else built, copy its directory (the one containing manifest.json) into the install location.

Check the Install

At startup, Engine logs loaded installed bundle with the extension id for each extension it loads. With automatic reloading on, it logs bundle installed when a new extension appears and bundle changed; restarting its data sources when an installed one changes. It logs skipping installed bundle with the reason when the manifest is invalid. These logs confirm the manifest and file layout; the extension's code first runs when it's used.

For data connectors, check that each entry loaded with List Installed Data Connectors, or in Studio as described in Find Extensions in Studio.

Find Extensions in Studio

Studio lists installed extensions with no setting to turn on. Each list shows an extension's name and id, then each of its entries, such as example/artic-connector marked Data Connector:

WhereWhat it lists
Workspace Settings > ExtensionsThe extensions available to the workspace
Organization > Extensions in the settings dialog, opened from your avatarEvery extension installed in the organization

Both pages are marked Preview, and each requires the extension read entitlement. Workspace Settings checks the workspace entitlement, which the built-in Studio Access policy includes. The settings dialog checks the organization entitlement. Data connectors also appear when you add a data source: Data Model > Add Source lists each one, marked Extension. See Add a Data Source in Studio.

If a new install is missing from these lists, Engine hasn't loaded it. See Check the Install.

Update an Extension

Install the new build over the old one. The CLI replaces the extension's directory whole. When you copy files by hand, replace the directory rather than merging into it.

With automatic reloading on, Engine picks up the new build once its files stop changing. Without automatic reloading, restart the instance. If the new build's manifest is invalid, Engine treats the extension as removed; see Install Directory Layout.

For data connectors, an update can require changes to existing data sources. With automatic reloading on, a build that changes an entry's query capabilities deactivates the entry's existing data sources until a restart or a workspace rebuild. See Update Data Sources After an Extension Update.

Remove an Extension

Delete the extension's directory from the install location. Without automatic reloading, restart the instance so Engine drops it from the installed extensions.

For data connectors, delete the data sources that use the extension first. See Before You Remove an Extension.

Limits of Self-Hosted Installs

Not availableInstead
Install API or Studio uploadPlace the built directory in the install location
Marketplace or registryDistribute the built directory yourself
Two versions of one extension side by sideOne directory per extension id. A second directory with the same id is skipped
Per-workspace installsEvery extension in the install location is available to every workspace

See Also

MonospaceThe governed API layer for every app, person, and agent.

Copyright © 2026 Monospace Inc.