Skip to content

feat(cli): add sandbox skill remove command#4563

Merged
cv merged 3 commits into
mainfrom
cv/salvage-skill-remove
May 30, 2026
Merged

feat(cli): add sandbox skill remove command#4563
cv merged 3 commits into
mainfrom
cv/salvage-skill-remove

Conversation

@cv
Copy link
Copy Markdown
Collaborator

@cv cv commented May 30, 2026

Summary

Salvages the skill removal work from #1962 onto a maintainer-owned, signed-off branch so the DCO-blocked contribution can proceed.
Adds nemoclaw <sandbox> skill remove <skill> for removing installed agent skills from a running sandbox.

Related Issue

Supersedes #1962.

Changes

  • Add the native sandbox skill remove oclif command and public argv translation.
  • Add removal logic for upload directories, OpenClaw mirror directories, and OpenClaw session refresh.
  • Validate skill names before constructing remote removal paths, including rejecting . and ...
  • Update command reference docs and CLI display metadata.
  • Add unit and command tests for remove behavior and safety validation.

Type of Change

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

Verification

  • 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)

Validation run:

  • npm run build:cli
  • npm test -- src/lib/skill-install.test.ts src/commands/sandbox/skill.test.ts src/lib/cli/public-argv-translation.test.ts src/lib/cli/command-registry.test.ts
  • npm run typecheck:cli
  • npm run docs:strict
  • commit/push hooks completed successfully, including CLI test and pre-push TypeScript checks.
  • npm run docs:strict completed with no errors (Fern reported existing upgrade warnings).

Signed-off-by: Carlos Villela cvillela@nvidia.com

Summary by CodeRabbit

  • New Features

    • Added a CLI command to remove an installed skill from a running sandbox by SKILL.md name, with validation and verification.
  • Documentation

    • CLI reference, help text, usage and examples updated to document the remove subcommand and agent-specific behavior (non-OpenClaw agents may require gateway restart).
  • Tests

    • Test suites expanded to cover removal flows, validation, and error cases.

Review Change Stack

Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@cv cv added the v0.0.56 Release target label May 30, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 30, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 0bba351b-a2a8-4acb-a0ca-da900b18d29e

📥 Commits

Reviewing files that changed from the base of the PR and between adf2d03 and 4c90cba.

📒 Files selected for processing (7)
  • src/lib/actions/sandbox/skill-install.test.ts
  • src/lib/actions/sandbox/skill-install.ts
  • src/lib/skill-install.test.ts
  • src/lib/skill-install.ts
  • src/lib/skill-name.ts
  • src/lib/skill-remote.test.ts
  • src/lib/skill-remote.ts
💤 Files with no reviewable changes (1)
  • src/lib/skill-install.test.ts
✅ Files skipped from review due to trivial changes (1)
  • src/lib/skill-name.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/actions/sandbox/skill-install.ts

📝 Walkthrough

Walkthrough

Adds a sandbox skill removal feature: CLI command + metadata, action orchestration (removeSandboxSkill), SSH remote helpers for probing/removal/verification, name validation and OpenClaw mirror path support, extensive tests, and reference docs.

Changes

Skill Removal Feature

Layer / File(s) Summary
CLI command and parent metadata
src/commands/sandbox/skill/remove.ts, src/commands/sandbox/skill.ts, src/commands/sandbox/skill.test.ts
Adds sandbox:skill:remove oclif command (args: sandbox, skill), updates parent CLI description/usage/examples to include remove, and expands CLI tests and shared clearSkillMocks() to cover removal calls.
CLI registry, translation, and display
src/lib/cli/command-registry.test.ts, src/lib/cli/public-argv-translation.test.ts, src/lib/cli/public-display-defaults.ts
Registers the new command in public display layout under "Skills" (order 16.1, flags <skill>), updates command counts in registry tests, and adds legacy skill removesandbox:skill:remove translation test.
Action orchestration and usage help
src/lib/actions/sandbox/skill-install.ts
Adds SkillRemoveRequest and removeSandboxSkill() orchestration: handles --help, validates inputs, enforces live sandbox guard, captures temp SSH config (0o600), checks existing state (handles null probe), invokes removeSkill/verifyRemove, formats messages, and always cleans temp SSH config; extends installSandboxSkill() to dispatch remove.
Skill name validation and path model
src/lib/skill-name.ts, src/lib/skill-install.ts, src/lib/skill-install.test.ts
Introduces validateSkillName() rejecting empty/./.. and allowing ^[A-Za-z0-9._-]+$; updates frontmatter parsing to use it; adds `mirrorDir: string
SSH remote helpers (probe/remove/verify)
src/lib/skill-remote.ts, src/lib/skill-remote.test.ts
New module exports sshExec, checkExisting (true
Integration/unit tests for action and remote helpers
src/lib/actions/sandbox/skill-install.test.ts, src/lib/skill-remote.test.ts, src/lib/skill-install.test.ts
Adds orchestration tests for remove/install flows, temp SSH config lifecycle, and probes; extends unit tests for validateSkillName, removeSkill, verifyRemove, and checkExisting (including SSH-unreachable behavior and mirrorDir expectations).
Reference documentation
docs/reference/commands.mdx
Documents nemoclaw <name> skill remove <skill> syntax, valid skill-name constraints, removal effects (uploadDir; mirrorDir and sessions.json for OpenClaw), note about restarting agent gateway for non-OpenClaw agents, and example invocation.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

  • NVIDIA/NemoClaw#3859: Overlaps on src/lib/actions/sandbox/skill-install.ts SSH config capture logic for skill operations.

Suggested labels

enhancement: skill, Sandbox

Suggested reviewers

  • ericksoa
  • jyaunches

Poem

🐰 A skill's farewell, so clean and bright—
Upload gone, mirror out of sight,
Sessions cleared in soft moonlight,
The remove command hops into the night.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 64.71% 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 title 'feat(cli): add sandbox skill remove command' directly and clearly summarizes the main change—adding a new CLI command for removing skills from a sandbox.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ 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 cv/salvage-skill-remove

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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

@cv cv added NemoClaw CLI Use this label to identify issues with the NemoClaw command-line interface (CLI). enhancement: feature Use this label to identify requests for new capabilities in NemoClaw. labels May 30, 2026
@github-actions
Copy link
Copy Markdown
Contributor

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 30, 2026

E2E Advisor Recommendation

Required E2E: skill-agent-e2e
Optional E2E: docs-validation-e2e, cloud-inference-e2e

Dispatch hint: skill-agent-e2e

Auto-dispatched E2E: skill-agent-e2e via nightly-e2e.yaml at 4c90cbaa6525770a63ec03190d8c74c97ac0ff3fnightly run

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • skill-agent-e2e (medium): Closest existing real-flow coverage for the changed skill lifecycle: installs NemoClaw, creates a live OpenClaw sandbox, injects a skill fixture, and verifies the assistant can read the SKILL.md content. This should run because the PR changes skill filesystem layout, OpenClaw mirror handling, and session refresh semantics that directly affect assistant skill discovery.

Optional E2E

  • docs-validation-e2e (low): Useful because the PR updates docs/reference/commands.mdx and public CLI command display metadata. This validates command/docs parity, but it is not the main runtime risk compared with the live skill sandbox flow.
  • cloud-inference-e2e (medium): Adjacent confidence check for OpenClaw runtime health and skill filesystem layout inside a live sandbox. It can catch broad breakage to /sandbox/.openclaw/skills, but it does not specifically exercise the new public skill remove command.

New E2E recommendations

  • sandbox skill CLI lifecycle (high): No existing E2E found that invokes the public nemoclaw <name> skill install <path> and new nemoclaw <name> skill remove <skill> commands against a live sandbox. The current skill-agent E2E injects skill content via a test helper rather than the changed CLI path.
    • Suggested test: Add a dispatchable skill-cli-lifecycle-e2e that creates a live OpenClaw sandbox, installs a fixture through the public CLI, verifies /sandbox/.openclaw/skills/<name> and $HOME/.openclaw/skills/<name> plus agent discovery, removes it through the public CLI, then verifies both directories are gone and sessions are refreshed.
  • non-OpenClaw skill removal (medium): The changed code has non-OpenClaw path handling and restart-hint behavior, but existing skill E2E coverage appears focused on OpenClaw skill discovery.
    • Suggested test: Add a lower-cost lifecycle check for a non-OpenClaw/Hermes sandbox that installs or seeds a skill directory, runs public skill remove, and verifies only the configured agent skill directory is removed while the user receives the restart-gateway hint.

Dispatch hint

  • Workflow: nightly-e2e.yaml
  • jobs input: skill-agent-e2e

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 30, 2026

E2E Scenario Advisor Recommendation

Required scenario E2E: ubuntu-repo-cloud-openclaw
Optional scenario E2E: ubuntu-repo-cloud-hermes

Dispatch required scenario E2E:

  • gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-openclaw

Workflow run

Full scenario advisor summary

E2E Scenario Advisor

Base: origin/main
Head: HEAD
Confidence: medium

Required scenario E2E

  • ubuntu-repo-cloud-openclaw: PR changes the public sandbox skill command surface and live-sandbox skill install/remove orchestration, with OpenClaw-specific path/session handling. The Ubuntu repo OpenClaw scenario is the smallest default scenario that boots a live OpenClaw sandbox from the changed checkout and validates core CLI/help and sandbox readiness paths around this command surface.
    • Dispatch: gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-openclaw

Optional scenario E2E

  • ubuntu-repo-cloud-hermes: Optional adjacent coverage for the non-OpenClaw agent path affected by skill path resolution and remove/install messaging; useful because the change includes Hermes/generic skill path behavior but OpenClaw is the primary target.
    • Dispatch: gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-hermes

Relevant changed files

  • src/commands/sandbox/skill.ts
  • src/commands/sandbox/skill/remove.ts
  • src/lib/actions/sandbox/skill-install.ts
  • src/lib/cli/public-display-defaults.ts
  • src/lib/skill-install.ts
  • src/lib/skill-name.ts
  • src/lib/skill-remote.ts

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 30, 2026

PR Review Advisor

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

Workflow run details

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

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

🤖 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/actions/sandbox/skill-install.ts`:
- Around line 93-96: The code incorrectly treats the literal skillName "help" as
a help sentinel which prevents uninstalling a real skill named "help"; change
the sentinel check in the skill install/remove flow to only treat "-h" and
"--help" (remove "help" from the condition), keep validateSkillName() unchanged
so "help" remains a valid skill name, and ensure calls to
printSkillInstallUsage() still occur for "-h"/"--help" only (update any
condition referencing skillName and the variables skillName,
validateSkillName(), and printSkillInstallUsage()).
- Around line 133-171: The try block currently calls process.exit() on several
failure paths which can prevent the finally cleanup
(fs.unlinkSync(tmpSshConfig)) from running; change those early-exit points
inside the try (the checks around skillInstall.checkExisting(ctx, paths), the
"not installed" branch, and the verification failure after
skillInstall.verifyRemove) to throw clear Errors (or set a local status and
return after the finally) instead of calling process.exit(), then handle
process.exit or process.exitCode at the top level after the try/finally; update
references to tmpSshConfig, skillInstall.checkExisting,
skillInstall.removeSkill, skillInstall.verifyRemove, skillName and sandboxName
to locate and replace the exit behavior so the finally block always runs and
cleanup always happens.

In `@src/lib/cli/public-display-defaults.ts`:
- Around line 372-377: The display metadata for the command identifier
"sandbox:skill:remove" uses flags: "<name>" which causes the CLI usage to render
an ambiguous second positional; update the metadata for sandbox:skill:remove to
use flags: "<skill>" instead of "<name>" so the rendered usage reads correctly
(e.g., nemoclaw <name> skill remove <skill>) and matches command/docs wording.

In `@src/lib/skill-install.ts`:
- Around line 331-342: The checkExisting function currently only tests for
SKILL.md and can return false when a partial upload left the directory present
but missing SKILL.md; update checkExisting (or add a new removal-specific helper
used by removeSandboxSkill) to probe directory existence too: test for the
uploadDir (and mirrorDir when paths.isOpenClaw && paths.mirrorDir) using a
directory-existence check (e.g., test -d ...) or combine file OR directory
checks so removeSandboxSkill will treat a present directory (even without
SKILL.md) as existing and allow cleanup; ensure sshExec calls and the
EXISTS/ABSENT logic (in checkExisting) are updated consistently to reflect the
new checks.
🪄 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: ae7bd40e-1879-4d9a-8766-0712f6ea5398

📥 Commits

Reviewing files that changed from the base of the PR and between e79461c and f9a4a27.

📒 Files selected for processing (10)
  • docs/reference/commands.mdx
  • src/commands/sandbox/skill.test.ts
  • src/commands/sandbox/skill.ts
  • src/commands/sandbox/skill/remove.ts
  • src/lib/actions/sandbox/skill-install.ts
  • src/lib/cli/command-registry.test.ts
  • src/lib/cli/public-argv-translation.test.ts
  • src/lib/cli/public-display-defaults.ts
  • src/lib/skill-install.test.ts
  • src/lib/skill-install.ts

Comment thread src/lib/actions/sandbox/skill-install.ts Outdated
Comment thread src/lib/actions/sandbox/skill-install.ts
Comment thread src/lib/cli/public-display-defaults.ts
Comment thread src/lib/skill-install.ts Outdated
@github-actions
Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 26677863025
Target ref: f9a4a27e8c36718eda096769b20340b484112c46
Workflow ref: main
Requested jobs: skill-agent-e2e
Summary: 1 passed, 0 failed, 0 skipped

Job Result
skill-agent-e2e ✅ success

Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@github-actions
Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 26678222063
Target ref: adf2d03d77e9a7bbad386662ae55dbefff501d36
Workflow ref: main
Requested jobs: skill-agent-e2e
Summary: 1 passed, 0 failed, 0 skipped

Job Result
skill-agent-e2e ✅ success

Copy link
Copy Markdown
Contributor

@cjagwani cjagwani left a comment

Choose a reason for hiding this comment

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

LGTM

@github-actions
Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 26692983320
Target ref: 4c90cbaa6525770a63ec03190d8c74c97ac0ff3f
Workflow ref: main
Requested jobs: skill-agent-e2e
Summary: 1 passed, 0 failed, 0 skipped

Job Result
skill-agent-e2e ✅ success

@cv cv merged commit be0f1d8 into main May 30, 2026
32 checks passed
@cv cv deleted the cv/salvage-skill-remove branch May 30, 2026 20:04
miyoungc added a commit that referenced this pull request Jun 1, 2026
## Summary

- Adds the v0.0.56 release notes section with links to the deeper docs
pages for installer, status, inference, messaging, policy, and lifecycle
changes.
- Updates source docs for the remaining release-prep gaps around `uv` in
the PyPI preset, compact WhatsApp pairing guidance, and `nemoclaw
inference set` command boundaries.
- Refreshes generated `nemoclaw-user-*` skills and removes skipped
experimental command terms from generated skill surfaces.

## Source summary

- #4613 -> `docs/manage-sandboxes/lifecycle.mdx`,
`docs/reference/commands.mdx`, `docs/about/release-notes.mdx`: Documents
that public installs and `nemoclaw update` follow the maintained `lkg`
tag by default.
- #4419 -> `docs/about/release-notes.mdx`: Notes that non-interactive
Linux installs can reactivate Docker group membership and continue in
one installer run when `sg docker` is available.
- #4550 -> `docs/reference/commands.mdx`,
`docs/about/release-notes.mdx`: Captures live sandbox agent-version
probing for status, connect, and upgrade checks.
- #4609 -> `docs/inference/use-local-inference.mdx`,
`docs/about/release-notes.mdx`: Captures the GPU Docker-driver
host-network local-inference reachability gate.
- #4607 -> `docs/manage-sandboxes/messaging-channels.mdx`,
`docs/reference/commands.mdx`, `docs/about/release-notes.mdx`: Documents
compact WhatsApp QR pairing guidance and gateway/session diagnostics.
- #4582 -> `docs/manage-sandboxes/messaging-channels.mdx`,
`docs/reference/commands.mdx`, `docs/about/release-notes.mdx`: Reflects
Slack credential validation before enabling the channel.
- #4554 -> `docs/manage-sandboxes/messaging-channels.mdx`,
`docs/reference/troubleshooting.mdx`, `docs/about/release-notes.mdx`:
Keeps Telegram allowlist alias guidance in the generated user skills and
release notes.
- #4563 -> `docs/reference/commands.mdx`,
`docs/about/release-notes.mdx`: Includes the new `nemoclaw <name> skill
remove <skill>` command in command docs and release notes.
- #4566 -> `docs/reference/commands.mdx`,
`docs/about/release-notes.mdx`: Documents the `nemoclaw inference set`
redirect boundary when `--provider` or `--model` is missing.
- #4323 -> `docs/reference/commands.mdx`,
`docs/about/release-notes.mdx`: Captures per-sandbox status JSON
support.
- #4506 -> `docs/reference/commands.mdx`,
`docs/about/release-notes.mdx`: Captures debug command sandbox-name
validation and safer tarball writing.
- #4569 -> `docs/network-policy/integration-policy-examples.mdx`,
`docs/about/release-notes.mdx`: Documents that the `pypi` preset allows
`/usr/local/bin/uv`.
- #4579 -> `docs/network-policy/integration-policy-examples.mdx`,
`docs/about/release-notes.mdx`: Captures observable Jira preset
validation guidance.
- #4229 -> `docs/manage-sandboxes/lifecycle.mdx`,
`docs/reference/commands.mdx`, `docs/about/release-notes.mdx`: Documents
user-data preservation defaults for uninstall.
- #4399 -> `docs/reference/commands.mdx`,
`docs/about/release-notes.mdx`: Captures CPU-only sandbox intent
preservation across rebuilds.
- #4058 -> `docs/reference/commands.mdx`,
`docs/about/release-notes.mdx`: Captures safer snapshot restore behavior
around existing destinations.
- #4155 and #4460 -> skipped by `docs/.docs-skip`: Removed skipped
experimental command terms from source docs and generated skill evals
instead of documenting those features.

## Verification

- `python3 scripts/docs-to-skills.py docs/ .agents/skills/ --prefix
nemoclaw-user --doc-platform fern-mdx`
- `npm run docs` (passes; Fern reports the pre-existing light-mode
accent contrast warning)
- `rg "permissive mode|shields down|shields up|shields status|config
rotate-token|rotate-token" .agents/skills` (no matches)
- `npm run build:cli` (run to refresh local CLI artifacts for the
pre-push TypeScript hook)
- Commit hooks passed, including `NEMOCLAW_* env-var documentation
gate`, `Verify docs-to-skills output`, `markdownlint-cli2`, `gitleaks`,
and `Test (skills YAML)`.

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

* **Documentation**
* Expanded Model Router setup with YAML examples, flow diagrams, and
credential handling; strengthened agent-config immutability and
integrity guidance; messaging channels updated (Telegram aliases,
WhatsApp pairing/diagnostics); CLI docs revised (GPU detection,
inference set behavior, uninstall/rebuild preservation); overview
rebranded to NemoClaw and added v0.0.56 release notes.

* **New Features**
* Added `nemoclaw <name> channels status` (messaging diagnostics, JSON);
added `nemoclaw <name> skill remove`; Hermes no longer marked
experimental; DGX Spark quickstart sandbox-name note.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement: feature Use this label to identify requests for new capabilities in NemoClaw. NemoClaw CLI Use this label to identify issues with the NemoClaw command-line interface (CLI). v0.0.56 Release target

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants