Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ci/platform-matrix.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"status": "tested",
"prd_priority": "P0",
"ci_tested": true,
"notes": "Primary tested path. Ubuntu 24.04 is the validated distro in production source (`DEFAULT_COMPAT_IMAGE` in `src/lib/onboard/docker-driver-gateway-compat.ts:11` and the preflight tests pin 24.04 only); the installer's package-manager probes assume apt-get. Other distros (Ubuntu 22.04, Fedora, Rocky, Alma, NixOS, Arch) may work but are not validated."
"notes": "Primary tested path. Ubuntu 24.04 is the validated distro in production source (`DEFAULT_COMPAT_IMAGE` in `src/lib/onboard/docker-driver-gateway-compat.ts:16` and the preflight tests pin 24.04 only); the installer's package-manager probes assume apt-get. Other distros (Ubuntu 22.04, Fedora, Rocky, Alma, NixOS, Arch) may work but are not validated."
},
{
"name": "macOS (Apple Silicon)",
Expand Down
2 changes: 1 addition & 1 deletion docs/get-started/prerequisites.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ The table comes from [`ci/platform-matrix.json`](https://github.com/NVIDIA/NemoC
{/* platform-matrix:begin */}
| OS | Container runtime | Status | Notes |
|----|-------------------|--------|-------|
| Linux | Docker | Tested | Primary tested path. Ubuntu 24.04 is the validated distro in production source (`DEFAULT_COMPAT_IMAGE` in `src/lib/onboard/docker-driver-gateway-compat.ts:11` and the preflight tests pin 24.04 only); the installer's package-manager probes assume apt-get. Other distros (Ubuntu 22.04, Fedora, Rocky, Alma, NixOS, Arch) may work but are not validated. |
| Linux | Docker | Tested | Primary tested path. Ubuntu 24.04 is the validated distro in production source (`DEFAULT_COMPAT_IMAGE` in `src/lib/onboard/docker-driver-gateway-compat.ts:16` and the preflight tests pin 24.04 only); the installer's package-manager probes assume apt-get. Other distros (Ubuntu 22.04, Fedora, Rocky, Alma, NixOS, Arch) may work but are not validated. |
| macOS (Apple Silicon) | Colima, Docker Desktop | Tested with limitations | Start the container runtime (Colima or Docker Desktop) before running the installer. Homebrew Colima users must install both Colima and the Docker CLI (`brew install colima docker`) before `docker info` can work. Xcode Command Line Tools (`xcode-select --install`) are typically required for Node native modules during install. NemoClaw recommends them but does not enforce them during preflight. |
| DGX Spark | Docker | Tested | Use the standard installer and `$$nemoclaw onboard`. For an end-to-end walkthrough with local inference, see the [NVIDIA Spark playbook](https://build.nvidia.com/spark/nemoclaw). |
| Windows WSL2 | Docker Desktop (WSL backend) | Tested with limitations | Requires WSL2 with Docker Desktop backend. |
Expand Down
1 change: 1 addition & 0 deletions docs/get-started/quickstart.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ At any prompt, press Enter to accept the default shown in `[brackets]`, type `ba
If registered sandboxes already exist, the installer prepares the current NemoClaw CLI without replacing OpenShell, then requires a fresh backup of every registered sandbox before it changes the gateway.
After the host upgrade, it runs `nemoclaw upgrade-sandboxes --auto` to rebuild stale sandboxes and restore validated backups for registered sandboxes that are not Ready.
Successful recovery completes the existing-sandbox upgrade and skips generic onboarding, so the installer does not create an extra sandbox or ask for a new provider credential.
If the recovery pass exits 0 but a recorded sandbox is not found on its own recorded gateway (for example after `nemoclaw uninstall` removed the gateway and Docker image while preserving `sandboxes.json`), the installer finishes with `Installation completed with warnings` and remediation guidance instead of claiming the sandbox was recovered.
For pre-fingerprint OpenClaw and Hermes registry entries, the installer asks you to confirm that every listed sandbox used a NemoClaw-managed image before it permits recovery onto the current managed image.
In non-interactive runs, set `NEMOCLAW_CONFIRM_LEGACY_MANAGED_RECREATE` to the exact JSON array of names printed by the installer, such as `["my-assistant","preserve-hermes"]`, only after you verify every named sandbox used a managed image.
Legacy managed-image confirmation never overrides recorded custom-image evidence.
Expand Down
2 changes: 2 additions & 0 deletions docs/manage-sandboxes/lifecycle.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ In a non-interactive run, set `NEMOCLAW_CONFIRM_LEGACY_MANAGED_RECREATE` to the
Legacy managed-image confirmation never overrides recorded custom-image evidence.
A custom OpenClaw sandbox can be recovered only when the selected validated backup independently carries complete authoritative image-plugin provenance; otherwise recovery stops before deletion.
The installer attempts every eligible recovery, exits with a nonzero status if any recovery fails, and skips generic onboarding after successful recovery.
A third outcome exists: when a recorded sandbox is not observed in any phase on its own recorded gateway (typically because a prior uninstall removed the gateway and Docker image while preserving `sandboxes.json`), the recovery pass exits 0 but reports the sandbox as not found rather than recovered, and the installer finishes with `Installation completed with warnings` plus remediation guidance (`$$nemoclaw <name> destroy`, then `$$nemoclaw onboard`) instead of claiming success.
For manual upgrade flows, create a snapshot first and then run the update or rebuild command you need:

```bash
Expand Down Expand Up @@ -421,6 +422,7 @@ For non-interactive runs (`--yes`, `NEMOCLAW_NON_INTERACTIVE=1`, or a non-TTY sh
`--yes` stays non-destructive by design.
It only acknowledges the global confirmation prompt and never purges preserved user data on its own.
Full purge always requires an explicit `--destroy-user-data` or the matching env var, so existing automation using `--yes` retains its safe behaviour.
Preserving `sandboxes.json` does not preserve the gateway registration, provider registrations, or Docker image its recorded sandboxes depend on; uninstall warns that those records cannot be recovered automatically on reinstall, and the remediation is `$$nemoclaw <name> destroy` followed by `$$nemoclaw onboard`.
For a full host-side file reference, see [Host Files and State](../reference/host-files-and-state).
Refer to the [Commands reference](../reference/commands#$$nemoclaw-uninstall) for the full preservation contract.
</Note>
Expand Down
7 changes: 7 additions & 0 deletions docs/reference/commands.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2412,8 +2412,10 @@ NemoClaw resolves the digest of `ghcr.io/nvidia/nemoclaw/sandbox-base:latest` fr
Sandboxes that match the current digest are left alone.
NemoClaw also checks the build fingerprint recorded on each managed sandbox image.
A sandbox needs upgrade when its agent version is stale, when its recorded NemoClaw image fingerprint differs from the running CLI, or both.
When the target version is older than the recorded one (for example after reinstalling with an older `NEMOCLAW_INSTALL_TAG`), the stale listing marks the change with a `(downgrade)` suffix instead of framing it as a routine upgrade.
Custom Dockerfile sandboxes are not classified by image drift because rebuilding them onto the default image would drop the custom image.
Legacy sandboxes without a recorded fingerprint opt into this check after their next rebuild.
A recorded sandbox that is not observed in any phase on its own recorded gateway is reported as not found there, with remediation guidance — this typically means its gateway registration or Docker image was removed (for example by `$$nemoclaw uninstall`, which preserves `sandboxes.json` but removes both).

```bash
$$nemoclaw upgrade-sandboxes [--check] [--auto] [--yes|-y]
Expand Down Expand Up @@ -2965,6 +2967,11 @@ Decision matrix:
The preserved entries survive uninstall as inert files on disk.
Reinstall NemoClaw and re-onboard the sandbox before `$$nemoclaw <name> snapshot restore` can use them.

Preserving `sandboxes.json` does not make the recorded sandboxes recoverable on their own: uninstall removes the gateway registration, provider registrations, and Docker image those records depend on.
Uninstall warns about this at preserve time.
After reinstalling, the installer reports such records as not found on their recorded gateway instead of claiming they were recovered; run `$$nemoclaw <name> destroy` to clear a stranded record, then `$$nemoclaw onboard` to rebuild it.
Pass `--destroy-user-data` at uninstall time if you prefer to purge the registry along with its dependencies.

#### `$$nemoclaw uninstall` vs. the hosted `uninstall.sh`

Both forms execute the same `uninstall.sh` with the same flags, but differ in where the script comes from and how much they trust the network.
Expand Down
1 change: 1 addition & 0 deletions docs/reference/host-files-and-state.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ If you see `registry.json` in older tests, notes, or discussions, treat it as le

`$$nemoclaw uninstall --yes` removes active NemoClaw runtime resources but preserves the user data needed for recovery by default.
Preserved entries include `rebuild-backups/`, `backups/`, and `sandboxes.json`.
Preserved `sandboxes.json` records are not automatically recoverable after reinstall, because uninstall removes the gateway registration, provider registrations, and Docker image they reference; uninstall warns about this at preserve time, and a later reinstall reports such records as not found on their recorded gateway with `$$nemoclaw <name> destroy` / `$$nemoclaw onboard` remediation.
Interactive uninstall prompts before removing preserved state.
For non-interactive runs, pass `--destroy-user-data` only when you accept losing local registry metadata and backups.

Expand Down
2 changes: 1 addition & 1 deletion docs/reference/platform-support.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ For the onboarding-time supported set without deferred rows, refer to [Prerequis
{/* platform-matrix-full:begin */}
| OS | Container runtime | Status | PRD priority | CI | Notes |
|----|-------------------|--------|--------------|----|-------|
| Linux | Docker | Tested | P0 | Yes | Primary tested path. Ubuntu 24.04 is the validated distro in production source (`DEFAULT_COMPAT_IMAGE` in `src/lib/onboard/docker-driver-gateway-compat.ts:11` and the preflight tests pin 24.04 only); the installer's package-manager probes assume apt-get. Other distros (Ubuntu 22.04, Fedora, Rocky, Alma, NixOS, Arch) may work but are not validated. |
| Linux | Docker | Tested | P0 | Yes | Primary tested path. Ubuntu 24.04 is the validated distro in production source (`DEFAULT_COMPAT_IMAGE` in `src/lib/onboard/docker-driver-gateway-compat.ts:16` and the preflight tests pin 24.04 only); the installer's package-manager probes assume apt-get. Other distros (Ubuntu 22.04, Fedora, Rocky, Alma, NixOS, Arch) may work but are not validated. |
| macOS (Apple Silicon) | Colima, Docker Desktop | Tested with limitations | P0 | Yes | Start the container runtime (Colima or Docker Desktop) before running the installer. Homebrew Colima users must install both Colima and the Docker CLI (`brew install colima docker`) before `docker info` can work. Xcode Command Line Tools (`xcode-select --install`) are typically required for Node native modules during install. NemoClaw recommends them but does not enforce them during preflight. |
| DGX Spark | Docker | Tested | P1 | Yes | Use the standard installer and `$$nemoclaw onboard`. For an end-to-end walkthrough with local inference, see the [NVIDIA Spark playbook](https://build.nvidia.com/spark/nemoclaw). |
| Windows WSL2 | Docker Desktop (WSL backend) | Tested with limitations | P1 | No | Requires WSL2 with Docker Desktop backend. |
Expand Down
71 changes: 66 additions & 5 deletions scripts/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -536,23 +536,41 @@ print_done() {
# #5735: do not claim a clean install when the automatic upgrade of a
# pre-existing sandbox failed (it may have been destroyed before its recreate
# failed). Surface an explicit incomplete/recovery status instead.
# #6520: same when recovery exited 0 but recorded sandboxes were not found
# on their own recorded gateway — they were not recovered, so the install is
# not clean either.
if [[ "${_UPGRADE_SANDBOXES_FAILED:-false}" == true ]]; then
warn "=== Installation completed with warnings ==="
elif [[ "${_PREEXISTING_SANDBOX_ORPHANED:-false}" == true ]]; then
warn "=== Installation completed with warnings ==="
else
info "=== Installation complete ==="
fi
printf "\n"
printf " ${C_GREEN}${C_BOLD}%s${C_RESET} ${C_DIM}(%ss)${C_RESET}\n" "$_CLI_DISPLAY" "$elapsed"
printf "\n"
if [[ "${_PREEXISTING_SANDBOX_RECOVERY_RAN:-false}" == true ]]; then
printf " ${C_GREEN}Existing sandboxes were recovered and upgraded.${C_RESET}\n"
if [[ "${_PREEXISTING_SANDBOX_ORPHANED:-false}" == true ]]; then
# #6520: recovery exited 0 but recorded sandboxes were not found on
# their own recorded gateway; do not report them as recovered, and give
# a concrete remediation path instead.
printf " ${C_YELLOW}Some recorded sandboxes were not found on their recorded gateway and were not recovered.${C_RESET}\n"
printf " ${C_YELLOW}Their gateway registration or Docker image may have been removed (see the recovery notes above).${C_RESET}\n"
printf " ${C_DIM}Clear a stranded sandbox with '%s <name> destroy', then rebuild it with '%s onboard'.${C_RESET}\n" "$_CLI_BIN" "$_CLI_BIN"
else
printf " ${C_GREEN}Existing sandboxes were recovered and upgraded.${C_RESET}\n"
fi
if [[ "$_needs_cli_refresh" == true ]]; then
printf " ${C_YELLOW}%s installed, but this shell needs PATH refresh before '%s' will run.${C_RESET}\n" "$_CLI_DISPLAY" "$_CLI_BIN"
printf "\n"
printf " ${C_GREEN}For this terminal:${C_RESET}\n"
print_cli_path_refresh_actions
fi
printf " ${C_DIM}No new sandbox onboarding was needed.${C_RESET}\n"
if [[ "${_PREEXISTING_SANDBOX_ORPHANED:-false}" == true ]]; then
printf " ${C_DIM}Generic onboarding was skipped because recorded sandboxes exist.${C_RESET}\n"
else
printf " ${C_DIM}No new sandbox onboarding was needed.${C_RESET}\n"
fi
elif [[ "$ONBOARD_RAN" == true ]]; then
local agent_name
agent_name="$(resolve_onboarded_agent)"
Expand Down Expand Up @@ -925,6 +943,11 @@ ONBOARD_RAN=false
_CLI_PATH=""
_PREEXISTING_SANDBOX_COUNT=0
_PREEXISTING_SANDBOX_RECOVERY_RAN=false
# #6520: set when the automatic recovery pass exited 0 but skipped recorded
# sandboxes it could not observe on the selected gateway (e.g. their gateway
# and Docker image were removed by a prior uninstall while sandboxes.json was
# preserved). The final summary must not claim those sandboxes were recovered.
_PREEXISTING_SANDBOX_ORPHANED=false
_LEGACY_MANAGED_RECOVERY_NAMES_JSON="[]"
# #5735: set when automatic recovery/upgrade of pre-existing sandboxes
# reported a failure. A failed/destructive rebuild must not be reported as a
Expand Down Expand Up @@ -2262,12 +2285,45 @@ recover_preexisting_sandboxes_before_onboard() {
# pre-upgrade backup signal is present, the CLI also recovers registered
# non-Ready sandboxes from their validated latest backup. It attempts every
# eligible sandbox before returning non-zero for any failure.
if NEMOCLAW_CONFIRMED_LEGACY_MANAGED_SANDBOXES="${_LEGACY_MANAGED_RECOVERY_NAMES_JSON:-[]}" \
"$cli_runner" upgrade-sandboxes --auto 2>&1; then
#
# #6520: mirror the CLI output into a temp log (while still streaming it) so
# the installer can tell "recovered" apart from "exited 0 but recorded
# sandboxes are unrecoverable" — e.g. after `nemoclaw uninstall` removed the
# gateway and Docker image a preserved sandboxes.json still references. The
# CLI emits a dedicated orphan marker only for sandboxes absent from their
# own recorded gateway (never for sandboxes bound to another live gateway or
# ones that reconnect mid-run); keep the grep in sync with the "recorded
# sandbox(es) were not found on their recorded gateway" line in
# src/lib/actions/upgrade-sandboxes.ts.
local recovery_log=""
recovery_log="$(mktemp "${TMPDIR:-/tmp}/nemoclaw-recovery-XXXXXX" 2>/dev/null)" || recovery_log=""
local recovery_status=0
if [ -n "$recovery_log" ]; then
_cleanup_files+=("$recovery_log")
if NEMOCLAW_CONFIRMED_LEGACY_MANAGED_SANDBOXES="${_LEGACY_MANAGED_RECOVERY_NAMES_JSON:-[]}" \
"$cli_runner" upgrade-sandboxes --auto 2>&1 | tee "$recovery_log"; then
recovery_status=0
else
# pipefail: take the CLI's own status, not tee's — a log-write failure
# (e.g. ENOSPC on TMPDIR) must not convert a successful recovery into
# the #5735 failure path.
recovery_status=${PIPESTATUS[0]}
fi
else
NEMOCLAW_CONFIRMED_LEGACY_MANAGED_SANDBOXES="${_LEGACY_MANAGED_RECOVERY_NAMES_JSON:-[]}" \
"$cli_runner" upgrade-sandboxes --auto 2>&1 || recovery_status=$?
fi
if [ "$recovery_status" -eq 0 ]; then
_PREEXISTING_SANDBOX_RECOVERY_RAN=true
if [ -n "$recovery_log" ] \
&& grep -Fq "recorded sandbox(es) were not found on their recorded gateway" "$recovery_log"; then
_PREEXISTING_SANDBOX_ORPHANED=true
fi
rm -f "$recovery_log" 2>/dev/null || true
return 0
fi

rm -f "$recovery_log" 2>/dev/null || true
_UPGRADE_SANDBOXES_FAILED=true
warn "One or more existing sandboxes could not be recovered automatically."
warn "Generic onboarding will not run; review the affected sandbox and preserved backup diagnostics above."
Expand Down Expand Up @@ -2858,7 +2914,12 @@ main() {
return 1
fi
if [[ "${_PREEXISTING_SANDBOX_RECOVERY_RAN:-false}" == true ]]; then
info "Existing sandboxes recovered; skipping generic onboarding."
if [[ "${_PREEXISTING_SANDBOX_ORPHANED:-false}" == true ]]; then
# #6520: do not claim recovery when recorded sandboxes are stranded.
warn "Some recorded sandboxes could not be recovered; skipping generic onboarding."
else
info "Existing sandboxes recovered; skipping generic onboarding."
fi
else
run_onboard || error "Onboarding did not complete successfully."
ONBOARD_RAN=true
Expand Down
Loading
Loading