Skip to content

feat(cli): add gateway-token command to retrieve sandbox auth token#2496

Merged
ericksoa merged 4 commits intomainfrom
feat/938-gateway-token-command
Apr 27, 2026
Merged

feat(cli): add gateway-token command to retrieve sandbox auth token#2496
ericksoa merged 4 commits intomainfrom
feat/938-gateway-token-command

Conversation

@ericksoa
Copy link
Copy Markdown
Contributor

@ericksoa ericksoa commented Apr 27, 2026

Summary

Add nemoclaw <name> gateway-token so automation can capture the OpenClaw gateway auth token after onboarding without scraping /sandbox/.openclaw/openclaw.json by hand.

Related Issue

Closes #938

Changes

  • Add src/lib/gateway-token-command.ts with a host-side handler that takes a fetchToken dependency plus log/error sinks, keeping it unit-testable in isolation.
  • Reuse the existing host-side helper fetchGatewayAuthTokenFromSandbox from src/lib/onboard.ts (now exported) instead of duplicating token retrieval.
  • Wire the new sandbox action into src/nemoclaw.ts dispatch, parse --quiet / -q, reject unknown flags, and silence EPIPE on stdout so consumers like ... | head -c 0 don't see a Node stack trace after the token has been written.
  • Register the command in src/lib/command-registry.ts so it appears in nemoclaw --help automatically.
  • Document the command under docs/reference/commands.md (skill page regenerated by the doc-to-skills hook).
  • Add unit tests in src/lib/gateway-token-command.test.ts covering the success path, --quiet, fetch returning null, fetch throwing, and empty-string token.

Output contract:

  • stdout: token only, no surrounding text (pipe-friendly).
  • stderr: one-line security warning, suppressed by --quiet / -q.
  • exit 0 when the token prints; exit 1 when the sandbox is unknown or the token cannot be retrieved (with a diagnostic on stderr).

Example:

TOKEN=$(nemoclaw my-assistant gateway-token --quiet)
export OPENCLAW_GATEWAY_TOKEN="$TOKEN"

Review Follow-ups

After the initial commit, an adversarial code review surfaced several issues. Addressed in commit 925673ec:

  • Dead getSandbox check + latent unbound-this risk — the upstream recoverRegistryEntries guard at src/nemoclaw.ts:3651 already rejects unknown sandbox names before the action switch is reached, so the in-command "not registered" branch was unreachable from the CLI. Dropped the dependency entirely; the unknown-sandbox path now relies on the same guard every other sandbox subcommand uses.
  • EPIPE on stdout — added a stdout error handler so nemoclaw foo gateway-token | head -c 0 no longer emits a Node stack trace after the token has been written.
  • Em-dash → -- — the stderr security warning now uses ASCII so it renders cleanly on legacy Windows consoles.

Considered and explicitly skipped, with reasoning:

  • TTY refusal / --print flag — issue Add CLI command to retrieve gateway auth token #938 carves out two commands: open to minimize TTY exposure, and gateway-token for the scripting use case. Adding TTY refusal here would depart from the issue's design.
  • Audit logging on token read — sibling sandbox subcommands (including the credential-related ones) don't audit reads, and the existing onboard wizard prints the same token without auditing. Adding it only here would be inconsistent and out of scope for Add CLI command to retrieve gateway auth token #938.
  • --help flag for the subcommand — no other sandbox subcommand accepts --help; matching convention.
  • Surface the underlying fetch errorfetchGatewayAuthTokenFromSandbox swallows every failure to null today, so there is nothing to surface without a deeper refactor of the helper. Out of scope.

Type of Change

  • Code change with doc updates

Verification

  • npm run typecheck:cli passes
  • npx vitest run --project cli passes for all tests except the four pre-existing slow-timeout flakes in test/onboard.test.ts (5 s timeout vs 7–12 s actual on slow hardware) that also fail on clean main and are unrelated to this change
  • npx prek run --all-files passes apart from the same pre-existing test/onboard.test.ts flakes
  • Tests added for new behavior
  • No secrets, API keys, or credentials committed
  • Docs updated for the new command

Summary by CodeRabbit

  • New Features

    • Added nemoclaw <name> gateway-token CLI command to output a sandbox's OpenClaw gateway auth token to stdout; emits a one-line security warning to stderr unless suppressed with --quiet/-q; exits non-zero with diagnostics on failure.
  • Documentation

    • Added command reference entry documenting usage, warning behavior, and failure semantics.
  • Tests

    • Added tests covering argument parsing, success/failure behavior, and expected stdout/stderr outputs.

Add `nemoclaw <name> gateway-token` so automation can capture the
OpenClaw gateway auth token after onboarding without scraping
`/sandbox/.openclaw/openclaw.json` by hand.

Output contract is pipe-friendly:
- stdout: token only, no surrounding text
- stderr: one-line security warning, suppressed by `--quiet` / `-q`
- exit 0: token printed; exit 1: token unavailable, with diagnostics

The command reuses the existing host-side helper
`fetchGatewayAuthTokenFromSandbox` from `src/lib/onboard.ts` instead
of duplicating token retrieval logic.

Closes #938
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 27, 2026

📝 Walkthrough

Walkthrough

Adds a new CLI command nemoclaw <name> gateway-token that retrieves a sandbox's OpenClaw gateway auth token, prints the token to stdout (no extra text), emits a one-line security warning to stderr unless --quiet/-q is set, and exits non‑zero with stderr diagnostics on failure.

Changes

Cohort / File(s) Summary
Documentation
​.agents/skills/nemoclaw-user-reference/references/commands.md, docs/reference/commands.md
Adds reference entries describing nemoclaw <name> gateway-token, stdout token output, stderr security warning and failure semantics.
Command Registry & Tests
src/lib/command-registry.ts, src/lib/command-registry.test.ts
Registers new visible sandbox usage nemoclaw <name> gateway-token and updates tests to expect one additional sandbox command and action token ("gateway-token").
Gateway Token Command & Tests
src/lib/gateway-token-command.ts, src/lib/gateway-token-command.test.ts
Implements parseGatewayTokenArgs and runGatewayTokenCommand with quiet flag handling, token fetch/error handling, stdout/stderr behaviours, and comprehensive tests for success and failure cases.
Onboarding Export
src/lib/onboard.ts
Exports fetchGatewayAuthTokenFromSandbox so it can be used by the new command.
CLI Integration
src/nemoclaw.ts
Wires new action into CLI dispatcher, validates unknown flags, registers EPIPE handler for stdout, and lists gateway-token in valid actions.

Sequence Diagram

sequenceDiagram
    participant User as CLI User
    participant CLI as nemoclaw.ts
    participant Parser as gateway-token-command.ts (parse)
    participant Runner as gateway-token-command.ts (run)
    participant Registry as command-registry
    participant Fetcher as onboard.ts (fetchGatewayAuthTokenFromSandbox)
    participant Stdout as stdout
    participant Stderr as stderr

    User->>CLI: nemoclaw <name> gateway-token [--quiet]
    CLI->>Parser: parseGatewayTokenArgs(args)
    Parser-->>CLI: { options, unknown }
    alt unknown flags
        CLI->>Stderr: Print "Unknown flag" + Usage
        CLI-->>User: Exit 1
    else valid
        CLI->>Runner: runGatewayTokenCommand(name, options, deps)
        Runner->>Registry: lookup sandbox
        alt sandbox missing
            Runner->>Stderr: Diagnostic lines (sandbox not registered)
            Runner-->>CLI: Exit 1
        else sandbox found
            Runner->>Fetcher: fetchGatewayAuthTokenFromSandbox(sandbox)
            Fetcher-->>Runner: token or null/empty/error
            alt token present
                Runner->>Stdout: Print token (only)
                alt not options.quiet
                    Runner->>Stderr: Print one-line security warning
                end
                Runner-->>CLI: Exit 0
            else token absent/error
                Runner->>Stderr: Two diagnostic lines (could not retrieve + status hint)
                Runner-->>CLI: Exit 1
            end
        end
    end
    CLI-->>User: exit code
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped into sandboxes, quiet and spry,

Pulled a tiny token and gave it a try.
"Treat it like treasure," I whisper, polite—
Quiet or not, keep it safe through the night.
🥕✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% 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
Title check ✅ Passed The title accurately summarizes the main change: adding a new CLI gateway-token command to retrieve sandbox auth token, which is the primary objective of the PR.
Linked Issues check ✅ Passed The PR implements the gateway-token mechanism from issue #938: adds CLI command to fetch the token, reuses fetchGatewayAuthTokenFromSandbox, displays security warning, and makes command discoverable via --help.
Out of Scope Changes check ✅ Passed All changes are in-scope: command implementation, documentation, registry updates, tests, and command dispatch are all directly related to the gateway-token feature.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/938-gateway-token-command

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

@ericksoa ericksoa self-assigned this Apr 27, 2026
@ericksoa ericksoa added Platform: Brev Support for Brev deployment NemoClaw CLI Use this label to identify issues with the NemoClaw command-line interface (CLI). enhancement: integration PRs or issues proposing integration of a third-party product or service into NemoClaw. labels Apr 27, 2026
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 (2)
docs/reference/commands.md (1)

301-303: Use active voice and inline code for stream names.

Please rewrite these lines in active voice and format stdout / stderr as inline code.

As per coding guidelines, "Active voice required. Flag passive constructions." and "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/commands.md` around lines 301 - 303, Rewrite the three
sentences using active voice and format the stream names and flags as inline
code: change "The token is written to stdout with no surrounding text." to
something like "Write the token to `stdout` with no surrounding text."; change
"A one-line security warning is written to stderr; pass `--quiet` (or `-q`) to
suppress it." to an active form like "Write a one-line security warning to
`stderr`; pass `--quiet` (or `-q`) to suppress it."; and change "The command
exits non-zero with a diagnostic on stderr when the sandbox is not registered or
when the token cannot be retrieved (for example, if the sandbox is not
running)." to an active form that formats the stream inline, e.g. "Exit with a
non-zero status and write a diagnostic to `stderr` when the sandbox is not
registered or when the token cannot be retrieved (for example, if the sandbox is
not running)." Ensure `stdout` and `stderr` and the flags remain inline code.
src/nemoclaw.ts (1)

3705-3708: Surface all unknown arguments in one diagnostic.

You currently report only the first unknown token. Printing all unknown inputs makes scripted failures easier to debug.

♻️ Proposed tweak
-        if (gatewayTokenUnknown.length > 0) {
-          console.error(`  Unknown flag: ${gatewayTokenUnknown[0]}`);
+        if (gatewayTokenUnknown.length > 0) {
+          console.error(`  Unknown argument(s): ${gatewayTokenUnknown.join(", ")}`);
           console.error("  Usage: nemoclaw <name> gateway-token [--quiet|-q]");
           process.exit(1);
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/nemoclaw.ts` around lines 3705 - 3708, The current handler prints only
the first unknown token (gatewayTokenUnknown[0]); update the block that checks
gatewayTokenUnknown in src/nemoclaw.ts to surface all unknown arguments by
joining or iterating gatewayTokenUnknown (e.g., gatewayTokenUnknown.join(', ')
or loop and print each) when logging the error, keep the same usage message and
exit call (process.exit(1)), and ensure you reference the gatewayTokenUnknown
variable and the surrounding conditional that currently prints the single token
so the diagnostics show every unknown input.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@docs/reference/commands.md`:
- Around line 301-303: Rewrite the three sentences using active voice and format
the stream names and flags as inline code: change "The token is written to
stdout with no surrounding text." to something like "Write the token to `stdout`
with no surrounding text."; change "A one-line security warning is written to
stderr; pass `--quiet` (or `-q`) to suppress it." to an active form like "Write
a one-line security warning to `stderr`; pass `--quiet` (or `-q`) to suppress
it."; and change "The command exits non-zero with a diagnostic on stderr when
the sandbox is not registered or when the token cannot be retrieved (for
example, if the sandbox is not running)." to an active form that formats the
stream inline, e.g. "Exit with a non-zero status and write a diagnostic to
`stderr` when the sandbox is not registered or when the token cannot be
retrieved (for example, if the sandbox is not running)." Ensure `stdout` and
`stderr` and the flags remain inline code.

In `@src/nemoclaw.ts`:
- Around line 3705-3708: The current handler prints only the first unknown token
(gatewayTokenUnknown[0]); update the block that checks gatewayTokenUnknown in
src/nemoclaw.ts to surface all unknown arguments by joining or iterating
gatewayTokenUnknown (e.g., gatewayTokenUnknown.join(', ') or loop and print
each) when logging the error, keep the same usage message and exit call
(process.exit(1)), and ensure you reference the gatewayTokenUnknown variable and
the surrounding conditional that currently prints the single token so the
diagnostics show every unknown input.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: f01a78f1-d7b4-4ad8-a490-539c13e0590d

📥 Commits

Reviewing files that changed from the base of the PR and between 1f615e2 and f446a25.

📒 Files selected for processing (8)
  • .agents/skills/nemoclaw-user-reference/references/commands.md
  • docs/reference/commands.md
  • src/lib/command-registry.test.ts
  • src/lib/command-registry.ts
  • src/lib/gateway-token-command.test.ts
  • src/lib/gateway-token-command.ts
  • src/lib/onboard.ts
  • src/nemoclaw.ts

- Drop the now-redundant `getSandbox` dependency. The upstream sandbox
  dispatch (`recoverRegistryEntries` + "does not exist" guard) already
  rejects unknown sandbox names before the action switch is reached, so
  the in-command check was dead code and only added a latent
  unbound-`this` risk by passing `registry.getSandbox` as a callback.
- Silence EPIPE on stdout so consumers like `... | head -c 0` don't see
  a Node stack trace after the token has already been written.
- Use ASCII `--` instead of an em-dash in the stderr security warning so
  it renders cleanly on legacy Windows consoles.

No functional change for the documented happy path; the unknown-sandbox
path now relies entirely on the upstream guard, which prints the same
"Sandbox 'X' does not exist" message used by every other sandbox
subcommand.
@ericksoa ericksoa merged commit 3192f4f into main Apr 27, 2026
18 checks passed
@ericksoa ericksoa deleted the feat/938-gateway-token-command branch April 27, 2026 03:17
@miyoungc miyoungc mentioned this pull request Apr 28, 2026
13 tasks
miyoungc added a commit that referenced this pull request Apr 28, 2026
## Summary
Refreshes user-facing docs for the last 24 hours of merged NemoClaw
history and bumps the docs metadata to 0.0.29, the next version after
v0.0.28. The updates are limited to behavior supported by merged PR
descriptions and diffs.

## Changes
- `docs/reference/commands.md`: documented `nemoclaw <name> policy-add
--from-file` and `--from-dir`, including custom preset review guidance,
from #2077 / commit `7720b175`.
- `docs/deployment/deploy-to-remote-gpu.md`: clarified that non-loopback
`CHAT_UI_URL` disables OpenClaw device pairing for remote browser-only
deployments, from #2449 / commit `f5ee8a4d`.
- `docs/inference/inference-options.md`: documented provider-aware
credential retry validation and the NVIDIA-only `nvapi-` prefix check,
from #2389 / commit `6f7f0c6d`.
- `docs/inference/switch-inference-providers.md`: documented
`NEMOCLAW_INFERENCE_INPUTS` for text/image-capable model metadata baked
into `openclaw.json`, from #2441 / commit `f4391892`.
- `docs/reference/troubleshooting.md`: added the Git certificate
verification entry for proxy CA propagation through `GIT_SSL_CAINFO`,
`GIT_SSL_CAPATH`, `CURL_CA_BUNDLE`, and `REQUESTS_CA_BUNDLE`, from #2345
/ commit `fa0dc1ab`.
- `docs/versions1.json` and `docs/project.json`: promoted docs version
`0.0.29`; `docs/versions1.json` omits unpublished `0.0.26`, `0.0.27`,
and `0.0.28` entries.
- `.agents/skills/nemoclaw-user-*`: regenerated derived user skill
references from the updated docs.
- Reviewed with no extra doc changes: #2575 / `d392ec07`, #2565 /
`a3231049`, #1965 / `db1ef3ca`, #1990 / `db665834`, #2495 / `7da86fa3`,
#2496 / `3192f4f4`, #2490 / `8c209058`, #2487 / `1f615e2f`, #2483 /
`5653d33a`, #2482 / `31c782c0`, #2464 / `23bb5703`, #2472 / `a54f9a34`,
and #2437 / `6bc860d7`.
- Skipped per docs policy: #2420 / `7b76df6b` touched the experimental
sandbox config path listed in `docs/.docs-skip`; #2466 / `cc15689c`
touched a skipped term and CI-only sandbox image files.

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

## Verification
<!-- Check each item you ran and confirmed. Leave unchecked items you
skipped. -->
- [x] `npx prek run --all-files` passes
- [ ] `npm test` passes — failed locally in installer-integration tests
and one onboard helper timeout; the doc-scoped hook test projects passed
under `prek`.
- [ ] 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
- [ ] `make docs` builds without warnings (doc changes only) — build
succeeded, but local Sphinx emitted the existing version-switcher file
read message.
- [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)

## AI Disclosure
<!-- If an AI agent authored or co-authored this PR, check the box and
name the tool. Remove this section for fully human-authored PRs. -->
- [x] AI-assisted — tool: Codex

---
<!-- 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**
* Support for custom YAML presets in policy configuration via
--from-file and --from-dir.
* New build-time inference input option to declare accepted modalities
(text or text,image).

* **Improvements**
* Credential validation now offers interactive recovery: re-enter key,
retry, choose another provider, or exit.
* Clarified provider-specific API key prefix handling (nvapi- only
applies to NVIDIA keys).

* **Documentation**
  * TLS certificate troubleshooting for inspected networks.
* Clarified remote dashboard security/device-pairing behavior; command
docs updated; docs version bumped.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Miyoung Choi <miyoungc@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement: integration PRs or issues proposing integration of a third-party product or service into NemoClaw. NemoClaw CLI Use this label to identify issues with the NemoClaw command-line interface (CLI). Platform: Brev Support for Brev deployment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add CLI command to retrieve gateway auth token

1 participant