Skip to content

feat(env): add configurable port overrides via .env files#652

Closed
jnun wants to merge 2 commits intoNVIDIA:mainfrom
jnun:feat/configurable-ports-v2
Closed

feat(env): add configurable port overrides via .env files#652
jnun wants to merge 2 commits intoNVIDIA:mainfrom
jnun:feat/configurable-ports-v2

Conversation

@jnun
Copy link

@jnun jnun commented Mar 22, 2026

Summary

  • Add configurable port overrides (GATEWAY_PORT, DASHBOARD_PORT, OLLAMA_PORT, VLLM_PORT) via .env / .env.local files
  • Introduce bin/lib/env.js (env loader with git-root + CWD search) and bin/lib/ports.js (central port config)
  • Replace all hardcoded ports across 30 files (JS, shell scripts, blueprint YAML, Python orchestrator, tests)
  • Add port-conflict detection in preflight() with .env.local override guidance
  • Add scripts/check-ports.sh diagnostic utility, docs/reference/port-configuration.md, and test/env.test.js

Bug fixes included

  1. bin/lib/env.js.env.local not found on fresh installs (only searched __dirname; now also searches git root and CWD)
  2. bin/lib/onboard.js — No .env bootstrapped on fresh clone; unhelpful port-conflict error (now copies .env.example.env and shows .env.local override instructions)
  3. Shell scripts (nemoclaw-start.sh, debug.sh, brev-setup.sh, etc.) — .env never loaded, so port overrides had no effect
  4. scripts/telegram-bridge.js — Removed unused crypto import
  5. test/onboard-readiness.test.js — Hardcoded port 8080; now reads from ports config
  6. bin/lib/env.js / scripts/check-ports.sh / uninstall.sh — Inline comment stripping corrupted quoted values containing # (fixed parse order per CodeRabbit review)
  7. bin/lib/onboard.js — Custom dashboard port not reaching build-time Dockerfile ARG (now patches Dockerfile copy before build)
  8. bin/lib/onboard.js — Ollama startup accepted without health verification (now retries with curl probe)

CodeRabbit review status

All actionable findings from PR #639 are addressed. One documented first-run edge case remains (ports resolved at module load before .env.example copy — defaults match, so behavior is identical).

Test plan

  • npm test — 311 tests (81 TS + 230 JS), all passing (5 pre-existing upstream failures in install-preflight.test.js)
  • node --test test/env.test.js test/preflight.test.js test/onboard-readiness.test.js — 46/46 port-config tests pass
  • node bin/nemoclaw.js --version / --help — CLI smoke test
  • Verify Dockerfile preserves os.environ security fix (C-2)
  • Pre-commit hooks pass: SPDX headers, shellcheck, ruff, commitlint
  • Pre-push hooks pass: TypeScript + Python type checks

Supersedes #639.

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Configurable ports for Dashboard, Gateway, vLLM/NIM, and Ollama services via environment variables (NEMOCLAW_DASHBOARD_PORT, NEMOCLAW_GATEWAY_PORT, NEMOCLAW_VLLM_PORT, NEMOCLAW_OLLAMA_PORT).
    • .env and .env.local file support for persistent port configuration.
    • Port conflict detection utility to identify conflicting services.
  • Documentation

    • Added port configuration reference guide with defaults and environment variable mappings.
    • Updated troubleshooting guide with port conflict resolution steps.
  • Tests

    • Added environment variable and port configuration tests.
    • Updated existing tests to use configurable ports.

jnun and others added 2 commits March 22, 2026 12:55
Allow users to override default service ports (GATEWAY_PORT, REDIS_PORT,
SANDBOX_PORT) through .env and .env.local files. This prevents conflicts
when default ports are already in use on the host, without relying on
ephemeral shell memory.

New files:
- bin/lib/env.js — .env/.env.local loader (dotenv)
- bin/lib/ports.js — port defaults and validation
- scripts/check-ports.sh — port diagnostic utility
- docs/reference/port-configuration.md — user-facing reference
- test/env.test.js — env loading tests
- .env.example — documents available overrides

Modified files:
- bin/nemoclaw.js — load env at CLI entry point
- bin/lib/onboard.js — port-conflict detection and .env bootstrap
- bin/lib/preflight.js — pass port env vars to preflight checks
- bin/lib/local-inference.js — use configured ports
- bin/lib/nim.js — use configured ports
- nemoclaw-blueprint/blueprint.yaml — parameterize service ports
- nemoclaw-blueprint/orchestrator/runner.py — read port env vars
- scripts/brev-setup.sh — source .env before start
- scripts/debug.sh — source .env before start
- scripts/lib/runtime.sh — source .env before start
- scripts/nemoclaw-start.sh — source .env before start
- scripts/setup.sh — source .env before start
- scripts/start-services.sh — source .env before start
- scripts/telegram-bridge.js — remove unused import
- uninstall.sh — load env, use configured ports
- README.md — add port configuration section
- docs/reference/troubleshooting.md — add port override guidance
- package-lock.json — lockfile update for dotenv
- test/e2e/test-double-onboard.sh — use configurable ports
- test/local-inference.test.js — use configurable ports
- test/onboard-readiness.test.js — use configurable ports
- test/onboard-selection.test.js — use configurable ports
- test/preflight.test.js — use configurable ports
- test/runtime-shell.test.js — use configurable ports
Aligns CLI examples with project documentation style guidelines.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Mar 22, 2026

📝 Walkthrough

Walkthrough

This pull request introduces a centralized, configurable port system for NemoClaw by replacing hardcoded port values with environment variable-driven constants. It adds environment loading infrastructure (.env.example, .env parsing module), a port configuration module with validation, a port conflict detection script, and updates ~20 scripts/modules across Node.js, shell, and Python to use the new configurable port system. Documentation is added for port configuration and troubleshooting.

Changes

Cohort / File(s) Summary
Configuration & Documentation
.env.example, README.md, docs/reference/port-configuration.md, docs/reference/troubleshooting.md
Added environment variable examples, port configuration guide with defaults/variable names, troubleshooting for port conflicts, and instructions for .env usage.
Environment Loading Module
bin/lib/env.js, test/env.test.js
New module implementing .env file parsing with git-root detection, quoted value support, and "first file wins" precedence. Includes comprehensive test coverage for parsing and file-discovery logic.
Port Configuration Module
bin/lib/ports.js, test/preflight.test.js
New centralized port configuration module exporting DASHBOARD_PORT, GATEWAY_PORT, VLLM_PORT, OLLAMA_PORT with validation (1024–65535 range), legacy fallback chain for dashboard port, and port resolution from environment variables.
Port Validation Script
scripts/check-ports.sh
New executable script to detect port conflicts by reading .env/.env.local and probing with lsof, supporting custom port arguments and detailed conflict reporting.
Local Inference & NIM Modules
bin/lib/local-inference.js, bin/lib/nim.js, test/local-inference.test.js, test/onboard-selection.test.js, scripts/lib/runtime.sh
Updated to use VLLM_PORT and OLLAMA_PORT constants in base URLs, health checks, and validation messages. Added JSDoc comments. Updated test assertions to use port constants.
Onboarding & CLI Entry
bin/lib/onboard.js, bin/nemoclaw.js, test/onboard-readiness.test.js
Integrated environment loading at startup, replaced hardcoded ports with configurable constants, added .env bootstrapping on first run, updated Ollama readiness polling and sandbox environment injection, added Dockerfile patching for build-time CORS configuration.
Preflight & Port Checking
bin/lib/preflight.js
Updated to use DASHBOARD_PORT constant as default when not provided.
Shell Scripts
scripts/brev-setup.sh, scripts/debug.sh, scripts/nemoclaw-start.sh, scripts/setup.sh, scripts/start-services.sh, uninstall.sh, test/e2e/test-double-onboard.sh
Added .env/.env.local sourcing, replaced hardcoded ports with environment variable defaults (NEMOCLAW_DASHBOARD_PORT, NEMOCLAW_GATEWAY_PORT, NEMOCLAW_VLLM_PORT, NEMOCLAW_OLLAMA_PORT). Updated port-dependent commands (forward, gateway startup, service binding) and test assertions.
Blueprint & Python Runtime
nemoclaw-blueprint/blueprint.yaml, nemoclaw-blueprint/orchestrator/runner.py
Added inline comments documenting port overrides. Implemented runtime port override logic in load_blueprint() to rewrite forward_ports and inference endpoint URLs based on NEMOCLAW_*_PORT environment variables. Added port parsing and validation helpers.
Cleanup
scripts/telegram-bridge.js
Removed unused crypto module import.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐰 Hardcoded ports? Oh what a sight!
Now environment variables set things right.
From .env files springs the magic flow,
Dashboard and Gateway dance, high and low.
Check for conflicts, no more surprise,
Configurable ports—the code's wise prize! 🎪

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately captures the main change: adding configurable port overrides via .env files, which is the core feature across all 30+ file modifications.
Docstring Coverage ✅ Passed Docstring coverage is 81.25% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
uninstall.sh (1)

281-286: ⚠️ Potential issue | 🟡 Minor

Honor the full dashboard fallback chain during cleanup.

bin/lib/ports.js still accepts DASHBOARD_PORT and PUBLIC_PORT, but Line 286 only checks NEMOCLAW_DASHBOARD_PORT. On legacy setups, the uninstaller falls back to 18789 here and can leave the forwarder running.

Proposed fix
   local -a pids=()
+  local dashboard_port="${NEMOCLAW_DASHBOARD_PORT:-${DASHBOARD_PORT:-${PUBLIC_PORT:-18789}}}"
   local pid
   while IFS= read -r pid; do
     [ -n "$pid" ] || continue
     pids+=("$pid")
-  done < <(pgrep -f "openshell.*forward.*${NEMOCLAW_DASHBOARD_PORT:-18789}" 2>/dev/null || true)
+  done < <(pgrep -f "openshell.*forward.*${dashboard_port}" 2>/dev/null || true)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@uninstall.sh` around lines 281 - 286, The cleanup currently only searches for
processes matching NEMOCLAW_DASHBOARD_PORT and misses legacy fallbacks; update
the pgrep invocation so it checks the full fallback chain
(NEMOCLAW_DASHBOARD_PORT, DASHBOARD_PORT, PUBLIC_PORT, and the default 18789).
Build a list/regex of ports (e.g. collect ${NEMOCLAW_DASHBOARD_PORT},
${DASHBOARD_PORT}, ${PUBLIC_PORT}, and 18789, dedupe/ignore empty) and change
the pgrep -f pattern "openshell.*forward.*${NEMOCLAW_DASHBOARD_PORT:-18789}" to
match any of those ports (e.g. use a grouped alternation like
"(portA|portB|portC)"). Ensure the surrounding variable handling (the pids array
population using the while read loop) remains the same.
🧹 Nitpick comments (5)
docs/reference/troubleshooting.md (1)

112-115: Format default port values as inline code in the table.

The default numeric values should be wrapped in inline code formatting for consistency with docs style (for example, 8080 instead of plain 8080).

As per coding guidelines, "CLI commands, file paths, flags, parameter names, and values must use inline code formatting."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/reference/troubleshooting.md` around lines 112 - 115, Update the table
rows so the numeric default port values are formatted as inline code: wrap the
plain numbers (e.g., 8080, 8000, 18789, 11434) in backticks where they appear
next to the environment variable names like NEMOCLAW_GATEWAY_PORT,
NEMOCLAW_VLLM_PORT, NEMOCLAW_DASHBOARD_PORT, and NEMOCLAW_OLLAMA_PORT to match
the docs style guide for CLI/parameter values.
docs/reference/port-configuration.md (2)

26-33: Start each H2 with an introductory sentence.

Default Ports and Next Steps both jump straight into structured content. Add a short lead-in sentence under each heading to match the docs page-structure rule.
As per coding guidelines, Sections use H2 and H3, each starting with an introductory sentence.

Also applies to: 115-118

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/reference/port-configuration.md` around lines 26 - 33, The H2 headings
"Default Ports" and "Next Steps" are missing the required introductory
sentences; add a short lead-in sentence immediately under each H2 that briefly
describes what the section covers (e.g., for "Default Ports" add a sentence like
"The following table lists the default service ports and their environment
variable overrides." and for "Next Steps" add a sentence summarizing the actions
or links that follow) so the documentation follows the rule that every H2/H3
starts with an introductory sentence; update the content near the "Default
Ports" and "Next Steps" headings accordingly.

6-8: Use canonical product casing in the frontmatter metadata.

The new keywords and tags entries lowercase NemoClaw, OpenClaw, and OpenShell. Keep the canonical casing in metadata too.
As per coding guidelines, NemoClaw, OpenClaw, and OpenShell must use correct casing.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/reference/port-configuration.md` around lines 6 - 8, Update the
frontmatter values so product names use canonical casing: change the entries in
keywords and tags to use "NemoClaw", "OpenClaw", and "OpenShell" (e.g., replace
"nemoclaw ports" with "NemoClaw ports" and lowercase tag values like "openclaw"
and "openshell" with "OpenClaw" and "OpenShell") ensuring the keywords and tags
arrays reflect the correct casing.
README.md (1)

184-190: Drop emoji from the new callout labels.

The added ℹ️ and ⚠️ markers violate the Markdown rule for technical prose. Use plain Note and Warning labels here.
As per coding guidelines, No emoji in technical prose.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` around lines 184 - 190, Replace the emoji-prefixed callout labels
with plain text labels: change the "ℹ️ Note" heading to "Note" and the "⚠️
Network exposure" heading to "Warning", leaving the surrounding callout content
unchanged so the guidance about rebuilding the sandbox image and network
exposure remains intact.
bin/lib/onboard.js (1)

551-559: Fail fast if the Dockerfile patch doesn't apply.

If ARG CHAT_UI_URL=... is renamed or reformatted, this replace becomes a silent no-op and the image is built with the stale dashboard origin even though onboarding keeps going.

🧩 Suggested hardening
   const dockerfilePath = path.join(buildCtx, "Dockerfile");
   const dockerfileContent = fs.readFileSync(dockerfilePath, "utf-8");
-  fs.writeFileSync(
-    dockerfilePath,
-    dockerfileContent.replace(
-      /^ARG CHAT_UI_URL=.*/m,
-      `ARG CHAT_UI_URL=${chatUiUrl}`
-    )
-  );
+  const patchedDockerfile = dockerfileContent.replace(
+    /^ARG CHAT_UI_URL=.*/m,
+    `ARG CHAT_UI_URL=${chatUiUrl}`
+  );
+  if (patchedDockerfile === dockerfileContent) {
+    fs.rmSync(buildCtx, { recursive: true, force: true });
+    console.error("  Failed to patch Dockerfile: missing ARG CHAT_UI_URL.");
+    process.exit(1);
+  }
+  fs.writeFileSync(dockerfilePath, patchedDockerfile);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@bin/lib/onboard.js` around lines 551 - 559, The current replacement of ARG
CHAT_UI_URL in dockerfileContent via dockerfileContent.replace(...) can silently
no-op if the Dockerfile line was renamed or reformatted; modify the logic around
dockerfilePath/dockerfileContent so you first test whether the regex /^ARG
CHAT_UI_URL=.*/m matches (or compare before/after content) and if no match
occurs, throw or exit with a clear error (including the expected token ARG
CHAT_UI_URL) to fail fast; only call fs.writeFileSync to overwrite when the
replacement actually changed the content, otherwise abort the onboarding flow
with a descriptive error.
🤖 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/ports.js`:
- Around line 26-31: DASHBOARD_PORT is being computed eagerly via nested
parsePort calls which will throw if a lower-priority env (e.g., PUBLIC_PORT) is
invalid even when a higher-priority env (NEMOCLAW_DASHBOARD_PORT) is set; change
the logic that initializes DASHBOARD_PORT to lazily evaluate in priority order
using parsePort only on the first defined environment variable: check
process.env["NEMOCLAW_DASHBOARD_PORT"], then process.env["DASHBOARD_PORT"], then
process.env["PUBLIC_PORT"], and finally fall back to 18789, calling parsePort
only for the selected value (keep referencing parsePort and the env var names
exactly as used).
- Around line 14-23: The parsePort function currently uses parseInt which
accepts strings like "8000abc"; update parsePort to reject any non-numeric
characters by validating raw against a strict digits-only regex (e.g. /^\d+$/)
before parsing, keep the existing range check (1024-65535) and fallback
behavior, and throw the same Error when the format is invalid so malformed env
values (envVar) no longer silently truncate to a valid port.

In `@scripts/check-ports.sh`:
- Around line 111-116: The loop that iterates custom ports (for p in "$@") must
validate each argument before calling check_port to avoid passing non-numeric
strings like "abc" to lsof; add a small validation (e.g., is_valid_port or
inline check using a regex/isdigit and range 1-65535) that logs and
exits/non-zero or skips invalid entries, and only call check_port "$p" for
validated numeric ports—update the script's parameter handling around the for p
in "$@" block to perform this validation and return a clear error for bad
arguments.
- Around line 51-54: The environment fallback for port variables is
inconsistent: update the assignments in check-ports.sh so GATEWAY_PORT,
VLLM_PORT, and OLLAMA_PORT follow the same fallback chain pattern used by
DASHBOARD_PORT (i.e., NEMOCLAW_<NAME>_PORT → <NAME>_PORT → PUBLIC_PORT →
default) by changing the expansion for GATEWAY_PORT, VLLM_PORT, and OLLAMA_PORT
to include the plain <NAME>_PORT and PUBLIC_PORT fallbacks; also review and, if
needed, mirror the same change in bin/lib/ports.js to keep behavior consistent
across scripts.

In `@scripts/debug.sh`:
- Around line 31-33: The debug.sh script's lsof-dashboard checks currently only
read NEMOCLAW_DASHBOARD_PORT so they miss alternate aliases; update the two
places that build/check the dashboard port (the lsof-dashboard checks) to
resolve the port using a fallback chain (use NEMOCLAW_DASHBOARD_PORT, then
DASHBOARD_PORT, then PUBLIC_PORT) instead of only NEMOCLAW_DASHBOARD_PORT;
change the port variable resolution wherever lsof-dashboard is invoked (the
occurrence around the initial env loading and the similar occurrence later near
line ~294) to compute the port once via that fallback chain and use that
resolved variable in the lsof check.

In `@scripts/lib/runtime.sh`:
- Around line 209-210: The health-check/base-URL cases vllm-local and
ollama-local use only NEMOCLAW_VLLM_PORT and NEMOCLAW_OLLAMA_PORT and therefore
ignore unprefixed VLLM_PORT/OLLAMA_PORT; update the printf calls in the
vllm-local and ollama-local branches (and the other similar branches around the
other host.openshell.internal cases) to fall back to the unprefixed env vars
before the hardcoded default (i.e. use nested parameter expansion so
NEMOCLAW_VLLM_PORT -> VLLM_PORT -> 8000 and NEMOCLAW_OLLAMA_PORT -> OLLAMA_PORT
-> 11434) so alias-based overrides work for shell health checks and base URL
construction.

In `@scripts/nemoclaw-start.sh`:
- Around line 21-22: PUBLIC_PORT is currently set from NEMOCLAW_DASHBOARD_PORT
then PUBLIC_PORT then 18789, but omits the legacy DASHBOARD_PORT env var; update
the PUBLIC_PORT assignment to also fallback to DASHBOARD_PORT (so it reads
NEMOCLAW_DASHBOARD_PORT -> DASHBOARD_PORT -> PUBLIC_PORT -> 18789) so existing
setups honored by bin/lib/ports.js keep the intended port, and leave CHAT_UI_URL
constructed from PUBLIC_PORT unchanged.
- Around line 14-18: Update the PUBLIC_PORT fallback chain to include
DASHBOARD_PORT so it matches the resolution in bin/lib/ports.js: change the
assignment of PUBLIC_PORT (currently using NEMOCLAW_DASHBOARD_PORT →
PUBLIC_PORT) to use NEMOCLAW_DASHBOARD_PORT → DASHBOARD_PORT → PUBLIC_PORT (with
the existing default 18789). Locate the PUBLIC_PORT assignment in
scripts/nemoclaw-start.sh and modify it to reference NEMOCLAW_DASHBOARD_PORT,
then DASHBOARD_PORT, then PUBLIC_PORT as the fallback order so CHAT_UI_URL and
other consumers stay consistent.

In `@scripts/setup.sh`:
- Around line 35-37: After sourcing .env and .env.local, add normalization that
maps the unprefixed alias env vars GATEWAY_PORT and OLLAMA_PORT into the
canonical prefixed env vars the rest of the script expects (i.e., if
GATEWAY_PORT is set and the prefixed variant is not, export the prefixed
variable with GATEWAY_PORT's value; do the same for OLLAMA_PORT), so the
overrides are honored regardless of whether callers set the aliased or prefixed
names.

---

Outside diff comments:
In `@uninstall.sh`:
- Around line 281-286: The cleanup currently only searches for processes
matching NEMOCLAW_DASHBOARD_PORT and misses legacy fallbacks; update the pgrep
invocation so it checks the full fallback chain (NEMOCLAW_DASHBOARD_PORT,
DASHBOARD_PORT, PUBLIC_PORT, and the default 18789). Build a list/regex of ports
(e.g. collect ${NEMOCLAW_DASHBOARD_PORT}, ${DASHBOARD_PORT}, ${PUBLIC_PORT}, and
18789, dedupe/ignore empty) and change the pgrep -f pattern
"openshell.*forward.*${NEMOCLAW_DASHBOARD_PORT:-18789}" to match any of those
ports (e.g. use a grouped alternation like "(portA|portB|portC)"). Ensure the
surrounding variable handling (the pids array population using the while read
loop) remains the same.

---

Nitpick comments:
In `@bin/lib/onboard.js`:
- Around line 551-559: The current replacement of ARG CHAT_UI_URL in
dockerfileContent via dockerfileContent.replace(...) can silently no-op if the
Dockerfile line was renamed or reformatted; modify the logic around
dockerfilePath/dockerfileContent so you first test whether the regex /^ARG
CHAT_UI_URL=.*/m matches (or compare before/after content) and if no match
occurs, throw or exit with a clear error (including the expected token ARG
CHAT_UI_URL) to fail fast; only call fs.writeFileSync to overwrite when the
replacement actually changed the content, otherwise abort the onboarding flow
with a descriptive error.

In `@docs/reference/port-configuration.md`:
- Around line 26-33: The H2 headings "Default Ports" and "Next Steps" are
missing the required introductory sentences; add a short lead-in sentence
immediately under each H2 that briefly describes what the section covers (e.g.,
for "Default Ports" add a sentence like "The following table lists the default
service ports and their environment variable overrides." and for "Next Steps"
add a sentence summarizing the actions or links that follow) so the
documentation follows the rule that every H2/H3 starts with an introductory
sentence; update the content near the "Default Ports" and "Next Steps" headings
accordingly.
- Around line 6-8: Update the frontmatter values so product names use canonical
casing: change the entries in keywords and tags to use "NemoClaw", "OpenClaw",
and "OpenShell" (e.g., replace "nemoclaw ports" with "NemoClaw ports" and
lowercase tag values like "openclaw" and "openshell" with "OpenClaw" and
"OpenShell") ensuring the keywords and tags arrays reflect the correct casing.

In `@docs/reference/troubleshooting.md`:
- Around line 112-115: Update the table rows so the numeric default port values
are formatted as inline code: wrap the plain numbers (e.g., 8080, 8000, 18789,
11434) in backticks where they appear next to the environment variable names
like NEMOCLAW_GATEWAY_PORT, NEMOCLAW_VLLM_PORT, NEMOCLAW_DASHBOARD_PORT, and
NEMOCLAW_OLLAMA_PORT to match the docs style guide for CLI/parameter values.

In `@README.md`:
- Around line 184-190: Replace the emoji-prefixed callout labels with plain text
labels: change the "ℹ️ Note" heading to "Note" and the "⚠️ Network exposure"
heading to "Warning", leaving the surrounding callout content unchanged so the
guidance about rebuilding the sandbox image and network exposure remains intact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e5ac7b1e-a0a1-41a0-93bc-b588aea0b01a

📥 Commits

Reviewing files that changed from the base of the PR and between 2ce2905 and a7d0e00.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (29)
  • .env.example
  • README.md
  • bin/lib/env.js
  • bin/lib/local-inference.js
  • bin/lib/nim.js
  • bin/lib/onboard.js
  • bin/lib/ports.js
  • bin/lib/preflight.js
  • bin/nemoclaw.js
  • docs/reference/port-configuration.md
  • docs/reference/troubleshooting.md
  • nemoclaw-blueprint/blueprint.yaml
  • nemoclaw-blueprint/orchestrator/runner.py
  • scripts/brev-setup.sh
  • scripts/check-ports.sh
  • scripts/debug.sh
  • scripts/lib/runtime.sh
  • scripts/nemoclaw-start.sh
  • scripts/setup.sh
  • scripts/start-services.sh
  • scripts/telegram-bridge.js
  • test/e2e/test-double-onboard.sh
  • test/env.test.js
  • test/local-inference.test.js
  • test/onboard-readiness.test.js
  • test/onboard-selection.test.js
  • test/preflight.test.js
  • test/runtime-shell.test.js
  • uninstall.sh
💤 Files with no reviewable changes (1)
  • scripts/telegram-bridge.js

Comment on lines +14 to +23
function parsePort(envVar, fallback) {
const raw = process.env[envVar];
if (raw === undefined || raw === "") return fallback;
const parsed = parseInt(raw, 10);
if (Number.isNaN(parsed) || parsed < 1024 || parsed > 65535) {
throw new Error(
`Invalid port: ${envVar}="${raw}" — must be an integer between 1024 and 65535`
);
}
return parsed;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n bin/lib/ports.js

Repository: NVIDIA/NemoClaw

Length of output: 1806


🏁 Script executed:

node -e "
console.log('parseInt(\"8000abc\", 10):', parseInt('8000abc', 10));
console.log('parseInt(\"9000#tmp\", 10):', parseInt('9000#tmp', 10));
console.log('parseInt(\"abc8000\", 10):', parseInt('abc8000', 10));
console.log('Number(\"8000abc\"):', Number('8000abc'));
console.log('Number(\"8000\"):', Number('8000'));
console.log('/^\\d+$/.test(\"8000abc\"):', /^\d+$/.test('8000abc'));
console.log('/^\\d+$/.test(\"8000\"):', /^\d+$/.test('8000'));
"

Repository: NVIDIA/NemoClaw

Length of output: 248


🏁 Script executed:

fd -e test -e spec | head -20

Repository: NVIDIA/NemoClaw

Length of output: 41


🏁 Script executed:

rg "parsePort" --type js -A 5 -B 5

Repository: NVIDIA/NemoClaw

Length of output: 1534


🏁 Script executed:

find . -name "*test*" -o -name "*spec*" | grep -i port

Repository: NVIDIA/NemoClaw

Length of output: 41


🏁 Script executed:

rg "DASHBOARD_PORT|GATEWAY_PORT|VLLM_PORT|OLLAMA_PORT" --type js -B 2 -A 2

Repository: NVIDIA/NemoClaw

Length of output: 22271


Reject malformed port strings instead of silently truncating them.

Line 17 uses parseInt, so values like 8000abc or 9000#tmp validate as 8000/9000 instead of failing. Typos in environment variables silently bind the wrong port. Use a strict whitelist pattern before parsing:

Proposed fix
 function parsePort(envVar, fallback) {
   const raw = process.env[envVar];
   if (raw === undefined || raw === "") return fallback;
-  const parsed = parseInt(raw, 10);
-  if (Number.isNaN(parsed) || parsed < 1024 || parsed > 65535) {
+  const normalized = raw.trim();
+  if (!/^\d+$/.test(normalized)) {
+    throw new Error(
+      `Invalid port: ${envVar}="${raw}" — must be an integer between 1024 and 65535`
+    );
+  }
+  const parsed = Number(normalized);
+  if (parsed < 1024 || parsed > 65535) {
     throw new Error(
       `Invalid port: ${envVar}="${raw}" — must be an integer between 1024 and 65535`
     );
   }
   return parsed;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@bin/lib/ports.js` around lines 14 - 23, The parsePort function currently uses
parseInt which accepts strings like "8000abc"; update parsePort to reject any
non-numeric characters by validating raw against a strict digits-only regex
(e.g. /^\d+$/) before parsing, keep the existing range check (1024-65535) and
fallback behavior, and throw the same Error when the format is invalid so
malformed env values (envVar) no longer silently truncate to a valid port.

Comment on lines +26 to +31
// Dashboard port supports legacy env var fallback chain:
// NEMOCLAW_DASHBOARD_PORT → DASHBOARD_PORT → PUBLIC_PORT → 18789
const DASHBOARD_PORT = parsePort(
"NEMOCLAW_DASHBOARD_PORT",
parsePort("DASHBOARD_PORT", parsePort("PUBLIC_PORT", 18789))
);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n bin/lib/ports.js | head -50

Repository: NVIDIA/NemoClaw

Length of output: 1806


Make the dashboard fallback chain lazy.

Lines 28–30 eagerly evaluate DASHBOARD_PORT and PUBLIC_PORT via nested function arguments. If either legacy variable contains an invalid value, the module throws before NEMOCLAW_DASHBOARD_PORT is checked, preventing the primary configuration from being honored.

For example, if NEMOCLAW_DASHBOARD_PORT=9000 (valid) but PUBLIC_PORT=invalid, the nested call parsePort("PUBLIC_PORT", 18789) throws immediately, blocking the valid primary setting.

Implement lazy evaluation to check environment variables in priority order and only attempt to parse the first defined one:

Proposed fix
+function parseFirstDefinedPort(envVars, fallback) {
+  for (const envVar of envVars) {
+    if (process.env[envVar] !== undefined && process.env[envVar] !== "") {
+      return parsePort(envVar, fallback);
+    }
+  }
+  return fallback;
+}
+
 // Dashboard port supports legacy env var fallback chain:
 //   NEMOCLAW_DASHBOARD_PORT → DASHBOARD_PORT → PUBLIC_PORT → 18789
-const DASHBOARD_PORT = parsePort(
-  "NEMOCLAW_DASHBOARD_PORT",
-  parsePort("DASHBOARD_PORT", parsePort("PUBLIC_PORT", 18789))
-);
+const DASHBOARD_PORT = parseFirstDefinedPort(
+  ["NEMOCLAW_DASHBOARD_PORT", "DASHBOARD_PORT", "PUBLIC_PORT"],
+  18789
+);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@bin/lib/ports.js` around lines 26 - 31, DASHBOARD_PORT is being computed
eagerly via nested parsePort calls which will throw if a lower-priority env
(e.g., PUBLIC_PORT) is invalid even when a higher-priority env
(NEMOCLAW_DASHBOARD_PORT) is set; change the logic that initializes
DASHBOARD_PORT to lazily evaluate in priority order using parsePort only on the
first defined environment variable: check
process.env["NEMOCLAW_DASHBOARD_PORT"], then process.env["DASHBOARD_PORT"], then
process.env["PUBLIC_PORT"], and finally fall back to 18789, calling parsePort
only for the selected value (keep referencing parsePort and the env var names
exactly as used).

Comment on lines +51 to +54
DASHBOARD_PORT="${NEMOCLAW_DASHBOARD_PORT:-${DASHBOARD_PORT:-${PUBLIC_PORT:-18789}}}"
GATEWAY_PORT="${NEMOCLAW_GATEWAY_PORT:-8080}"
VLLM_PORT="${NEMOCLAW_VLLM_PORT:-8000}"
OLLAMA_PORT="${NEMOCLAW_OLLAMA_PORT:-11434}"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

pattern='NEMOCLAW_(DASHBOARD|GATEWAY|VLLM|OLLAMA)_PORT|\b(DASHBOARD|GATEWAY|VLLM|OLLAMA)_PORT\b'

for file in .env.example bin/lib/ports.js docs/reference/port-configuration.md scripts/check-ports.sh; do
  echo "=== $file ==="
  rg -n "$pattern" "$file" || true
  echo
done

Repository: NVIDIA/NemoClaw

Length of output: 1906


Align port environment variable fallbacks with DASHBOARD_PORT pattern.

The script treats DASHBOARD_PORT differently from GATEWAY_PORT, VLLM_PORT, and OLLAMA_PORT: only dashboard respects a fallback chain (NEMOCLAW_DASHBOARD_PORTDASHBOARD_PORTPUBLIC_PORT → default), while the others skip straight to NEMOCLAW_* without checking for plain environment keys. This is inconsistent within the same script.

If the .env uses plain keys like GATEWAY_PORT, VLLM_PORT, or OLLAMA_PORT (whether explicitly set or inherited), those values are ignored in favor of hardcoded defaults—unlike the dashboard port.

Fix
 DASHBOARD_PORT="${NEMOCLAW_DASHBOARD_PORT:-${DASHBOARD_PORT:-${PUBLIC_PORT:-18789}}}"
-GATEWAY_PORT="${NEMOCLAW_GATEWAY_PORT:-8080}"
-VLLM_PORT="${NEMOCLAW_VLLM_PORT:-8000}"
-OLLAMA_PORT="${NEMOCLAW_OLLAMA_PORT:-11434}"
+GATEWAY_PORT="${NEMOCLAW_GATEWAY_PORT:-${GATEWAY_PORT:-8080}}"
+VLLM_PORT="${NEMOCLAW_VLLM_PORT:-${VLLM_PORT:-8000}}"
+OLLAMA_PORT="${NEMOCLAW_OLLAMA_PORT:-${OLLAMA_PORT:-11434}}"

Note: bin/lib/ports.js uses the same pattern for gateway/vLLM/ollama (no fallback to plain keys), so verify whether that file should also be updated for consistency.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/check-ports.sh` around lines 51 - 54, The environment fallback for
port variables is inconsistent: update the assignments in check-ports.sh so
GATEWAY_PORT, VLLM_PORT, and OLLAMA_PORT follow the same fallback chain pattern
used by DASHBOARD_PORT (i.e., NEMOCLAW_<NAME>_PORT → <NAME>_PORT → PUBLIC_PORT →
default) by changing the expansion for GATEWAY_PORT, VLLM_PORT, and OLLAMA_PORT
to include the plain <NAME>_PORT and PUBLIC_PORT fallbacks; also review and, if
needed, mirror the same change in bin/lib/ports.js to keep behavior consistent
across scripts.

Comment on lines +111 to +116
if [[ $# -gt 0 ]]; then
echo ""
echo "Custom ports:"
for p in "$@"; do
check_port "$p" || true
done
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Validate custom port arguments before checking them.

A typo like scripts/check-ports.sh abc currently falls through to lsof failure and gets reported as ok, so manual checks can return a false negative.

🛠️ Suggested fix
 if [[ $# -gt 0 ]]; then
   echo ""
   echo "Custom ports:"
   for p in "$@"; do
+    validate_port "custom port" "$p"
     check_port "$p" || true
   done
 fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/check-ports.sh` around lines 111 - 116, The loop that iterates custom
ports (for p in "$@") must validate each argument before calling check_port to
avoid passing non-numeric strings like "abc" to lsof; add a small validation
(e.g., is_valid_port or inline check using a regex/isdigit and range 1-65535)
that logs and exits/non-zero or skips invalid entries, and only call check_port
"$p" for validated numeric ports—update the script's parameter handling around
the for p in "$@" block to perform this validation and return a clear error for
bad arguments.

Comment on lines +31 to +33
[ -f "${SCRIPT_DIR}/../.env" ] && set -a && . "${SCRIPT_DIR}/../.env" && set +a
# shellcheck source=/dev/null
[ -f "${SCRIPT_DIR}/../.env.local" ] && set -a && . "${SCRIPT_DIR}/../.env.local" && set +a
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Honor DASHBOARD_PORT / PUBLIC_PORT fallbacks in debug diagnostics.
This script only uses NEMOCLAW_DASHBOARD_PORT, so users relying on alias vars supported by bin/lib/ports.js can get incorrect lsof-dashboard checks.

Suggested patch
 [ -f "${SCRIPT_DIR}/../.env" ] && set -a && . "${SCRIPT_DIR}/../.env" && set +a
 [ -f "${SCRIPT_DIR}/../.env.local" ] && set -a && . "${SCRIPT_DIR}/../.env.local" && set +a
+DEBUG_DASHBOARD_PORT="${NEMOCLAW_DASHBOARD_PORT:-${DASHBOARD_PORT:-${PUBLIC_PORT:-18789}}}"

@@
-  collect "lsof-dashboard" lsof -i :"${NEMOCLAW_DASHBOARD_PORT:-18789}"
+  collect "lsof-dashboard" lsof -i :"${DEBUG_DASHBOARD_PORT}"

Also applies to: 294-294

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/debug.sh` around lines 31 - 33, The debug.sh script's lsof-dashboard
checks currently only read NEMOCLAW_DASHBOARD_PORT so they miss alternate
aliases; update the two places that build/check the dashboard port (the
lsof-dashboard checks) to resolve the port using a fallback chain (use
NEMOCLAW_DASHBOARD_PORT, then DASHBOARD_PORT, then PUBLIC_PORT) instead of only
NEMOCLAW_DASHBOARD_PORT; change the port variable resolution wherever
lsof-dashboard is invoked (the occurrence around the initial env loading and the
similar occurrence later near line ~294) to compute the port once via that
fallback chain and use that resolved variable in the lsof check.

Comment on lines +209 to +210
vllm-local) printf 'http://host.openshell.internal:%s/v1\n' "${NEMOCLAW_VLLM_PORT:-8000}" ;;
ollama-local) printf 'http://host.openshell.internal:%s/v1\n' "${NEMOCLAW_OLLAMA_PORT:-11434}" ;;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add unprefixed port fallbacks for shell/runtime parity.
These paths ignore VLLM_PORT and OLLAMA_PORT, so alias-based overrides can silently fail in shell health checks and base URL construction.

Suggested patch
 get_local_provider_base_url() {
   local provider="${1:-}"
+  local vllm_port="${NEMOCLAW_VLLM_PORT:-${VLLM_PORT:-8000}}"
+  local ollama_port="${NEMOCLAW_OLLAMA_PORT:-${OLLAMA_PORT:-11434}}"

   case "$provider" in
-    vllm-local) printf 'http://host.openshell.internal:%s/v1\n' "${NEMOCLAW_VLLM_PORT:-8000}" ;;
-    ollama-local) printf 'http://host.openshell.internal:%s/v1\n' "${NEMOCLAW_OLLAMA_PORT:-11434}" ;;
+    vllm-local) printf 'http://host.openshell.internal:%s/v1\n' "${vllm_port}" ;;
+    ollama-local) printf 'http://host.openshell.internal:%s/v1\n' "${ollama_port}" ;;
     *) return 1 ;;
   esac
 }

 check_local_provider_health() {
   local provider="${1:-}"
+  local vllm_port="${NEMOCLAW_VLLM_PORT:-${VLLM_PORT:-8000}}"
+  local ollama_port="${NEMOCLAW_OLLAMA_PORT:-${OLLAMA_PORT:-11434}}"

   case "$provider" in
     vllm-local)
-      curl -sf "http://localhost:${NEMOCLAW_VLLM_PORT:-8000}/v1/models" > /dev/null 2>&1
+      curl -sf "http://localhost:${vllm_port}/v1/models" > /dev/null 2>&1
       ;;
     ollama-local)
-      curl -sf "http://localhost:${NEMOCLAW_OLLAMA_PORT:-11434}/api/tags" > /dev/null 2>&1
+      curl -sf "http://localhost:${ollama_port}/api/tags" > /dev/null 2>&1
       ;;

Also applies to: 220-223

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/lib/runtime.sh` around lines 209 - 210, The health-check/base-URL
cases vllm-local and ollama-local use only NEMOCLAW_VLLM_PORT and
NEMOCLAW_OLLAMA_PORT and therefore ignore unprefixed VLLM_PORT/OLLAMA_PORT;
update the printf calls in the vllm-local and ollama-local branches (and the
other similar branches around the other host.openshell.internal cases) to fall
back to the unprefixed env vars before the hardcoded default (i.e. use nested
parameter expansion so NEMOCLAW_VLLM_PORT -> VLLM_PORT -> 8000 and
NEMOCLAW_OLLAMA_PORT -> OLLAMA_PORT -> 11434) so alias-based overrides work for
shell health checks and base URL construction.

Comment on lines +14 to +18
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# shellcheck source=/dev/null
[ -f "${SCRIPT_DIR}/../.env" ] && set -a && . "${SCRIPT_DIR}/../.env" && set +a
# shellcheck source=/dev/null
[ -f "${SCRIPT_DIR}/../.env.local" ] && set -a && . "${SCRIPT_DIR}/../.env.local" && set +a
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Find and read the full nemoclaw-start.sh script
cd /dev/null || true
find . -name "nemoclaw-start.sh" -type f

Repository: NVIDIA/NemoClaw

Length of output: 153


🏁 Script executed:

# Also look for ports.js mentioned in the comment
find . -name "ports.js" -type f

Repository: NVIDIA/NemoClaw

Length of output: 77


🏁 Script executed:

# Search for .env sourcing patterns elsewhere in the codebase
rg 'source.*\.env|\..*\.env' --type sh --type bash -B2 -A2

Repository: NVIDIA/NemoClaw

Length of output: 87


🏁 Script executed:

cat -n ./scripts/nemoclaw-start.sh

Repository: NVIDIA/NemoClaw

Length of output: 5437


🏁 Script executed:

cat -n ./bin/lib/ports.js

Repository: NVIDIA/NemoClaw

Length of output: 1806


🏁 Script executed:

# Search for .env sourcing patterns in sh/bash files
rg 'source.*\.env|\. .*\.env' -A2 -B2

Repository: NVIDIA/NemoClaw

Length of output: 5735


Add DASHBOARD_PORT to the fallback chain for PUBLIC_PORT.

Line 21 uses NEMOCLAW_DASHBOARD_PORTPUBLIC_PORT, but the JavaScript port resolution in bin/lib/ports.js includes an additional fallback: NEMOCLAW_DASHBOARD_PORTDASHBOARD_PORTPUBLIC_PORT. Update line 21 to match:

PUBLIC_PORT="${NEMOCLAW_DASHBOARD_PORT:-${DASHBOARD_PORT:-${PUBLIC_PORT:-18789}}}"

This ensures consistency with the port resolution chain used elsewhere in the PR and prevents desynchronization between PUBLIC_PORT and CHAT_UI_URL when DASHBOARD_PORT is set but PUBLIC_PORT is not.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/nemoclaw-start.sh` around lines 14 - 18, Update the PUBLIC_PORT
fallback chain to include DASHBOARD_PORT so it matches the resolution in
bin/lib/ports.js: change the assignment of PUBLIC_PORT (currently using
NEMOCLAW_DASHBOARD_PORT → PUBLIC_PORT) to use NEMOCLAW_DASHBOARD_PORT →
DASHBOARD_PORT → PUBLIC_PORT (with the existing default 18789). Locate the
PUBLIC_PORT assignment in scripts/nemoclaw-start.sh and modify it to reference
NEMOCLAW_DASHBOARD_PORT, then DASHBOARD_PORT, then PUBLIC_PORT as the fallback
order so CHAT_UI_URL and other consumers stay consistent.

Comment on lines +21 to +22
PUBLIC_PORT="${NEMOCLAW_DASHBOARD_PORT:-${PUBLIC_PORT:-18789}}"
CHAT_UI_URL="${CHAT_UI_URL:-http://127.0.0.1:${PUBLIC_PORT}}"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Restore the legacy DASHBOARD_PORT fallback here.

Line 21 skips DASHBOARD_PORT, even though bin/lib/ports.js still honors it. Existing setups that only export the legacy name will default PUBLIC_PORT back to 18789, which can skew CHAT_UI_URL and the printed dashboard links.

Proposed fix
-PUBLIC_PORT="${NEMOCLAW_DASHBOARD_PORT:-${PUBLIC_PORT:-18789}}"
+PUBLIC_PORT="${NEMOCLAW_DASHBOARD_PORT:-${DASHBOARD_PORT:-${PUBLIC_PORT:-18789}}}"
 CHAT_UI_URL="${CHAT_UI_URL:-http://127.0.0.1:${PUBLIC_PORT}}"
📝 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.

Suggested change
PUBLIC_PORT="${NEMOCLAW_DASHBOARD_PORT:-${PUBLIC_PORT:-18789}}"
CHAT_UI_URL="${CHAT_UI_URL:-http://127.0.0.1:${PUBLIC_PORT}}"
PUBLIC_PORT="${NEMOCLAW_DASHBOARD_PORT:-${DASHBOARD_PORT:-${PUBLIC_PORT:-18789}}}"
CHAT_UI_URL="${CHAT_UI_URL:-http://127.0.0.1:${PUBLIC_PORT}}"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/nemoclaw-start.sh` around lines 21 - 22, PUBLIC_PORT is currently set
from NEMOCLAW_DASHBOARD_PORT then PUBLIC_PORT then 18789, but omits the legacy
DASHBOARD_PORT env var; update the PUBLIC_PORT assignment to also fallback to
DASHBOARD_PORT (so it reads NEMOCLAW_DASHBOARD_PORT -> DASHBOARD_PORT ->
PUBLIC_PORT -> 18789) so existing setups honored by bin/lib/ports.js keep the
intended port, and leave CHAT_UI_URL constructed from PUBLIC_PORT unchanged.

Comment on lines +35 to +37
# Load port overrides if present (.env.local takes precedence)
[ -f "${REPO_DIR}/.env" ] && set -a && . "${REPO_DIR}/.env" && set +a
[ -f "${REPO_DIR}/.env.local" ] && set -a && . "${REPO_DIR}/.env.local" && set +a
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Setup path should normalize alias env vars before use.
GATEWAY_PORT / OLLAMA_PORT overrides are not honored here unless prefixed variants are set, which can break expected behavior from the new port configuration flow.

Suggested patch
 # Load port overrides if present (.env.local takes precedence)
 [ -f "${REPO_DIR}/.env" ] && set -a && . "${REPO_DIR}/.env" && set +a
 [ -f "${REPO_DIR}/.env.local" ] && set -a && . "${REPO_DIR}/.env.local" && set +a
+NEMOCLAW_GATEWAY_PORT="${NEMOCLAW_GATEWAY_PORT:-${GATEWAY_PORT:-8080}}"
+NEMOCLAW_OLLAMA_PORT="${NEMOCLAW_OLLAMA_PORT:-${OLLAMA_PORT:-11434}}"

Also applies to: 114-114, 164-164

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/setup.sh` around lines 35 - 37, After sourcing .env and .env.local,
add normalization that maps the unprefixed alias env vars GATEWAY_PORT and
OLLAMA_PORT into the canonical prefixed env vars the rest of the script expects
(i.e., if GATEWAY_PORT is set and the prefixed variant is not, export the
prefixed variable with GATEWAY_PORT's value; do the same for OLLAMA_PORT), so
the overrides are honored regardless of whether callers set the aliased or
prefixed names.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant