Install OpenClaw Plugins

View as Markdown

This is a source-based workaround until the managed plugin lifecycle in issue #5998 is available. It requires a source checkout and base image that exactly match your installed NemoClaw CLI.

The example below targets NemoClaw v0.0.71 and its pinned OpenClaw 2026.5.27 runtime. For another release, replace every v0.0.71 occurrence and use the OpenClaw version pinned by that release wherever this example uses 2026.5.27.

OpenClaw plugins extend the OpenClaw runtime with hooks, services, tools, or provider integrations. They are different from NemoClaw-managed agent skills:

  • Plugins are code packages loaded by OpenClaw.
  • Skills are SKILL.md directories that teach an agent how to perform a task.
  • Policy presets are network-egress rules that control what sandboxed code can reach.

Until NemoClaw provides that managed lifecycle, bake the plugin into a version-matched full NemoClaw runtime image.

Understand the Custom Image Contract

The --from option supplies the complete sandbox image definition. It does not add your Dockerfile as a layer on top of NemoClaw’s normal managed runtime.

Do not start a custom OpenClaw image from ghcr.io/nvidia/nemoclaw/sandbox-base alone. That intermediate image contains Node.js, OpenClaw, and other runtime dependencies, but it does not contain nemoclaw-start, the generated openclaw.json, or the managed gateway health check.

A sandbox created from the base image alone can report a successful create while the gateway and dashboard remain unavailable.

nemoclaw onboard --from <Dockerfile> uses the Dockerfile’s parent directory as its Docker build context. The workaround therefore starts with the complete source context for the installed NemoClaw release.

For a first-class add, list, status, and remove lifecycle that does not require a source checkout, follow issue #5998.

Prepare a Version-Matched Build Context

Use the same NemoClaw release for the installed CLI, source checkout, and sandbox-base image. The following commands reproduce the workflow for NemoClaw v0.0.71, which includes OpenClaw 2026.5.27.

$nemoclaw --version
$git clone --depth 1 --branch v0.0.71 https://github.com/NVIDIA/NemoClaw.git my-plugin-sandbox
$cp -R /path/to/my-plugin ./my-plugin-sandbox/my-plugin
$cd my-plugin-sandbox

For a different release, replace v0.0.71 everywhere in this workflow and start from that release’s stock Dockerfile. Do not reuse this patch across releases because the managed image contract can change.

The plugin directory must contain the inputs used by its build, including its manifest and dependency lockfile. This example expects the following files:

my-plugin/
├── openclaw.plugin.json
├── package-lock.json
├── package.json
├── src/
└── tsconfig.json

The example Dockerfile uses npm ci, so my-plugin/ must include package-lock.json. If your plugin does not have a lockfile yet, create one in the plugin project with npm install --package-lock-only.

OpenClaw 2026.5.27 also requires the plugin manifest to declare each registered tool in contracts.tools; for example, a weather plugin that registers get_weather must declare "tools": ["get_weather"].

Declare OpenClaw as both a runtime peer and an exact, release-matched development dependency. The peer range expresses runtime compatibility, while the development dependency provides the plugin SDK during the build:

1{
2 "devDependencies": {
3 "openclaw": "2026.5.27"
4 },
5 "peerDependencies": {
6 "openclaw": ">=2026.5.17"
7 }
8}

With current npm versions, npm ci installs peer dependencies automatically. The build stage below therefore omits both development and peer dependencies after compilation so the staged plugin does not carry a private OpenClaw runtime.

Extend the Full Managed Dockerfile

Make two changes to the stock Dockerfile from the v0.0.71 checkout. First, pin the base image to the same release.

1-ARG BASE_IMAGE=ghcr.io/nvidia/nemoclaw/sandbox-base:latest
2+ARG BASE_IMAGE=ghcr.io/nvidia/nemoclaw/sandbox-base:v0.0.71

Next, name the completed runtime stage so the plugin layer can extend it.

1-FROM ${BASE_IMAGE}
2+FROM ${BASE_IMAGE} AS nemoclaw-runtime

Append the following stages to the end of the stock Dockerfile. Replace weather with the plugin ID from openclaw.plugin.json in the stage name, staging directory, and OpenClaw plugin commands.

1# Build the plugin from its lockfile.
2FROM builder AS weather-plugin-builder
3WORKDIR /opt/my-plugin
4COPY my-plugin/package.json my-plugin/package-lock.json my-plugin/tsconfig.json ./
5RUN npm ci --ignore-scripts --no-audit --no-fund
6COPY my-plugin/openclaw.plugin.json ./
7COPY my-plugin/src/ ./src/
8RUN npm run build \
9 && npm prune --omit=dev --omit=peer --ignore-scripts --no-audit --no-fund \
10 && test ! -e node_modules/openclaw
11
12# Extend the completed managed runtime.
13FROM nemoclaw-runtime AS weather-runtime
14ARG NEMOCLAW_TOOL_DISCLOSURE=progressive
15ENV NEMOCLAW_TOOL_DISCLOSURE=${NEMOCLAW_TOOL_DISCLOSURE}
16COPY --from=weather-plugin-builder --chown=sandbox:sandbox \
17 /opt/my-plugin/package.json \
18 /opt/my-plugin/package-lock.json \
19 /opt/my-plugin/openclaw.plugin.json \
20 /opt/weather-plugin/
21COPY --from=weather-plugin-builder --chown=sandbox:sandbox \
22 /opt/my-plugin/dist/ /opt/weather-plugin/dist/
23COPY --from=weather-plugin-builder --chown=sandbox:sandbox \
24 /opt/my-plugin/node_modules/ /opt/weather-plugin/node_modules/
25
26USER sandbox
27RUN test ! -e /opt/weather-plugin/node_modules/openclaw \
28 && HOME=/sandbox openclaw plugins install /opt/weather-plugin \
29 && test -L /sandbox/.openclaw/extensions/weather/node_modules/openclaw \
30 && test "$(realpath /sandbox/.openclaw/extensions/weather/node_modules/openclaw)" = /usr/local/lib/node_modules/openclaw \
31 && HOME=/sandbox openclaw plugins enable weather \
32 && HOME=/sandbox openclaw plugins inspect weather --json > /dev/null
33
34# Enabling the plugin changes openclaw.json after the managed runtime hashes it.
35# hadolint ignore=DL3002
36USER root
37RUN chown sandbox:sandbox /sandbox/.openclaw/openclaw.json \
38 && chmod 660 /sandbox/.openclaw/openclaw.json \
39 && sha256sum /sandbox/.openclaw/openclaw.json > /sandbox/.openclaw/.config-hash \
40 && chown sandbox:sandbox /sandbox/.openclaw/.config-hash \
41 && chmod 660 /sandbox/.openclaw/.config-hash

The final stage inherits the stock runtime entrypoint, command, gateway health check, generated configuration, and file permissions. It redeclares and promotes the tool-disclosure build argument because Docker build arguments are scoped to a stage and the appended plugin stage becomes the final image stage.

The local install copies the staged plugin into OpenClaw’s extensions tree, records the install, links it to the image’s OpenClaw runtime, and leaves existing managed plugin load paths intact before the explicit enable and inspect steps. The pre-install test commands fail the image build if npm retained a private node_modules/openclaw directory that would prevent OpenClaw from creating its runtime link.

The post-install checks then prove that OpenClaw created the link and that it resolves to the image’s global runtime. The last RUN refreshes the managed config hash after openclaw plugins enable updates openclaw.json.

Create and Verify the Sandbox

Pin NemoClaw’s base-image resolver to the same release when you onboard.

$NEMOCLAW_SANDBOX_BASE_IMAGE_REF=ghcr.io/nvidia/nemoclaw/sandbox-base:v0.0.71 \
> nemoclaw onboard \
> --fresh \
> --no-gpu \
> --name weather-agent \
> --from "$PWD/Dockerfile"

Verify the managed runtime and plugin after onboarding completes.

$nemoclaw weather-agent status
$nemoclaw weather-agent exec -- test -s /tmp/gateway.log
$nemoclaw weather-agent exec -- env HOME=/sandbox openclaw plugins inspect weather --runtime --json
$nemoclaw weather-agent exec -- bash -lc \
> '. /tmp/nemoclaw-proxy-env.sh && printf "header = \"Authorization: Bearer %s\"\n" "$OPENCLAW_GATEWAY_TOKEN" | curl --noproxy "*" --max-time 30 --silent --show-error --fail-with-body --config - -H "Content-Type: application/json" --data "{\"agentId\":\"main\",\"tool\":\"get_weather\",\"args\":{\"location\":\"Santa Clara\"}}" "http://127.0.0.1:${OPENCLAW_GATEWAY_PORT:-18789}/tools/invoke"'

The plugin inspection must report the loaded weather plugin and list get_weather in toolNames. The authenticated HTTP invocation must return the deterministic Santa Clara weather result.

The piped curl config keeps the managed gateway token out of process arguments. NemoClaw’s live regression also verifies that the running gateway’s tool catalog contains get_weather.

Keep the source checkout and Dockerfile at the recorded path if you plan to run nemoclaw weather-agent rebuild --yes. This source-based workflow can reproduce the plugin during that rebuild, but it is not the durable managed-plugin lifecycle proposed in issue #5998.

The provenance safeguards below start in NemoClaw v0.0.76. The v0.0.71 worked example demonstrates custom-image construction but does not provide these lifecycle guards. To rely on them, use NemoClaw v0.0.76 or later and match its CLI, source checkout, base image, and pinned OpenClaw version.

Preserve Plugin Provenance During Rebuild

Starting with v0.0.76, custom-image onboarding records validated plugin IDs and canonical install paths from OpenClaw’s install index. It derives direct extension-directory ownership from those paths and records exact configured load paths owned by linked path installs.

Use openclaw plugins install as shown above; manually copied, unregistered extension directories are outside this provenance contract. During rebuild or warm recreation, the new image remains authoritative for those image-owned plugins: updated plugins keep the fresh image copy, removed plugins stay removed, and renamed plugins do not restore their old IDs.

NemoClaw continues to restore backup-only user plugins and their configuration.

Validate Replacement Images

Before rebuild or the default state-preserving warm recreation path deletes an existing custom-image sandbox, NemoClaw requires complete, validated provenance from the registry or selected backup. If that previous provenance is missing or invalid, the operation stops with the existing sandbox and backup untouched.

Setting NEMOCLAW_RECREATE_WITHOUT_BACKUP=1 deliberately bypasses the warm-recreation backup and provenance guard; use it only after making an independent backup and accepting loss of the current sandbox state. After initial onboarding or replacement creation, NemoClaw validates the fresh image again before it restores state or publishes registry metadata.

If fresh discovery or restore-time reconciliation fails, NemoClaw does not publish the fresh replacement metadata. Direct onboarding or recreation leaves the created sandbox unregistered; rebuild preserves the backup, restores retry metadata, and prints manual recovery commands.

Preserve any reported backup, then inspect and remove an unregistered sandbox with OpenShell before you retry the original onboarding command. If the fresh image itself fails validation, correct its plugin install records or linked load paths before you retry onboarding.

Migrate Older Custom Images

Custom-image sandboxes created before v0.0.76 cannot enter the state-preserving path automatically when they lack recorded provenance. Keep the older sandbox intact, onboard the current release under a different name, and migrate its state manually.

Maintain the Plugin Image

Rerun the plugin inspection and HTTP invocation after a gateway restart or sandbox rebuild to verify that the plugin remains available.

If the plugin imports runtime packages, keep those packages in dependencies rather than devDependencies so the prune step preserves them. Keep openclaw in the release-matched peer and development dependency fields shown above; do not move it to dependencies.

If the plugin needs configuration in openclaw.json, apply it before refreshing .config-hash.

Never bake plugin credentials into the Dockerfile or openclaw.json. Use OpenShell credential providers for secrets.

Build Performance

Custom plugin images are normal Docker builds, so build time depends on the build context size and the Docker layer cache rather than on NemoClaw. NemoClaw sends user-supplied --from contexts to the OpenShell gateway builder and reserves its host-side local BuildKit prebuild for contexts that NemoClaw generates itself.

On a local Docker-driver gateway, a Local BuildKit build skipped notice is expected and the custom image build continues through the gateway.

Keep the Dockerfile at the release checkout root because the full managed image copies repository scripts, blueprint files, and the built-in NemoClaw plugin. Use the checkout’s .dockerignore, and do not place unrelated datasets, model files, caches, or credentials under that directory.

NemoClaw also applies secret-safety exclusions for credential-like paths such as .env*, .ssh/, .aws/, .npmrc, secrets/, *.pem, and *.key.

Distinguish cold builds from warm rebuilds. The first build on a fresh host is a cold build that downloads the base image and package indexes, so it is the slowest run. Later warm rebuilds reuse cached layers when the base image and earlier layers are unchanged.

Order Dockerfile instructions from least-changing to most-changing so warm rebuilds reuse cached dependency layers:

  1. Base image.
  2. System package installs.
  3. Dependency manifests such as package.json and package-lock.json.
  4. Dependency install such as npm ci.
  5. Application source.

Pin the base image to an explicit tag or digest so warm rebuilds resolve the same cached base instead of pulling a new one.

When a build is slow, set NEMOCLAW_TRACE=1 before onboarding to capture phase timings that separate context staging, Docker build, image upload, and sandbox readiness. For the full --from build-context rules and trace details, refer to CLI Commands Reference.

Network Access

Plugins still run inside the sandbox policy boundary. If a plugin needs network egress, add or update a policy preset for the required hostnames and binaries before rebuilding the sandbox.

For policy concepts, refer to Network Policies. For custom preset workflows, refer to Customize Network Policy.

Common Mistakes

The following mistakes commonly mix plugin installation with other NemoClaw extension paths.

  • Do not use nemoclaw <sandbox> skill install for OpenClaw plugins. That command only installs SKILL.md agent skills.
  • Do not use sandbox-base as the final custom image. It is an intermediate dependency image.
  • Do not combine one NemoClaw release’s Dockerfile with another release’s base image.
  • Do not copy a plugin into /sandbox/.openclaw/extensions/<id> and then run plugins install --link on that same path. Stage it outside the managed extensions directory and use the local install shown above.
  • Do not move or delete the recorded source checkout before rebuilding the sandbox.
  • Do not rely on .dockerignore to include credential-like paths; NemoClaw excludes those from staged custom build contexts for safety.
  • Keep plugin dependencies in the build stage or plugin directory, and avoid copying unrelated host files into the sandbox image.

Next Steps