feat(onboard): add user-local Ollama install fallback for non-interactive Linux (#4114)#4135
Conversation
…tive Linux The `install-ollama` provider previously called `https://ollama.com/install.sh` unconditionally. The official installer is sudo-bound, so a headless `NEMOCLAW_NON_INTERACTIVE=1` run without passwordless sudo crashed at the sudo password prompt mid-install. Replicate the binary-extraction portion of `install.sh` (lines 159-187) into `src/lib/onboard/install-ollama-linux.ts`, targeting `${HOME}/.local` and running without sudo, systemd, or the `ollama` system user. Use the same auto-detect decision tree as `scripts/install-openshell.sh` (root or passwordless sudo → system; non-interactive headless → user-local; interactive → system so sudo can prompt). Add `NEMOCLAW_OLLAMA_INSTALL_MODE` for explicit override. Resolves #4114 Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
📝 WalkthroughWalkthroughAdds a new Linux installer module that selects system vs user-local Ollama installs, integrates it into onboarding (replacing inline shell logic), updates docs for install modes and zstd guidance, and adds comprehensive tests for mode decision and both install paths. ChangesLinux Ollama Install Modes
Sequence Diagram(s)sequenceDiagram
participant Onboard as onboard.ts
participant Decide as decideInstallOllamaLinuxMode
participant System as installOllamaSystem
participant UserLocal as installOllamaUserLocal
participant Daemon as OllamaDaemon
Onboard->>Decide: resolve mode (env / root / sudo / TTY)
Decide-->>Onboard: "user-local"
Onboard->>UserLocal: download & extract to ~/.local
UserLocal->>Daemon: start serve (127.0.0.1) via nohup
UserLocal->>UserLocal: waitForHttp readiness
UserLocal-->>Onboard: InstallOllamaLinuxResult{ok,true}
Onboard->>Decide: resolve mode (env / root / sudo / TTY)
Decide-->>Onboard: "system"
Onboard->>System: run official install.sh (may use sudo)
System->>System: apply systemd loopback override
System->>Daemon: systemd start or manual fallback
System->>System: waitForHttp readiness
System-->>Onboard: InstallOllamaLinuxResult{ok,true}
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add Comment |
|
🌿 Preview your docs: https://nvidia-preview-pr-4135.docs.buildwithfern.com/nemoclaw |
E2E Advisor RecommendationRequired E2E: Dispatch hint: Auto-dispatched E2E: Full advisor summaryE2E Recommendation AdvisorBase: Required E2E
Optional E2E
New E2E recommendations
Dispatch hint
|
E2E Scenario Advisor RecommendationRequired scenario E2E: None Full scenario advisor summaryE2E Scenario AdvisorBase: Required scenario E2E
Optional scenario E2E
Relevant changed files
|
Selective E2E Results —
|
| Job | Result |
|---|---|
| gpu-e2e | ⏭️ skipped |
PR Review AdvisorFindings: 1 needs attention, 1 worth checking, 0 nice ideas Review findings🛠️ Needs attention
🔎 Worth checking
🌱 Nice ideas
Since last review detailsCurrent findings:
This is an automated advisory review. A human maintainer must make the final merge decision. |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
docs/inference/use-local-inference.mdx (2)
47-47: ⚡ Quick winSplit this into one sentence per source line.
Line 47 currently packs multiple sentences onto one line. Please break each sentence onto its own line.
As per coding guidelines, "One sentence per line in source (makes diffs readable). Flag paragraphs where multiple sentences appear on the same line."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/inference/use-local-inference.mdx` at line 47, The paragraph beginning "The user-local install replicates only the binary extraction step of the official installer." currently contains multiple sentences on one source line; split it so each sentence is on its own line (e.g., break after "...official installer.", after "It downloads the release tarball, extracts it to `${HOME}/.local`, and launches `${HOME}/.local/bin/ollama serve` once.", after "It does not configure a systemd service, does not create the `ollama` system user, and does not install CUDA drivers,", and after "so the daemon must be relaunched manually after a reboot."), ensuring one sentence per line for the paragraph that starts with that phrase.
39-39: ⚡ Quick winUse active voice for the mode-selection sentence.
Line 39 is passive ("The choice is made automatically"). Please rewrite it in active voice.
As per coding guidelines, "Active voice required. Flag passive constructions."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/inference/use-local-inference.mdx` at line 39, Replace the passive sentence "The choice is made automatically" with an active-voice sentence; e.g., change it to "The system selects the mode automatically" (or "We automatically select the mode") so the document uses active voice for the mode-selection statement.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/lib/onboard/install-ollama-linux.ts`:
- Around line 250-259: The shell commands in install-ollama-linux.ts interpolate
installDir and binPath directly into strings passed to runShellImpl (see the
lines building commands with zstUrl/tgzUrl and the tar/curl pipelines), which
breaks if the home path contains single quotes; update those call sites to
safely quote or escape shell arguments (installDir and binPath) before building
the command string—either use a shell-quoting helper (e.g., a shellEscape
function) around installDir/binPath or stop interpolating and call
runShellImpl/child_process with an argv array so arguments are passed safely;
ensure all occurrences that reference installDir/binPath (including the commands
using zstUrl, tgzUrl and the tar/curl pipelines) are updated.
In `@test/onboard-selection.test.ts`:
- Around line 5800-5813: The spawnSync call that creates `result` can hang if a
sudo prompt appears; update the options object passed to
`spawnSync(process.execPath, [scriptPath], {...})` to include a `timeout` (e.g.,
5000–10000 ms) so the test fails deterministically instead of hanging, by adding
`timeout: <ms>` to the options; keep the rest of the env and encoding settings
the same and adjust any assertions if needed to account for a timeout-terminated
process.
---
Nitpick comments:
In `@docs/inference/use-local-inference.mdx`:
- Line 47: The paragraph beginning "The user-local install replicates only the
binary extraction step of the official installer." currently contains multiple
sentences on one source line; split it so each sentence is on its own line
(e.g., break after "...official installer.", after "It downloads the release
tarball, extracts it to `${HOME}/.local`, and launches
`${HOME}/.local/bin/ollama serve` once.", after "It does not configure a systemd
service, does not create the `ollama` system user, and does not install CUDA
drivers,", and after "so the daemon must be relaunched manually after a
reboot."), ensuring one sentence per line for the paragraph that starts with
that phrase.
- Line 39: Replace the passive sentence "The choice is made automatically" with
an active-voice sentence; e.g., change it to "The system selects the mode
automatically" (or "We automatically select the mode") so the document uses
active voice for the mode-selection statement.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 4e3ae3a9-9cba-4067-806c-6471ca34fa59
📒 Files selected for processing (6)
docs/inference/use-local-inference.mdxdocs/reference/commands.mdxsrc/lib/onboard.tssrc/lib/onboard/install-ollama-linux.test.tssrc/lib/onboard/install-ollama-linux.tstest/onboard-selection.test.ts
| const result = spawnSync(process.execPath, [scriptPath], { | ||
| cwd: repoRoot, | ||
| encoding: "utf-8", | ||
| env: { | ||
| ...process.env, | ||
| HOME: tmpDir, | ||
| PATH: `${fakeBin}:${process.env.PATH || ""}`, | ||
| NEMOCLAW_NON_INTERACTIVE: "1", | ||
| NEMOCLAW_PROVIDER: "ollama", | ||
| NEMOCLAW_YES: "1", | ||
| // No NEMOCLAW_OLLAMA_INSTALL_MODE — auto-detect routes through | ||
| // user-local because the stubbed `sudo -n true` returns exit 1. | ||
| }, | ||
| }); |
There was a problem hiding this comment.
Add a spawnSync timeout to this fallback regression test.
This case is specifically guarding against a non-interactive sudo hang. Without timeout on spawnSync, a regression back to a password prompt can wedge the worker instead of failing deterministically.
Suggested fix
const result = spawnSync(process.execPath, [scriptPath], {
cwd: repoRoot,
encoding: "utf-8",
+ timeout: PROVIDER_SELECTION_TEST_TIMEOUT_MS,
env: {
...process.env,
HOME: tmpDir,
PATH: `${fakeBin}:${process.env.PATH || ""}`,
NEMOCLAW_NON_INTERACTIVE: "1",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const result = spawnSync(process.execPath, [scriptPath], { | |
| cwd: repoRoot, | |
| encoding: "utf-8", | |
| env: { | |
| ...process.env, | |
| HOME: tmpDir, | |
| PATH: `${fakeBin}:${process.env.PATH || ""}`, | |
| NEMOCLAW_NON_INTERACTIVE: "1", | |
| NEMOCLAW_PROVIDER: "ollama", | |
| NEMOCLAW_YES: "1", | |
| // No NEMOCLAW_OLLAMA_INSTALL_MODE — auto-detect routes through | |
| // user-local because the stubbed `sudo -n true` returns exit 1. | |
| }, | |
| }); | |
| const result = spawnSync(process.execPath, [scriptPath], { | |
| cwd: repoRoot, | |
| encoding: "utf-8", | |
| timeout: PROVIDER_SELECTION_TEST_TIMEOUT_MS, | |
| env: { | |
| ...process.env, | |
| HOME: tmpDir, | |
| PATH: `${fakeBin}:${process.env.PATH || ""}`, | |
| NEMOCLAW_NON_INTERACTIVE: "1", | |
| NEMOCLAW_PROVIDER: "ollama", | |
| NEMOCLAW_YES: "1", | |
| // No NEMOCLAW_OLLAMA_INSTALL_MODE — auto-detect routes through | |
| // user-local because the stubbed `sudo -n true` returns exit 1. | |
| }, | |
| }); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@test/onboard-selection.test.ts` around lines 5800 - 5813, The spawnSync call
that creates `result` can hang if a sudo prompt appears; update the options
object passed to `spawnSync(process.execPath, [scriptPath], {...})` to include a
`timeout` (e.g., 5000–10000 ms) so the test fails deterministically instead of
hanging, by adding `timeout: <ms>` to the options; keep the rest of the env and
encoding settings the same and adjust any assertions if needed to account for a
timeout-terminated process.
Selective E2E Results —
|
| Job | Result |
|---|---|
| gpu-e2e | ⏭️ skipped |
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Selective E2E Results —
|
| Job | Result |
|---|---|
| gpu-e2e | ⏭️ skipped |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
test/onboard-selection.test.ts (1)
5842-5874:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAssert that the fallback stays fully non-interactive.
This test records
promptCalls, but never checks it. If onboarding accidentally starts prompting again, the stubbedcredentials.promptwill feed empty strings and this case can still pass. Add an explicitpromptCalls === 0assertion here.Suggested fix
const payload = JSON.parse(result.stdout.trim()); + assert.equal(payload.promptCalls, 0); assert.equal(payload.result.provider, "ollama-local"); assert.ok( !payload.runCommands.some((cmd: string) => cmd.includes("ollama.com/install.sh")), "User-local install must NOT run the official curl|sh installer", );🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/onboard-selection.test.ts` around lines 5842 - 5874, The test parses payload but never asserts the recorded promptCalls; add an explicit assertion that promptCalls is zero (e.g., using assert.equal or assert.strictEqual) to ensure onboarding remained fully non-interactive. Place this check after payload is parsed (after const payload = JSON.parse(...)) and before other payload.runCommands assertions, referencing the existing promptCalls variable so the test fails if any credential prompt was invoked.
♻️ Duplicate comments (1)
test/onboard-selection.test.ts (1)
5825-5838:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAdd a timeout to the fallback subprocess.
This regression test is meant to catch non-interactive install failures, but the outer
spawnSynccan still hang indefinitely if the child script regresses into a blocking path. Make it fail deterministically instead.Suggested fix
const result = spawnSync(process.execPath, [scriptPath], { cwd: repoRoot, encoding: "utf-8", env: { ...process.env, HOME: tmpDir, PATH: `${fakeBin}:${process.env.PATH || ""}`, NEMOCLAW_NON_INTERACTIVE: "1", NEMOCLAW_PROVIDER: "ollama", NEMOCLAW_YES: "1", // No NEMOCLAW_OLLAMA_INSTALL_MODE — auto-detect routes through // user-local because the stubbed `sudo -n true` returns exit 1. }, + timeout: PROVIDER_SELECTION_TEST_TIMEOUT_MS, });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/onboard-selection.test.ts` around lines 5825 - 5838, The spawnSync call that runs the test harness (the variable result created by spawnSync(process.execPath, [scriptPath], { ... })) can hang indefinitely; add a deterministic timeout to the options passed into spawnSync (e.g., timeout in milliseconds) so the child is killed and the test fails fast; update the same options object (where HOME, PATH, NEMOCLAW_* env are set) to include timeout and optionally killSignal/encoding/maxBuffer to ensure the subprocess is terminated and output captured reliably.
🧹 Nitpick comments (3)
docs/inference/use-local-inference.mdx (2)
158-158: ⚡ Quick winRewrite this sentence in active voice.
Line 158 uses passive construction (“are still passed through”). Use active voice with a clear actor.
As per coding guidelines, "Active voice required. Flag passive constructions."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/inference/use-local-inference.mdx` at line 158, Replace the passive clause "are still passed through" with an active actor: rewrite the sentence to say that the bootstrap registry passes unknown or custom tags through to the Ollama runner, and mention that the Ollama runner validates the choice (e.g., "The bootstrap registry passes unknown or custom tags through to the Ollama runner, which validates the choice itself.").
50-50: ⚡ Quick winUse active voice for the reboot behavior.
Line 50 switches to passive voice (“must be relaunched manually”). Rewrite this as a direct action to keep the doc voice consistent.
As per coding guidelines, "Active voice required. Flag passive constructions."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/inference/use-local-inference.mdx` at line 50, Rewrite the passive sentence "must be relaunched manually after a reboot" into active voice; for example, change the clause in the sentence that reads "so the daemon must be relaunched manually after a reboot" to an active construction such as "so you must relaunch the daemon manually after a reboot" (update the line that contains "does not configure a systemd service, does not create the `ollama` system user, and does not install CUDA drivers, so the daemon must be relaunched manually after a reboot" accordingly).src/lib/onboard/install-ollama-linux.ts (1)
384-393: 💤 Low valueConsider using the full binary path in the manual fallback launch.
The manual fallback at line 386 uses
ollama servewithout an explicit path, relying on/usr/local/binbeing inPATH. For consistency with the returnedbinPathand robustness in edge-case shell environments, consider using the full path.Suggested fix
if (overrideState === "not-applicable" && !findReachableOllamaHostImpl()) { log(" Starting Ollama..."); - runShellImpl(`OLLAMA_HOST=127.0.0.1:${OLLAMA_PORT} ollama serve > /dev/null 2>&1 &`, { + runShellImpl(`OLLAMA_HOST=127.0.0.1:${OLLAMA_PORT} /usr/local/bin/ollama serve > /dev/null 2>&1 &`, { ignoreError: true, });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/lib/onboard/install-ollama-linux.ts` around lines 384 - 393, The fallback launch uses a bare "ollama serve" which may fail if /usr/local/bin isn't in PATH; update the runShellImpl invocation in the overrideState === "not-applicable" branch (the block that checks findReachableOllamaHostImpl() and uses OLLAMA_PORT) to call the explicit binary path (matching the returned binPath "/usr/local/bin/ollama") when invoking the daemon, leaving the rest of the command, ignoreError option, and subsequent waitForHttpImpl and errorLog logic unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@test/onboard-selection.test.ts`:
- Around line 5842-5874: The test parses payload but never asserts the recorded
promptCalls; add an explicit assertion that promptCalls is zero (e.g., using
assert.equal or assert.strictEqual) to ensure onboarding remained fully
non-interactive. Place this check after payload is parsed (after const payload =
JSON.parse(...)) and before other payload.runCommands assertions, referencing
the existing promptCalls variable so the test fails if any credential prompt was
invoked.
---
Duplicate comments:
In `@test/onboard-selection.test.ts`:
- Around line 5825-5838: The spawnSync call that runs the test harness (the
variable result created by spawnSync(process.execPath, [scriptPath], { ... }))
can hang indefinitely; add a deterministic timeout to the options passed into
spawnSync (e.g., timeout in milliseconds) so the child is killed and the test
fails fast; update the same options object (where HOME, PATH, NEMOCLAW_* env are
set) to include timeout and optionally killSignal/encoding/maxBuffer to ensure
the subprocess is terminated and output captured reliably.
---
Nitpick comments:
In `@docs/inference/use-local-inference.mdx`:
- Line 158: Replace the passive clause "are still passed through" with an active
actor: rewrite the sentence to say that the bootstrap registry passes unknown or
custom tags through to the Ollama runner, and mention that the Ollama runner
validates the choice (e.g., "The bootstrap registry passes unknown or custom
tags through to the Ollama runner, which validates the choice itself.").
- Line 50: Rewrite the passive sentence "must be relaunched manually after a
reboot" into active voice; for example, change the clause in the sentence that
reads "so the daemon must be relaunched manually after a reboot" to an active
construction such as "so you must relaunch the daemon manually after a reboot"
(update the line that contains "does not configure a systemd service, does not
create the `ollama` system user, and does not install CUDA drivers, so the
daemon must be relaunched manually after a reboot" accordingly).
In `@src/lib/onboard/install-ollama-linux.ts`:
- Around line 384-393: The fallback launch uses a bare "ollama serve" which may
fail if /usr/local/bin isn't in PATH; update the runShellImpl invocation in the
overrideState === "not-applicable" branch (the block that checks
findReachableOllamaHostImpl() and uses OLLAMA_PORT) to call the explicit binary
path (matching the returned binPath "/usr/local/bin/ollama") when invoking the
daemon, leaving the rest of the command, ignoreError option, and subsequent
waitForHttpImpl and errorLog logic unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 247b1fa4-968a-4580-af77-78aae5002af5
📒 Files selected for processing (5)
docs/inference/use-local-inference.mdxsrc/lib/onboard.tssrc/lib/onboard/install-ollama-linux.test.tssrc/lib/onboard/install-ollama-linux.tstest/onboard-selection.test.ts
## Summary Refresh NemoClaw documentation and generated user skills for the v0.0.50 and v0.0.51 release-prep window. Remove obsolete legacy docs version metadata now that Fern docs no longer use `docs/project.json`, `docs/versions1.json`, or the legacy Sphinx config. ## Source summary - #1757 -> `docs/manage-sandboxes/messaging-channels.mdx`, `docs/reference/commands.mdx`, `docs/about/release-notes.mdx`: Document Slack channel allowlisting with `SLACK_ALLOWED_CHANNELS`. - #4134 -> `docs/manage-sandboxes/messaging-channels.mdx`, `docs/reference/commands.mdx`, `docs/about/release-notes.mdx`: Document Cloudflare named tunnel support through `CLOUDFLARE_TUNNEL_TOKEN`. - #4186 and #4135 -> `docs/inference/use-local-inference.mdx`, `docs/reference/commands.mdx`, `docs/about/release-notes.mdx`: Document Ollama upgrade and user-local install behavior. - #4185 -> `docs/network-policy/integration-policy-examples.mdx`, `docs/about/release-notes.mdx`: Clarify Jira policy validation probes. - Release cleanup -> `.claude/skills/nemoclaw-contributor-update-docs/SKILL.md`, `docs/CONTRIBUTING.md`, `.github/PULL_REQUEST_TEMPLATE.md`, `scripts/bump-version.ts`: Stop using legacy docs version JSON files and align docs verification on `npm run docs`. ## Changes - Add v0.0.50 and v0.0.51 release notes. - Regenerate NemoClaw user skills from the current Fern docs. - Remove obsolete `docs/conf.py`, `docs/project.json`, and `docs/versions1.json`. - Update docs workflow guidance and PR templates to use `npm run docs` instead of `make docs`. - Remove release-version JSON handling from `scripts/bump-version.ts`. ## Type of Change - [ ] Code change (feature, bug fix, or refactor) - [ ] Code change with doc updates - [x] Doc only (prose changes, no code sample modifications) - [ ] Doc only (includes code sample changes) ## Verification - [ ] `npx prek run --all-files` passes - [ ] `npm test` passes - [ ] Tests added or updated for new or changed behavior - [x] No secrets, API keys, or credentials committed - [x] Docs updated for user-facing behavior changes - [ ] `npm run docs` builds without warnings (doc changes only) - [x] Doc pages follow the [style guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md) (doc changes only) - [ ] New doc pages include SPDX header and frontmatter (new pages only) Additional verification: - `python3 scripts/docs-to-skills.py docs/ .agents/skills/ --prefix nemoclaw-user --doc-platform fern-mdx` - `npm run build:cli` - `npx tsc --noEmit --allowSyntheticDefaultImports --module NodeNext --moduleResolution NodeNext --target ES2022 --types node scripts/bump-version.ts` - `ReadLints` on touched docs, skills, template, and script files - Searched for stale `versions1.json`, `project.json`, and `make docs` references Known gaps: - `npm run docs` was not rerun after cleanup because the earlier Fern CLI fetch failed with npm registry `403 Forbidden` in this environment. - A broad `npm run typecheck -- --noEmit` hit an unrelated existing `scripts/dev-tier-selector.js` type error. --- Signed-off-by: Miyoung Cho <miyoungc@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added resource profiling with CPU/RAM configuration controls for sandboxes * Enhanced local Ollama inference with automatic GPU memory-aware model fallback * Added `nemoclaw resources` command to display host hardware inventory * Enabled Cloudflare named tunnel support via environment configuration * **Documentation** * Improved setup guides for local inference, sandbox hardening, and policy validation * Enhanced troubleshooting for messaging delivery and host service routing * Added release notes for v0.0.50 and v0.0.51 * **Chores** * Updated build documentation commands from `make docs` to `npm run docs` <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/NVIDIA/NemoClaw/pull/4262?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Summary
NEMOCLAW_PROVIDER=install-ollamacallshttps://ollama.com/install.sh, which is sudo-bound with no opt-out env var. A headlessNEMOCLAW_NON_INTERACTIVE=1run without passwordless sudo aborts at the password prompt mid-install.Add a sudo-free user-local install mode that replicates the binary-extraction portion of
install.sh(L159-187) into${HOME}/.local. Auto-detect mirrorsscripts/install-openshell.shL385-429: root or passwordless sudo → system; non-interactive without sudo → user-local; interactive → system so sudo can prompt.NEMOCLAW_OLLAMA_INSTALL_MODE=user/systempins explicitly.Related Issue
Resolves #4114
Changes
src/lib/onboard/install-ollama-linux.ts— new module holding the mode-decision logic plus the system and user-local install paths.src/lib/onboard.ts— Linux install branch collapses to a single helper call (net+7/-47).docs/inference/use-local-inference.mdx— new "Linux Install Modes" subsection.docs/reference/commands.mdx— env-var allowlist entry forNEMOCLAW_OLLAMA_INSTALL_MODE.Type of Change
Verification
npx prek run --all-filespassesnpm testpassesmake docsbuilds without warnings (doc changes only)Signed-off-by: Tinson Lai tinsonl@nvidia.com
Summary by CodeRabbit
Documentation
New Features
Tests