Skip to content

fix(dashboard): inject NEMOCLAW_DASHBOARD_PORT into sandbox so gateway uses configured port (#1925)#1939

Open
Dongni-Yang wants to merge 9 commits intoNVIDIA:mainfrom
Dongni-Yang:fix/dashboard-port-forward-1925
Open

fix(dashboard): inject NEMOCLAW_DASHBOARD_PORT into sandbox so gateway uses configured port (#1925)#1939
Dongni-Yang wants to merge 9 commits intoNVIDIA:mainfrom
Dongni-Yang:fix/dashboard-port-forward-1925

Conversation

@Dongni-Yang
Copy link
Copy Markdown
Contributor

@Dongni-Yang Dongni-Yang commented Apr 16, 2026

Summary

Fixes #1925.

Setting NEMOCLAW_DASHBOARD_PORT to a custom value had no effect — the SSH tunnel forwarded the correct host port, but the OpenClaw gateway inside the sandbox was still listening on the default port (18789), so the tunnel connected to nothing.

The bug has three independent failure points, all of which must be fixed.

Failure point 1 — NEMOCLAW_DASHBOARD_PORT was never passed into the container

createSandbox() builds an envArgs array injected at container start time. Only CHAT_UI_URL was in that array; NEMOCLAW_DASHBOARD_PORT was absent, so the script inside the container had no way to know a custom port was requested.

Failure point 2 — the shell fallback could not override the Docker ENV

nemoclaw-start.sh used CHAT_UI_URL=${CHAT_UI_URL:-http://127.0.0.1:${_DASHBOARD_PORT}}. The :- operator only fires when the variable is unset or empty. When the Docker image was built, CHAT_UI_URL was baked in as an ENV directive by patchStagedDockerfile, so the fallback never fired and the gateway always started on the port from the image.

Failure point 3 — openclaw gateway run was not told which port to bind

The gateway binary reads its listen port from the --port flag, not from CHAT_UI_URL or openclaw.json. Without --port, the gateway always defaulted to 18789 regardless of any env var. nemoclaw-start.sh has two gateway launch lines (non-root path line 904 and root path line 963); both were missing --port. Recovery scripts in nemoclaw.ts and agent-runtime.ts also lacked --port, meaning a crashed gateway would restart on the wrong port even after the initial start was correct.

Note: The initial fix only patched line 963 (root/local-test path). End-to-end verification via nemoclaw onboard revealed the gateway was still on 18789 because openshell always takes the non-root path (line 904, reached after exec gosu sandbox re-enters the script with NEMOCLAW_CMD non-empty). Line 904 and the recovery scripts were patched in follow-up commits.

Fix

src/lib/onboard.ts — inject NEMOCLAW_DASHBOARD_PORT into the container via envArgs:

if (process.env.NEMOCLAW_DASHBOARD_PORT) {
  envArgs.push(formatEnvAssignment("NEMOCLAW_DASHBOARD_PORT", String(DASHBOARD_PORT)));
}

scripts/nemoclaw-start.sh — unconditionally override CHAT_UI_URL when NEMOCLAW_DASHBOARD_PORT is present; pass --port on both gateway launch lines:

if [ -n "${NEMOCLAW_DASHBOARD_PORT:-}" ]; then
  CHAT_UI_URL="http://127.0.0.1:${_DASHBOARD_PORT}"
else
  CHAT_UI_URL="${CHAT_UI_URL:-http://127.0.0.1:${_DASHBOARD_PORT}}"
fi
# ...
nohup "$OPENCLAW" gateway run --port "${_DASHBOARD_PORT}" >/tmp/gateway.log 2>&1 &          # line 904 non-root
nohup gosu gateway "$OPENCLAW" gateway run --port "${_DASHBOARD_PORT}" >/tmp/gateway.log 2>&1 &  # line 963 root

src/lib/agent-runtime.ts and src/nemoclaw.ts — pass port to recovery scripts so a crashed gateway restarts on the configured port, not the hardcoded default.

Data flow after fix:

NEMOCLAW_DASHBOARD_PORT=19000
  → onboard.ts: injected into container via envArgs
  → nemoclaw-start.sh: detects var, overrides CHAT_UI_URL unconditionally
  → openclaw gateway run --port 19000
  → gateway listens on ws://127.0.0.1:19000 inside sandbox
  → openshell forward start 19000 sandbox-name
  → tunnel: host:19000 → sandbox:19000 ✓

Changes

File Change
src/lib/ports.ts Consolidate 18789 default into SANDBOX_DASHBOARD_PORT; remove duplicate literal
src/lib/onboard.ts Inject NEMOCLAW_DASHBOARD_PORT into sandbox envArgs when set
scripts/nemoclaw-start.sh (1) Unconditionally override CHAT_UI_URL; (2) --port "${_DASHBOARD_PORT}" on both gateway launch lines (904 non-root, 963 root)
src/lib/agent-runtime.ts Add port parameter to buildRecoveryScript; embed --port in recovery command
src/nemoclaw.ts Pass DASHBOARD_PORT to buildRecoveryScript; add --port to inline OpenClaw recovery script
test/onboard.test.ts Fix forward-command assertions + new integration test for envArgs injection
test/nemoclaw-start.test.ts Tests for CHAT_UI_URL override logic; --port assertions for both non-root (line 904) and root (line 963) gateway launch lines
src/lib/agent-runtime.test.ts New test file: buildRecoveryScript port embedding
src/lib/dashboard.test.ts New test for buildControlUiUrls with custom port
docs/reference/troubleshooting.md Add multi-sandbox section; add runtime entry for NEMOCLAW_DASHBOARD_PORT not reachable

Test plan

  • NEMOCLAW_DASHBOARD_PORT=19000 nemoclaw onboardopenshell sandbox exec -- grep "listening on" /tmp/gateway.log shows ws://127.0.0.1:19000; dashboard URL opens in browser
  • openshell forward list shows port 19000 forwarded after onboard
  • Default (no env var) — dashboard responds on port 18789, no regression
  • Two sandboxes simultaneously — each on its own port, openshell forward list shows both
  • npx vitest run --project cli test/onboard.test.ts — all cases pass
  • npx vitest run --project cli test/nemoclaw-start.test.ts — all cases pass
  • npx vitest run --project cli src/lib/agent-runtime.test.ts — all cases pass
  • npx vitest run --project plugin src/lib/dashboard.test.ts — custom-port URL test passes

Signed-off-by: Dongni Yang dongniy@nvidia.com

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 16, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

When NEMOCLAW_DASHBOARD_PORT is set, the host-side onboarding now injects that port into sandbox env during sandbox create; the sandbox startup script uses the injected value to set CHAT_UI_URL. Defaults and constants for sandbox vs host dashboard ports were clarified and tests expanded to validate forwarding and URL construction.

Changes

Cohort / File(s) Summary
Port constants
src/lib/ports.ts
Added SANDBOX_DASHBOARD_PORT = 18789; updated DASHBOARD_PORT to fallback to SANDBOX_DASHBOARD_PORT; clarified comments distinguishing sandbox-internal vs host-side port.
Onboarding / sandbox creation
src/lib/onboard.ts
createSandbox always injects CHAT_UI_URL into sandbox env; injects NEMOCLAW_DASHBOARD_PORT into envArgs only when host process.env.NEMOCLAW_DASHBOARD_PORT is set, using the computed DASHBOARD_PORT value for the injected string.
Startup script
scripts/nemoclaw-start.sh
Changed CHAT_UI_URL assignment so that when NEMOCLAW_DASHBOARD_PORT is present the script force-assigns CHAT_UI_URL="http://127.0.0.1:${_DASHBOARD_PORT}"; otherwise preserves the prior defaulting fallback.
Tests — onboarding & forwarding
test/onboard.test.ts
Expanded tests: more assertions for WSL forwarding, added getDashboardForwardStartCommand() cases (default and custom port behaviors), and an integration-style test that runs compiled dist/lib/onboard.js to assert NEMOCLAW_DASHBOARD_PORT is injected and that forwarding uses same-port mapping.
Tests — dashboard URL
src/lib/dashboard.test.ts
Added test verifying buildControlUiUrls uses an explicitly provided dashboard port (19000) in the displayed local URL.
Tests — startup script
test/nemoclaw-start.test.ts
Added tests asserting the new if [ -n "${NEMOCLAW_DASHBOARD_PORT:-}" ] branch and exact CHAT_UI_URL assignment semantics versus the else fallback.

Sequence Diagram(s)

sequenceDiagram
  participant Host as Host (env)
  participant CLI as Onboard CLI
  participant Sandbox as Sandbox (container)
  participant Script as nemoclaw-start.sh
  participant SSH as OpenShell/SSH

  Host->>CLI: export NEMOCLAW_DASHBOARD_PORT=19000
  Host->>CLI: run `onboard create` (compute DASHBOARD_PORT)
  CLI->>Sandbox: `sandbox create` with envArgs -> CHAT_UI_URL, (NEMOCLAW_DASHBOARD_PORT=19000)
  Sandbox->>Script: start -> script reads NEMOCLAW_DASHBOARD_PORT
  Script->>Script: set CHAT_UI_URL="http://127.0.0.1:19000"
  Host->>SSH: start port forward bind 127.0.0.1:19000 -> 127.0.0.1:19000
  Host->>Sandbox: HTTP request 127.0.0.1:19000 -> forwarded to sandbox dashboard
  Sandbox-->>Host: HTTP response (dashboard UI)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I tunneled a port with care,
Injected it right into the lair,
Host says nineteen thousand bold,
Sandbox answers, bright and gold,
Tests hop, tunnels sing, all fair. 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Changes comprehensively address #1925 requirements: NEMOCLAW_DASHBOARD_PORT is properly injected into sandbox environment, getDashboardForwardTarget() now correctly maps custom host port to fixed sandbox port 18789, and tests validate both custom and default port scenarios.
Out of Scope Changes check ✅ Passed All changes directly support the #1925 objective of fixing dashboard port forwarding; no unrelated or out-of-scope modifications detected across onboard logic, ports configuration, and associated tests.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Title check ✅ Passed The title clearly describes the main change: injecting NEMOCLAW_DASHBOARD_PORT into the sandbox so the gateway uses the configured port. This is directly aligned with the PR's core objective of fixing port forwarding to ensure the dashboard uses the correct sandbox port.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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
Copy Markdown
Contributor

@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: 1

🧹 Nitpick comments (1)
src/lib/ports.ts (1)

34-41: De-duplicate the dashboard default port constant.

DASHBOARD_PORT fallback and SANDBOX_DASHBOARD_PORT both hardcode 18789. Using one source of truth avoids future drift.

♻️ Suggested refactor
 /** OpenShell gateway port (default 8080, override via NEMOCLAW_GATEWAY_PORT). */
 export const GATEWAY_PORT = parsePort("NEMOCLAW_GATEWAY_PORT", 8080);
-/** Dashboard UI port (default 18789, override via NEMOCLAW_DASHBOARD_PORT). This is the host-side port. */
-export const DASHBOARD_PORT = parsePort("NEMOCLAW_DASHBOARD_PORT", 18789);
 /**
  * The port the OpenClaw dashboard always listens on *inside* the sandbox.
  * This is baked into the sandbox image at build time (via CHAT_UI_URL ARG in the Dockerfile)
  * and cannot be changed at runtime. NEMOCLAW_DASHBOARD_PORT controls only the host-side port;
  * the tunnel must map host:DASHBOARD_PORT → sandbox:SANDBOX_DASHBOARD_PORT when they differ.
  */
 export const SANDBOX_DASHBOARD_PORT = 18789;
+/** Dashboard UI port (default 18789, override via NEMOCLAW_DASHBOARD_PORT). This is the host-side port. */
+export const DASHBOARD_PORT = parsePort("NEMOCLAW_DASHBOARD_PORT", SANDBOX_DASHBOARD_PORT);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/ports.ts` around lines 34 - 41, DASHBOARD_PORT and
SANDBOX_DASHBOARD_PORT both hardcode 18789 causing duplicated source-of-truth;
change the code so SANDBOX_DASHBOARD_PORT is the single constant (export const
SANDBOX_DASHBOARD_PORT = 18789) and make DASHBOARD_PORT call
parsePort("NEMOCLAW_DASHBOARD_PORT", SANDBOX_DASHBOARD_PORT) instead of
hardcoding 18789, referencing the existing parsePort, DASHBOARD_PORT and
SANDBOX_DASHBOARD_PORT symbols.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/nemoclaw.ts`:
- Around line 288-295: The current forwardTarget assignment drops the WSL host
bind when restoring forwards; update the construction used before calling
runOpenshell so it matches the onboard logic: compute sandboxPort and localPort
as now, but set forwardTarget to include the explicit host bind (e.g., if
localPort !== sandboxPort use `0.0.0.0:${localPort}:${sandboxPort}` else
`0.0.0.0:${localPort}`) and then pass that forwardTarget into
runOpenshell(["forward", "start", ...], ...) so recovered sandboxes on WSL
preserve the 0.0.0.0 bind (referencing sandboxPort, localPort, forwardTarget,
and the runOpenshell calls).

---

Nitpick comments:
In `@src/lib/ports.ts`:
- Around line 34-41: DASHBOARD_PORT and SANDBOX_DASHBOARD_PORT both hardcode
18789 causing duplicated source-of-truth; change the code so
SANDBOX_DASHBOARD_PORT is the single constant (export const
SANDBOX_DASHBOARD_PORT = 18789) and make DASHBOARD_PORT call
parsePort("NEMOCLAW_DASHBOARD_PORT", SANDBOX_DASHBOARD_PORT) instead of
hardcoding 18789, referencing the existing parsePort, DASHBOARD_PORT and
SANDBOX_DASHBOARD_PORT symbols.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 47a06aad-9fa4-471b-a503-d04608799c6e

📥 Commits

Reviewing files that changed from the base of the PR and between bb5fdb4 and 3bbfc4a.

📒 Files selected for processing (4)
  • src/lib/onboard.ts
  • src/lib/ports.ts
  • src/nemoclaw.ts
  • test/onboard.test.ts

Comment thread src/nemoclaw.ts Outdated
@Dongni-Yang Dongni-Yang force-pushed the fix/dashboard-port-forward-1925 branch 2 times, most recently from b10a45d to 0030bab Compare April 16, 2026 05:02
Copy link
Copy Markdown
Contributor

@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.

🧹 Nitpick comments (1)
src/lib/ports.ts (1)

34-42: Avoid duplicating the dashboard default literal.

18789 is now defined in two places (DASHBOARD_PORT fallback and SANDBOX_DASHBOARD_PORT). Using one source of truth will prevent silent drift later.

♻️ Suggested refactor
-export const DASHBOARD_PORT = parsePort("NEMOCLAW_DASHBOARD_PORT", 18789);
+export const SANDBOX_DASHBOARD_PORT = 18789;
+export const DASHBOARD_PORT = parsePort("NEMOCLAW_DASHBOARD_PORT", SANDBOX_DASHBOARD_PORT);

-/**
- * The default port the OpenClaw dashboard listens on inside the sandbox.
- * The sandbox image is built with CHAT_UI_URL=http://127.0.0.1:DASHBOARD_PORT (patched
- * by patchStagedDockerfile), so the gateway starts on whichever port was configured
- * via NEMOCLAW_DASHBOARD_PORT at onboard time. This constant represents the hardcoded
- * default when no override is set.
- */
-export const SANDBOX_DASHBOARD_PORT = 18789;
+/**
+ * The default port the OpenClaw dashboard listens on inside the sandbox.
+ */
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/ports.ts` around lines 34 - 42, The literal 18789 is duplicated;
consolidate into a single constant and use it as the fallback for parsePort.
Replace the numeric fallback in the DASHBOARD_PORT declaration so it references
the SANDBOX_DASHBOARD_PORT (or create a single DEFAULT_DASHBOARD_PORT and use
that in both places), ensuring parsePort("NEMOCLAW_DASHBOARD_PORT",
SANDBOX_DASHBOARD_PORT) and any other references use the single constant
(affecting DASHBOARD_PORT, SANDBOX_DASHBOARD_PORT and the parsePort call).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/lib/ports.ts`:
- Around line 34-42: The literal 18789 is duplicated; consolidate into a single
constant and use it as the fallback for parsePort. Replace the numeric fallback
in the DASHBOARD_PORT declaration so it references the SANDBOX_DASHBOARD_PORT
(or create a single DEFAULT_DASHBOARD_PORT and use that in both places),
ensuring parsePort("NEMOCLAW_DASHBOARD_PORT", SANDBOX_DASHBOARD_PORT) and any
other references use the single constant (affecting DASHBOARD_PORT,
SANDBOX_DASHBOARD_PORT and the parsePort call).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ea22061e-3d40-4217-882a-adbe542d2f7e

📥 Commits

Reviewing files that changed from the base of the PR and between b10a45d and 0030bab.

📒 Files selected for processing (4)
  • scripts/nemoclaw-start.sh
  • src/lib/onboard.ts
  • src/lib/ports.ts
  • test/onboard.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/onboard.ts

@Dongni-Yang Dongni-Yang force-pushed the fix/dashboard-port-forward-1925 branch from 0030bab to db451f6 Compare April 16, 2026 05:39
@Dongni-Yang Dongni-Yang changed the title fix(ports): map host DASHBOARD_PORT to sandbox port 18789 in forward command (#1925) fix(dashboard): propagate NEMOCLAW_DASHBOARD_PORT into sandbox so gateway starts on configured port (#1925) Apr 16, 2026
@Dongni-Yang Dongni-Yang changed the title fix(dashboard): propagate NEMOCLAW_DASHBOARD_PORT into sandbox so gateway starts on configured port (#1925) fix(dashboard): inject NEMOCLAW_DASHBOARD_PORT into sandbox so gateway uses configured port (#1925) Apr 16, 2026
@Dongni-Yang Dongni-Yang force-pushed the fix/dashboard-port-forward-1925 branch from 2b402b5 to b61331f Compare April 16, 2026 06:24
Dongni-Yang and others added 8 commits April 16, 2026 18:42
When NEMOCLAW_DASHBOARD_PORT is set to a custom value, the SSH tunnel
correctly forwards that host port, but the gateway inside the sandbox
was still listening on the baked-in Docker ENV port (18789 by default).
This meant the tunnel found nothing on the other end.

Two-part fix:
- onboard.ts: pass NEMOCLAW_DASHBOARD_PORT into the container via
  envArgs so the runtime script can act on it
- nemoclaw-start.sh: unconditionally override CHAT_UI_URL when
  NEMOCLAW_DASHBOARD_PORT is injected, ensuring the gateway starts
  on the correct port regardless of what the Docker image has baked in

The build-time fix (patchStagedDockerfile baking CHAT_UI_URL at onboard
time) is already in place; this runtime fix handles containers that were
built with a different default or where the Docker ENV takes precedence.

Signed-off-by: Dongni Yang <dongniy@nvidia.com>
- dashboard.test.ts: assert buildControlUiUrls produces the correct URL
  when called with a custom port (the path getDashboardAccessInfo takes
  when NEMOCLAW_DASHBOARD_PORT is set)
- onboard.test.ts: integration test that NEMOCLAW_DASHBOARD_PORT=19000 is
  injected into sandbox create envArgs (Part 1 of fix) and that the
  openshell forward command uses same-port mapping
- nemoclaw-start.test.ts: static-source assertions that the shell script
  unconditionally overrides CHAT_UI_URL when NEMOCLAW_DASHBOARD_PORT is
  injected (Part 2 of fix) and falls back to the baked-in value otherwise
- ports.ts: consolidate the 18789 default into SANDBOX_DASHBOARD_PORT so
  DASHBOARD_PORT references it instead of duplicating the literal

Signed-off-by: Dongni Yang <dongniy@nvidia.com>
Explain that each sandbox needs a distinct dashboard port and show how
to assign one at onboard time with NEMOCLAW_DASHBOARD_PORT.

Signed-off-by: Dongni Yang <dongniy@nvidia.com>
…box section

Add language tag to the URL example block introduced in the multi-sandbox
port section to satisfy markdownlint MD040. Regenerate skills file.

Signed-off-by: Dongni Yang <dongniy@nvidia.com>
…e listen port

openclaw gateway run accepts a --port flag that controls the WebSocket bind
port. Without it the gateway always defaults to 18789 regardless of CHAT_UI_URL
or openclaw.json. Pass _DASHBOARD_PORT (already validated at lines 159-184) so
the gateway binds to the user-configured port when NEMOCLAW_DASHBOARD_PORT is set.

Verified locally: ss -tlnp shows ws://127.0.0.1:19000 when started with
NEMOCLAW_DASHBOARD_PORT=19000; gateway.log confirms the listen address.

Signed-off-by: Dongni Yang <dongniy@nvidia.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…not reachable (NVIDIA#1925)

Add a Runtime section entry explaining the symptom, root cause, and fix for
when the dashboard is unreachable after setting NEMOCLAW_DASHBOARD_PORT. The
symptom — SSH tunnel forwarding the custom port while the gateway listens on
18789 — was a bug fixed in NVIDIA#1925. Users on older images need to re-run
nemoclaw onboard on the current release.

Signed-off-by: Dongni Yang <dongniy@nvidia.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…shooting update

Auto-generated from docs/ via scripts/docs-to-skills.py. Reflects the new
"Dashboard not reachable after setting NEMOCLAW_DASHBOARD_PORT" entry added
to docs/reference/troubleshooting.md.

Signed-off-by: Dongni Yang <dongniy@nvidia.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…th --port

The initial --port fix (cc94c0d) only patched the root path (line 963,
gosu gateway). openshell sandbox create always takes the non-root path
(line 904) because it passes CMD args that make NEMOCLAW_CMD non-empty,
re-execing as the sandbox user. Line 904 was still missing --port, so
the gateway continued listening on 18789 despite the tunnel forwarding
the configured port.

Also patch recovery scripts so a crashed gateway restarts on the
correct port rather than falling back to the hardcoded default:
- buildRecoveryScript() in agent-runtime.ts now takes a port parameter
- recoverSandboxProcesses() in nemoclaw.ts passes DASHBOARD_PORT to
  buildRecoveryScript and to the inline OpenClaw fallback script

Tests: add root-path --port assertion to nemoclaw-start.test.ts and
new agent-runtime.test.ts covering buildRecoveryScript port embedding.

Signed-off-by: Dongni Yang <dongniy@nvidia.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Dongni-Yang Dongni-Yang force-pushed the fix/dashboard-port-forward-1925 branch from 85fc4dd to 9c92f34 Compare April 16, 2026 10:42
@Dongni-Yang
Copy link
Copy Markdown
Contributor Author

Dongni-Yang commented Apr 16, 2026

locally verified that I can open html with 19000 port with this patch
OpenClaw Control.pdf

…conflict

openshell forward start --background fails silently when the host port
is already bound by another process (e.g. a local Docker test container
started with -p PORT:PORT). With ignoreError:true + stdio:ignore, the
failure was completely invisible — the dashboard URL appeared in the
output but was unreachable with no explanation.

The parent process of openshell forward start exits non-zero immediately
when it cannot bind the port, before forking the background child.
Capture that exit code and surface a diagnostic warning with a docker ps
command to identify the conflicting process.

Signed-off-by: Dongni Yang <dongniy@nvidia.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.

[NemoClaw][All Platform] NEMOCLAW_DASHBOARD_PORT override: SSH tunnel from custom port does not forward traffic to sandbox dashboard

1 participant