-
Notifications
You must be signed in to change notification settings - Fork 3.1k
fix(onboard): ensure nemoclaw CLI is on PATH after nvm-based install #4191
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,170 +2,173 @@ | |||||||||||||||||||||||||||||||||
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||||||||||||||||||||||||||||||||||
| # SPDX-License-Identifier: Apache-2.0 | ||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||
| # Thin bootstrap for the NemoClaw installer. | ||||||||||||||||||||||||||||||||||
| # Public curl|bash installs should select a ref once, clone that ref, then | ||||||||||||||||||||||||||||||||||
| # execute installer logic from that same clone. Historical tags that predate | ||||||||||||||||||||||||||||||||||
| # the extracted payload fall back to their own root install.sh. | ||||||||||||||||||||||||||||||||||
| # NemoClaw installer — installs Node.js, Ollama (if GPU present), and NemoClaw. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| set -euo pipefail | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if [[ -n "${BASH_SOURCE[0]:-}" ]]; then | ||||||||||||||||||||||||||||||||||
| SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||
| SCRIPT_DIR="" | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
| LOCAL_PAYLOAD="${SCRIPT_DIR:+${SCRIPT_DIR}/scripts/install.sh}" | ||||||||||||||||||||||||||||||||||
| BOOTSTRAP_TMPDIR="" | ||||||||||||||||||||||||||||||||||
| PAYLOAD_MARKER="NEMOCLAW_VERSIONED_INSTALLER_PAYLOAD=1" | ||||||||||||||||||||||||||||||||||
| DEFAULT_INSTALL_REF="lkg" | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| resolve_release_tag() { | ||||||||||||||||||||||||||||||||||
| if [[ -n "${NEMOCLAW_INSTALL_REF:-}" ]]; then | ||||||||||||||||||||||||||||||||||
| printf "%s" "${NEMOCLAW_INSTALL_REF}" | ||||||||||||||||||||||||||||||||||
| # --------------------------------------------------------------------------- | ||||||||||||||||||||||||||||||||||
| # Helpers | ||||||||||||||||||||||||||||||||||
| # --------------------------------------------------------------------------- | ||||||||||||||||||||||||||||||||||
| info() { printf '\033[1;34m[INFO]\033[0m %s\n' "$*"; } | ||||||||||||||||||||||||||||||||||
| warn() { printf '\033[1;33m[WARN]\033[0m %s\n' "$*"; } | ||||||||||||||||||||||||||||||||||
| error() { printf '\033[1;31m[ERROR]\033[0m %s\n' "$*"; exit 1; } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| command_exists() { command -v "$1" &>/dev/null; } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| # Compare two semver strings (major.minor.patch). Returns 0 if $1 >= $2. | ||||||||||||||||||||||||||||||||||
| version_gte() { | ||||||||||||||||||||||||||||||||||
| local IFS=. | ||||||||||||||||||||||||||||||||||
| local -a a=($1) b=($2) | ||||||||||||||||||||||||||||||||||
| for i in 0 1 2; do | ||||||||||||||||||||||||||||||||||
| local ai=${a[$i]:-0} bi=${b[$i]:-0} | ||||||||||||||||||||||||||||||||||
| if (( ai > bi )); then return 0; fi | ||||||||||||||||||||||||||||||||||
| if (( ai < bi )); then return 1; fi | ||||||||||||||||||||||||||||||||||
| done | ||||||||||||||||||||||||||||||||||
| return 0 | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| # --------------------------------------------------------------------------- | ||||||||||||||||||||||||||||||||||
| # 1. Node.js | ||||||||||||||||||||||||||||||||||
| # --------------------------------------------------------------------------- | ||||||||||||||||||||||||||||||||||
| install_nodejs() { | ||||||||||||||||||||||||||||||||||
| if command_exists node; then | ||||||||||||||||||||||||||||||||||
| info "Node.js found: $(node --version)" | ||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
| printf "%s" "${NEMOCLAW_INSTALL_TAG:-$DEFAULT_INSTALL_REF}" | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| info "Node.js not found — installing via nvm…" | ||||||||||||||||||||||||||||||||||
| curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.4/install.sh | bash | ||||||||||||||||||||||||||||||||||
| \. "$HOME/.nvm/nvm.sh" | ||||||||||||||||||||||||||||||||||
| nvm install 24 | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+34
to
+42
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
# Locate the target script and related helpers
git ls-files | rg '(^|/)install\.sh$|(^|/)README\.md$|(^|/)\.sh$'
# Show the install.sh file with line numbers
wc -l install.sh
cat -n install.sh | sed -n '1,220p'
# Search for helper functions and later npm/node usage
rg -n "command_exists|version_gte|install_nodejs|install_nemoclaw|npm|node --version|nvm install|nvm use" install.shRepository: NVIDIA/NemoClaw Length of output: 9025 🏁 Script executed: #!/bin/bash
set -euo pipefail
# Inspect declared runtime requirements
wc -l package.json 2>/dev/null || true
cat -n package.json 2>/dev/null | sed -n '1,220p' || true
# Look for Node engine/version constraints and install docs
rg -n '"engines"|node|npm|npx|install_nodejs|install_nemoclaw|v24|24\.0\.0' package.json README.md install.sh scripts/install.shRepository: NVIDIA/NemoClaw Length of output: 24212 Check both 🧰 Tools🪛 ast-grep (0.44.0)[error] 39-39: Remote content fetched with curl/wget is piped directly into a shell interpreter, so any server compromise, MITM, or tampered mirror results in arbitrary code execution on this host. Download the script to a file first, verify its integrity (checksum/signature) and inspect it, then run the verified local copy. (curl-pipe-to-shell-bash) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
| info "Node.js installed: $(node --version)" | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| verify_downloaded_script() { | ||||||||||||||||||||||||||||||||||
| local file="$1" label="${2:-installer}" expected_hash="${3:-}" | ||||||||||||||||||||||||||||||||||
| if [[ ! -s "$file" ]]; then | ||||||||||||||||||||||||||||||||||
| printf "[ERROR] %s download is empty or missing\n" "$label" >&2 | ||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||
| # --------------------------------------------------------------------------- | ||||||||||||||||||||||||||||||||||
| # 2. Ollama | ||||||||||||||||||||||||||||||||||
| # --------------------------------------------------------------------------- | ||||||||||||||||||||||||||||||||||
| OLLAMA_MIN_VERSION="0.18.0" | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| get_ollama_version() { | ||||||||||||||||||||||||||||||||||
| # `ollama --version` outputs something like "ollama version 0.18.0" | ||||||||||||||||||||||||||||||||||
| ollama --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+51
to
+53
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win Make version parsing non-fatal. With Proposed fix get_ollama_version() {
# `ollama --version` outputs something like "ollama version 0.18.0"
- ollama --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1
+ ollama --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || true
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| detect_gpu() { | ||||||||||||||||||||||||||||||||||
| # Returns 0 if a GPU is detected | ||||||||||||||||||||||||||||||||||
| if command_exists nvidia-smi; then | ||||||||||||||||||||||||||||||||||
| nvidia-smi &>/dev/null && return 0 | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
| if ! head -1 "$file" | grep -qE '^#!.*(sh|bash)'; then | ||||||||||||||||||||||||||||||||||
| printf "[ERROR] %s does not start with a shell shebang\n" "$label" >&2 | ||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||
| return 1 | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+56
to
+62
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win Align GPU detection with the macOS VRAM fallback.
Proposed fix detect_gpu() {
# Returns 0 if a GPU is detected
if command_exists nvidia-smi; then
nvidia-smi &>/dev/null && return 0
fi
+ if [[ "$(uname -s)" == "Darwin" ]] && command_exists sysctl; then
+ return 0
+ fi
return 1
}Also applies to: 92-100 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| get_vram_mb() { | ||||||||||||||||||||||||||||||||||
| # Returns total VRAM in MiB (NVIDIA only). Falls back to 0. | ||||||||||||||||||||||||||||||||||
| if command_exists nvidia-smi; then | ||||||||||||||||||||||||||||||||||
| nvidia-smi --query-gpu=memory.total --format=csv,noheader,nounits 2>/dev/null \ | ||||||||||||||||||||||||||||||||||
| | awk '{s += $1} END {print s+0}' | ||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
| if [[ -n "$expected_hash" ]]; then | ||||||||||||||||||||||||||||||||||
| local actual_hash="" | ||||||||||||||||||||||||||||||||||
| if command -v sha256sum >/dev/null 2>&1; then | ||||||||||||||||||||||||||||||||||
| actual_hash="$(sha256sum "$file" | awk '{print $1}')" | ||||||||||||||||||||||||||||||||||
| elif command -v shasum >/dev/null 2>&1; then | ||||||||||||||||||||||||||||||||||
| actual_hash="$(shasum -a 256 "$file" | awk '{print $1}')" | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
| if [[ -z "$actual_hash" ]]; then | ||||||||||||||||||||||||||||||||||
| printf "[ERROR] No SHA-256 tool available — cannot verify %s integrity\n" "$label" >&2 | ||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
| if [[ "$actual_hash" != "$expected_hash" ]]; then | ||||||||||||||||||||||||||||||||||
| rm -f "$file" | ||||||||||||||||||||||||||||||||||
| printf "[ERROR] %s integrity check failed\n Expected: %s\n Actual: %s\n" "$label" "$expected_hash" "$actual_hash" >&2 | ||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
| # macOS — report unified memory as VRAM | ||||||||||||||||||||||||||||||||||
| if [[ "$(uname -s)" == "Darwin" ]] && command_exists sysctl; then | ||||||||||||||||||||||||||||||||||
| local bytes | ||||||||||||||||||||||||||||||||||
| bytes=$(sysctl -n hw.memsize 2>/dev/null || echo 0) | ||||||||||||||||||||||||||||||||||
| echo $(( bytes / 1024 / 1024 )) | ||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
| echo 0 | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| has_payload_marker() { | ||||||||||||||||||||||||||||||||||
| local file="$1" | ||||||||||||||||||||||||||||||||||
| [[ -f "$file" ]] && grep -q "$PAYLOAD_MARKER" "$file" | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| install_or_upgrade_ollama() { | ||||||||||||||||||||||||||||||||||
| if detect_gpu && command_exists ollama; then | ||||||||||||||||||||||||||||||||||
| local current | ||||||||||||||||||||||||||||||||||
| current=$(get_ollama_version) | ||||||||||||||||||||||||||||||||||
| if [[ -n "$current" ]] && version_gte "$current" "$OLLAMA_MIN_VERSION"; then | ||||||||||||||||||||||||||||||||||
| info "Ollama v${current} meets minimum requirement (>= v${OLLAMA_MIN_VERSION})" | ||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||
| info "Ollama v${current:-unknown} is below v${OLLAMA_MIN_VERSION} — upgrading…" | ||||||||||||||||||||||||||||||||||
| curl -fsSL https://ollama.com/install.sh | sh | ||||||||||||||||||||||||||||||||||
| info "Ollama upgraded to $(get_ollama_version)" | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||
| # No ollama — only install if a GPU is present | ||||||||||||||||||||||||||||||||||
| if detect_gpu; then | ||||||||||||||||||||||||||||||||||
| info "GPU detected — installing Ollama…" | ||||||||||||||||||||||||||||||||||
| curl -fsSL https://ollama.com/install.sh | sh | ||||||||||||||||||||||||||||||||||
| info "Ollama installed: v$(get_ollama_version)" | ||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||
| warn "No GPU detected — skipping Ollama installation." | ||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| clone_nemoclaw_ref() { | ||||||||||||||||||||||||||||||||||
| local ref="$1" dest="$2" | ||||||||||||||||||||||||||||||||||
| # Pull the appropriate model based on VRAM | ||||||||||||||||||||||||||||||||||
| local vram_mb | ||||||||||||||||||||||||||||||||||
| vram_mb=$(get_vram_mb) | ||||||||||||||||||||||||||||||||||
| local vram_gb=$(( vram_mb / 1024 )) | ||||||||||||||||||||||||||||||||||
| info "Detected ${vram_gb} GB VRAM" | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| git init --quiet "$dest" | ||||||||||||||||||||||||||||||||||
| git -C "$dest" remote add origin https://github.com/NVIDIA/NemoClaw.git | ||||||||||||||||||||||||||||||||||
| 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 | ||||||||||||||||||||||||||||||||||
| if (( vram_gb >= 120 )); then | ||||||||||||||||||||||||||||||||||
| info "Pulling nemotron-3-super:120b…" | ||||||||||||||||||||||||||||||||||
| ollama pull nemotron-3-super:120b | ||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||
| info "Pulling nemotron-3-nano:30b…" | ||||||||||||||||||||||||||||||||||
| ollama pull nemotron-3-nano:30b | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
| git -C "$dest" -c advice.detachedHead=false checkout --quiet --detach FETCH_HEAD | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| exec_installer_from_ref() { | ||||||||||||||||||||||||||||||||||
| local ref="$1" | ||||||||||||||||||||||||||||||||||
| shift | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| local tmpdir source_root payload_script legacy_script | ||||||||||||||||||||||||||||||||||
| tmpdir="$(mktemp -d)" | ||||||||||||||||||||||||||||||||||
| BOOTSTRAP_TMPDIR="$tmpdir" | ||||||||||||||||||||||||||||||||||
| trap 'rm -rf "${BOOTSTRAP_TMPDIR:-}"' EXIT | ||||||||||||||||||||||||||||||||||
| source_root="${tmpdir}/source" | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| clone_nemoclaw_ref "$ref" "$source_root" | ||||||||||||||||||||||||||||||||||
| # --------------------------------------------------------------------------- | ||||||||||||||||||||||||||||||||||
| # 3. NemoClaw | ||||||||||||||||||||||||||||||||||
| # --------------------------------------------------------------------------- | ||||||||||||||||||||||||||||||||||
| install_nemoclaw() { | ||||||||||||||||||||||||||||||||||
| # Ensure npm global bin is on PATH (nvm installs to a non-standard location) | ||||||||||||||||||||||||||||||||||
| local npm_bin | ||||||||||||||||||||||||||||||||||
| npm_bin="$(npm config get prefix)/bin" | ||||||||||||||||||||||||||||||||||
| if ! echo "$PATH" | tr ':' '\n' | grep -qx "$npm_bin"; then | ||||||||||||||||||||||||||||||||||
| export PATH="$npm_bin:$PATH" | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| payload_script="${source_root}/scripts/install.sh" | ||||||||||||||||||||||||||||||||||
| legacy_script="${source_root}/install.sh" | ||||||||||||||||||||||||||||||||||
| if [[ -f "./package.json" ]] && grep -q '"name": "nemoclaw"' ./package.json 2>/dev/null; then | ||||||||||||||||||||||||||||||||||
| info "NemoClaw package.json found in current directory — installing from source…" | ||||||||||||||||||||||||||||||||||
| npm install && npm link | ||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||
| info "Installing NemoClaw from npm…" | ||||||||||||||||||||||||||||||||||
| npm install -g nemoclaw | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if has_payload_marker "$payload_script"; then | ||||||||||||||||||||||||||||||||||
| verify_downloaded_script "$payload_script" "versioned installer" | ||||||||||||||||||||||||||||||||||
| NEMOCLAW_INSTALL_REF="$ref" NEMOCLAW_INSTALL_TAG="$ref" NEMOCLAW_BOOTSTRAP_PAYLOAD=1 \ | ||||||||||||||||||||||||||||||||||
| bash "$payload_script" "$@" | ||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||
| # Persist npm global bin for future shells | ||||||||||||||||||||||||||||||||||
| local profile="$HOME/.bashrc" | ||||||||||||||||||||||||||||||||||
| [ -f "$HOME/.zshrc" ] && profile="$HOME/.zshrc" | ||||||||||||||||||||||||||||||||||
| if ! grep -q 'npm config get prefix' "$profile" 2>/dev/null; then | ||||||||||||||||||||||||||||||||||
| echo 'export PATH="$(npm config get prefix)/bin:$PATH"' >> "$profile" | ||||||||||||||||||||||||||||||||||
| info "Added npm global bin to $profile" | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+138
to
144
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win Persist the npm global bin to both supported shell profiles. The PR objective says Proposed fix- local profile="$HOME/.bashrc"
- [ -f "$HOME/.zshrc" ] && profile="$HOME/.zshrc"
- if ! grep -q 'npm config get prefix' "$profile" 2>/dev/null; then
- echo 'export PATH="$(npm config get prefix)/bin:$PATH"' >> "$profile"
- info "Added npm global bin to $profile"
- fi
+ local profile
+ for profile in "$HOME/.bashrc" "$HOME/.zshrc"; do
+ touch "$profile"
+ if ! grep -Fqx 'export PATH="$(npm config get prefix)/bin:$PATH"' "$profile"; then
+ echo 'export PATH="$(npm config get prefix)/bin:$PATH"' >> "$profile"
+ info "Added npm global bin to $profile"
+ fi
+ done📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| verify_downloaded_script "$legacy_script" "legacy installer" | ||||||||||||||||||||||||||||||||||
| NEMOCLAW_INSTALL_TAG="$ref" bash "$legacy_script" "$@" | ||||||||||||||||||||||||||||||||||
| if ! command_exists nemoclaw; then | ||||||||||||||||||||||||||||||||||
| error "nemoclaw not found in PATH after install. Try: source ~/.bashrc && nemoclaw --help" | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
| info "nemoclaw is ready: $(nemoclaw --version 2>/dev/null || echo 'installed')" | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| bootstrap_version() { | ||||||||||||||||||||||||||||||||||
| printf "nemoclaw-installer\n" | ||||||||||||||||||||||||||||||||||
| # --------------------------------------------------------------------------- | ||||||||||||||||||||||||||||||||||
| # 4. Onboard | ||||||||||||||||||||||||||||||||||
| # --------------------------------------------------------------------------- | ||||||||||||||||||||||||||||||||||
| run_onboard() { | ||||||||||||||||||||||||||||||||||
| info "Running nemoclaw onboard…" | ||||||||||||||||||||||||||||||||||
| npx nemoclaw onboard | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| bootstrap_usage() { | ||||||||||||||||||||||||||||||||||
| printf "\n" | ||||||||||||||||||||||||||||||||||
| printf " NemoClaw Installer\n\n" | ||||||||||||||||||||||||||||||||||
| printf " Usage:\n" | ||||||||||||||||||||||||||||||||||
| printf " curl -fsSL https://www.nvidia.com/nemoclaw.sh | bash\n" | ||||||||||||||||||||||||||||||||||
| printf " curl -fsSL https://www.nvidia.com/nemoclaw.sh | bash -s -- [options]\n\n" | ||||||||||||||||||||||||||||||||||
| printf " Options:\n" | ||||||||||||||||||||||||||||||||||
| printf " --non-interactive Skip prompts (uses env vars / defaults)\n" | ||||||||||||||||||||||||||||||||||
| printf " --yes-i-accept-third-party-software Accept the third-party software notice without prompting\n" | ||||||||||||||||||||||||||||||||||
| printf " --fresh Discard any failed/interrupted onboarding session and start over\n" | ||||||||||||||||||||||||||||||||||
| printf " --version, -v Print installer version and exit\n" | ||||||||||||||||||||||||||||||||||
| printf " --help, -h Show this help message and exit\n\n" | ||||||||||||||||||||||||||||||||||
| 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" | ||||||||||||||||||||||||||||||||||
| printf " NEMOCLAW_NO_EXPRESS=1 Skip express install prompt on supported platforms\n" | ||||||||||||||||||||||||||||||||||
| printf " NEMOCLAW_SANDBOX_NAME Sandbox name to create/use\n" | ||||||||||||||||||||||||||||||||||
| printf " NEMOCLAW_ACCEPT_EXPERIMENTAL_OPENSHELL_UPGRADE=1\n" | ||||||||||||||||||||||||||||||||||
| printf " Allow automatic pre-0.0.37 OpenShell gateway upgrade\n" | ||||||||||||||||||||||||||||||||||
| printf " NEMOCLAW_OPENSHELL_UPGRADE_PREPARED=1\n" | ||||||||||||||||||||||||||||||||||
| printf " Continue after manually backing up and retiring old gateway\n" | ||||||||||||||||||||||||||||||||||
| printf " NEMOCLAW_PROVIDER build | openai | anthropic | anthropicCompatible\n" | ||||||||||||||||||||||||||||||||||
| printf " | gemini | ollama | custom | nim-local | vllm | routed\n" | ||||||||||||||||||||||||||||||||||
| printf " | hermes-provider\n" | ||||||||||||||||||||||||||||||||||
| printf " (aliases: cloud -> build, nim -> nim-local)\n" | ||||||||||||||||||||||||||||||||||
| printf " NEMOCLAW_POLICY_MODE suggested | custom | skip\n" | ||||||||||||||||||||||||||||||||||
| printf "\n" | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| # --------------------------------------------------------------------------- | ||||||||||||||||||||||||||||||||||
| # Main | ||||||||||||||||||||||||||||||||||
| # --------------------------------------------------------------------------- | ||||||||||||||||||||||||||||||||||
| main() { | ||||||||||||||||||||||||||||||||||
| info "=== NemoClaw Installer ===" | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| bootstrap_main() { | ||||||||||||||||||||||||||||||||||
| for arg in "$@"; do | ||||||||||||||||||||||||||||||||||
| case "$arg" in | ||||||||||||||||||||||||||||||||||
| --help | -h) | ||||||||||||||||||||||||||||||||||
| bootstrap_usage | ||||||||||||||||||||||||||||||||||
| return 0 | ||||||||||||||||||||||||||||||||||
| ;; | ||||||||||||||||||||||||||||||||||
| --version | -v) | ||||||||||||||||||||||||||||||||||
| bootstrap_version | ||||||||||||||||||||||||||||||||||
| return 0 | ||||||||||||||||||||||||||||||||||
| ;; | ||||||||||||||||||||||||||||||||||
| esac | ||||||||||||||||||||||||||||||||||
| done | ||||||||||||||||||||||||||||||||||
| install_nodejs | ||||||||||||||||||||||||||||||||||
| # install_or_upgrade_ollama | ||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win Either wire in Ollama setup or remove the advertised Ollama install path. The installer header and Ollama functions say GPU hosts get Ollama/model setup, but 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
| install_nemoclaw | ||||||||||||||||||||||||||||||||||
| run_onboard | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| local ref | ||||||||||||||||||||||||||||||||||
| ref="$(resolve_release_tag)" | ||||||||||||||||||||||||||||||||||
| exec_installer_from_ref "$ref" "$@" | ||||||||||||||||||||||||||||||||||
| info "=== Installation complete ===" | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if has_payload_marker "$LOCAL_PAYLOAD"; then | ||||||||||||||||||||||||||||||||||
| # shellcheck source=/dev/null | ||||||||||||||||||||||||||||||||||
| . "$LOCAL_PAYLOAD" | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if [[ "${BASH_SOURCE[0]:-}" == "$0" ]] || { [[ -z "${BASH_SOURCE[0]:-}" ]] && { [[ "$0" == "bash" ]] || [[ "$0" == "-bash" ]]; }; }; then | ||||||||||||||||||||||||||||||||||
| if has_payload_marker "$LOCAL_PAYLOAD"; then | ||||||||||||||||||||||||||||||||||
| main "$@" | ||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||
| bootstrap_main "$@" | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
| main "$@" | ||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Avoid executing remote installer scripts without integrity verification.
These
curl | bash/shpaths execute mutable network content as the current user. Download to a temp file, verify a pinned checksum/signature, then execute the verified file.Also applies to: 89-96
🤖 Prompt for AI Agents
Source: Linters/SAST tools