Repository navigation
fix(uninstall): preserve user data by default #4229
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 5 commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
412ebf0
fix(uninstall): gate destruction of host snapshots behind explicit ack
laitingsheng 2fd61ae
feat(uninstall): bundle host snapshot gate, --save-host, download/upl…
laitingsheng cec34c1
fix(uninstall): harden gate, save-host path, docs parity
laitingsheng 06fce3c
fix(uninstall): fail closed on unreadable sandbox registry
laitingsheng 4e0ec06
fix(uninstall): split detect errors and validate registry shape
laitingsheng 6aaa7c3
fix(uninstall): tidy ack path and reject unsafe --save-host dests
laitingsheng 128dbc1
fix(uninstall): include Docker container probe in user-data gate
laitingsheng e4ae80a
fix(uninstall): protect ~/.nemoclaw/backups and resolve save-host sym…
laitingsheng 112bcf8
fix(uninstall): docker-only remediation, default backups outside ~/.n…
laitingsheng 032147a
fix(uninstall): per-signal remediation hints
laitingsheng 3b947a2
revert: roll back review-iteration churn to cec34c1 baseline
laitingsheng d7d13b6
fix(uninstall): fail closed on unreadable sandbox registry
laitingsheng 4a31f06
Merge remote-tracking branch 'origin/main' into fix-4226-uninstall-co…
laitingsheng c676738
fix(uninstall): preserve rebuild-backups/ and sandboxes.json by default
laitingsheng b7ada9a
fix(uninstall): preserve backups/, harden symlinked state dir
laitingsheng 95929e6
fix(uninstall): sync confirm prompt and docs with preserve-by-default
laitingsheng 9d175ac
Merge branch 'main' into fix-4226-uninstall-confirm-backups
laitingsheng 2c070fa
fix(uninstall): surface lstat failures and tidy doc/code wording
laitingsheng 9c883db
fix(uninstall): exit non-zero when state dir lstat fails
laitingsheng 0418a11
fix(uninstall): suppress goodbye on failure, cover NON_INTERACTIVE en…
laitingsheng 3393b36
fix(uninstall): treat NEMOCLAW_NON_INTERACTIVE=1 as implicit --yes
laitingsheng 48792d1
revert(uninstall): drop NEMOCLAW_NON_INTERACTIVE=1 implicit --yes
laitingsheng File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| import { Args } from "@oclif/core"; | ||
| import { downloadSandbox } from "../../lib/actions/sandbox/transfer"; | ||
| import { NemoClawCommand } from "../../lib/cli/nemoclaw-oclif-command"; | ||
|
|
||
| export default class SandboxDownloadCommand extends NemoClawCommand { | ||
| static id = "sandbox:download"; | ||
| static strict = true; | ||
| static summary = "Download a file or directory from a running sandbox to the host"; | ||
| static description = | ||
| "Thin wrapper around `openshell sandbox download` so users can pull workspace files out of a sandbox without remembering the raw OpenShell command. Useful as a manual escape hatch when snapshot or backup-all coverage is incomplete."; | ||
| static usage = ["<name> <sandbox-path> [<dest>]"]; | ||
| static examples = [ | ||
| "<%= config.bin %> sandbox download alpha /sandbox/.openclaw/workspace/USER.md", | ||
| "<%= config.bin %> sandbox download alpha /sandbox/.openclaw/workspace ./alpha-workspace", | ||
| ]; | ||
| static args = { | ||
| sandboxName: Args.string({ name: "sandbox", description: "Sandbox name", required: true }), | ||
| sandboxPath: Args.string({ | ||
| name: "sandbox-path", | ||
| description: "Path inside the sandbox to download", | ||
| required: true, | ||
| }), | ||
| destination: Args.string({ | ||
| name: "dest", | ||
| description: "Local destination (defaults to the current directory)", | ||
| required: false, | ||
| }), | ||
| }; | ||
|
|
||
| public async run(): Promise<void> { | ||
| const { args } = await this.parse(SandboxDownloadCommand); | ||
| await downloadSandbox(args.sandboxName, args.sandboxPath, { | ||
| destination: args.destination, | ||
| }); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| import { Args, Flags } from "@oclif/core"; | ||
| import { uploadSandbox } from "../../lib/actions/sandbox/transfer"; | ||
| import { NemoClawCommand } from "../../lib/cli/nemoclaw-oclif-command"; | ||
|
|
||
| export default class SandboxUploadCommand extends NemoClawCommand { | ||
| static id = "sandbox:upload"; | ||
| static strict = true; | ||
| static summary = "Upload a local file or directory into a running sandbox"; | ||
| static description = | ||
| "Thin wrapper around `openshell sandbox upload` so users can push host files into a sandbox without remembering the raw OpenShell command. Useful for restoring workspace files after a wipe or for staging configuration the agent needs."; | ||
| static usage = ["<name> <local-path> [<dest>] [--no-git-ignore]"]; | ||
| static examples = [ | ||
| "<%= config.bin %> sandbox upload alpha ./USER.md /sandbox/.openclaw/workspace/USER.md", | ||
| "<%= config.bin %> sandbox upload alpha ./workspace /sandbox/.openclaw/workspace --no-git-ignore", | ||
| ]; | ||
| static args = { | ||
| sandboxName: Args.string({ name: "sandbox", description: "Sandbox name", required: true }), | ||
| localPath: Args.string({ | ||
| name: "local-path", | ||
| description: "Local path to upload", | ||
| required: true, | ||
| }), | ||
| destination: Args.string({ | ||
| name: "dest", | ||
| description: "Destination path inside the sandbox (defaults to the working directory)", | ||
| required: false, | ||
| }), | ||
| }; | ||
| static flags = { | ||
| "no-git-ignore": Flags.boolean({ | ||
| description: "Disable `.gitignore` filtering so the upload includes everything", | ||
| }), | ||
| }; | ||
|
|
||
| public async run(): Promise<void> { | ||
| const { args, flags } = await this.parse(SandboxUploadCommand); | ||
| await uploadSandbox(args.sandboxName, args.localPath, { | ||
| destination: args.destination, | ||
| noGitIgnore: flags["no-git-ignore"], | ||
| }); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.