feat(cli): add setup-apple command for macOS/Apple Silicon#274
feat(cli): add setup-apple command for macOS/Apple Silicon#274mihai-chiorean wants to merge 10 commits intoNVIDIA:mainfrom
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a new Changes
Sequence DiagramsequenceDiagram
participant User
participant CLI as bin/nemoclaw.js
participant Setup as scripts/setup-apple.sh
participant System as macOS
participant Services as Docker/Colima/Ollama
User->>CLI: run `nemoclaw setup-apple`
CLI->>Setup: spawn `scripts/setup-apple.sh`
Setup->>System: verify Darwin, ARCH, HOME
System-->>Setup: platform & env info
Setup->>System: check Node.js presence & version
System-->>Setup: node version / missing
Setup->>Services: detect Docker Desktop or Colima socket
Services-->>Setup: socket presence / responsiveness
Setup->>Services: query Docker memory allocation
Services-->>Setup: memory info
Setup->>Services: detect Ollama and OLLAMA_HOST
Services-->>Setup: Ollama status
Setup->>System: ensure OpenShell CLI installed (may call install-openshell.sh)
System-->>Setup: CLI status / install result
Setup->>System: detect Apple GPU / unified memory
System-->>Setup: GPU details
Setup-->>User: print structured report, warnings, and next steps
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
Partially addresses #260 (setup-apple command and install-openshell.sh security hardening items) |
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@scripts/install-openshell.sh`:
- Around line 25-62: The download is saved as "$tmpdir/openshell.tar.gz" but the
SHA256SUMS entries reference the actual asset filename ($ASSET), causing shasum
-c to fail; change the curl download to save to "$tmpdir/$ASSET" (use the ASSET
variable) and update subsequent references—file validation, checksum grep/shasum
invocation, and tar extraction—to operate on "$tmpdir/$ASSET" instead of
"$tmpdir/openshell.tar.gz" so the names match the SHA256SUMS entries and
verification succeeds (adjust usages around DOWNLOAD_URL, CHECKSUM_URL,
SHA256SUMS, grep "$ASSET" | shasum -a 256 -c -s, and the tar xzf invocation).
In `@scripts/setup-apple.sh`:
- Around line 145-156: The script currently treats any non-empty OLLAMA_HOST as
valid; update the check around the OLLAMA_HOST handling to parse out the host
(e.g., strip the port with parameter expansion) and reject common loopback
values (localhost, 127.* , ::1) as not container-reachable; keep using the same
info/warn helpers but only call info "OLLAMA_HOST=..." when the parsed host is
not a loopback and equals a container-reachable value (e.g., 0.0.0.0 or a
non-loopback IP/hostname), otherwise emit the existing warn messages. Locate the
OLLAMA_HOST conditional and adjust the validation logic that determines whether
to call info vs warn (refer to the OLLAMA_HOST variable and the info/warn calls
in that block).
- Around line 79-121: The script currently calls docker info without targeting
the detected DOCKER_SOCKET, causing wrong results when multiple Docker contexts
exist; update both places where docker is invoked (the connectivity check `if !
docker info > /dev/null 2>&1; then` and the memory probe that sets
`DOCKER_MEM_BYTES=$(docker info --format '{{.MemTotal}}' 2>/dev/null || echo
"0")`) to explicitly use the detected socket by invoking docker with the host
set to the socket (e.g. either prefix with `DOCKER_HOST=unix://$DOCKER_SOCKET`
or use `docker --host unix://$DOCKER_SOCKET`), making sure all docker calls in
this block reference `DOCKER_SOCKET` so the connectivity and memory checks
target the same socket that was detected earlier.
- Around line 52-64: The current logic checks sysctl.proc_translated only inside
the ARM branch, causing Rosetta-launched shells (uname -m == x86_64) to be
misclassified as Intel; change the detection order to first query hardware
capability using sysctl -n hw.optional.arm64 (or check sysctl.proc_translated
separately) before branching on ARCH, then set ARCH-aware messages: use the
hw.optional.arm64 result to detect Apple Silicon hardware regardless of process
translation and still warn when sysctl.proc_translated == 1 about Rosetta;
adjust the conditional that currently references ARCH and sysctl.proc_translated
so the script prints the native-ARM recommendations when hardware is Apple
Silicon even if uname -m reports x86_64.
- Around line 175-180: The script uses GNU `timeout` which isn't available on
stock macOS, causing GPU_INFO to be empty; replace that call with a portable
timeout strategy (e.g., use a Perl alarm wrapper: run system_profiler via `perl
-e 'alarm shift; exec `@ARGV`' 15 system_profiler SPDisplaysDataType` or implement
a shell watchdog that spawns system_profiler in background, records its PID,
sleeps 15s then kills the PID if still running) and update the GPU detection
block that sets GPU_INFO to use the chosen portable runner (referencing GPU_INFO
and system_profiler in the same block); optionally detect gtimeout and prefer it
if present as a final fallback.
In `@test/setup-apple.test.js`:
- Around line 179-250: The tests in the "Docker socket detection" and "Docker
memory allocation checks" suites are nondeterministic because they use real
filesystem and runtime state (fs.existsSync, os.homedir, process.platform,
runSetupApple) and short-circuit with assert.ok(true); replace those
placeholders by mocking the environment: stub process.platform and os.homedir,
create temporary directories and Unix sockets at the paths built with path.join
(e.g., ".docker/run/docker.sock", ".colima/.../docker.sock"), and stub external
commands used by the setup logic (uname, docker, curl, system_profiler) to
return deterministic outputs; then call runSetupApple() (and any other setup
functions exercised in the surrounding ranges) and assert on the expected
strings ("Docker Desktop detected", "Colima detected", memory warning messages)
instead of assert.ok(true) so CI covers both presence and absence branches
reliably.
- Around line 14-35: runSetupApple currently runs `bash` via PATH lookup which
can fail when tests override PATH with a mockBin; change the execSync invocation
so the shell is invoked directly (use the absolute `/bin/bash` executable) and
pass SETUP_APPLE_SCRIPT as its argument, or alternately ensure the env passed to
execSync preserves the original system PATH (e.g., merge process.env.PATH into
env) so callers that replace PATH with mock bins don't cause `bash: command not
found`; update the execSync call in runSetupApple to reference `/bin/bash` or
merge PATH in the env before running the script.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: e5961b9c-047a-4126-be69-b6fe2c81b3ed
📒 Files selected for processing (4)
bin/nemoclaw.jsscripts/install-openshell.shscripts/setup-apple.shtest/setup-apple.test.js
| describe("Docker socket detection", () => { | ||
| it("fails when no Docker socket is found", function () { | ||
| if (process.platform !== "darwin") { | ||
| this.skip(); | ||
| return; | ||
| } | ||
|
|
||
| // This is hard to test in isolation without mocking filesystem | ||
| // We'd need to ensure no Docker sockets exist | ||
| assert.ok(true, "Docker socket detection requires filesystem mocking"); | ||
| }); | ||
|
|
||
| it("detects Docker Desktop socket", function () { | ||
| if (process.platform !== "darwin") { | ||
| this.skip(); | ||
| return; | ||
| } | ||
|
|
||
| // Check if Docker Desktop socket exists | ||
| const desktopSocket = path.join(os.homedir(), ".docker/run/docker.sock"); | ||
| if (fs.existsSync(desktopSocket)) { | ||
| const result = runSetupApple(); | ||
| if (result.out.includes("Docker Desktop detected")) { | ||
| assert.ok(true, "Docker Desktop detected successfully"); | ||
| } | ||
| } else { | ||
| assert.ok(true, "No Docker Desktop socket found - skipping"); | ||
| } | ||
| }); | ||
|
|
||
| it("detects Colima socket", function () { | ||
| if (process.platform !== "darwin") { | ||
| this.skip(); | ||
| return; | ||
| } | ||
|
|
||
| // Check if Colima socket exists | ||
| const colimaSocket1 = path.join(os.homedir(), ".colima/default/docker.sock"); | ||
| const colimaSocket2 = path.join(os.homedir(), ".config/colima/default/docker.sock"); | ||
|
|
||
| if (fs.existsSync(colimaSocket1) || fs.existsSync(colimaSocket2)) { | ||
| const result = runSetupApple(); | ||
| if (result.out.includes("Colima detected")) { | ||
| assert.ok(true, "Colima detected successfully"); | ||
| } | ||
| } else { | ||
| assert.ok(true, "No Colima socket found - skipping"); | ||
| } | ||
| }); | ||
|
|
||
| it("fails when Docker is installed but not responding", function () { | ||
| if (process.platform !== "darwin") { | ||
| this.skip(); | ||
| return; | ||
| } | ||
|
|
||
| // This requires Docker to be installed but not running - hard to test reliably | ||
| assert.ok(true, "Docker responsiveness test requires specific setup"); | ||
| }); | ||
| }); | ||
|
|
||
| describe("Docker memory allocation checks", () => { | ||
| it("warns when Docker memory is less than 8GB", function () { | ||
| if (process.platform !== "darwin") { | ||
| this.skip(); | ||
| return; | ||
| } | ||
|
|
||
| // This requires a running Docker with low memory allocation | ||
| // Hard to test without actually configuring Docker | ||
| assert.ok(true, "Docker memory check requires running Docker instance"); | ||
| }); |
There was a problem hiding this comment.
Most of these cases don't assert the branch they claim to cover.
Lines 186-189, 235-236, 247-249, 311-314, 447-449, and 640-642 all pass with assert.ok(true, ...), and many surrounding cases only assert if the current host already has Docker/Ollama/OpenShell installed. That leaves the new setup logic largely untested in CI. Please make these branches deterministic with mocked uname/docker/curl/system_profiler, a fake HOME, and temporary Unix sockets instead of depending on local machine state.
Also applies to: 283-394, 397-450, 453-660
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@test/setup-apple.test.js` around lines 179 - 250, The tests in the "Docker
socket detection" and "Docker memory allocation checks" suites are
nondeterministic because they use real filesystem and runtime state
(fs.existsSync, os.homedir, process.platform, runSetupApple) and short-circuit
with assert.ok(true); replace those placeholders by mocking the environment:
stub process.platform and os.homedir, create temporary directories and Unix
sockets at the paths built with path.join (e.g., ".docker/run/docker.sock",
".colima/.../docker.sock"), and stub external commands used by the setup logic
(uname, docker, curl, system_profiler) to return deterministic outputs; then
call runSetupApple() (and any other setup functions exercised in the surrounding
ranges) and assert on the expected strings ("Docker Desktop detected", "Colima
detected", memory warning messages) instead of assert.ok(true) so CI covers both
presence and absence branches reliably.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
scripts/install-openshell.sh (1)
28-58:⚠️ Potential issue | 🔴 CriticalChecksum verification still targets a different filename than the downloaded asset.
Line 28 saves the tarball as
openshell.tar.gz, but Line 48 verifies the checksum entry for$ASSETviashasum -c, which expects the checksum-listed filename to exist in the working directory. This will break verification when checksums are published for the asset filename. The same mismatch propagates to extraction on Line 58.Proposed fix
-if ! curl -fsSL "$DOWNLOAD_URL" -o "$tmpdir/openshell.tar.gz" 2>"$tmpdir/curl.err"; then +if ! curl -fsSL "$DOWNLOAD_URL" -o "$tmpdir/$ASSET" 2>"$tmpdir/curl.err"; then @@ -if ! file "$tmpdir/openshell.tar.gz" 2>/dev/null | grep -q "gzip compressed data"; then +if ! file "$tmpdir/$ASSET" 2>/dev/null | grep -q "gzip compressed data"; then @@ -if ! tar xzf "$tmpdir/openshell.tar.gz" -C "$tmpdir" 2>"$tmpdir/tar.err"; then +if ! tar xzf "$tmpdir/$ASSET" -C "$tmpdir" 2>"$tmpdir/tar.err"; then#!/bin/bash set -euo pipefail python - <<'PY' from pathlib import Path p = Path("scripts/install-openshell.sh") lines = p.read_text().splitlines() download = next((l.strip() for l in lines if 'curl -fsSL "$DOWNLOAD_URL"' in l), None) verify = next((l.strip() for l in lines if 'shasum -a 256 -c -s' in l), None) extract = next((l.strip() for l in lines if 'tar xzf "$tmpdir/' in l), None) print("download:", download) print("verify :", verify) print("extract:", extract) if download and verify and 'openshell.tar.gz' in download and '$ASSET' in verify: print("\nMismatch confirmed: local download filename differs from checksum target filename.") else: print("\nNo mismatch detected in current script shape.") PY🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/install-openshell.sh` around lines 28 - 58, The checksum verification fails because the script saves the download as "$tmpdir/openshell.tar.gz" but verifies and extracts using "$ASSET"; fix by making the downloaded filename and subsequent verification/extraction target the same symbol: change the curl output to "$tmpdir/$ASSET" (replace occurrences of "$tmpdir/openshell.tar.gz" with "$tmpdir/$ASSET") and update the tar extraction and grep/shasum invocation to use "$tmpdir/$ASSET"/"$ASSET" consistently (i.e., grep -F "$ASSET" SHA256SUMS | shasum -a 256 -c -s should run in the directory containing "$ASSET" or run shasum against the checksum entry while referencing "$tmpdir/$ASSET"), ensuring the variables CHECKSUM_URL, SHA256SUMS, grep -F "$ASSET", shasum -a 256 -c -s, and tar xzf are all aligned to the same filename.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@scripts/install-openshell.sh`:
- Around line 41-55: The installer currently treats a missing checksum as a
warning and proceeds; change this to fail by default unless an explicit opt-in
override is provided (e.g. an env var like INSECURE_INSTALL or SKIP_CHECKSUM).
Update the branch that handles curl -fsSL "$CHECKSUM_URL" (and the else that
prints "Warning: No checksum file available...") so that when SHA256SUMS is not
fetched or when grep -qF "$ASSET" fails, the script calls fail "Checksum missing
for $ASSET; aborting installation" (or similar) unless the override env var is
set, and document/check the override at the top of the script; keep the existing
checksum verification using (cd "$tmpdir" && grep -F "$ASSET" SHA256SUMS |
shasum -a 256 -c -s) and only skip it when the explicit override is present.
---
Duplicate comments:
In `@scripts/install-openshell.sh`:
- Around line 28-58: The checksum verification fails because the script saves
the download as "$tmpdir/openshell.tar.gz" but verifies and extracts using
"$ASSET"; fix by making the downloaded filename and subsequent
verification/extraction target the same symbol: change the curl output to
"$tmpdir/$ASSET" (replace occurrences of "$tmpdir/openshell.tar.gz" with
"$tmpdir/$ASSET") and update the tar extraction and grep/shasum invocation to
use "$tmpdir/$ASSET"/"$ASSET" consistently (i.e., grep -F "$ASSET" SHA256SUMS |
shasum -a 256 -c -s should run in the directory containing "$ASSET" or run
shasum against the checksum entry while referencing "$tmpdir/$ASSET"), ensuring
the variables CHECKSUM_URL, SHA256SUMS, grep -F "$ASSET", shasum -a 256 -c -s,
and tar xzf are all aligned to the same filename.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 4125749a-24d3-400e-b4c7-2f5d17ff3153
📒 Files selected for processing (2)
scripts/install-openshell.shscripts/setup-apple.sh
🚧 Files skipped from review as they are similar to previous changes (1)
- scripts/setup-apple.sh
Critical fixes based on code review feedback: install-openshell.sh: - Fix checksum verification filename mismatch by saving download as $ASSET instead of openshell.tar.gz to match SHA256SUMS entries - Ensures shasum -c can verify the downloaded file correctly setup-apple.sh: - Use detected DOCKER_SOCKET for all docker commands via DOCKER_HOST env var to fix issues with multiple Docker contexts - Add OLLAMA_HOST validation to reject loopback addresses (localhost, 127.*, ::1) and warn users that containers cannot reach loopback bindings - Fix Rosetta 2 detection by checking hw.optional.arm64 first to detect Apple Silicon hardware even when uname reports x86_64 under translation - Replace GNU timeout with portable solution: try gtimeout, fall back to Perl alarm wrapper, or run without timeout if neither available All 86 tests pass. Manual testing verified on M3 Max.
There was a problem hiding this comment.
🧹 Nitpick comments (1)
scripts/install-openshell.sh (1)
34-37: Consider explicitfilecommand check or consistent error handling.If the
filecommand is unavailable,2>/dev/nullsuppresses the error, causing a misleading message about "not a valid gzip tarball" rather than indicating the missing dependency. Line 70 doesn't redirectfileerrors, creating inconsistency.♻️ Suggested consistency fix
Either check for
fileupfront or handle both locations consistently:+# Verify required tools +command -v file >/dev/null 2>&1 || fail "Required command 'file' not found" + # Validate the downloaded file is actually a gzip tarball -if ! file "$tmpdir/$ASSET" 2>/dev/null | grep -q "gzip compressed data"; then +if ! file "$tmpdir/$ASSET" | grep -q "gzip compressed data"; then fail "Downloaded file is not a valid gzip tarball. GitHub may be unavailable or the release may be missing." fi🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/install-openshell.sh` around lines 34 - 37, The script currently masks errors from the file utility when validating "$tmpdir/$ASSET" (leading to a misleading "not a valid gzip tarball" via fail), so either add an explicit availability check for the file command (e.g., use command -v file and fail with a clear message if missing) before any validation or make the two uses of file consistent by not swallowing stderr (remove 2>/dev/null) and surface file errors into fail; update the validation around "$tmpdir/$ASSET" and the earlier/other file usage (line ~70) to use the same approach so missing `file` is reported instead of a misleading tarball error.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/install-openshell.sh`:
- Around line 34-37: The script currently masks errors from the file utility
when validating "$tmpdir/$ASSET" (leading to a misleading "not a valid gzip
tarball" via fail), so either add an explicit availability check for the file
command (e.g., use command -v file and fail with a clear message if missing)
before any validation or make the two uses of file consistent by not swallowing
stderr (remove 2>/dev/null) and surface file errors into fail; update the
validation around "$tmpdir/$ASSET" and the earlier/other file usage (line ~70)
to use the same approach so missing `file` is reported instead of a misleading
tarball error.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 2a7a8e13-27bc-4866-8e2d-9bf2558597ff
📒 Files selected for processing (2)
scripts/install-openshell.shscripts/setup-apple.sh
🚧 Files skipped from review as they are similar to previous changes (1)
- scripts/setup-apple.sh
There was a problem hiding this comment.
♻️ Duplicate comments (1)
scripts/install-openshell.sh (1)
44-58:⚠️ Potential issue | 🟠 MajorFail closed when checksum metadata is unavailable.
Line 48 and Line 57 still allow installation to continue without a verified checksum. That keeps an unverified install path open in a hardened installer; please abort by default and require an explicit insecure override.
🔐 Suggested fail-closed patch
CHECKSUM_URL="https://github.com/NVIDIA/OpenShell/releases/latest/download/SHA256SUMS" if curl -fsSL "$CHECKSUM_URL" -o "$tmpdir/SHA256SUMS" 2>/dev/null; then @@ - if ! grep -qF "$ASSET" "$tmpdir/SHA256SUMS"; then - printf "Warning: Checksum not found for %s in SHA256SUMS\n" "$ASSET" >&2 + if ! grep -qF "$ASSET" "$tmpdir/SHA256SUMS"; then + if [ "${NEMOCLAW_ALLOW_UNVERIFIED:-0}" = "1" ]; then + printf "Warning: Checksum not found for %s; continuing due to NEMOCLAW_ALLOW_UNVERIFIED=1\n" "$ASSET" >&2 + else + fail "Checksum not found for $ASSET in SHA256SUMS; aborting unverified install" + fi else @@ else - printf "Warning: No checksum file available, skipping integrity verification\n" >&2 + if [ "${NEMOCLAW_ALLOW_UNVERIFIED:-0}" = "1" ]; then + printf "Warning: No checksum file available; continuing due to NEMOCLAW_ALLOW_UNVERIFIED=1\n" >&2 + else + fail "No checksum file available; aborting unverified install" + fi fi🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/install-openshell.sh` around lines 44 - 58, The script currently prints warnings and continues when checksum metadata is missing or the ASSET entry isn't found; change both branches so the installer fails by default using the existing fail function instead of printf, and only allow continuation when an explicit override environment variable (e.g., INSECURE_ALLOW_INSTALL or a --insecure flag) is present and truthy; update the branch handling the grep -qF "$ASSET" check and the else branch for the curl -fsSL "$CHECKSUM_URL" failure to call fail "Checksum metadata missing or ASSET not found; aborting" unless the override is set, and ensure the override check is performed consistently in both places (use the current fail(), CHECKSUM_URL, tmpdir/SHA256SUMS, and ASSET identifiers).
🧹 Nitpick comments (1)
scripts/install-openshell.sh (1)
85-85: Use the installed binary path for the post-install version probe.Line 85 runs
openshell --versionviaPATH, which can resolve a different binary than the one just installed. Prefer/usr/local/bin/openshell --versionhere.♻️ Minimal patch
-printf "openshell %s\n" "$(openshell --version 2>&1 || echo 'installed')" +printf "openshell %s\n" "$(/usr/local/bin/openshell --version 2>&1 || echo 'installed')"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/install-openshell.sh` at line 85, The post-install probe currently invokes openshell via PATH ("openshell --version") which may call a different binary; update the probe in scripts/install-openshell.sh to call the installed binary directly (e.g., /usr/local/bin/openshell --version) so the version check targets the just-installed executable and still falls back gracefully if missing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@scripts/install-openshell.sh`:
- Around line 44-58: The script currently prints warnings and continues when
checksum metadata is missing or the ASSET entry isn't found; change both
branches so the installer fails by default using the existing fail function
instead of printf, and only allow continuation when an explicit override
environment variable (e.g., INSECURE_ALLOW_INSTALL or a --insecure flag) is
present and truthy; update the branch handling the grep -qF "$ASSET" check and
the else branch for the curl -fsSL "$CHECKSUM_URL" failure to call fail
"Checksum metadata missing or ASSET not found; aborting" unless the override is
set, and ensure the override check is performed consistently in both places (use
the current fail(), CHECKSUM_URL, tmpdir/SHA256SUMS, and ASSET identifiers).
---
Nitpick comments:
In `@scripts/install-openshell.sh`:
- Line 85: The post-install probe currently invokes openshell via PATH
("openshell --version") which may call a different binary; update the probe in
scripts/install-openshell.sh to call the installed binary directly (e.g.,
/usr/local/bin/openshell --version) so the version check targets the
just-installed executable and still falls back gracefully if missing.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: d3eef83f-4439-4f23-85bf-6c8fe819593f
📒 Files selected for processing (1)
scripts/install-openshell.sh
… version check - Require NEMOCLAW_ALLOW_UNVERIFIED=1 to bypass missing checksums (fail-closed security model) - Use /usr/local/bin/openshell for version check instead of PATH lookup - Addresses CodeRabbit feedback from PR NVIDIA#274
There was a problem hiding this comment.
🧹 Nitpick comments (2)
scripts/install-openshell.sh (2)
93-94: Minor: Version output may duplicate program name.If
openshell --versionoutputs something likeopenshell 1.2.3, the result would beopenshell openshell 1.2.3. Consider capturing just the version number or using the raw output directly.♻️ Suggested refinement
# Verify installation using the full path to ensure we check the just-installed binary -printf "openshell %s\n" "$(/usr/local/bin/openshell --version 2>&1 || echo 'installed')" +printf "openshell installed: %s\n" "$(/usr/local/bin/openshell --version 2>&1 || echo '(version unknown)')"Or simply print the raw output:
-printf "openshell %s\n" "$(/usr/local/bin/openshell --version 2>&1 || echo 'installed')" +/usr/local/bin/openshell --version 2>&1 || printf "openshell installed successfully\n"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/install-openshell.sh` around lines 93 - 94, The current verification prints a prefixed program name then the full output of "/usr/local/bin/openshell --version", which can duplicate the name (e.g., "openshell openshell 1.2.3"); change the check in scripts/install-openshell.sh so it either prints the raw version output from the command (use the command's stdout/stderr directly) or capture and extract only the version token from the output of "/usr/local/bin/openshell --version" before passing it to printf, updating the printf invocation that references "/usr/local/bin/openshell --version" accordingly.
55-55: Consider adding a fallback forsha256sumon minimal Linux systems.The script uses
shasumfor checksum verification (line 55), which is available on macOS and most desktop Linux distributions. However, some minimal or musl-based Linux systems may only havesha256sum. Following the pattern already used for thefilecommand check (line 23), consider detecting the available checksum tool upfront and using a fallback.♻️ Suggested enhancement (optional)
Add after line 23:
# Determine checksum command if command -v shasum >/dev/null 2>&1; then SHASUM_CMD="shasum -a 256" elif command -v sha256sum >/dev/null 2>&1; then SHASUM_CMD="sha256sum" else fail "Required command 'shasum' or 'sha256sum' not found" fiThen update line 55:
if ! (cd "$tmpdir" && grep -F "$ASSET" SHA256SUMS | $SHASUM_CMD -c -s); then🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/install-openshell.sh` at line 55, Add detection for available checksum tool and use a variable instead of hardcoding shasum: check for shasum then sha256sum and set SHASUM_CMD accordingly (or call fail if neither found), then replace the hardcoded invocation in the verification step that uses (cd "$tmpdir" && grep -F "$ASSET" SHA256SUMS | shasum -a 256 -c -s) to use $SHASUM_CMD -c -s so the script works on minimal/musl systems; reference the variable name SHASUM_CMD and the existing variables ASSET, tmpdir and SHA256SUMS when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/install-openshell.sh`:
- Around line 93-94: The current verification prints a prefixed program name
then the full output of "/usr/local/bin/openshell --version", which can
duplicate the name (e.g., "openshell openshell 1.2.3"); change the check in
scripts/install-openshell.sh so it either prints the raw version output from the
command (use the command's stdout/stderr directly) or capture and extract only
the version token from the output of "/usr/local/bin/openshell --version" before
passing it to printf, updating the printf invocation that references
"/usr/local/bin/openshell --version" accordingly.
- Line 55: Add detection for available checksum tool and use a variable instead
of hardcoding shasum: check for shasum then sha256sum and set SHASUM_CMD
accordingly (or call fail if neither found), then replace the hardcoded
invocation in the verification step that uses (cd "$tmpdir" && grep -F "$ASSET"
SHA256SUMS | shasum -a 256 -c -s) to use $SHASUM_CMD -c -s so the script works
on minimal/musl systems; reference the variable name SHASUM_CMD and the existing
variables ASSET, tmpdir and SHA256SUMS when making the change.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 8197b5df-d78a-4595-b987-398e8833d005
📒 Files selected for processing (1)
scripts/install-openshell.sh
914a439 to
ec8c6f7
Compare
Critical fixes based on code review feedback: install-openshell.sh: - Fix checksum verification filename mismatch by saving download as $ASSET instead of openshell.tar.gz to match SHA256SUMS entries - Ensures shasum -c can verify the downloaded file correctly setup-apple.sh: - Use detected DOCKER_SOCKET for all docker commands via DOCKER_HOST env var to fix issues with multiple Docker contexts - Add OLLAMA_HOST validation to reject loopback addresses (localhost, 127.*, ::1) and warn users that containers cannot reach loopback bindings - Fix Rosetta 2 detection by checking hw.optional.arm64 first to detect Apple Silicon hardware even when uname reports x86_64 under translation - Replace GNU timeout with portable solution: try gtimeout, fall back to Perl alarm wrapper, or run without timeout if neither available All 86 tests pass. Manual testing verified on M3 Max.
Critical fixes based on code review feedback: install-openshell.sh: - Fix checksum verification filename mismatch by saving download as $ASSET instead of openshell.tar.gz to match SHA256SUMS entries - Ensures shasum -c can verify the downloaded file correctly setup-apple.sh: - Use detected DOCKER_SOCKET for all docker commands via DOCKER_HOST env var to fix issues with multiple Docker contexts - Add OLLAMA_HOST validation to reject loopback addresses (localhost, 127.*, ::1) and warn users that containers cannot reach loopback bindings - Fix Rosetta 2 detection by checking hw.optional.arm64 first to detect Apple Silicon hardware even when uname reports x86_64 under translation - Replace GNU timeout with portable solution: try gtimeout, fall back to Perl alarm wrapper, or run without timeout if neither available All 86 tests pass. Manual testing verified on M3 Max.
ec8c6f7 to
2bd6d9f
Compare
Critical fixes based on code review feedback: install-openshell.sh: - Fix checksum verification filename mismatch by saving download as $ASSET instead of openshell.tar.gz to match SHA256SUMS entries - Ensures shasum -c can verify the downloaded file correctly setup-apple.sh: - Use detected DOCKER_SOCKET for all docker commands via DOCKER_HOST env var to fix issues with multiple Docker contexts - Add OLLAMA_HOST validation to reject loopback addresses (localhost, 127.*, ::1) and warn users that containers cannot reach loopback bindings - Fix Rosetta 2 detection by checking hw.optional.arm64 first to detect Apple Silicon hardware even when uname reports x86_64 under translation - Replace GNU timeout with portable solution: try gtimeout, fall back to Perl alarm wrapper, or run without timeout if neither available All 86 tests pass. Manual testing verified on M3 Max.
… version check - Require NEMOCLAW_ALLOW_UNVERIFIED=1 to bypass missing checksums (fail-closed security model) - Use /usr/local/bin/openshell for version check instead of PATH lookup - Addresses CodeRabbit feedback from PR NVIDIA#274
2bd6d9f to
051315b
Compare
* feat(tui): add log copy and visual selection mode Add clipboard support for the TUI log viewer using OSC 52 escape sequences. Users can copy individual log lines (y), the visible viewport (Y), or enter visual selection mode (v) to select a range of lines with j/k and yank with y. - Add clipboard module with OSC 52 base64 encoding - Add format_log_line_plain() for plain-text log rendering - Add visual selection mode with highlight styling and status bar - Context-switch nav bar hints between normal and visual modes - Add 7 unit tests for plain-text log formatting Closes NVIDIA#274 * fix(tui): write OSC 52 to /dev/tty instead of stdout ratatui owns stdout via the alternate screen buffer, so OSC 52 escape sequences written to stdout are swallowed by the backend. Write directly to /dev/tty to bypass the buffer and reach the terminal emulator.
Add a new `nemoclaw setup-apple` command that validates macOS-specific prerequisites before running `nemoclaw onboard`: - Verify macOS platform and Node.js 20+ - Check Docker Desktop or Colima socket and memory allocation - Check/recommend Ollama for local inference with OLLAMA_HOST binding - Install openshell CLI if missing (Darwin/aarch64) - Detect Apple GPU chip, cores, and unified memory - Warn about nvm PATH issues (NVIDIA#120) - Print next steps Unlike setup-spark, this command does not require sudo since Docker Desktop on macOS needs no daemon.json edits or group changes.
Add 30 tests covering all aspects of the setup-apple.sh script: - Platform detection (macOS, Apple Silicon) - Node.js version validation - Docker socket detection (Desktop and Colima) - Docker memory allocation checks - Ollama installation and configuration - OpenShell CLI installation - Apple GPU detection and unified memory - nvm warnings - CLI integration via nemoclaw setup-apple All tests pass on macOS. Tests are environment-aware and skip appropriately on non-macOS platforms.
… robust error handling Security improvements: - Add SHA256 checksum verification when available - Validate downloaded file is actually a gzip tarball - Validate extracted binary is a valid executable - Add trap for cleanup on error - Better error messages with stderr redirection - Prompt user before sudo with explanatory message Error handling: - Explicit error capture for curl and tar operations - File type validation before extraction - Binary existence check after extraction - Use printf instead of echo for consistency File permissions: - Make script executable (chmod +x)
…er UX Architecture & Platform Detection: - Add Apple Silicon (ARM64) vs Intel Mac detection - Add Rosetta 2 translation detection with performance warnings - Validate HOME environment variable for security Security Improvements: - Replace echo -e with printf to prevent escape sequence injection - Fix Docker memory check with proper numeric validation - Add timeout (15s) to system_profiler to prevent hanging - Send error messages to stderr appropriately User Experience Improvements: - Add Colima-specific DNS warning (handled during onboard) - Add Colima-specific memory increase command - Improve Ollama guidance with clearer skip instructions - Add sudo warning before OpenShell CLI installation - Better Node.js install instructions (brew + nodejs.org) - Improve next steps messaging with detailed onboard actions - Add visual spacing (echo "") between sections Error Handling: - Fix Docker memory allocation check (validate numeric before comparison) - Handle system_profiler timeout gracefully - Better error messaging for GPU detection failures All 86 tests pass.
Security Fixes: - Use grep -F for literal string matching in checksum verification (prevents regex injection via ASSET variable) - Use subshell for checksum verification to avoid directory changes - Add grep -F to Colima detection for literal string matching Code Quality Improvements: - Standardize helper functions to use echo -e (consistent with setup-spark) - Improve HOME validation with clearer error messages for each failure mode - Fix Docker memory check to validate DOCKER_MEM_BYTES before arithmetic - Send warnings to stderr for proper error handling All 86 tests pass. Manual testing verified on M3 Max.
Critical fixes based on code review feedback: install-openshell.sh: - Fix checksum verification filename mismatch by saving download as $ASSET instead of openshell.tar.gz to match SHA256SUMS entries - Ensures shasum -c can verify the downloaded file correctly setup-apple.sh: - Use detected DOCKER_SOCKET for all docker commands via DOCKER_HOST env var to fix issues with multiple Docker contexts - Add OLLAMA_HOST validation to reject loopback addresses (localhost, 127.*, ::1) and warn users that containers cannot reach loopback bindings - Fix Rosetta 2 detection by checking hw.optional.arm64 first to detect Apple Silicon hardware even when uname reports x86_64 under translation - Replace GNU timeout with portable solution: try gtimeout, fall back to Perl alarm wrapper, or run without timeout if neither available All 86 tests pass. Manual testing verified on M3 Max.
Address CodeRabbit nitpick: - Add upfront check for 'file' command to provide clear error if missing - Remove 2>/dev/null from file validation to surface actual errors - Ensures consistent error handling across both file command usages Prevents misleading "not a valid gzip tarball" error when file command is not available on the system.
… version check - Require NEMOCLAW_ALLOW_UNVERIFIED=1 to bypass missing checksums (fail-closed security model) - Use /usr/local/bin/openshell for version check instead of PATH lookup - Addresses CodeRabbit feedback from PR NVIDIA#274
Adds usage, examples, and next-step guidance when running nemoclaw setup-apple --help, matching the pattern used by deploy. Partially addresses NVIDIA#755.
Upstream migrated to "type": "module" and vitest. Convert require() to import and remove node:test dependency.
051315b to
bf5d1ef
Compare
|
Thanks for the PR. This overlaps with #285, which was opened the same day with the same If your implementation has capabilities not covered by #285, feel free to leave a comment there noting what's different. |
Summary
Adds
nemoclaw setup-apple— a macOS-equivalent ofsetup-sparkthat validates and configures Apple Silicon (and Intel) Macs for NemoClaw.What it does
OLLAMA_HOST=0.0.0.0binding for Docker accesssystem_profiler(with 15s timeout)setup-spark, macOS doesn't need daemon.json or group changesSecurity improvements
install-openshell.shhardened:setup-apple.sh:printfinstead ofecho -e(injection prevention)system_profiler(can hang on some Macs)Test results
test/setup-apple.test.js— all passChanges
scripts/setup-apple.shscripts/install-openshell.shbin/nemoclaw.jssetup-applecommand + help texttest/setup-apple.test.jsPartially addresses #260 (
setup-appleitem)Testing on your Mac
Summary by CodeRabbit
New Features
Bug Fixes
Tests