feat: add non-interactive mode for CI/CD onboarding - #318
Conversation
Closes #250. Adds --non-interactive flag and NEMOCLAW_NON_INTERACTIVE=1 env var to nemoclaw onboard and install.sh. When active, all interactive prompts use environment variable overrides or sensible defaults: NEMOCLAW_SANDBOX_NAME — sandbox name (default: my-assistant) NEMOCLAW_PROVIDER — inference provider: cloud, ollama, vllm, nim NEMOCLAW_MODEL — model override NVIDIA_API_KEY — required for cloud/nim, not needed for ollama/vllm Non-interactive mode auto-recreates existing sandboxes and applies suggested policy presets without prompting. Usage: NEMOCLAW_NON_INTERACTIVE=1 NVIDIA_API_KEY=nvapi-... ./install.sh nemoclaw onboard --non-interactive ./install.sh --non-interactive
…mode When only cloud was in the options list (no GPU, not experimental), the options.length > 1 branch was skipped entirely, so the NEMOCLAW_PROVIDER env var was never checked. Ollama/vLLM provider selection now happens before the interactive options are built.
There was a problem hiding this comment.
Pull request overview
This PR adds a non-interactive onboarding flow intended for CI/CD usage by introducing a --non-interactive flag and NEMOCLAW_NON_INTERACTIVE=1 environment variable, and wiring those through the installer and nemoclaw onboard command.
Changes:
- Add
--non-interactivesupport toinstall.shand propagateNEMOCLAW_NON_INTERACTIVE. - Extend
nemoclaw onboardCLI dispatch to pass anonInteractiveoption into the onboarding library. - Update the onboarding wizard to avoid prompts in non-interactive mode by using env var overrides/defaults and fail-fast behavior.
Reviewed changes
Copilot reviewed 1 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| install.sh | Parses --non-interactive, sets NEMOCLAW_NON_INTERACTIVE, and calls nemoclaw onboard --non-interactive when enabled. |
| bin/nemoclaw.js | Detects --non-interactive in args for onboard and forwards it into bin/lib/onboard. |
| bin/lib/onboard.js | Adds non-interactive plumbing, prompt bypasses, provider/model selection via env vars, and API key fail-fast logic. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
One issue I found is that the cgroups v2 check that we had removed yesterday from main had been reintroduced. I committed the removal in 71ef852 |
📝 WalkthroughWalkthroughAdds a non-interactive onboarding/install mode driven by Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Installer as install.sh
participant CLI as nemoclaw.js
participant Onboard as bin/lib/onboard.js
participant Sandbox
User->>Installer: ./install.sh --non-interactive
Installer->>Installer: export NEMOCLAW_NON_INTERACTIVE=1
Installer->>CLI: nemoclaw onboard --non-interactive
CLI->>CLI: validate args, set opts.nonInteractive
CLI->>Onboard: onboard({ nonInteractive: true })
Onboard->>Onboard: read env vars (PROVIDER, MODEL, POLICY_PRESETS, ...)
Onboard->>Onboard: validate provider/model/creds
Onboard->>Sandbox: create or poll sandbox readiness
Sandbox-->>Onboard: ready
Onboard->>Onboard: apply policy presets (with retries)
Onboard-->>CLI: return status
CLI-->>Installer: exit status
Installer-->>User: finish
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 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)
📝 Coding Plan
Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@bin/lib/onboard.js`:
- Around line 305-315: The code is currently taking process.env.NEMOCLAW_MODEL
and passing it through (and into registry.updateSandbox and later run(...))
without validation; change this so any NEMOCLAW_MODEL is checked against the
allowed models list (the existing models array) and only accepted if it exactly
matches an entry; if it does not match, set model = models[0] (or another
explicit safe default), log a clear warning/error, and never write the raw env
value into registry.updateSandbox or interpolate it into run(...); apply this
validation/sanitization wherever model is set for non-interactive providers
(e.g., the providerKey === "vllm" branch, and the similar Ollama/cloud branches
mentioned) and ensure any use passed to run(...) is the validated model
variable.
- Around line 199-206: Currently in isNonInteractive() mode the code silently
proceeds to recreate the sandbox; change this to refuse to delete by default:
when isNonInteractive() is true, check a dedicated opt-in env var (e.g.
NEMOCLAW_RECREATE_SANDBOX) and only proceed with recreation if that var is set
to a truthy value; otherwise print a clear error mentioning sandboxName and
exit/non-zero (or return) without deleting. Update the logic around
isNonInteractive(), the prompt handling branch, and any console messages so
non-interactive runs fail fast unless NEMOCLAW_RECREATE_SANDBOX is explicitly
enabled.
- Around line 295-319: In the non-interactive branch that reads
process.env.NEMOCLAW_PROVIDER (see isNonInteractive, providerKey, ollamaRunning,
vllmRunning), add explicit validation so unknown values do not fall through to
"cloud": if providerKey is not one of the supported tokens (e.g., "ollama",
"vllm", "nim", "cloud") then log a clear error and process.exit(1); for
supported local providers ("ollama", "vllm", and any "nim" local variant) also
fail fast when the corresponding runtime check (ollamaRunning, vllmRunning, or
your nim availability check) is false by logging the specific failure and
exiting instead of falling through; continue to call
registry.updateSandbox(sandboxName, { model, provider, nimContainer }) only
after a validated provider and available runtime.
In `@bin/nemoclaw.js`:
- Around line 31-35: The onboard function currently only recognizes
"--non-interactive" and silently ignores typos; update onboard to validate args
and fail fast on unknown options by parsing args array, allowing only
"--non-interactive" (and no other tokens), and throwing or exiting with a clear
error when any unknown option is present; adjust the logic around the
nonInteractive variable and the call to runOnboard in async function onboard to
perform this validation before invoking require("./lib/onboard").
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: dc7b691b-eb96-4c23-8b09-f4b694b92747
📒 Files selected for processing (5)
bin/lib/onboard.jsbin/nemoclaw.jsinstall.shscripts/install-openshell.shuninstall.sh
| model = process.env.NEMOCLAW_MODEL || "nemotron-3-nano"; | ||
| registry.updateSandbox(sandboxName, { model, provider, nimContainer }); | ||
| return { model, provider }; | ||
| } else if (providerKey === "vllm") { | ||
| if (!vllmRunning) { | ||
| console.error(" vLLM is not running on localhost:8000. Start it first."); | ||
| process.exit(1); | ||
| } | ||
| provider = "vllm-local"; | ||
| model = process.env.NEMOCLAW_MODEL || "vllm-local"; | ||
| registry.updateSandbox(sandboxName, { model, provider, nimContainer }); |
There was a problem hiding this comment.
Validate NEMOCLAW_MODEL instead of silently defaulting or passing it through.
The non-interactive paths treat bad model values inconsistently: local NIM quietly swaps to models[0], while cloud/Ollama/vLLM carry the raw env string into later shell commands. That both hides CI misconfiguration and creates a command-injection/broken-command risk once model is interpolated into run(...).
Suggested fix
+function assertSafeModelName(value) {
+ if (!/^[A-Za-z0-9._/:+-]+$/.test(value)) {
+ console.error(` Invalid NEMOCLAW_MODEL: ${value}`);
+ process.exit(1);
+ }
+ return value;
+}
+
...
- model = process.env.NEMOCLAW_MODEL || "nemotron-3-nano";
+ model = assertSafeModelName(process.env.NEMOCLAW_MODEL || "nemotron-3-nano");
...
- model = process.env.NEMOCLAW_MODEL || "vllm-local";
+ model = assertSafeModelName(process.env.NEMOCLAW_MODEL || "vllm-local");
...
- sel = envModel ? models.find((m) => m.name === envModel) || models[0] : models[0];
+ if (envModel) {
+ sel = models.find((m) => m.name === assertSafeModelName(envModel));
+ if (!sel) {
+ console.error(` Unsupported NEMOCLAW_MODEL for local NIM: ${envModel}`);
+ process.exit(1);
+ }
+ } else {
+ sel = models[0];
+ }
...
- model = model || process.env.NEMOCLAW_MODEL || "nvidia/nemotron-3-super-120b-a12b";
+ model = model || assertSafeModelName(process.env.NEMOCLAW_MODEL || "nvidia/nemotron-3-super-120b-a12b");Also applies to: 369-371, 438-439
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@bin/lib/onboard.js` around lines 305 - 315, The code is currently taking
process.env.NEMOCLAW_MODEL and passing it through (and into
registry.updateSandbox and later run(...)) without validation; change this so
any NEMOCLAW_MODEL is checked against the allowed models list (the existing
models array) and only accepted if it exactly matches an entry; if it does not
match, set model = models[0] (or another explicit safe default), log a clear
warning/error, and never write the raw env value into registry.updateSandbox or
interpolate it into run(...); apply this validation/sanitization wherever model
is set for non-interactive providers (e.g., the providerKey === "vllm" branch,
and the similar Ollama/cloud branches mentioned) and ensure any use passed to
run(...) is the validated model variable.
There was a problem hiding this comment.
🧹 Nitpick comments (2)
bin/lib/onboard.js (2)
636-654: Dead code in retry logic.The
if (!appliedOk)block (lines 650-653) is unreachable: the loop either setsappliedOk = trueand breaks, or throws on the final attempt. The check can never be false after normal loop completion.Simplification
for (let attempt = 0; attempt < 3; attempt += 1) { try { policies.applyPreset(sandboxName, name); - appliedOk = true; break; } catch (err) { const message = err && err.message ? err.message : String(err); if (!message.includes("sandbox not found") || attempt === 2) { - throw err; + console.error(` Failed to apply policy preset '${name}' to sandbox '${sandboxName}'.`); + process.exit(1); } sleep(2); } } - if (!appliedOk) { - console.error(` Failed to apply policy preset '${name}' to sandbox '${sandboxName}'.`); - process.exit(1); - }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@bin/lib/onboard.js` around lines 636 - 654, The retry loop around policies.applyPreset(sandboxName, name) uses an appliedOk flag and a final if (!appliedOk) block that is unreachable because the loop either breaks with appliedOk=true or throws on the last attempt; remove the appliedOk variable and the final if-block, and simplify to: attempt up to 3 times calling policies.applyPreset(...) inside the try, on success break/return, on failure inspect err.message and only rethrow on the last attempt, sleeping between retries as already done (retain sleep(2)); update references to appliedOk accordingly so no dead branch remains.
469-471: Minor indentation inconsistency.Line 470 has 8-space indentation while the surrounding block uses 6 spaces.
Fix indentation
run("OLLAMA_HOST=0.0.0.0:11434 ollama serve > /dev/null 2>&1 &", { ignoreError: true }); - sleep(2); + sleep(2); console.log(" ✓ Using Ollama on localhost:11434");🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@bin/lib/onboard.js` around lines 469 - 471, Indentation of the sleep call is inconsistent with the surrounding block; change the indentation of the line containing sleep(2); so it uses the same 6-space indentation level as the adjacent run("OLLAMA_HOST=0.0.0.0:11434 ollama serve > /dev/null 2>&1 &", { ignoreError: true }); and console.log(" ✓ Using Ollama on localhost:11434"); lines (i.e., align sleep(2); with those statements) to fix the minor formatting issue.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@bin/lib/onboard.js`:
- Around line 636-654: The retry loop around policies.applyPreset(sandboxName,
name) uses an appliedOk flag and a final if (!appliedOk) block that is
unreachable because the loop either breaks with appliedOk=true or throws on the
last attempt; remove the appliedOk variable and the final if-block, and simplify
to: attempt up to 3 times calling policies.applyPreset(...) inside the try, on
success break/return, on failure inspect err.message and only rethrow on the
last attempt, sleeping between retries as already done (retain sleep(2)); update
references to appliedOk accordingly so no dead branch remains.
- Around line 469-471: Indentation of the sleep call is inconsistent with the
surrounding block; change the indentation of the line containing sleep(2); so it
uses the same 6-space indentation level as the adjacent
run("OLLAMA_HOST=0.0.0.0:11434 ollama serve > /dev/null 2>&1 &", { ignoreError:
true }); and console.log(" ✓ Using Ollama on localhost:11434"); lines (i.e.,
align sleep(2); with those statements) to fix the minor formatting issue.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: f5fdd5b2-dada-4be1-ae75-cb570ac7b35a
📒 Files selected for processing (3)
bin/lib/onboard.jsbin/nemoclaw.jstest/cli.test.js
🚧 Files skipped from review as they are similar to previous changes (1)
- bin/nemoclaw.js
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
bin/lib/onboard.js (1)
650-668: Align interactive policy application with the non-interactive safety checks.The interactive path applies presets without the readiness wait/retry and preset validation used above, so behavior is less reliable and less consistent for the same operation.
Refactor direction
- if (answer.toLowerCase() === "list") { + if (answer.toLowerCase() === "list") { // Let user pick const picks = await prompt(" Enter preset names (comma-separated): "); const selected = picks.split(",").map((s) => s.trim()).filter(Boolean); - for (const name of selected) { - policies.applyPreset(sandboxName, name); - } + const knownPresets = new Set(allPresets.map((p) => p.name)); + const invalid = selected.filter((name) => !knownPresets.has(name)); + if (invalid.length > 0) { + console.error(` Unknown policy preset(s): ${invalid.join(", ")}`); + process.exit(1); + } + if (!waitForSandboxReady(sandboxName)) { + console.error(` Sandbox '${sandboxName}' was not ready for policy application.`); + process.exit(1); + } + for (const name of selected) { + policies.applyPreset(sandboxName, name); + } } else {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@bin/lib/onboard.js` around lines 650 - 668, The interactive branch calls policies.applyPreset(sandboxName, name) directly for both "list" and default suggested flows, skipping the readiness wait/retry and preset validation used earlier; update the interactive flow to reuse the same validated-and-retried apply logic (the helper used above for non-interactive safety checks) so each selected preset goes through the same readiness wait/retry and validation steps before calling policies.applyPreset; reference prompt, suggestions, sandboxName, and policies.applyPreset and ensure you validate preset names and apply the same retry/backoff logic for each selected name as in the non-interactive path.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@bin/lib/onboard.js`:
- Around line 67-70: The PATH guard in installOpenshell() is unsafe because
process.env.PATH may be undefined; update the check that uses
process.env.PATH.split(...) to first coerce or default PATH (e.g., use
(process.env.PATH || "") or a typeof check) before calling split so it won't
throw in minimal CI shells; change the condition around localBin and
process.env.PATH to safely handle a missing PATH while preserving the existing
behavior (refer to localBin and the code that currently does
process.env.PATH.split(path.delimiter).includes(localBin)).
---
Nitpick comments:
In `@bin/lib/onboard.js`:
- Around line 650-668: The interactive branch calls
policies.applyPreset(sandboxName, name) directly for both "list" and default
suggested flows, skipping the readiness wait/retry and preset validation used
earlier; update the interactive flow to reuse the same validated-and-retried
apply logic (the helper used above for non-interactive safety checks) so each
selected preset goes through the same readiness wait/retry and validation steps
before calling policies.applyPreset; reference prompt, suggestions, sandboxName,
and policies.applyPreset and ensure you validate preset names and apply the same
retry/backoff logic for each selected name as in the non-interactive path.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: f1bb2af4-5605-4410-893c-eb2a8cc3d5bd
📒 Files selected for processing (1)
bin/lib/onboard.js
| const localBin = process.env.XDG_BIN_HOME || path.join(process.env.HOME || "", ".local", "bin"); | ||
| if (fs.existsSync(path.join(localBin, "openshell")) && !process.env.PATH.split(path.delimiter).includes(localBin)) { | ||
| process.env.PATH = `${localBin}${path.delimiter}${process.env.PATH}`; | ||
| } |
There was a problem hiding this comment.
Guard PATH handling before splitting it in installOpenshell().
At Line 68, process.env.PATH.split(...) can throw if PATH is undefined (common in minimal CI shells), which would crash onboarding right after install.
Suggested fix
const localBin = process.env.XDG_BIN_HOME || path.join(process.env.HOME || "", ".local", "bin");
- if (fs.existsSync(path.join(localBin, "openshell")) && !process.env.PATH.split(path.delimiter).includes(localBin)) {
- process.env.PATH = `${localBin}${path.delimiter}${process.env.PATH}`;
+ const currentPath = process.env.PATH || "";
+ if (fs.existsSync(path.join(localBin, "openshell")) && !currentPath.split(path.delimiter).includes(localBin)) {
+ process.env.PATH = currentPath ? `${localBin}${path.delimiter}${currentPath}` : localBin;
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@bin/lib/onboard.js` around lines 67 - 70, The PATH guard in
installOpenshell() is unsafe because process.env.PATH may be undefined; update
the check that uses process.env.PATH.split(...) to first coerce or default PATH
(e.g., use (process.env.PATH || "") or a typeof check) before calling split so
it won't throw in minimal CI shells; change the condition around localBin and
process.env.PATH to safely handle a missing PATH while preserving the existing
behavior (refer to localBin and the code that currently does
process.env.PATH.split(path.delimiter).includes(localBin)).
OpenShell's nested k3s cluster cannot resolve Kubernetes DNS names, so inference requests fail with 502 Bad Gateway. This adds: - socat TCP proxy setup in setup.sh to forward localhost:8000 to the K8s vLLM service endpoint - Provider configuration using host.openshell.internal:8000 which resolves to the workspace container from inside k3s - Documentation explaining the network architecture and workaround - Updated env var names to match PR NVIDIA#318 (NEMOCLAW_NON_INTERACTIVE) - cgroup v2 compatibility fix for Docker daemon - Removed memory limits that caused OOM Tested: Inference requests from sandboxes now route correctly through the socat proxy to the Dynamo vLLM endpoint. Depends on: NVIDIA#318 (non-interactive mode), NVIDIA#365 (Dynamo provider) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat: add non-interactive mode for CI/CD onboarding Closes NVIDIA#250. Adds --non-interactive flag and NEMOCLAW_NON_INTERACTIVE=1 env var to nemoclaw onboard and install.sh. When active, all interactive prompts use environment variable overrides or sensible defaults: NEMOCLAW_SANDBOX_NAME — sandbox name (default: my-assistant) NEMOCLAW_PROVIDER — inference provider: cloud, ollama, vllm, nim NEMOCLAW_MODEL — model override NVIDIA_API_KEY — required for cloud/nim, not needed for ollama/vllm Non-interactive mode auto-recreates existing sandboxes and applies suggested policy presets without prompting. Usage: NEMOCLAW_NON_INTERACTIVE=1 NVIDIA_API_KEY=nvapi-... ./install.sh nemoclaw onboard --non-interactive ./install.sh --non-interactive * fix: handle NEMOCLAW_PROVIDER before options list in non-interactive mode When only cloud was in the options list (no GPU, not experimental), the options.length > 1 branch was skipped entirely, so the NEMOCLAW_PROVIDER env var was never checked. Ollama/vLLM provider selection now happens before the interactive options are built. * remove stale cgroup preflight regression * fix non-interactive onboarding regressions * add standalone openshell installer script * add env-controlled non-interactive policy selection * avoid sudo prompt for non-interactive openshell install * avoid sudo prompt during non-interactive uninstall * harden non-interactive onboard validation * simplify policy retry loop --------- Co-authored-by: Kevin Jones <kejones@nvidia.com>
* feat: add non-interactive mode for CI/CD onboarding Closes NVIDIA#250. Adds --non-interactive flag and NEMOCLAW_NON_INTERACTIVE=1 env var to nemoclaw onboard and install.sh. When active, all interactive prompts use environment variable overrides or sensible defaults: NEMOCLAW_SANDBOX_NAME — sandbox name (default: my-assistant) NEMOCLAW_PROVIDER — inference provider: cloud, ollama, vllm, nim NEMOCLAW_MODEL — model override NVIDIA_API_KEY — required for cloud/nim, not needed for ollama/vllm Non-interactive mode auto-recreates existing sandboxes and applies suggested policy presets without prompting. Usage: NEMOCLAW_NON_INTERACTIVE=1 NVIDIA_API_KEY=nvapi-... ./install.sh nemoclaw onboard --non-interactive ./install.sh --non-interactive * fix: handle NEMOCLAW_PROVIDER before options list in non-interactive mode When only cloud was in the options list (no GPU, not experimental), the options.length > 1 branch was skipped entirely, so the NEMOCLAW_PROVIDER env var was never checked. Ollama/vLLM provider selection now happens before the interactive options are built. * remove stale cgroup preflight regression * fix non-interactive onboarding regressions * add standalone openshell installer script * add env-controlled non-interactive policy selection * avoid sudo prompt for non-interactive openshell install * avoid sudo prompt during non-interactive uninstall * harden non-interactive onboard validation * simplify policy retry loop --------- Co-authored-by: Kevin Jones <kejones@nvidia.com>
* feat: add Kubernetes testing infrastructure Add k8s-testing/ directory with scripts and manifests for testing NemoClaw on Kubernetes with Dynamo vLLM inference. Includes: - test-installer.sh: Public installer test (requires unattended install support) - setup.sh: Manual setup from source for development - Pod manifests for Docker-in-Docker execution Architecture: OpenShell runs k3s inside Docker, so we use DinD pods to provide the Docker daemon on Kubernetes. Signed-off-by: rwipfelnv * fix: add socat proxy for K8s DNS isolation workaround OpenShell's nested k3s cluster cannot resolve Kubernetes DNS names, so inference requests fail with 502 Bad Gateway. This adds: - socat TCP proxy setup in setup.sh to forward localhost:8000 to the K8s vLLM service endpoint - Provider configuration using host.openshell.internal:8000 which resolves to the workspace container from inside k3s - Documentation explaining the network architecture and workaround - Updated env var names to match PR #318 (NEMOCLAW_NON_INTERACTIVE) - cgroup v2 compatibility fix for Docker daemon - Removed memory limits that caused OOM Tested: Inference requests from sandboxes now route correctly through the socat proxy to the Dynamo vLLM endpoint. Depends on: #318 (non-interactive mode), #365 (Dynamo provider) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: NemoKlaw - NemoClaw on Kubernetes with Dynamo support Complete K8s deployment solution for NemoClaw: - nemoklaw.yaml: Pod manifest with DinD, init containers, hostPath storage - install.sh: Interactive installer with preflight checks - Rename k8s-testing -> k8s, move old files to dev/ Key learnings: - hostPath storage (/mnt/k8s-disks) avoids ephemeral storage eviction - Init containers for docker config, openshell CLI, NemoClaw build - Workspace container installs apt packages at runtime (can't share via volumes) - socat proxy bridges K8s DNS to nested k3s (host.openshell.internal) Tested successfully with Dynamo vLLM backend on EKS. Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> * fix: rename NemoKlaw to NemoClaw and document known limitations Address PR feedback: - Rename NemoKlaw -> NemoClaw (avoid confusing naming) - Rename nemoklaw.yaml -> nemoclaw-k8s.yaml - Fix hardcoded endpoint to use generic example - Remove log file from repo - Document known limitations (HTTPS proxy issue) - Update README with accurate status of what works/doesn't work Signed-off-by: rwipfelnv Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: update DYNAMO_HOST to vllm-agg-frontend The aggregated frontend service is the correct endpoint for Dynamo vLLM inference. Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> * docs: add Using NemoClaw section with CLI commands - Add workspace shell access command - Add sandbox status/logs/list commands - Add chat completion test example - Rename section from "What Can You Do?" to "Using NemoClaw" Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> * refactor(k8s): simplify deployment to use official installer - Use official NemoClaw installer (`curl | bash`) instead of git clone/build - Switch to `custom` provider from PR #648 (supersedes dynamo-specific provider) - Remove k8s/dev/ directory (no longer needed for testing) - Use emptyDir volumes for portability across clusters - Add /etc/hosts workaround for endpoint validation during onboarding - Update README with verification steps for local inference Tested end-to-end with Dynamo vLLM backend. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(k8s): resolve lint errors in yaml and markdown - Remove multi-document YAML (move namespace creation to README) - Add language specifier to fenced code block (```text) - Add blank lines before lists per markdownlint rules Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> * docs(k8s): add experimental warning and clarify requirements - Add explicit experimental warning at top of README - Clarify this is for trying NemoClaw on k8s, not production - Document privileged pod and DinD requirements upfront - Add resource requirements to prerequisites Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> --------- Signed-off-by: rwipfelnv Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: Carlos Villela <cvillela@nvidia.com> Co-authored-by: KJ <kejones@nvidia.com>
* feat: add Kubernetes testing infrastructure Add k8s-testing/ directory with scripts and manifests for testing NemoClaw on Kubernetes with Dynamo vLLM inference. Includes: - test-installer.sh: Public installer test (requires unattended install support) - setup.sh: Manual setup from source for development - Pod manifests for Docker-in-Docker execution Architecture: OpenShell runs k3s inside Docker, so we use DinD pods to provide the Docker daemon on Kubernetes. Signed-off-by: rwipfelnv * fix: add socat proxy for K8s DNS isolation workaround OpenShell's nested k3s cluster cannot resolve Kubernetes DNS names, so inference requests fail with 502 Bad Gateway. This adds: - socat TCP proxy setup in setup.sh to forward localhost:8000 to the K8s vLLM service endpoint - Provider configuration using host.openshell.internal:8000 which resolves to the workspace container from inside k3s - Documentation explaining the network architecture and workaround - Updated env var names to match PR NVIDIA#318 (NEMOCLAW_NON_INTERACTIVE) - cgroup v2 compatibility fix for Docker daemon - Removed memory limits that caused OOM Tested: Inference requests from sandboxes now route correctly through the socat proxy to the Dynamo vLLM endpoint. Depends on: NVIDIA#318 (non-interactive mode), NVIDIA#365 (Dynamo provider) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: NemoKlaw - NemoClaw on Kubernetes with Dynamo support Complete K8s deployment solution for NemoClaw: - nemoklaw.yaml: Pod manifest with DinD, init containers, hostPath storage - install.sh: Interactive installer with preflight checks - Rename k8s-testing -> k8s, move old files to dev/ Key learnings: - hostPath storage (/mnt/k8s-disks) avoids ephemeral storage eviction - Init containers for docker config, openshell CLI, NemoClaw build - Workspace container installs apt packages at runtime (can't share via volumes) - socat proxy bridges K8s DNS to nested k3s (host.openshell.internal) Tested successfully with Dynamo vLLM backend on EKS. Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> * fix: rename NemoKlaw to NemoClaw and document known limitations Address PR feedback: - Rename NemoKlaw -> NemoClaw (avoid confusing naming) - Rename nemoklaw.yaml -> nemoclaw-k8s.yaml - Fix hardcoded endpoint to use generic example - Remove log file from repo - Document known limitations (HTTPS proxy issue) - Update README with accurate status of what works/doesn't work Signed-off-by: rwipfelnv Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: update DYNAMO_HOST to vllm-agg-frontend The aggregated frontend service is the correct endpoint for Dynamo vLLM inference. Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> * docs: add Using NemoClaw section with CLI commands - Add workspace shell access command - Add sandbox status/logs/list commands - Add chat completion test example - Rename section from "What Can You Do?" to "Using NemoClaw" Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> * refactor(k8s): simplify deployment to use official installer - Use official NemoClaw installer (`curl | bash`) instead of git clone/build - Switch to `custom` provider from PR NVIDIA#648 (supersedes dynamo-specific provider) - Remove k8s/dev/ directory (no longer needed for testing) - Use emptyDir volumes for portability across clusters - Add /etc/hosts workaround for endpoint validation during onboarding - Update README with verification steps for local inference Tested end-to-end with Dynamo vLLM backend. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(k8s): resolve lint errors in yaml and markdown - Remove multi-document YAML (move namespace creation to README) - Add language specifier to fenced code block (```text) - Add blank lines before lists per markdownlint rules Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> * docs(k8s): add experimental warning and clarify requirements - Add explicit experimental warning at top of README - Clarify this is for trying NemoClaw on k8s, not production - Document privileged pod and DinD requirements upfront - Add resource requirements to prerequisites Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> --------- Signed-off-by: rwipfelnv Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: Carlos Villela <cvillela@nvidia.com> Co-authored-by: KJ <kejones@nvidia.com>
* feat: add Kubernetes testing infrastructure Add k8s-testing/ directory with scripts and manifests for testing NemoClaw on Kubernetes with Dynamo vLLM inference. Includes: - test-installer.sh: Public installer test (requires unattended install support) - setup.sh: Manual setup from source for development - Pod manifests for Docker-in-Docker execution Architecture: OpenShell runs k3s inside Docker, so we use DinD pods to provide the Docker daemon on Kubernetes. Signed-off-by: rwipfelnv * fix: add socat proxy for K8s DNS isolation workaround OpenShell's nested k3s cluster cannot resolve Kubernetes DNS names, so inference requests fail with 502 Bad Gateway. This adds: - socat TCP proxy setup in setup.sh to forward localhost:8000 to the K8s vLLM service endpoint - Provider configuration using host.openshell.internal:8000 which resolves to the workspace container from inside k3s - Documentation explaining the network architecture and workaround - Updated env var names to match PR #318 (NEMOCLAW_NON_INTERACTIVE) - cgroup v2 compatibility fix for Docker daemon - Removed memory limits that caused OOM Tested: Inference requests from sandboxes now route correctly through the socat proxy to the Dynamo vLLM endpoint. Depends on: #318 (non-interactive mode), #365 (Dynamo provider) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: NemoKlaw - NemoClaw on Kubernetes with Dynamo support Complete K8s deployment solution for NemoClaw: - nemoklaw.yaml: Pod manifest with DinD, init containers, hostPath storage - install.sh: Interactive installer with preflight checks - Rename k8s-testing -> k8s, move old files to dev/ Key learnings: - hostPath storage (/mnt/k8s-disks) avoids ephemeral storage eviction - Init containers for docker config, openshell CLI, NemoClaw build - Workspace container installs apt packages at runtime (can't share via volumes) - socat proxy bridges K8s DNS to nested k3s (host.openshell.internal) Tested successfully with Dynamo vLLM backend on EKS. Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> * fix: rename NemoKlaw to NemoClaw and document known limitations Address PR feedback: - Rename NemoKlaw -> NemoClaw (avoid confusing naming) - Rename nemoklaw.yaml -> nemoclaw-k8s.yaml - Fix hardcoded endpoint to use generic example - Remove log file from repo - Document known limitations (HTTPS proxy issue) - Update README with accurate status of what works/doesn't work Signed-off-by: rwipfelnv Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: update DYNAMO_HOST to vllm-agg-frontend The aggregated frontend service is the correct endpoint for Dynamo vLLM inference. Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> * docs: add Using NemoClaw section with CLI commands - Add workspace shell access command - Add sandbox status/logs/list commands - Add chat completion test example - Rename section from "What Can You Do?" to "Using NemoClaw" Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> * refactor(k8s): simplify deployment to use official installer - Use official NemoClaw installer (`curl | bash`) instead of git clone/build - Switch to `custom` provider from PR #648 (supersedes dynamo-specific provider) - Remove k8s/dev/ directory (no longer needed for testing) - Use emptyDir volumes for portability across clusters - Add /etc/hosts workaround for endpoint validation during onboarding - Update README with verification steps for local inference Tested end-to-end with Dynamo vLLM backend. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(k8s): resolve lint errors in yaml and markdown - Remove multi-document YAML (move namespace creation to README) - Add language specifier to fenced code block (```text) - Add blank lines before lists per markdownlint rules Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> * docs(k8s): add experimental warning and clarify requirements - Add explicit experimental warning at top of README - Clarify this is for trying NemoClaw on k8s, not production - Document privileged pod and DinD requirements upfront - Add resource requirements to prerequisites Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> --------- Signed-off-by: rwipfelnv Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: Carlos Villela <cvillela@nvidia.com> Co-authored-by: KJ <kejones@nvidia.com>
* feat: add Kubernetes testing infrastructure Add k8s-testing/ directory with scripts and manifests for testing NemoClaw on Kubernetes with Dynamo vLLM inference. Includes: - test-installer.sh: Public installer test (requires unattended install support) - setup.sh: Manual setup from source for development - Pod manifests for Docker-in-Docker execution Architecture: OpenShell runs k3s inside Docker, so we use DinD pods to provide the Docker daemon on Kubernetes. Signed-off-by: rwipfelnv * fix: add socat proxy for K8s DNS isolation workaround OpenShell's nested k3s cluster cannot resolve Kubernetes DNS names, so inference requests fail with 502 Bad Gateway. This adds: - socat TCP proxy setup in setup.sh to forward localhost:8000 to the K8s vLLM service endpoint - Provider configuration using host.openshell.internal:8000 which resolves to the workspace container from inside k3s - Documentation explaining the network architecture and workaround - Updated env var names to match PR NVIDIA#318 (NEMOCLAW_NON_INTERACTIVE) - cgroup v2 compatibility fix for Docker daemon - Removed memory limits that caused OOM Tested: Inference requests from sandboxes now route correctly through the socat proxy to the Dynamo vLLM endpoint. Depends on: NVIDIA#318 (non-interactive mode), NVIDIA#365 (Dynamo provider) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: NemoKlaw - NemoClaw on Kubernetes with Dynamo support Complete K8s deployment solution for NemoClaw: - nemoklaw.yaml: Pod manifest with DinD, init containers, hostPath storage - install.sh: Interactive installer with preflight checks - Rename k8s-testing -> k8s, move old files to dev/ Key learnings: - hostPath storage (/mnt/k8s-disks) avoids ephemeral storage eviction - Init containers for docker config, openshell CLI, NemoClaw build - Workspace container installs apt packages at runtime (can't share via volumes) - socat proxy bridges K8s DNS to nested k3s (host.openshell.internal) Tested successfully with Dynamo vLLM backend on EKS. Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> * fix: rename NemoKlaw to NemoClaw and document known limitations Address PR feedback: - Rename NemoKlaw -> NemoClaw (avoid confusing naming) - Rename nemoklaw.yaml -> nemoclaw-k8s.yaml - Fix hardcoded endpoint to use generic example - Remove log file from repo - Document known limitations (HTTPS proxy issue) - Update README with accurate status of what works/doesn't work Signed-off-by: rwipfelnv Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: update DYNAMO_HOST to vllm-agg-frontend The aggregated frontend service is the correct endpoint for Dynamo vLLM inference. Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> * docs: add Using NemoClaw section with CLI commands - Add workspace shell access command - Add sandbox status/logs/list commands - Add chat completion test example - Rename section from "What Can You Do?" to "Using NemoClaw" Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> * refactor(k8s): simplify deployment to use official installer - Use official NemoClaw installer (`curl | bash`) instead of git clone/build - Switch to `custom` provider from PR NVIDIA#648 (supersedes dynamo-specific provider) - Remove k8s/dev/ directory (no longer needed for testing) - Use emptyDir volumes for portability across clusters - Add /etc/hosts workaround for endpoint validation during onboarding - Update README with verification steps for local inference Tested end-to-end with Dynamo vLLM backend. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(k8s): resolve lint errors in yaml and markdown - Remove multi-document YAML (move namespace creation to README) - Add language specifier to fenced code block (```text) - Add blank lines before lists per markdownlint rules Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> * docs(k8s): add experimental warning and clarify requirements - Add explicit experimental warning at top of README - Clarify this is for trying NemoClaw on k8s, not production - Document privileged pod and DinD requirements upfront - Add resource requirements to prerequisites Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> --------- Signed-off-by: rwipfelnv Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: Carlos Villela <cvillela@nvidia.com> Co-authored-by: KJ <kejones@nvidia.com>
* feat: add Kubernetes testing infrastructure Add k8s-testing/ directory with scripts and manifests for testing NemoClaw on Kubernetes with Dynamo vLLM inference. Includes: - test-installer.sh: Public installer test (requires unattended install support) - setup.sh: Manual setup from source for development - Pod manifests for Docker-in-Docker execution Architecture: OpenShell runs k3s inside Docker, so we use DinD pods to provide the Docker daemon on Kubernetes. Signed-off-by: rwipfelnv * fix: add socat proxy for K8s DNS isolation workaround OpenShell's nested k3s cluster cannot resolve Kubernetes DNS names, so inference requests fail with 502 Bad Gateway. This adds: - socat TCP proxy setup in setup.sh to forward localhost:8000 to the K8s vLLM service endpoint - Provider configuration using host.openshell.internal:8000 which resolves to the workspace container from inside k3s - Documentation explaining the network architecture and workaround - Updated env var names to match PR NVIDIA#318 (NEMOCLAW_NON_INTERACTIVE) - cgroup v2 compatibility fix for Docker daemon - Removed memory limits that caused OOM Tested: Inference requests from sandboxes now route correctly through the socat proxy to the Dynamo vLLM endpoint. Depends on: NVIDIA#318 (non-interactive mode), NVIDIA#365 (Dynamo provider) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: NemoKlaw - NemoClaw on Kubernetes with Dynamo support Complete K8s deployment solution for NemoClaw: - nemoklaw.yaml: Pod manifest with DinD, init containers, hostPath storage - install.sh: Interactive installer with preflight checks - Rename k8s-testing -> k8s, move old files to dev/ Key learnings: - hostPath storage (/mnt/k8s-disks) avoids ephemeral storage eviction - Init containers for docker config, openshell CLI, NemoClaw build - Workspace container installs apt packages at runtime (can't share via volumes) - socat proxy bridges K8s DNS to nested k3s (host.openshell.internal) Tested successfully with Dynamo vLLM backend on EKS. Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> * fix: rename NemoKlaw to NemoClaw and document known limitations Address PR feedback: - Rename NemoKlaw -> NemoClaw (avoid confusing naming) - Rename nemoklaw.yaml -> nemoclaw-k8s.yaml - Fix hardcoded endpoint to use generic example - Remove log file from repo - Document known limitations (HTTPS proxy issue) - Update README with accurate status of what works/doesn't work Signed-off-by: rwipfelnv Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: update DYNAMO_HOST to vllm-agg-frontend The aggregated frontend service is the correct endpoint for Dynamo vLLM inference. Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> * docs: add Using NemoClaw section with CLI commands - Add workspace shell access command - Add sandbox status/logs/list commands - Add chat completion test example - Rename section from "What Can You Do?" to "Using NemoClaw" Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> * refactor(k8s): simplify deployment to use official installer - Use official NemoClaw installer (`curl | bash`) instead of git clone/build - Switch to `custom` provider from PR NVIDIA#648 (supersedes dynamo-specific provider) - Remove k8s/dev/ directory (no longer needed for testing) - Use emptyDir volumes for portability across clusters - Add /etc/hosts workaround for endpoint validation during onboarding - Update README with verification steps for local inference Tested end-to-end with Dynamo vLLM backend. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(k8s): resolve lint errors in yaml and markdown - Remove multi-document YAML (move namespace creation to README) - Add language specifier to fenced code block (```text) - Add blank lines before lists per markdownlint rules Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> * docs(k8s): add experimental warning and clarify requirements - Add explicit experimental warning at top of README - Clarify this is for trying NemoClaw on k8s, not production - Document privileged pod and DinD requirements upfront - Add resource requirements to prerequisites Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> --------- Signed-off-by: rwipfelnv Signed-off-by: Robert Wipfel <rwipfel@nvidia.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: Carlos Villela <cvillela@nvidia.com> Co-authored-by: KJ <kejones@nvidia.com>
Closes #250.
Summary
--non-interactiveflag andNEMOCLAW_NON_INTERACTIVE=1env var tonemoclaw onboardandinstall.shNVIDIA_API_KEYfor cloud provider)Environment variables
NEMOCLAW_NON_INTERACTIVE=1NEMOCLAW_SANDBOX_NAMEmy-assistantNEMOCLAW_PROVIDERcloud,ollama,vllm,nim)cloudNEMOCLAW_MODELnvidia/nemotron-3-super-120b-a12bNVIDIA_API_KEYcloud/nim, not needed forollama/vllm)Usage
Test plan
NEMOCLAW_SANDBOX_NAMENVIDIA_API_KEYexits with clear error, no hangNEMOCLAW_PROVIDER=ollamaskips API keySummary by CodeRabbit