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
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Commands

The `nemoclaw` CLI is the primary interface for managing NemoClaw sandboxes. It is installed when you run `npm install -g nemoclaw`.
The `nemoclaw` CLI is the primary interface for managing NemoClaw sandboxes.
It is installed automatically by the installer (`curl -fsSL https://www.nvidia.com/nemoclaw.sh | bash`).

## `/nemoclaw` Slash Command

Expand Down
3 changes: 2 additions & 1 deletion docs/reference/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ status: published

# Commands

The `nemoclaw` CLI is the primary interface for managing NemoClaw sandboxes. It is installed when you run `npm install -g nemoclaw`.
The `nemoclaw` CLI is the primary interface for managing NemoClaw sandboxes.
It is installed automatically by the installer (`curl -fsSL https://www.nvidia.com/nemoclaw.sh | bash`).

## `/nemoclaw` Slash Command

Expand Down
63 changes: 43 additions & 20 deletions scripts/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -898,39 +898,62 @@ install_nemoclaw() {
# ---------------------------------------------------------------------------
# 4. Verify
# ---------------------------------------------------------------------------

# Verify that a nemoclaw binary is the real NemoClaw CLI and not the broken
# placeholder npm package (npmjs.org/nemoclaw 0.1.0 — 249 bytes, no build
# artifacts). The real CLI prints "nemoclaw v<semver>" on --version.
# Mirrors the isOpenshellCLI() pattern from resolve-openshell.js (PR #970).
is_real_nemoclaw_cli() {
local bin_path="${1:-nemoclaw}"
local version_output
version_output="$("$bin_path" --version 2>/dev/null)" || return 1
# Real CLI outputs: "nemoclaw v0.1.0" (or any semver, with optional pre-release)
[[ "$version_output" =~ ^nemoclaw[[:space:]]+v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]
}

verify_nemoclaw() {
if command_exists nemoclaw; then
NEMOCLAW_READY_NOW=true
ensure_nemoclaw_shim || true
info "Verified: nemoclaw is available at $(command -v nemoclaw)"
return 0
if is_real_nemoclaw_cli "$(command -v nemoclaw)"; then
NEMOCLAW_READY_NOW=true
ensure_nemoclaw_shim || true
info "Verified: nemoclaw is available at $(command -v nemoclaw)"
return 0
else
warn "Found nemoclaw at $(command -v nemoclaw) but it is not the real NemoClaw CLI."
warn "This is likely the broken placeholder npm package."
npm uninstall -g nemoclaw 2>/dev/null || true
fi
fi

local npm_bin
npm_bin="$(npm config get prefix 2>/dev/null)/bin" || true

if [[ -n "$npm_bin" && -x "$npm_bin/nemoclaw" ]]; then
ensure_nemoclaw_shim || true
if command_exists nemoclaw; then
NEMOCLAW_READY_NOW=true
info "Verified: nemoclaw is available at $(command -v nemoclaw)"
return 0
fi
if is_real_nemoclaw_cli "$npm_bin/nemoclaw"; then
ensure_nemoclaw_shim || true
if command_exists nemoclaw; then
NEMOCLAW_READY_NOW=true
info "Verified: nemoclaw is available at $(command -v nemoclaw)"
return 0
fi

NEMOCLAW_RECOVERY_PROFILE="$(detect_shell_profile)"
if [[ -x "$NEMOCLAW_SHIM_DIR/nemoclaw" ]]; then
NEMOCLAW_RECOVERY_EXPORT_DIR="$NEMOCLAW_SHIM_DIR"
NEMOCLAW_RECOVERY_PROFILE="$(detect_shell_profile)"
if [[ -x "$NEMOCLAW_SHIM_DIR/nemoclaw" ]]; then
NEMOCLAW_RECOVERY_EXPORT_DIR="$NEMOCLAW_SHIM_DIR"
else
NEMOCLAW_RECOVERY_EXPORT_DIR="$npm_bin"
fi
warn "Found nemoclaw at $npm_bin/nemoclaw but this shell still cannot resolve it."
warn "Onboarding will be skipped until PATH is updated."
return 0
else
NEMOCLAW_RECOVERY_EXPORT_DIR="$npm_bin"
warn "Found nemoclaw at $npm_bin/nemoclaw but it is not the real NemoClaw CLI."
npm uninstall -g nemoclaw 2>/dev/null || true
fi
warn "Found nemoclaw at $npm_bin/nemoclaw but this shell still cannot resolve it."
warn "Onboarding will be skipped until PATH is updated."
return 0
else
warn "Could not locate the nemoclaw executable."
warn "Try running: npm install -g git+https://github.com/NVIDIA/NemoClaw.git"
fi

warn "Could not locate the nemoclaw executable."
warn "Try re-running: curl -fsSL https://www.nvidia.com/nemoclaw.sh | bash"
error "Installation failed: nemoclaw binary not found."
}

Expand Down
43 changes: 32 additions & 11 deletions test/install-preflight.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,14 +177,17 @@ fi
if [ "$1" = "run" ]; then
exit 0
fi
if [ "$1" = "uninstall" ]; then
exit 0
fi
if [ "$1" = "link" ]; then
cat > "$NPM_PREFIX/bin/nemoclaw" <<'EOS'
#!/usr/bin/env bash
if [ "$1" = "onboard" ]; then
exit 0
fi
if [ "$1" = "--version" ]; then
echo "v0.1.0-test"
echo "nemoclaw v0.1.0-test"
exit 0
fi
exit 0
Expand Down Expand Up @@ -277,6 +280,9 @@ fi
if [ "$1" = "run" ]; then
exit 0
fi
if [ "$1" = "uninstall" ]; then
exit 0
fi
if [ "$1" = "link" ]; then
exit 0
fi
Expand All @@ -300,7 +306,7 @@ exit 98

const output = `${result.stdout}${result.stderr}`;
expect(result.status).not.toBe(0);
expect(output).toMatch(new RegExp(GITHUB_INSTALL_URL.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")));
expect(output).toMatch(/curl -fsSL https:\/\/www\.nvidia\.com\/nemoclaw\.sh \| bash/);
expect(output).not.toMatch(/npm install -g nemoclaw/);
});

Expand Down Expand Up @@ -427,7 +433,8 @@ if [ "$1" = "run" ] && { [ "$2" = "build" ] || [ "$2" = "build:cli" ] || [ "$2"
if [ "$1" = "link" ]; then
cat > "$NPM_PREFIX/bin/nemoclaw" <<'EOS'
#!/usr/bin/env bash
if [ "$1" = "onboard" ] || [ "$1" = "--version" ]; then exit 0; fi
if [ "$1" = "--version" ]; then echo "nemoclaw v0.1.0-test"; exit 0; fi
if [ "$1" = "onboard" ]; then exit 0; fi
exit 0
EOS
chmod +x "$NPM_PREFIX/bin/nemoclaw"
Expand Down Expand Up @@ -518,6 +525,7 @@ if [ "$1" = "run" ] && { [ "$2" = "build" ] || [ "$2" = "build:cli" ] || [ "$2"
if [ "$1" = "link" ]; then
cat > "$NPM_PREFIX/bin/nemoclaw" <<'EOS'
#!/usr/bin/env bash
if [ "$1" = "--version" ]; then echo "nemoclaw v0.1.0-test"; exit 0; fi
printf '%s\\n' "$*" >> "$NEMOCLAW_ONBOARD_LOG"
exit 0
EOS
Expand Down Expand Up @@ -612,6 +620,7 @@ if [ "$1" = "run" ] && { [ "$2" = "build" ] || [ "$2" = "build:cli" ] || [ "$2"
if [ "$1" = "link" ]; then
cat > "$NPM_PREFIX/bin/nemoclaw" <<'EOS'
#!/usr/bin/env bash
if [ "$1" = "--version" ]; then echo "nemoclaw v0.1.0-test"; exit 0; fi
printf '%s\\n' "$*" >> "$NEMOCLAW_ONBOARD_LOG"
exit 0
EOS
Expand Down Expand Up @@ -674,6 +683,7 @@ if [ "$1" = "run" ] && { [ "$2" = "build" ] || [ "$2" = "build:cli" ] || [ "$2"
if [ "$1" = "link" ]; then
cat > "$NPM_PREFIX/bin/nemoclaw" <<'EOS'
#!/usr/bin/env bash
if [ "$1" = "--version" ]; then echo "nemoclaw v0.1.0-test"; exit 0; fi
printf '%s\\n' "$*" >> "$NEMOCLAW_ONBOARD_LOG"
exit 0
EOS
Expand Down Expand Up @@ -760,6 +770,7 @@ if [ "$1" = "run" ] && { [ "$2" = "build" ] || [ "$2" = "build:cli" ] || [ "$2"
if [ "$1" = "link" ]; then
cat > "$NPM_PREFIX/bin/nemoclaw" <<'EOS'
#!/usr/bin/env bash
if [ "$1" = "--version" ]; then echo "nemoclaw v0.1.0-test"; exit 0; fi
printf '%s\\n' "$*" >> "$NEMOCLAW_ONBOARD_LOG"
exit 0
EOS
Expand Down Expand Up @@ -830,6 +841,7 @@ if [ "$1" = "run" ] && { [ "$2" = "build" ] || [ "$2" = "build:cli" ] || [ "$2"
if [ "$1" = "link" ]; then
cat > "$NPM_PREFIX/bin/nemoclaw" <<'EOS'
#!/usr/bin/env bash
if [ "$1" = "--version" ]; then echo "nemoclaw v0.1.0-test"; exit 0; fi
printf '%s\\n' "$*" >> "$NEMOCLAW_ONBOARD_LOG"
exit 0
EOS
Expand Down Expand Up @@ -976,14 +988,17 @@ fi
if [ "$1" = "run" ]; then
exit 0
fi
if [ "$1" = "uninstall" ]; then
exit 0
fi
if [ "$1" = "link" ]; then
cat > "$NPM_PREFIX/bin/nemoclaw" <<'EOS'
#!/usr/bin/env bash
if [ "$1" = "onboard" ]; then
exit 0
fi
if [ "$1" = "--version" ]; then
echo "v0.1.0-test"
echo "nemoclaw v0.1.0-test"
exit 0
fi
exit 0
Expand Down Expand Up @@ -1103,12 +1118,14 @@ fi
if [ "$1" = "run" ]; then
exit 0
fi
if [ "$1" = "uninstall" ]; then
exit 0
fi
if [ "$1" = "link" ]; then
cat > "$NPM_PREFIX/bin/nemoclaw" <<'EOS'
#!/usr/bin/env bash
if [ "$1" = "onboard" ] || [ "$1" = "--version" ]; then
exit 0
fi
if [ "$1" = "--version" ]; then echo "nemoclaw v0.1.0-test"; exit 0; fi
if [ "$1" = "onboard" ]; then exit 0; fi
exit 0
EOS
chmod +x "$NPM_PREFIX/bin/nemoclaw"
Expand Down Expand Up @@ -1200,7 +1217,8 @@ if [ "$1" = "install" ] || [ "$1" = "run" ]; then exit 0; fi
if [ "$1" = "link" ]; then
cat > "$NPM_PREFIX/bin/nemoclaw" <<'EOS'
#!/usr/bin/env bash
if [ "$1" = "onboard" ] || [ "$1" = "--version" ]; then exit 0; fi
if [ "$1" = "--version" ]; then echo "nemoclaw v0.1.0-test"; exit 0; fi
if [ "$1" = "onboard" ]; then exit 0; fi
exit 0
EOS
chmod +x "$NPM_PREFIX/bin/nemoclaw"
Expand Down Expand Up @@ -1317,7 +1335,8 @@ if [ "$1" = "install" ] || [ "$1" = "run" ]; then exit 0; fi
if [ "$1" = "link" ]; then
cat > "$NPM_PREFIX/bin/nemoclaw" <<'EOS'
#!/usr/bin/env bash
if [ "$1" = "onboard" ] || [ "$1" = "--version" ]; then exit 0; fi
if [ "$1" = "--version" ]; then echo "nemoclaw v0.1.0-test"; exit 0; fi
if [ "$1" = "onboard" ]; then exit 0; fi
exit 0
EOS
chmod +x "$NPM_PREFIX/bin/nemoclaw"
Expand Down Expand Up @@ -1422,7 +1441,8 @@ if [ "$1" = "install" ] || [ "$1" = "run" ]; then exit 0; fi
if [ "$1" = "link" ]; then
cat > "$NPM_PREFIX/bin/nemoclaw" <<'EOS'
#!/usr/bin/env bash
if [ "$1" = "onboard" ] || [ "$1" = "--version" ]; then exit 0; fi
if [ "$1" = "--version" ]; then echo "nemoclaw v0.1.0-test"; exit 0; fi
if [ "$1" = "onboard" ]; then exit 0; fi
exit 0
EOS
chmod +x "$NPM_PREFIX/bin/nemoclaw"
Expand Down Expand Up @@ -1892,10 +1912,11 @@ if [ "$1" = "config" ] && [ "$2" = "get" ] && [ "$3" = "prefix" ]; then echo "$N
if [ "$1" = "pack" ]; then exit 1; fi
if [ "$1" = "install" ] && [[ "$*" == *"--ignore-scripts"* ]]; then exit 0; fi
if [ "$1" = "run" ]; then exit 0; fi
if [ "$1" = "uninstall" ]; then exit 0; fi
if [ "$1" = "link" ]; then
cat > "$NPM_PREFIX/bin/nemoclaw" <<'EOS'
#!/usr/bin/env bash
if [ "$1" = "--version" ]; then echo "v0.5.0-test"; exit 0; fi
if [ "$1" = "--version" ]; then echo "nemoclaw v0.5.0-test"; exit 0; fi
exit 0
EOS
chmod +x "$NPM_PREFIX/bin/nemoclaw"
Expand Down
2 changes: 1 addition & 1 deletion test/runner.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ describe("regression guards", () => {
const normalized = normalize(src, "#");
return normalized.split("\n").filter((line) => {
const t = line.trim();
if (t.startsWith("printf") || t.startsWith("echo")) return false;
if (t.startsWith("printf") || t.startsWith("echo") || t.startsWith("warn")) return false;
return shellViolationRe.test(t);
});
};
Expand Down
Loading