Skip to content

feat(hermes): expose optional web dashboard#4442

Merged
ericksoa merged 12 commits into
mainfrom
issue-2979-Add-the-Hermes-Web-dashboard-on-port-9119
May 29, 2026
Merged

feat(hermes): expose optional web dashboard#4442
ericksoa merged 12 commits into
mainfrom
issue-2979-Add-the-Hermes-Web-dashboard-on-port-9119

Conversation

@ahunnargikar-nvidia
Copy link
Copy Markdown
Contributor

@ahunnargikar-nvidia ahunnargikar-nvidia commented May 28, 2026

Summary

Adds an opt-in NemoHermes native web dashboard path so Hermes sandboxes can expose the upstream browser dashboard separately from the OpenAI-compatible API. The API remains on port 8642, while the dashboard defaults to port 9119 when enabled.

Related Issue

Fixes #2979

Changes

  • Add Hermes dashboard environment parsing for NEMOCLAW_HERMES_DASHBOARD, dashboard port, internal port, and optional TUI mode.
  • Start hermes dashboard --no-open inside Hermes sandboxes and bridge it through a separate host forward on port 9119.
  • Persist dashboard settings in the sandbox registry, detect setting drift, and recover the dashboard forward during reconnect/status recovery.
  • Add agent manifest metadata so onboarding output can show the optional Hermes dashboard URL.
  • Update Hermes quickstart and command reference docs with dashboard enablement instructions.
  • Add tests for dashboard config parsing, manifest parsing, onboarding output, port forwarding, process recovery, and Hermes startup cleanup.

Type of Change

  • Code change (feature, bug fix, or refactor)
  • Code change with doc updates
  • Doc only (prose changes, no code sample modifications)
  • Doc only (includes code sample changes)

Verification

Passed:

  • npm run build:cli
  • npm run typecheck:cli
  • npm run lint (passes with one existing Biome warning in src/lib/onboard/child-exit-tracker.test.ts)
  • npx vitest run --project cli src/lib/hermes-dashboard.test.ts src/lib/agent/defs.test.ts src/lib/agent/onboard.test.ts test/onboard-dashboard.test.ts test/process-recovery.test.ts
  • npx vitest run --project cli test/hermes-start.test.ts --reporter verbose
  • npm run docs (0 errors, 2 existing Fern warnings)

Attempted:

  • npx prek run --all-files is blocked locally because the global gitignore marks tracked lockfiles as ignored and hadolint is not installed.

  • npm test full suite was attempted outside the sandbox; one unrelated test/sandbox-connect-inference.test.ts case timed out once, and that file passed on isolated rerun.

  • npx prek run --all-files passes

  • npm test passes

  • Tests added or updated for new or changed behavior

  • No secrets, API keys, or credentials committed

  • Docs updated for user-facing behavior changes

  • npm run docs builds without warnings (doc changes only)

  • Doc pages follow the style guide (doc changes only)

  • New doc pages include SPDX header and frontmatter (new pages only)


Signed-off-by: Ashish Hunnargikar ahunnargikar@nvidia.com

Summary by CodeRabbit

  • New Features

    • Optional Hermes web dashboard: opt-in via env, configurable public/internal ports, optional TUI, printed dashboard URL and automatic local forwarding during sandbox onboarding; recovery tooling for dashboard process and forwards; registry persisted dashboard metadata.
  • Bug Fixes

    • Strict port validation, collision prevention, improved forward health checks and automated recovery/restart behavior.
  • Documentation

    • Quickstart and command reference updated with dashboard setup, ports, TUI, and access guidance.
  • Tests

    • Expanded unit, integration, and E2E coverage for onboarding, forwarding, recovery, and runtime behavior.

Review Change Stack

Signed-off-by: Ashish Hunnargikar <ahunnargikar@nvidia.com>
@ahunnargikar-nvidia ahunnargikar-nvidia added the documentation Improvements or additions to documentation label May 28, 2026
@ahunnargikar-nvidia ahunnargikar-nvidia self-assigned this May 28, 2026
@copy-pr-bot
Copy link
Copy Markdown

copy-pr-bot Bot commented May 28, 2026

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 28, 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

Adds optional Hermes web dashboard: manifest dashboard_ui, Dockerfile/UI build updates, start.sh runtime dashboard launch/port-forwarding/validation/cleanup, forward-health and recovery helpers, onboarding forwarding and registry persistence, plus tests and docs.

Changes

Hermes Web Dashboard

Layer / File(s) Summary
Aggregate feature checkpoint
*
All edits implementing the Hermes web dashboard feature: manifest, Dockerfile UI builds, start.sh dashboard launch/socat forwarding/validation/cleanup, forward-health and recovery helpers, runtime recovery script changes, onboarding/dashboard forwarding, registry fields, tests, E2E job and scripts, and documentation.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • NVIDIA/NemoClaw#4072: Related onboarding dashboard-forwarding helper changes and forward-start orchestration.
  • NVIDIA/NemoClaw#3919: Related onboarding dashboard helper surface changes touching src/lib/onboard/dashboard.ts.

Suggested labels

NemoClaw CLI, Sandbox, v0.0.54, E2E

Suggested reviewers

  • ericksoa
  • cv

"I stitched a dashboard where ports align just right,
Hermes hums on nine-one-one-nine into the night,
With TUI tabs, forwards, and recovery in tow,
The rabbit checks the logs where tiny LEDs glow,
Forwarded, tested, documented — off we go!"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 19.44% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat(hermes): expose optional web dashboard' directly and clearly summarizes the main change—adding an opt-in Hermes web dashboard feature.
Linked Issues check ✅ Passed The changeset comprehensively addresses all coding requirements from issue #2979: adds pty to HERMES_UV_EXTRAS, builds UI components, implements dashboard startup via hermes dashboard command, bridges port 9119 via socat, and provides recovery/configuration persistence.
Out of Scope Changes check ✅ Passed All changes remain in scope: Hermes dashboard enablement, port forwarding, recovery logic, manifest metadata, documentation, and corresponding tests—no unrelated modifications detected.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-2979-Add-the-Hermes-Web-dashboard-on-port-9119

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

@github-actions
Copy link
Copy Markdown
Contributor

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 28, 2026

E2E Advisor Recommendation

Required E2E: hermes-dashboard-e2e, hermes-e2e, hermes-root-entrypoint-smoke-e2e, hermes-onboard-security-posture-e2e
Optional E2E: rebuild-hermes-e2e, tunnel-lifecycle-e2e, sandbox-survival-e2e

Dispatch hint: hermes-dashboard-e2e,hermes-e2e,hermes-root-entrypoint-smoke-e2e,hermes-onboard-security-posture-e2e

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • hermes-dashboard-e2e (high): Primary merge-blocking coverage for this PR: exercises install/onboard with NEMOCLAW_HERMES_DASHBOARD enabled, validates Hermes API and dashboard ports are recorded separately, checks OpenShell forwards, and probes dashboard reachability from the host and inside the sandbox.
  • hermes-e2e (high): Validates the default Hermes install → onboard → health → live inference path remains healthy when the new optional dashboard is not enabled. This is required because Dockerfile.base, manifest, start.sh, onboarding, and runtime code changed.
  • hermes-root-entrypoint-smoke-e2e (medium): agents/hermes/start.sh and Dockerfile.base changed entrypoint behavior, service launch, permissions, layout repair, and process cleanup. This smoke test specifically covers the real Hermes image and root-entrypoint startup/security posture.
  • hermes-onboard-security-posture-e2e (high): The PR changes sandbox startup privilege separation and adds a dashboard service/forward. Run the Hermes non-root/security-posture onboard flow to catch regressions in trusted rc-file handling, runtime guards, and security-sensitive startup behavior.

Optional E2E

  • rebuild-hermes-e2e (high): Useful adjacent confidence for Hermes image/manifest/runtime metadata changes because rebuild paths must preserve Hermes state and recreate the sandbox from the updated assets, but the direct dashboard/default Hermes E2Es are the merge-blocking coverage.
  • tunnel-lifecycle-e2e (high): Forward-health and process-recovery changes are adjacent to tunnel/forward lifecycle behavior. Run if extra confidence is desired for generic OpenShell forward lifecycle interactions.
  • sandbox-survival-e2e (medium): Process-recovery changes may affect sandbox health/recovery reporting across gateway restarts. This OpenClaw-oriented survival test is useful regression coverage but less targeted than Hermes dashboard E2E.

New E2E recommendations

  • Hermes dashboard recovery after process or forward loss (high): The new Hermes dashboard recovery helpers are unit-tested, and hermes-dashboard-e2e validates initial dashboard startup, but there is no clearly existing E2E that kills the dashboard process or host forward and verifies status/connect recovery restores port 9119 without taking over an occupied port.
    • Suggested test: Add a Hermes dashboard recovery E2E: onboard with NEMOCLAW_HERMES_DASHBOARD=1, kill the dashboard process and separately stop/remove the dashboard forward, run the lifecycle command that triggers recovery, assert API 8642 remains healthy, dashboard 9119 is restored, and occupied-port cases are reported without takeover.
  • Custom Hermes dashboard port and TUI option (medium): The PR adds NEMOCLAW_HERMES_DASHBOARD_PORT and NEMOCLAW_HERMES_DASHBOARD_TUI paths, but the current dashboard E2E uses the default port and does not enable TUI. A lightweight variant would cover env parsing and non-default forwarding.
    • Suggested test: Extend or add a Hermes dashboard E2E variant that sets NEMOCLAW_HERMES_DASHBOARD_PORT to a non-default high port and NEMOCLAW_HERMES_DASHBOARD_TUI=1, then verifies registry metadata, OpenShell forward list, and host reachability on the custom port.

Dispatch hint

  • Workflow: .github/workflows/nightly-e2e.yaml
  • jobs input: hermes-dashboard-e2e,hermes-e2e,hermes-root-entrypoint-smoke-e2e,hermes-onboard-security-posture-e2e

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 28, 2026

E2E Scenario Advisor Recommendation

Required scenario E2E: None
Optional scenario E2E: None

Workflow run

Full scenario advisor summary

E2E Scenario Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required scenario E2E

  • None. No scenario workflow, scenario metadata, scenario runtime, or validation-suite files changed.

Optional scenario E2E

  • None.

Relevant changed files

  • None.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 28, 2026

PR Review Advisor

Findings: 0 needs attention, 13 worth checking, 0 nice ideas
Since last review: 0 prior items resolved, 12 still apply, 0 new items found

Review findings

🛠️ Needs attention

  • None.

🔎 Worth checking

  • Source-of-truth review needed: src/lib/actions/sandbox/hermes-dashboard-recovery.ts getHermesDashboardRecoveryConfig: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: `getHermesDashboardRecoveryConfig()` returns `null` for invalid `hermesDashboardPort` and `hermesDashboardInternalPort`, and callers no-op.
  • Source-of-truth review needed: src/lib/agent/runtime.ts and src/lib/actions/sandbox/hermes-dashboard-recovery.ts recovery marker protocol: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: `recoverHermesDashboardProcessIfEnabled()` accepts `DASHBOARD_ALREADY_RUNNING` as `true`; `checkAndRecoverSandboxProcesses()` folds that into `forwardRecovered`.
  • Source-of-truth review needed: src/lib/agent/dashboard-ui.ts optional dashboard URL parsing: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: `printOptionalDashboardUi()` catches `new URL(withoutHash)` failures, sets `urlPort = ""`, and continues.
  • Source-of-truth review needed: agents/hermes/start.sh dashboard log streaming and src/lib/agent/runtime.ts recovery tails: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: `start_dashboard_log_stream()` tails `/tmp/hermes-dashboard.log`; recovery script tails `$_DASHBOARD_LOG` on failure.
  • Optional Hermes dashboard exposure lacks an enforced auth and bind-scope invariant (agents/hermes/start.sh:445): The PR starts the upstream Hermes web dashboard and creates a host-forwardable path, but NemoClaw does not verify that the dashboard requires authentication or that the host-side forward remains loopback-only unless explicitly remote-bound. Documentation says to treat it as a local management UI, but the security boundary is not enforced or covered by a negative test.
    • Recommendation: Before exposing the dashboard forward, either verify/enforce the native dashboard authentication model or add tests proving the dashboard forward remains loopback-only unless explicitly opted into remote exposure. Document the dashboard auth model separately from the OpenAI-compatible API bearer-token auth.
    • Evidence: `start_hermes_dashboard_current_user` and `start_hermes_dashboard_sandbox_user` launch `hermes dashboard --host 127.0.0.1 --port ... --skip-build --no-open`; `start_socat_forwarder` bridges to `0.0.0.0:${HERMES_DASHBOARD_PUBLIC_PORT}` inside the sandbox; `test/e2e/test-hermes-e2e.sh` accepts HTTP 2xx/3xx reachability rather than checking auth or bind scope.
  • Dashboard logs are streamed without a redaction boundary (agents/hermes/start.sh:206): When the optional dashboard is enabled, NemoClaw tails upstream dashboard logs into startup output, and recovery can tail dashboard failure logs. If upstream Hermes logs request URLs, headers, session state, prompts, user content, or tokens, NemoClaw may copy those values into user-visible logs and CI artifacts.
    • Recommendation: Confirm and document that upstream dashboard logs cannot contain secrets, or filter/redact dashboard log streams before emitting them. Add a regression test for the chosen redaction or non-secret invariant.
    • Evidence: `start_dashboard_log_stream()` runs `tail -n +1 -F /tmp/hermes-dashboard.log | sed ...`; `src/lib/agent/runtime.ts` recovery script tails `$_DASHBOARD_LOG` on `DASHBOARD_FAILED`.
  • Dashboard and TUI dependencies are prebaked into every Hermes sandbox (agents/hermes/Dockerfile.base:25): The base image now installs the `pty` extra and builds both `ui-tui` and `web` npm dependency trees for all Hermes sandboxes, even when the optional dashboard and TUI are disabled. That expands the dependency attack surface and npm lifecycle-script review burden globally.
    • Recommendation: Document dependency/security review for the added `pty`, `ui-tui`, and `web` dependency sets, or scope dashboard/TUI-only dependency installation and builds to the enabled dashboard path if feasible. Consider whether npm lifecycle scripts should be disabled or explicitly justified.
    • Evidence: `ARG HERMES_UV_EXTRAS` changes to `messaging web pty`; the Dockerfile adds `npm ci --prefix ui-tui`, `npm run build --prefix ui-tui`, `npm ci --prefix web`, and `npm run build --prefix web`.
  • New dashboard E2E job expands a secret-bearing target-ref execution path (.github/workflows/nightly-e2e.yaml:691): The new `hermes-dashboard-e2e` job runs the selected target ref's E2E script with `NVIDIA_API_KEY` and `GITHUB_TOKEN` available. The reusable workflow has good mitigations, but this still adds another path where target-ref code executes with secrets during manual/selective dispatch.
    • Recommendation: Keep the reusable workflow/action boundary from the trusted workflow ref, keep checkout credentials disabled, and add or maintain tests that verify script allowlisting, `env_json` validation, and selective-dispatch job discovery include this new job safely.
    • Evidence: The new job uses `test/e2e/test-hermes-e2e.sh`, sets dashboard env flags, and passes `nvidia_api_key: true` and `github_token: true`; `.github/workflows/e2e-script.yaml` mitigates with `persist-credentials: false` and `test/e2e/*.sh` allowlisting.
  • Invalid enabled Hermes dashboard registry state is silently skipped (src/lib/actions/sandbox/hermes-dashboard-recovery.ts:29): Recovery treats non-Hermes/disabled dashboard state the same as an enabled Hermes dashboard with missing or invalid port metadata. Corrupt or partially migrated registry state can therefore disable dashboard process and forward recovery without an actionable diagnostic.
    • Recommendation: Differentiate disabled/non-Hermes state from invalid enabled-dashboard metadata. Surface a clear diagnostic and add integrated negative tests for missing, privileged, non-number, and out-of-range `hermesDashboardPort` and `hermesDashboardInternalPort` when `hermesDashboardEnabled` is true.
    • Evidence: `getHermesDashboardRecoveryConfig()` returns `null` for non-Hermes, disabled dashboard state, invalid `hermesDashboardPort`, and invalid `hermesDashboardInternalPort`; callers then return `null` and no-op.
  • Already-running dashboard is reported as recovery (src/lib/actions/sandbox/hermes-dashboard-recovery.ts:66): Dashboard process recovery returns `true` for both a newly relaunched dashboard and a dashboard that was already responding. `checkAndRecoverSandboxProcesses()` folds that boolean into `forwardRecovered`, so status/connect paths can report a repair even when no process or forward was repaired.
    • Recommendation: Return distinct states such as `already_running`, `restarted`, and `failed`, and only set repair indicators when a process or forward was actually recreated. Add tests for already-running, relaunched, failed, and missing-forward cases.
    • Evidence: `recoverHermesDashboardProcessIfEnabled()` treats stdout containing `DASHBOARD_ALREADY_RUNNING` as success; `src/lib/actions/sandbox/process-recovery.ts` includes `dashboardProcessRecovered === true` in `forwardRecovered`.
  • Optional dashboard URL generation hides malformed NemoClaw-generated URLs (src/lib/agent/dashboard-ui.ts:113): The optional dashboard printer catches URL parsing failures and silently omits the dashboard URL. In this path, URLs come from NemoClaw's own dashboard URL builder, so malformed output indicates source-of-truth drift rather than user input that should be ignored.
    • Recommendation: Make `buildControlUiUrls`/dashboard delivery produce valid URLs by construction for this path, or emit an explicit diagnostic when parsing fails. Add a negative test proving malformed generated URLs are not silently omitted.
    • Evidence: `printOptionalDashboardUi()` wraps `new URL(withoutHash)` in `catch { urlPort = ""; }` and then continues when `urlPort` does not match the dashboard port.
  • Dashboard lifecycle recovery lacks integrated state-machine coverage (src/lib/actions/sandbox/process-recovery.ts:390): The changed behavior spans Docker packaging, sandbox startup, dashboard launch, in-sandbox socat bridging, host forwarding, registry metadata, reconnect/status recovery, and restart recovery. Current tests cover helper return values, generated snippets, startup cleanup, and live reachability, but not the combined enabled-dashboard recovery state machine.
    • Recommendation: Add targeted integrated tests around `checkAndRecoverSandboxProcesses()` with enabled Hermes dashboard registry fields, missing/occupied dashboard forwards, corrupt dashboard metadata, already-running dashboard process, dashboard restart, forward start failure diagnostics, and recovery after sandbox restart.
    • Evidence: `src/lib/actions/sandbox/hermes-dashboard-recovery.test.ts` covers helpers; `src/lib/agent/runtime.test.ts` checks script substrings; `test/hermes-start.test.ts` covers orphan dashboard socat cleanup; `test/process-recovery.test.ts` directly exercises the OpenClaw scoped-stop path, not the full Hermes dashboard recovery matrix.
  • Issue-requested dashboard interactions are only validated as reachability (test/e2e/test-hermes-e2e.sh:560): The linked issue asks for a web dashboard that makes it easier to configure and interact/chat with Hermes, and a later comment highlights the built-in kanban board. The PR validates that the dashboard responds, but not that the requested dashboard interaction surfaces actually work through NemoClaw's forwarding path.
    • Recommendation: Add or identify a targeted runtime validation for a representative dashboard interaction, or explicitly narrow the accepted scope to exposing the upstream dashboard URL and port rather than validating configuration/chat/kanban behavior.
    • Evidence: The E2E dashboard block checks `curl -L` returns 2xx/3xx with a non-empty body on `http://127.0.0.1:${HERMES\_DASHBOARD\_PORT}/\` and that the internal port responds; it does not exercise configure, chat, or kanban functionality.

🌱 Nice ideas

  • None.
Since last review details

Current findings:

  • Source-of-truth review needed: src/lib/actions/sandbox/hermes-dashboard-recovery.ts getHermesDashboardRecoveryConfig: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: `getHermesDashboardRecoveryConfig()` returns `null` for invalid `hermesDashboardPort` and `hermesDashboardInternalPort`, and callers no-op.
  • Source-of-truth review needed: src/lib/agent/runtime.ts and src/lib/actions/sandbox/hermes-dashboard-recovery.ts recovery marker protocol: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: `recoverHermesDashboardProcessIfEnabled()` accepts `DASHBOARD_ALREADY_RUNNING` as `true`; `checkAndRecoverSandboxProcesses()` folds that into `forwardRecovered`.
  • Source-of-truth review needed: src/lib/agent/dashboard-ui.ts optional dashboard URL parsing: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: `printOptionalDashboardUi()` catches `new URL(withoutHash)` failures, sets `urlPort = ""`, and continues.
  • Source-of-truth review needed: agents/hermes/start.sh dashboard log streaming and src/lib/agent/runtime.ts recovery tails: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: `start_dashboard_log_stream()` tails `/tmp/hermes-dashboard.log`; recovery script tails `$_DASHBOARD_LOG` on failure.
  • Optional Hermes dashboard exposure lacks an enforced auth and bind-scope invariant (agents/hermes/start.sh:445): The PR starts the upstream Hermes web dashboard and creates a host-forwardable path, but NemoClaw does not verify that the dashboard requires authentication or that the host-side forward remains loopback-only unless explicitly remote-bound. Documentation says to treat it as a local management UI, but the security boundary is not enforced or covered by a negative test.
    • Recommendation: Before exposing the dashboard forward, either verify/enforce the native dashboard authentication model or add tests proving the dashboard forward remains loopback-only unless explicitly opted into remote exposure. Document the dashboard auth model separately from the OpenAI-compatible API bearer-token auth.
    • Evidence: `start_hermes_dashboard_current_user` and `start_hermes_dashboard_sandbox_user` launch `hermes dashboard --host 127.0.0.1 --port ... --skip-build --no-open`; `start_socat_forwarder` bridges to `0.0.0.0:${HERMES_DASHBOARD_PUBLIC_PORT}` inside the sandbox; `test/e2e/test-hermes-e2e.sh` accepts HTTP 2xx/3xx reachability rather than checking auth or bind scope.
  • Dashboard logs are streamed without a redaction boundary (agents/hermes/start.sh:206): When the optional dashboard is enabled, NemoClaw tails upstream dashboard logs into startup output, and recovery can tail dashboard failure logs. If upstream Hermes logs request URLs, headers, session state, prompts, user content, or tokens, NemoClaw may copy those values into user-visible logs and CI artifacts.
    • Recommendation: Confirm and document that upstream dashboard logs cannot contain secrets, or filter/redact dashboard log streams before emitting them. Add a regression test for the chosen redaction or non-secret invariant.
    • Evidence: `start_dashboard_log_stream()` runs `tail -n +1 -F /tmp/hermes-dashboard.log | sed ...`; `src/lib/agent/runtime.ts` recovery script tails `$_DASHBOARD_LOG` on `DASHBOARD_FAILED`.
  • Dashboard and TUI dependencies are prebaked into every Hermes sandbox (agents/hermes/Dockerfile.base:25): The base image now installs the `pty` extra and builds both `ui-tui` and `web` npm dependency trees for all Hermes sandboxes, even when the optional dashboard and TUI are disabled. That expands the dependency attack surface and npm lifecycle-script review burden globally.
    • Recommendation: Document dependency/security review for the added `pty`, `ui-tui`, and `web` dependency sets, or scope dashboard/TUI-only dependency installation and builds to the enabled dashboard path if feasible. Consider whether npm lifecycle scripts should be disabled or explicitly justified.
    • Evidence: `ARG HERMES_UV_EXTRAS` changes to `messaging web pty`; the Dockerfile adds `npm ci --prefix ui-tui`, `npm run build --prefix ui-tui`, `npm ci --prefix web`, and `npm run build --prefix web`.
  • New dashboard E2E job expands a secret-bearing target-ref execution path (.github/workflows/nightly-e2e.yaml:691): The new `hermes-dashboard-e2e` job runs the selected target ref's E2E script with `NVIDIA_API_KEY` and `GITHUB_TOKEN` available. The reusable workflow has good mitigations, but this still adds another path where target-ref code executes with secrets during manual/selective dispatch.
    • Recommendation: Keep the reusable workflow/action boundary from the trusted workflow ref, keep checkout credentials disabled, and add or maintain tests that verify script allowlisting, `env_json` validation, and selective-dispatch job discovery include this new job safely.
    • Evidence: The new job uses `test/e2e/test-hermes-e2e.sh`, sets dashboard env flags, and passes `nvidia_api_key: true` and `github_token: true`; `.github/workflows/e2e-script.yaml` mitigates with `persist-credentials: false` and `test/e2e/*.sh` allowlisting.
  • Invalid enabled Hermes dashboard registry state is silently skipped (src/lib/actions/sandbox/hermes-dashboard-recovery.ts:29): Recovery treats non-Hermes/disabled dashboard state the same as an enabled Hermes dashboard with missing or invalid port metadata. Corrupt or partially migrated registry state can therefore disable dashboard process and forward recovery without an actionable diagnostic.
    • Recommendation: Differentiate disabled/non-Hermes state from invalid enabled-dashboard metadata. Surface a clear diagnostic and add integrated negative tests for missing, privileged, non-number, and out-of-range `hermesDashboardPort` and `hermesDashboardInternalPort` when `hermesDashboardEnabled` is true.
    • Evidence: `getHermesDashboardRecoveryConfig()` returns `null` for non-Hermes, disabled dashboard state, invalid `hermesDashboardPort`, and invalid `hermesDashboardInternalPort`; callers then return `null` and no-op.
  • Already-running dashboard is reported as recovery (src/lib/actions/sandbox/hermes-dashboard-recovery.ts:66): Dashboard process recovery returns `true` for both a newly relaunched dashboard and a dashboard that was already responding. `checkAndRecoverSandboxProcesses()` folds that boolean into `forwardRecovered`, so status/connect paths can report a repair even when no process or forward was repaired.
    • Recommendation: Return distinct states such as `already_running`, `restarted`, and `failed`, and only set repair indicators when a process or forward was actually recreated. Add tests for already-running, relaunched, failed, and missing-forward cases.
    • Evidence: `recoverHermesDashboardProcessIfEnabled()` treats stdout containing `DASHBOARD_ALREADY_RUNNING` as success; `src/lib/actions/sandbox/process-recovery.ts` includes `dashboardProcessRecovered === true` in `forwardRecovered`.
  • Optional dashboard URL generation hides malformed NemoClaw-generated URLs (src/lib/agent/dashboard-ui.ts:113): The optional dashboard printer catches URL parsing failures and silently omits the dashboard URL. In this path, URLs come from NemoClaw's own dashboard URL builder, so malformed output indicates source-of-truth drift rather than user input that should be ignored.
    • Recommendation: Make `buildControlUiUrls`/dashboard delivery produce valid URLs by construction for this path, or emit an explicit diagnostic when parsing fails. Add a negative test proving malformed generated URLs are not silently omitted.
    • Evidence: `printOptionalDashboardUi()` wraps `new URL(withoutHash)` in `catch { urlPort = ""; }` and then continues when `urlPort` does not match the dashboard port.
  • Dashboard lifecycle recovery lacks integrated state-machine coverage (src/lib/actions/sandbox/process-recovery.ts:390): The changed behavior spans Docker packaging, sandbox startup, dashboard launch, in-sandbox socat bridging, host forwarding, registry metadata, reconnect/status recovery, and restart recovery. Current tests cover helper return values, generated snippets, startup cleanup, and live reachability, but not the combined enabled-dashboard recovery state machine.
    • Recommendation: Add targeted integrated tests around `checkAndRecoverSandboxProcesses()` with enabled Hermes dashboard registry fields, missing/occupied dashboard forwards, corrupt dashboard metadata, already-running dashboard process, dashboard restart, forward start failure diagnostics, and recovery after sandbox restart.
    • Evidence: `src/lib/actions/sandbox/hermes-dashboard-recovery.test.ts` covers helpers; `src/lib/agent/runtime.test.ts` checks script substrings; `test/hermes-start.test.ts` covers orphan dashboard socat cleanup; `test/process-recovery.test.ts` directly exercises the OpenClaw scoped-stop path, not the full Hermes dashboard recovery matrix.
  • Issue-requested dashboard interactions are only validated as reachability (test/e2e/test-hermes-e2e.sh:560): The linked issue asks for a web dashboard that makes it easier to configure and interact/chat with Hermes, and a later comment highlights the built-in kanban board. The PR validates that the dashboard responds, but not that the requested dashboard interaction surfaces actually work through NemoClaw's forwarding path.
    • Recommendation: Add or identify a targeted runtime validation for a representative dashboard interaction, or explicitly narrow the accepted scope to exposing the upstream dashboard URL and port rather than validating configuration/chat/kanban behavior.
    • Evidence: The E2E dashboard block checks `curl -L` returns 2xx/3xx with a non-empty body on `http://127.0.0.1:${HERMES\_DASHBOARD\_PORT}/\` and that the internal port responds; it does not exercise configure, chat, or kanban functionality.

Workflow run details

This is an automated advisory review. A human maintainer must make the final merge decision.

@ericksoa ericksoa marked this pull request as ready for review May 28, 2026 21:22
@ericksoa
Copy link
Copy Markdown
Contributor

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 28, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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: 6

🧹 Nitpick comments (3)
src/lib/hermes-dashboard.test.ts (1)

38-44: ⚡ Quick win

Add boundary assertions for port-range validation.

This suite only checks non-numeric input. Add explicit assertions for out-of-range numeric values (e.g., 1023, 65536) to lock the port contract and prevent regressions.

Suggested test addition
   it("rejects invalid port values", () => {
     expect(() =>
       readHermesDashboardConfig({
         NEMOCLAW_HERMES_DASHBOARD_PORT: "abc",
       }),
     ).toThrow(/NEMOCLAW_HERMES_DASHBOARD_PORT/);
   });
+
+  it("rejects out-of-range dashboard port values", () => {
+    expect(() =>
+      readHermesDashboardConfig({
+        NEMOCLAW_HERMES_DASHBOARD_PORT: "1023",
+      }),
+    ).toThrow(/NEMOCLAW_HERMES_DASHBOARD_PORT/);
+
+    expect(() =>
+      readHermesDashboardConfig({
+        NEMOCLAW_HERMES_DASHBOARD_PORT: "65536",
+      }),
+    ).toThrow(/NEMOCLAW_HERMES_DASHBOARD_PORT/);
+  });
 });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/hermes-dashboard.test.ts` around lines 38 - 44, Extend the "rejects
invalid port values" test for readHermesDashboardConfig to also assert numeric
out-of-range ports are rejected: within the same it block (or a new it near it)
call readHermesDashboardConfig with NEMOCLAW_HERMES_DASHBOARD_PORT: "1023" and
with "65536" and assert each invocation throws (toThrow) matching the existing
port-related error (e.g., /NEMOCLAW_HERMES_DASHBOARD_PORT/ or the module's
port-range message) so the contract enforces the valid port range.
src/lib/actions/sandbox/hermes-dashboard-recovery.test.ts (1)

45-77: ⚡ Quick win

Add explicit coverage for the "occupied" forward-health branch.

This test block currently doesn’t assert the non-takeover path when isPortForwardHealthy returns "occupied" (Line 56/65/73 only exercise false/true). Please add one case asserting return false and that ensurePortForward is not called.

✅ Suggested test addition
   it("restarts the dashboard forward only when the recorded forward is unhealthy", () => {
     const ensurePortForward = vi.fn(() => true);
     const getRecoveryConfig = () => ({
       publicPort: 9119,
       internalPort: 19119,
       tuiEnabled: false,
     });

@@
     expect(
       ensureHermesDashboardPortForwardIfEnabled("alpha", {
         getRecoveryConfig,
         isPortForwardHealthy: () => true,
         ensurePortForward,
       }),
     ).toBe(false);

+    const ensurePortForwardWhenOccupied = vi.fn(() => true);
+    expect(
+      ensureHermesDashboardPortForwardIfEnabled("alpha", {
+        getRecoveryConfig,
+        isPortForwardHealthy: () => "occupied",
+        ensurePortForward: ensurePortForwardWhenOccupied,
+      }),
+    ).toBe(false);
+    expect(ensurePortForwardWhenOccupied).not.toHaveBeenCalled();
+
     expect(
       ensureHermesDashboardPortForwardIfEnabled("alpha", {
         getRecoveryConfig: () => null,
         isPortForwardHealthy: () => false,
         ensurePortForward,
       }),
     ).toBeNull();
   });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/actions/sandbox/hermes-dashboard-recovery.test.ts` around lines 45 -
77, Add a test case in the existing "restarts the dashboard forward only when
the recorded forward is unhealthy" block to cover the "occupied" branch: call
ensureHermesDashboardPortForwardIfEnabled("alpha", { getRecoveryConfig,
isPortForwardHealthy: () => "occupied", ensurePortForward }) and assert it
returns false and that the mock ensurePortForward was not called; reference the
existing test helpers ensureHermesDashboardPortForwardIfEnabled,
getRecoveryConfig and ensurePortForward to locate where to insert the assertion.
agents/hermes/start.sh (1)

854-917: Run the Hermes E2E matrix for lifecycle/forwarding confidence.

Given this startup-path change wires dashboard process + port forwarding + cleanup in both privilege paths, run the Hermes-specific E2E jobs before merge to validate onboarding, health probes, and live routing behavior end-to-end.

As per coding guidelines, agents/hermes/** changes affect multi-agent onboarding, health probes, and inference routing, and include explicit Hermes E2E recommendations.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@agents/hermes/start.sh` around lines 854 - 917, Run the Hermes E2E matrix to
validate the changes that wire dashboard process, port forwarding and cleanup in
both privilege paths: execute the Hermes E2E jobs covering onboarding, health
probes, and live routing and confirm behavior for the flows that exercise
start_hermes_dashboard_current_user and start_hermes_dashboard_sandbox_user,
start_socat_forwarder forwarding (api/PUBLIC_PORT/INTERNAL_PORT), and
cleanup_on_signal/SANDBOX_CHILD_PIDS handling; report any failures so we can fix
lifecycle/forwarding, PID collection races, or log/port binding regressions
before merge.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@agents/hermes/start.sh`:
- Around line 157-164: Add two additional port-collision checks in start.sh to
catch cross-binding conflicts: verify HERMES_DASHBOARD_PUBLIC_PORT is not equal
to INTERNAL_PORT and HERMES_DASHBOARD_INTERNAL_PORT is not equal to PUBLIC_PORT;
if either equality holds, emit a clear error to stderr (similar format to the
existing checks) and exit 1. Use the same numeric comparison operator (-eq) and
mirror the error message pattern that references the conflicting variable names
(HERMES_DASHBOARD_PUBLIC_PORT vs INTERNAL_PORT and
HERMES_DASHBOARD_INTERNAL_PORT vs PUBLIC_PORT) so the script fails fast on
cross-collisions.

In `@docs/get-started/quickstart-hermes.mdx`:
- Around line 90-93: Replace the non-copyable console fences with copyable
bash/sh fences and remove the leading "$" prompt markers in the two code blocks:
change the block that currently shows "$ export NEMOCLAW_HERMES_DASHBOARD=1" and
"$ nemohermes onboard" to a ```bash (or ```sh) block containing the two lines
without "$", and likewise change the block that shows "$ openshell forward start
--background 9119 my-hermes" to a ```bash (or ```sh) block with that command
without the "$"; ensure only the language tag is used and no prompt markers
remain so users can copy the commands directly.

In `@src/lib/agent/dashboard-ui.ts`:
- Around line 82-85: The env-port parser currently accepts ports 1..65535
(checks raw and sets const port) which conflicts with the shared Hermes parser
that requires 1024..65535; update the validation in the same function (the block
that reads raw, tests /^\d+$/, assigns const port) to enforce port >= 1024 &&
port <= 65535 and return only in that case so the dashboardUiPort behavior
matches the shared Hermes env parser.

In `@src/lib/onboard.ts`:
- Around line 2820-2828: hermesDashboardState is computed using effectivePort
before ensureDashboardForward() may rebind to a different host port, causing
stale config to be used later; move the call to
onboardHermesDashboard.resolveHermesDashboardOnboardState (or recompute
hermesDashboardState) after ensureDashboardForward() completes and returns the
finalized host port, and update all downstream uses (drift checks and registry
writes) to read the newly computed hermesDashboardState so they operate on the
final, authoritative port value.
- Around line 2829-2840: The rollback lambda passed into
onboardHermesDashboard.createHermesDashboardForwardEnsurer only deletes the
sandbox but must also remove any already-created Hermes dashboard forward to
avoid orphaned host forwards; update the rollbackSandbox function to call the
same cleanup used for forwards (e.g., invoke runOpenshell to delete the
dashboard forward) before or after deleting the sandbox, using the targetSandbox
value and preserve { ignoreError: true } so failures don't block rollback;
locate ensureHermesDashboardForwardIfEnabled /
createHermesDashboardForwardEnsurer and modify the rollbackSandbox arrow
function to run both the dashboard-forward delete command and the existing
sandbox delete command.

In `@test/onboard-dashboard.test.ts`:
- Around line 98-116: The test currently maps runOpenshell.mock.calls to
stopArgs and only checks there is no 3-arg global stop; update the assertions to
ensure any "forward stop" invocation is scoped to "hermes-sandbox" (or exactly
matches the expected ["forward","stop","9119","hermes-sandbox"]). Specifically,
after computing stopArgs (from runOpenshell.mock.calls), add an assertion that
for every args where args[0]==="forward" && args[1]==="stop", either args equals
the expected four-item array or args[args.length-1] === "hermes-sandbox" (i.e.,
no stop call targets a different sandbox); reference runOpenshell.mock.calls and
the stopArgs variable to locate where to add this check.

---

Nitpick comments:
In `@agents/hermes/start.sh`:
- Around line 854-917: Run the Hermes E2E matrix to validate the changes that
wire dashboard process, port forwarding and cleanup in both privilege paths:
execute the Hermes E2E jobs covering onboarding, health probes, and live routing
and confirm behavior for the flows that exercise
start_hermes_dashboard_current_user and start_hermes_dashboard_sandbox_user,
start_socat_forwarder forwarding (api/PUBLIC_PORT/INTERNAL_PORT), and
cleanup_on_signal/SANDBOX_CHILD_PIDS handling; report any failures so we can fix
lifecycle/forwarding, PID collection races, or log/port binding regressions
before merge.

In `@src/lib/actions/sandbox/hermes-dashboard-recovery.test.ts`:
- Around line 45-77: Add a test case in the existing "restarts the dashboard
forward only when the recorded forward is unhealthy" block to cover the
"occupied" branch: call ensureHermesDashboardPortForwardIfEnabled("alpha", {
getRecoveryConfig, isPortForwardHealthy: () => "occupied", ensurePortForward })
and assert it returns false and that the mock ensurePortForward was not called;
reference the existing test helpers ensureHermesDashboardPortForwardIfEnabled,
getRecoveryConfig and ensurePortForward to locate where to insert the assertion.

In `@src/lib/hermes-dashboard.test.ts`:
- Around line 38-44: Extend the "rejects invalid port values" test for
readHermesDashboardConfig to also assert numeric out-of-range ports are
rejected: within the same it block (or a new it near it) call
readHermesDashboardConfig with NEMOCLAW_HERMES_DASHBOARD_PORT: "1023" and with
"65536" and assert each invocation throws (toThrow) matching the existing
port-related error (e.g., /NEMOCLAW_HERMES_DASHBOARD_PORT/ or the module's
port-range message) so the contract enforces the valid port range.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 005f83fc-1431-4869-ab1f-0a24474e5f3e

📥 Commits

Reviewing files that changed from the base of the PR and between ea10007 and 42291d9.

📒 Files selected for processing (27)
  • agents/hermes/Dockerfile.base
  • agents/hermes/manifest.yaml
  • agents/hermes/start.sh
  • docs/get-started/quickstart-hermes.mdx
  • docs/reference/commands.mdx
  • src/lib/actions/sandbox/forward-health.ts
  • src/lib/actions/sandbox/hermes-dashboard-recovery.test.ts
  • src/lib/actions/sandbox/hermes-dashboard-recovery.ts
  • src/lib/actions/sandbox/process-recovery.ts
  • src/lib/agent/dashboard-ui.ts
  • src/lib/agent/defs.test.ts
  • src/lib/agent/defs.ts
  • src/lib/agent/onboard.test.ts
  • src/lib/agent/onboard.ts
  • src/lib/agent/runtime.test.ts
  • src/lib/agent/runtime.ts
  • src/lib/hermes-dashboard.test.ts
  • src/lib/hermes-dashboard.ts
  • src/lib/onboard.ts
  • src/lib/onboard/agent-fixed-forward.ts
  • src/lib/onboard/dashboard.ts
  • src/lib/onboard/hermes-dashboard.test.ts
  • src/lib/onboard/hermes-dashboard.ts
  • src/lib/onboard/landlock-warning.ts
  • src/lib/state/registry.ts
  • test/hermes-start.test.ts
  • test/onboard-dashboard.test.ts

Comment thread agents/hermes/start.sh Outdated
Comment thread docs/get-started/quickstart-hermes.mdx Outdated
Comment thread src/lib/agent/dashboard-ui.ts
Comment thread src/lib/onboard.ts Outdated
Comment thread src/lib/onboard.ts Outdated
Comment thread test/onboard-dashboard.test.ts
@github-actions
Copy link
Copy Markdown
Contributor

Selective E2E Results — ❌ Some jobs failed

Run: 26603871082
Target ref: 42291d977d80900080e7aa50ae2fc39861898625
Workflow ref: main
Requested jobs: hermes-e2e,hermes-root-entrypoint-smoke-e2e,hermes-onboard-security-posture-e2e,rebuild-hermes-e2e
Summary: 3 passed, 1 failed, 0 skipped

Job Result
hermes-e2e ✅ success
hermes-onboard-security-posture-e2e ✅ success
hermes-root-entrypoint-smoke-e2e ✅ success
rebuild-hermes-e2e ❌ failure

Failed jobs: rebuild-hermes-e2e. Check run artifacts for logs.

ericksoa added 2 commits May 28, 2026 14:51
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@github-actions
Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 26604431598
Target ref: 15de2fab0db3ddf60009d945f01337faffcc129d
Workflow ref: main
Requested jobs: hermes-e2e,hermes-root-entrypoint-smoke-e2e,hermes-onboard-security-posture-e2e,sandbox-survival-e2e,sandbox-operations-e2e,rebuild-hermes-e2e
Summary: 1 passed, 0 failed, 0 skipped

Job Result
hermes-e2e ⚠️ cancelled
hermes-onboard-security-posture-e2e ⚠️ cancelled
hermes-root-entrypoint-smoke-e2e ✅ success
rebuild-hermes-e2e ⚠️ cancelled
sandbox-operations-e2e ⚠️ cancelled
sandbox-survival-e2e ⚠️ cancelled

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@github-actions
Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 26604622802
Target ref: 6712417e31205fea151851afd076fee54dccc8d5
Workflow ref: main
Requested jobs: hermes-e2e,hermes-root-entrypoint-smoke-e2e,hermes-onboard-security-posture-e2e,sandbox-survival-e2e,sandbox-operations-e2e,rebuild-hermes-e2e
Summary: 0 passed, 0 failed, 0 skipped

Job Result
hermes-e2e ⚠️ cancelled
hermes-onboard-security-posture-e2e ⚠️ cancelled
hermes-root-entrypoint-smoke-e2e ⚠️ cancelled
rebuild-hermes-e2e ⚠️ cancelled
sandbox-operations-e2e ⚠️ cancelled
sandbox-survival-e2e ⚠️ cancelled

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 28, 2026

Actionable comments posted: 0

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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/onboard.ts`:
- Around line 3113-3117: The hermes dashboard ensure path uses a closure
capturing the old chatUiUrl so when reusing a dashboard forward you must update
chatUiUrl (and any related env var) to the new port before calling
hermesDashboardForwarding.ensureForState; specifically, after calling
ensureDashboardForward(sandboxName, chatUiUrl) and computing reusedPort via
hermesDashboardForwarding.resolveStateForPort(reusedPort), assign chatUiUrl to
the new URL (e.g., `http://127.0.0.1:${reusedPort}`) and update
process.env.CHAT_UI_URL prior to invoking
hermesDashboardForwarding.ensureForState(reusedHermesDashboardState,
sandboxName); apply the same change in the interactive reuse branch as well so
ensureForState sees the updated API port.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 9a3e45ad-943c-4be7-a851-0147e48e69ca

📥 Commits

Reviewing files that changed from the base of the PR and between 15de2fa and 75cd2ec.

📒 Files selected for processing (3)
  • src/lib/onboard.ts
  • src/lib/onboard/hermes-dashboard.ts
  • test/process-recovery.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/process-recovery.test.ts

Comment thread src/lib/onboard.ts Outdated
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@github-actions
Copy link
Copy Markdown
Contributor

Selective E2E Results — ❌ Some jobs failed

Run: 26604709304
Target ref: 75cd2eca2d1418ad0c9ed14cc127f322d748e3da
Workflow ref: main
Requested jobs: hermes-e2e,hermes-root-entrypoint-smoke-e2e,hermes-onboard-security-posture-e2e,sandbox-survival-e2e,sandbox-operations-e2e,rebuild-hermes-e2e
Summary: 5 passed, 1 failed, 0 skipped

Job Result
hermes-e2e ✅ success
hermes-onboard-security-posture-e2e ✅ success
hermes-root-entrypoint-smoke-e2e ✅ success
rebuild-hermes-e2e ❌ failure
sandbox-operations-e2e ✅ success
sandbox-survival-e2e ✅ success

Failed jobs: rebuild-hermes-e2e. Check run artifacts for logs.

@github-actions
Copy link
Copy Markdown
Contributor

Selective E2E Results — ❌ Some jobs failed

Run: 26605357981
Target ref: 896dad5781c3aa6276b20700bfcafd0c476f6206
Workflow ref: main
Requested jobs: hermes-dashboard-e2e
Summary: 0 passed, 0 failed, 0 skipped

Job Result
hermes-dashboard-e2e ❓ not reported

Missing requested jobs: hermes-dashboard-e2e. The reporting workflow needs to include these jobs.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 28, 2026

Actionable comments posted: 0

@github-actions
Copy link
Copy Markdown
Contributor

Selective E2E Results — ❌ Some jobs failed

Run: 26605382605
Target ref: 896dad5781c3aa6276b20700bfcafd0c476f6206
Workflow ref: issue-2979-Add-the-Hermes-Web-dashboard-on-port-9119
Requested jobs: hermes-dashboard-e2e
Summary: 0 passed, 1 failed, 0 skipped

Job Result
hermes-dashboard-e2e ❌ failure

Failed jobs: hermes-dashboard-e2e. Check run artifacts for logs.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@github-actions
Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 26608228607
Target ref: b25cf951aef2adcc485ff57e23e79c114e9ed343
Workflow ref: issue-2979-Add-the-Hermes-Web-dashboard-on-port-9119
Requested jobs: hermes-dashboard-e2e
Summary: 1 passed, 0 failed, 0 skipped

Job Result
hermes-dashboard-e2e ✅ success

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@github-actions
Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 26608758607
Target ref: 4cb7ca32ba2c5968414b2186a4e82c1fcdfcc1e8
Workflow ref: issue-2979-Add-the-Hermes-Web-dashboard-on-port-9119
Requested jobs: hermes-dashboard-e2e
Summary: 1 passed, 0 failed, 0 skipped

Job Result
hermes-dashboard-e2e ✅ success

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@github-actions
Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 26609084519
Target ref: 3fd5e5f413892e7e4eaeec347c1bcd1e100b40ec
Workflow ref: issue-2979-Add-the-Hermes-Web-dashboard-on-port-9119
Requested jobs: hermes-dashboard-e2e
Summary: 1 passed, 0 failed, 0 skipped

Job Result
hermes-dashboard-e2e ✅ success

Copy link
Copy Markdown
Contributor

@ericksoa ericksoa left a comment

Choose a reason for hiding this comment

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

Approved. Re-checked current head 3fd5e5f: required PR checks pass, CodeRabbit completed, no unresolved non-outdated review threads, and the branch-ref Hermes dashboard E2E succeeded. The dashboard/parser fixes look scoped and validated end to end.

@ericksoa ericksoa merged commit 40ea247 into main May 29, 2026
79 checks passed
@ericksoa ericksoa deleted the issue-2979-Add-the-Hermes-Web-dashboard-on-port-9119 branch May 29, 2026 00:02
@miyoungc miyoungc mentioned this pull request May 29, 2026
12 tasks
miyoungc added a commit that referenced this pull request May 29, 2026
## Summary
Refreshes the NemoClaw documentation for the v0.0.54 release and
regenerates user skills from the Fern MDX source. Also keeps the Fern
CLI pin current so local docs checks use the upgraded Fern version.

## Related Issue
<!-- No single related issue. This is release-prep documentation
catch-up. -->

## Changes
- #4403 -> `docs/manage-sandboxes/messaging-channels.mdx`,
`docs/reference/commands.mdx`, `docs/about/release-notes.mdx`: Document
Telegram, Discord, and Slack post-rebuild bridge verification and
summarize channel activation fixes.
- #4222 -> `docs/about/release-notes.mdx`: Include Slack generated
channel enablement in the v0.0.54 messaging summary.
- #4346 -> `docs/get-started/windows-preparation.mdx`,
`docs/about/release-notes.mdx`: Document safer Windows bootstrap
behavior for Ubuntu first-run and Docker Desktop WSL integration.
- #4416 -> `docs/inference/use-local-inference.mdx`,
`docs/about/release-notes.mdx`: Document the Docker Desktop WSL
requirement for Windows-host Ollama.
- #4442 -> `docs/about/release-notes.mdx`: Summarize the optional
NemoHermes native web dashboard and related environment variables.
- #4426 -> `docs/about/release-notes.mdx`: Summarize copy-paste recovery
hints for invalid sandbox names and missing NVIDIA API keys.
- #4459 -> `docs/about/release-notes.mdx`: Summarize the Linuxbrew
prefix fix for sandbox Homebrew usage.
- #4450 -> `docs/about/release-notes.mdx`: Summarize `/nemoclaw` slash
command startup activation.
- #4468 -> `docs/about/release-notes.mdx`: Summarize scope-upgrade
approval recovery.
- #4325 -> `docs/about/release-notes.mdx`: Summarize the narrowed
`web_fetch` host-gateway allowance.
- #4474 -> `docs/about/release-notes.mdx`: Summarize Hermes Provider
smoke-check behavior for OAuth versus Nous API key setup.
- Refresh generated `.agents/skills/nemoclaw-user-*` references from
`docs/` and update `fern/fern.config.json` to Fern `5.41.2`.

## Type of Change
- [ ] Code change (feature, bug fix, or refactor)
- [ ] Code change with doc updates
- [x] Doc only (prose changes, no code sample modifications)
- [ ] Doc only (includes code sample changes)

## Verification
<!-- Check each item you ran and confirmed. Leave unchecked items you
skipped. Doc-only changes do not require npm test unless you ran it. -->
- [ ] `npx prek run --all-files` passes
- [ ] `npm test` passes
- [ ] Tests added or updated for new or changed behavior
- [x] No secrets, API keys, or credentials committed
- [x] Docs updated for user-facing behavior changes
- [ ] `npm run docs` builds without warnings (doc changes only)
- [x] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)

---
<!-- DCO sign-off required by CI. Run: git config user.name && git
config user.email -->
Signed-off-by: Miyoung Choi <miyoungc@nvidia.com>

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
  * Optional NemoHermes native web dashboard (configurable port and TUI)
* GPU memory cleanup now unloads Ollama models when switching providers
or stopping services

* **Bug Fixes**
  * Improved sandbox name validation with suggested slug recovery
* Windows-host Ollama now requires Docker Desktop WSL integration and
exits with remediation guidance when unsupported

* **Documentation**
* Clarified quickstart/onboard flow, installer TTY/non‑TTY guidance,
Hermes Docker prerequisites, sandbox hardening, and channels add rebuild
checks

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/NVIDIA/NemoClaw/pull/4539?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
@oparoz
Copy link
Copy Markdown

oparoz commented May 30, 2026

🥳 Thank you!

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

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[hermes] Add the Web dashboard on port 9119

4 participants