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
11 changes: 11 additions & 0 deletions docs/manage-sandboxes/lifecycle.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,17 @@ When a maintained NemoClaw release becomes available, update the `nemoclaw` CLI
When a maintained NemoClaw release becomes available, update the `nemohermes` CLI on your host and check existing sandboxes for stale agent/runtime versions.
</AgentOnly>
The standard installer follows the admin-promoted `lkg` release tag by default, so it can trail the newest semver or `latest` tag while validation completes.
To pin a specific release in a `curl | bash` install, set `NEMOCLAW_INSTALL_TAG` on the `bash` side of the pipe, or export it before the pipeline:

```bash
curl -fsSL https://www.nvidia.com/nemoclaw.sh | NEMOCLAW_INSTALL_TAG=v0.0.56 bash
# or
export NEMOCLAW_INSTALL_TAG=v0.0.56
curl -fsSL https://www.nvidia.com/nemoclaw.sh | bash
```

Do not place `NEMOCLAW_INSTALL_TAG=...` only before `curl`; shell assignment in that position applies to `curl`, not to the installer running under `bash`.
If the requested ref cannot be fetched, the installer exits with a clear error instead of falling back to `lkg`.

### Update the NemoClaw CLI

Expand Down
8 changes: 7 additions & 1 deletion install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,11 @@ clone_nemoclaw_ref() {

git init --quiet "$dest"
git -C "$dest" remote add origin https://github.com/NVIDIA/NemoClaw.git
git -C "$dest" fetch --quiet --depth 1 origin "$ref"
if ! git -C "$dest" fetch --quiet --depth 1 origin "$ref"; then
printf "[ERROR] Requested install ref '%s' is not available from https://github.com/NVIDIA/NemoClaw.git.\n" "$ref" >&2
printf " Check NEMOCLAW_INSTALL_TAG/NEMOCLAW_INSTALL_REF and try again.\n" >&2
exit 1
fi
git -C "$dest" -c advice.detachedHead=false checkout --quiet --detach FETCH_HEAD
}

Expand Down Expand Up @@ -115,6 +119,8 @@ bootstrap_usage() {
printf " Environment:\n"
printf " NEMOCLAW_INSTALL_REF Exact Git ref/SHA to install\n"
printf " NEMOCLAW_INSTALL_TAG Git ref to install (default: lkg)\n"
printf " In curl pipes, set this on bash or export it first.\n"
printf " Example: curl -fsSL https://www.nvidia.com/nemoclaw.sh | NEMOCLAW_INSTALL_TAG=v0.0.56 bash\n"
printf " NEMOCLAW_NON_INTERACTIVE=1 Same as --non-interactive\n"
printf " NEMOCLAW_FRESH=1 Same as --fresh\n"
printf " NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 Same as --yes-i-accept-third-party-software\n"
Expand Down
9 changes: 7 additions & 2 deletions scripts/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,9 @@ clone_nemoclaw_ref() {

git init --quiet "$dest"
git -C "$dest" remote add origin https://github.com/NVIDIA/NemoClaw.git
git -C "$dest" fetch --quiet --depth 1 origin "$ref"
if ! git -C "$dest" fetch --quiet --depth 1 origin "$ref"; then
error "Requested install ref '$ref' is not available from https://github.com/NVIDIA/NemoClaw.git. Check NEMOCLAW_INSTALL_TAG/NEMOCLAW_INSTALL_REF and try again."
fi
git -C "$dest" -c advice.detachedHead=false checkout --quiet --detach FETCH_HEAD
}

Expand Down Expand Up @@ -552,7 +554,10 @@ usage() {
printf " NEMOCLAW_OPENSHELL_UPGRADE_PREPARED=1\n"
printf " Continue after manually backing up and retiring old gateway\n"
printf " NEMOCLAW_RECREATE_SANDBOX=1 Recreate an existing sandbox\n"
printf " NEMOCLAW_INSTALL_TAG Git ref to install (default: lkg)\n"
printf " NEMOCLAW_INSTALL_TAG Git ref to install (default: lkg)\n"
printf " In curl pipes, set this on bash or export it first.\n"
printf " Example: curl -fsSL https://www.nvidia.com/nemoclaw.sh | NEMOCLAW_INSTALL_TAG=v0.0.56 bash\n"
printf " NEMOCLAW_INSTALL_REF Exact Git ref/SHA to install\n"
printf " NEMOCLAW_PROVIDER build | openai | anthropic | anthropicCompatible\n"
printf " | gemini | ollama | custom | nim-local | vllm | routed\n"
printf " | hermes-provider\n"
Expand Down
53 changes: 51 additions & 2 deletions test/install-preflight.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2885,8 +2885,11 @@ describe("installer flag parsing", () => {
});

expect(result.status).toBe(0);
expect(`${result.stdout}${result.stderr}`).toMatch(/NEMOCLAW_INSTALL_TAG/);
expect(`${result.stdout}${result.stderr}`).toMatch(/default: lkg/);
const output = `${result.stdout}${result.stderr}`;
expect(output).toMatch(/NEMOCLAW_INSTALL_TAG/);
expect(output).toMatch(/default: lkg/);
expect(output).toMatch(/set this on bash or export it first/);
expect(output).toMatch(/curl .* \| NEMOCLAW_INSTALL_TAG=v0\.0\.56 bash/);
});
});

Expand Down Expand Up @@ -3698,6 +3701,52 @@ main() {
expect(`${result.stdout}${result.stderr}`).not.toMatch(/LOCAL_PAYLOAD_USED/);
});

it("piped root installer fails clearly when the selected ref is unavailable", () => {
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-curl-pipe-missing-ref-"));
const fakeBin = path.join(tmp, "bin");
const gitLog = path.join(tmp, "git.log");
fs.mkdirSync(fakeBin);
writeExecutable(
path.join(fakeBin, "git"),
`#!/usr/bin/env bash
printf '%s\\n' "$*" >> "$GIT_LOG_PATH"
if [ "$1" = "init" ]; then
target="\${@: -1}"
mkdir -p "$target"
exit 0
fi
if [ "\${1:-}" = "-C" ]; then
shift 2
fi
if [ "$1" = "remote" ]; then exit 0; fi
if [ "$1" = "fetch" ]; then
echo "fatal: couldn't find remote ref \${@: -1}" >&2
exit 128
fi
exit 0`,
);

const installerInput = fs.readFileSync(CURL_PIPE_INSTALLER, "utf-8");
const result = spawnSync("bash", [], {
cwd: tmp,
input: installerInput,
encoding: "utf-8",
env: {
...process.env,
HOME: tmp,
PATH: `${fakeBin}:${TEST_SYSTEM_PATH}`,
GIT_LOG_PATH: gitLog,
NEMOCLAW_INSTALL_TAG: "v9.9.9",
},
});

const output = `${result.stdout}${result.stderr}`;
expect(result.status).not.toBe(0);
expect(output).toMatch(/Requested install ref 'v9\.9\.9' is not available/);
expect(output).toMatch(/Check NEMOCLAW_INSTALL_TAG\/NEMOCLAW_INSTALL_REF/);
expect(fs.readFileSync(gitLog, "utf-8")).toMatch(/fetch --quiet --depth 1 origin v9\.9\.9/);
});

it("falls back to the legacy root installer when the selected ref only has the old scripts/install.sh wrapper", () => {
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-curl-pipe-legacy-ref-"));
const legacyLog = path.join(tmp, "legacy.log");
Expand Down
Loading