05 · NemoClaw — The Integration Layer (deep dive)
What lives in
NemoClaw/: NVIDIA's opinionated reference stack for running OpenClaw inside OpenShell. It doesn't reinvent either project — it's a CLI, a plugin, a versioned blueprint, and a set of YAML policies that wire them together the way NVIDIA recommends.
What NemoClaw actually is (concretely)
Four things:
| Piece | What it is | Where it lives |
|---|---|---|
nemoclaw CLI |
Host‑side binary. Primary entrypoint. Orchestrates OpenShell under the hood. | bin/, src/lib/ (TS, compiled to dist/) |
| NemoClaw plugin | A small TypeScript package loaded inside the sandbox alongside OpenClaw. Registers a custom inference provider and the /nemoclaw slash command. |
nemoclaw/src/ |
| Blueprint | A versioned, digest‑pinned YAML manifest describing which image, which policy, which inference profile, which NVIDIA model. This is the thing the plugin "runs". | nemoclaw-blueprint/blueprint.yaml |
| Network policies | The actual YAML enforced by OpenShell inside the sandbox. A base + presets per integration. | nemoclaw-blueprint/policies/ |
Rule of thumb: thin plugin, versioned blueprint. The CLI/plugin are stable and small; the interesting stuff (image digest, policy, inference profile) lives in the blueprint and evolves on its own cadence with digest verification.
The one‑minute tour
curl -fsSL https://www.nvidia.com/nemoclaw.sh | bash # installs Node via nvm + nemoclaw CLI
nemoclaw onboard # guided wizard
nemoclaw my-assistant connect # SSH into the sandbox
sandbox$ openclaw tui # you are now using OpenClaw
That's it. From the assistant's point of view, OpenClaw is just OpenClaw — same CLI, same sessions, same tools. From your point of view, everything is inside an OpenShell sandbox with policies applied.
What nemoclaw onboard actually does
This single command does a lot. Conceptually it walks the blueprint lifecycle:
resolve → verify digest → plan → apply → status
- Preflight — checks Docker is reachable, warns on Podman, installs Node if needed.
- Prompt for provider — NVIDIA Endpoints, OpenAI, Anthropic, Gemini, Ollama, or an OpenAI/Anthropic‑compatible endpoint. Validates the credential from the host before committing.
- Prompt for sandbox name (RFC 1123 subdomain rules:
my-assistant, notMy_Assistant). - Prompt for channels — e.g. Telegram (collects
TELEGRAM_BOT_TOKEN, allowed IDs), Discord (server ID, @mention vs all‑message, user allowlist). - Resolve the blueprint — downloads the blueprint artifact, checks
min_openshell_version/min_openclaw_version, verifies its digest. - Plan — decides which OpenShell resources to create or update: gateway, providers, sandbox, inference route, policy.
- Apply — calls the
openshellCLI under the hood:openshell gateway start(if needed)openshell provider createfor each credential (provider API key, channel tokens)openshell sandbox create --from <pinned digest>openshell policy setto push the NemoClaw policy (base + any selected presets)openshell inference setto routeinference.localto the chosen provider/model
- Bake host config — writes
~/.nemoclaw/credentials.json,~/.nemoclaw/sandboxes.json. - Install the plugin into the sandbox — so
/nemoclawworks from inside OpenClaw chat.
Running it again is idempotent and reproducible — that is the whole point of a digest‑pinned blueprint.
What the blueprint actually says
From nemoclaw-blueprint/blueprint.yaml:
version: "0.1.0"
min_openshell_version: "0.0.24"
min_openclaw_version: "2026.3.0"
digest: "sha256:b3d832b596ab6b7184a9dcb4ae93337ca32851a4f93b00765cc12de26baa3a9a"
profiles: [default, ncp, nim-local, vllm]
components:
sandbox:
image: "ghcr.io/nvidia/openshell-community/sandboxes/openclaw@sha256:b3d..."
name: "openclaw"
forward_ports: [18789] # ← OpenClaw Gateway WS
inference:
profiles:
default:
provider_type: "nvidia"
endpoint: "https://integrate.api.nvidia.com/v1"
model: "nvidia/nemotron-3-super-120b-a12b"
nim-local:
provider_type: "openai"
endpoint: "http://nim-service.local:8000/v1"
vllm:
endpoint: "http://localhost:8000/v1"
policy:
base: "sandboxes/openclaw/policy.yaml"
additions:
nim_service: { ... }
Key points:
- Image digest is pinned and mirrored at the top level so release tooling catches cases where someone bumps the image but forgets the blueprint (issue #1438).
forward_ports: [18789]— this is how OpenClaw's Gateway WebSocket becomes reachable from host tools even though it's running inside a sandbox.- Inference is a profile — NemoClaw lets you pick
default(NVIDIA Endpoints),ncp(NVIDIA Cloud Provider),nim-local(your own NIM container), orvllm(local vLLM). The sandbox always talks toinference.local; the profile decides where that routes.
What NemoClaw adds beyond "just use OpenShell's community sandbox"
OpenShell already ships a community sandbox: openshell sandbox create --from openclaw gives you a running OpenClaw with default isolation. NemoClaw layers on:
| Area | NemoClaw hardening |
|---|---|
| Filesystem | /sandbox (home) is read‑only. Gateway config /sandbox/.openclaw is immutable (auth tokens and CORS cannot be tampered with). Writable state is pinned to /sandbox/.openclaw-data, /sandbox/.nemoclaw, /tmp. Workdir auto‑grant is disabled. |
| Image | Strips gcc, g++, make, netcat from the runtime image to shrink attack surface. |
| Processes | ulimit -u 512 in the entrypoint to cap process count (anti fork‑bomb). |
| Credentials | Filters provider API keys, DISCORD_BOT_TOKEN, SLACK_BOT_TOKEN, TELEGRAM_BOT_TOKEN out of host env during sandbox creation so they can't leak via build args. They become OpenShell providers instead. |
| Sentry exfil | Blocks POST sentry.io/** entirely — Sentry is a multi‑tenant SaaS and any authed client can POST to any project, making a path‑based allowlist useless. Only GET stays open (issue #1437). |
| Blueprint | Version‑pinned, digest‑verified. Reproducible setup across machines. |
| State migration | Safe snapshot/restore with credential stripping and SSRF validation (see nemoclaw/src/blueprint/snapshot.ts, ssrf.ts). |
| Channel bridges | No separate host daemon. Tokens live in OpenShell providers; OpenClaw config holds placeholders; L7 proxy resolves them at egress (including Telegram's /bot<token>/ URL pattern). |
Host‑side state
NemoClaw keeps operator state on the host so sandboxes stay replaceable:
| Path | Purpose |
|---|---|
~/.nemoclaw/credentials.json |
Provider credentials from onboarding (plaintext, filesystem‑perm protected) |
~/.nemoclaw/sandboxes.json |
Registered sandbox metadata + default selection |
~/.openclaw/openclaw.json |
Host OpenClaw config that NemoClaw snapshots during migration flows |
For normal use you do not edit these by hand — rerun nemoclaw onboard.
Credential storage — what's actually on disk
~/.nemoclaw/credentials.json is plaintext JSON. NemoClaw does not encrypt it and does not integrate with the macOS Keychain or any OS secret store. What protects it is Unix file ownership and permissions:
~/.nemoclaw/is created with mode0700(directory accessible only to you)~/.nemoclaw/credentials.jsonis written with mode0600(file readable only by you)- NemoClaw refuses to use obviously unsafe
HOMEpaths like/tmp,/var/tmp,/dev/shm, or/and aborts onboarding rather than write secrets there
A typical file looks like:
{
"NVIDIA_API_KEY": "nvapi-...",
"OPENAI_API_KEY": "sk-...",
"GITHUB_TOKEN": "ghp_..."
}
Lookup precedence: when NemoClaw needs a credential, it checks environment variables first, then falls back to this file. This means NVIDIA_API_KEY=... nemoclaw onboard in a CI job skips the file entirely — use that for ephemeral automation.
Inspect: ls -ld ~/.nemoclaw ~/.nemoclaw/credentials.json should show drwx------ and -rw-------. If the perms drift, tighten with chmod 700 ~/.nemoclaw && chmod 600 ~/.nemoclaw/credentials.json.
Rotate / remove: the easiest rotation path is to rm -f ~/.nemoclaw/credentials.json (or nemoclaw credentials reset <KEY> to remove one entry) and rerun nemoclaw onboard. Do not copy this file into container images, git repos, bug reports, or nemoclaw debug output — treat it like any other local secret material.
The "do not fight the tooling" rule
The docs are blunt about this: for a NemoClaw‑managed environment, use nemoclaw onboard when you need to create or recreate the gateway or sandbox. Avoid:
openshell self-updateopenshell gateway start --recreateopenshell sandbox createdirectlynpm update -g openshell
…unless you intend to manage OpenShell independently and then re‑run nemoclaw onboard to put things back in a known state. The blueprint's job is to be the source of truth; sidestepping it breaks that.
Next: 06-openshell.md — the sandbox runtime NemoClaw sits on top of.