Skip to content

Fix uninstall.sh for curl-to-bash execution - #426

Merged
kjw3 merged 10 commits into
mainfrom
fix/uninstall-stdin-entrypoint
Mar 19, 2026
Merged

Fix uninstall.sh for curl-to-bash execution#426
kjw3 merged 10 commits into
mainfrom
fix/uninstall-stdin-entrypoint

Conversation

@kjw3

@kjw3 kjw3 commented Mar 19, 2026

Copy link
Copy Markdown
Contributor

Summary

  • make the uninstall script entrypoint guard safe under set -u
  • support stdin execution via curl -fsSL ... | bash
  • preserve normal file-based execution

Testing

  • bash -n uninstall.sh
  • validated a stdin execution path with the updated entrypoint guard

Closes #425

Summary by CodeRabbit

  • New Features
    • Added an uninstall command to the CLI to run the uninstall flow locally or via the provided remote script.
  • Refactor
    • Improved uninstall script to better detect direct execution contexts and behave more robustly across shells.
  • Bug Fixes
    • Made confirmation prompt input handling more reliable in TTY and non‑TTY environments.
    • Reordered uninstall steps so local state removal occurs after binary/container/image/volume cleanup.
  • Documentation
    • Added an explicit uninstall section to Quick Start with a one‑line uninstall command.

@coderabbitai

coderabbitai Bot commented Mar 19, 2026

Copy link
Copy Markdown
Contributor

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 an uninstall CLI command and remote/local uninstall execution logic, hardens the uninstall.sh script for piped curl | bash usage (fixing unset BASH_SOURCE under set -u), adjusts confirmation reading, and reorders state removal to occur after binary and Docker cleanup; README updated with uninstall example.

Changes

Cohort / File(s) Summary
Uninstall CLI
bin/nemoclaw.js
Add uninstall command, dispatch logic to run a local uninstall.sh if present or fall back to piping remote uninstall.sh via `curl
Uninstall script
uninstall.sh
Robustify confirmation prompt by initializing reply and preferring /dev/tty (silencing errors) with a fallback `read -r reply
Documentation
README.md
Add explicit uninstall step to Quick Start with a `curl ... uninstall.sh

Sequence Diagram(s)

sequenceDiagram
    participant User as User
    participant CLI as nemoclaw CLI
    participant FS as Local FS
    participant Shell as Shell
    participant Remote as Remote URL

    rect rgba(200,200,255,0.5)
    User->>CLI: run `nemoclaw uninstall [args]`
    CLI->>FS: resolveUninstallScript() (check `ROOT/uninstall.sh`, `../uninstall.sh`)
    end

    alt local script found
        CLI->>Shell: spawnSync("bash", ["<localScript>", ...args]) (inherit stdio)
        Shell-->>CLI: exit status
        CLI-->>User: exit with status
    else no local script
        CLI->>Remote: build `curl -fsSL <url> | bash` with shell-quoted args
        CLI->>Shell: spawn remote command (bash -c ...)
        Shell-->>Remote: fetch & pipe script
        Remote-->>Shell: script stream
        Shell-->>CLI: exit status
        CLI-->>User: exit with status
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I nibble at scripts with tidy delight,
I peek at /dev/tty in the moonlight,
I default the source so pipes don't break,
I hop state removal to a safer take,
Now uninstall dances without a fright. 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% 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 accurately describes the primary change: fixing uninstall.sh to work with curl-to-bash execution, which aligns with the main objective of supporting stdin execution.
Linked Issues check ✅ Passed All coding requirements from #425 are met: entrypoint guard handles unset BASH_SOURCE via defaulting, stdin execution is supported, and both platforms work as verified.
Out of Scope Changes check ✅ Passed All changes directly address #425 requirements. The uninstall.sh fixes, README documentation update, and bin/nemoclaw.js enhancements are all part of the documented uninstall feature scope.

✏️ 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 fix/uninstall-stdin-entrypoint
📝 Coding Plan
  • Generate coding plan for human review comments

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 the current code and only fix it if needed.

Inline comments:
In `@uninstall.sh`:
- Line 457: The current guard calling main runs even when the file is sourced in
an interactive shell because $0 == "bash"/"-bash"; update the guard to call main
only when the script is being executed (when "${BASH_SOURCE[0]}" = "$0") OR when
BASH_SOURCE is unset (meaning input came from stdin/pipe) and $0 is "bash" or
"-bash"; specifically replace the existing if condition with a compound check
that requires either BASH_SOURCE[0] == $0 OR (BASH_SOURCE[0] is unset AND ($0 ==
"bash" OR $0 == "-bash")), so interactive sourcing (where BASH_SOURCE is set to
the sourced filename) will not trigger main.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: deeda9cc-c9f6-4d43-86ce-d86411b0fc0e

📥 Commits

Reviewing files that changed from the base of the PR and between 60992be and d811cfa.

📒 Files selected for processing (1)
  • uninstall.sh

Comment thread uninstall.sh Outdated
@kjw3

kjw3 commented Mar 19, 2026

Copy link
Copy Markdown
Contributor Author

Verification update:

Validated the curl-to-bash uninstall flow on the fix branch using a sanitized command form:

curl -fsSL https://raw.githubusercontent.com/NVIDIA/NemoClaw/refs/heads/fix/uninstall-stdin-entrypoint/uninstall.sh | bash

Observed behavior:

  • the script prompts successfully for confirmation when executed from stdin
  • entering y continues the uninstall flow instead of returning to the shell
  • the run completes cleanly and reaches Uninstall complete.
  • the final cleanup step removes NemoClaw state at the end of the uninstall flow

Representative output confirmed the expected sequence:

  • confirmation prompt accepted interactive input
  • helper-service cleanup ran
  • runtime/temp/docker cleanup steps completed or skipped cleanly when tools were absent
  • final Removing NemoClaw state... step ran immediately before completion

Local machine/user-specific prompt prefixes and paths omitted from this note.

@kjw3

kjw3 commented Mar 19, 2026

Copy link
Copy Markdown
Contributor Author

Additional verification update:

Also validated the same stdin execution path on macOS with the fix branch:

curl -fsSL https://raw.githubusercontent.com/NVIDIA/NemoClaw/refs/heads/fix/uninstall-stdin-entrypoint/uninstall.sh | bash

Observed behavior on macOS:

  • the confirmation prompt accepted interactive input from the terminal
  • entering y continued execution within the uninstall script
  • the uninstall completed successfully with the expected final Removing NemoClaw state... step followed by Uninstall complete.
  • cleanup steps that depended on absent tools or resources skipped cleanly without breaking the run

This matches the previously verified stdin behavior on Linux and confirms the prompt handling works in both environments.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
README.md (2)

82-84: Align the console block with markdownlint MD014

The snippet at Line 83 uses $ prompts without output, which triggers MD014 in many markdownlint setups. Either remove $ or include expected output.

Proposed lint-friendly edit
-```console
-$ curl -fsSL https://raw.githubusercontent.com/NVIDIA/NemoClaw/refs/heads/main/uninstall.sh | bash
-```
+```bash
+curl -fsSL https://raw.githubusercontent.com/NVIDIA/NemoClaw/refs/heads/main/uninstall.sh | bash
+```
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` around lines 82 - 84, The markdown snippet includes a console
block with a leading "$" prompt which triggers markdownlint MD014; update the
fenced code block around the curl command (the block containing "curl -fsSL
https://raw.githubusercontent.com/NVIDIA/NemoClaw/refs/heads/main/uninstall.sh |
bash") to be lint-friendly by removing the "$" prompt and changing the fence
language to bash (i.e., replace the "console" fence and "$ curl..." line with a
"bash" fence followed by "curl -fsSL ... | bash" so the example contains no
prompts).

83-83: Prefer an immutable uninstall URL in curl-to-bash docs

Line 83 points to refs/heads/main, which is mutable. For safer reproducibility, document a tagged release (or commit-pinned) URL for the uninstall script.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` at line 83, The curl command in README.md uses a mutable
refs/heads/main URL; update that example to point to an immutable release or
commit (e.g., use refs/tags/<release-tag> or refs/commits/<commit-sha>) so the
uninstall script URL is pinned and reproducible—replace the existing curl URL
string shown on the line with one that references a specific tag or commit SHA
and mention the chosen tag/sha in the README example.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@README.md`:
- Around line 82-84: The markdown snippet includes a console block with a
leading "$" prompt which triggers markdownlint MD014; update the fenced code
block around the curl command (the block containing "curl -fsSL
https://raw.githubusercontent.com/NVIDIA/NemoClaw/refs/heads/main/uninstall.sh |
bash") to be lint-friendly by removing the "$" prompt and changing the fence
language to bash (i.e., replace the "console" fence and "$ curl..." line with a
"bash" fence followed by "curl -fsSL ... | bash" so the example contains no
prompts).
- Line 83: The curl command in README.md uses a mutable refs/heads/main URL;
update that example to point to an immutable release or commit (e.g., use
refs/tags/<release-tag> or refs/commits/<commit-sha>) so the uninstall script
URL is pinned and reproducible—replace the existing curl URL string shown on the
line with one that references a specific tag or commit SHA and mention the
chosen tag/sha in the README example.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d558ada1-9705-4d9f-9dde-7c8bfb06c809

📥 Commits

Reviewing files that changed from the base of the PR and between f40b061 and deb6ed6.

📒 Files selected for processing (1)
  • README.md

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 the current code and only fix it if needed.

Inline comments:
In `@bin/nemoclaw.js`:
- Around line 182-200: The current exit logic uses process.exit(result.status ||
0) which treats a null result.status (e.g., subprocess killed by signal or spawn
failure) as success; update the termination handling in the blocks that call
spawnSync (the variables named result from spawnSync and the subsequent
process.exit calls) to: if result.status !== null then exit with result.status;
else if result.signal is set then exit with a nonzero code derived from the
signal (common convention: 128 + signal number) or at minimum a distinct nonzero
code; otherwise exit with 1 to indicate failure. Ensure you reference the
spawnSync return object’s status and signal fields and replace the current
process.exit(...) use with this three-way logic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 65ad17df-97d5-42a0-85ec-55406e770482

📥 Commits

Reviewing files that changed from the base of the PR and between deb6ed6 and cfedd1e.

📒 Files selected for processing (1)
  • bin/nemoclaw.js

Comment thread bin/nemoclaw.js Outdated
@kjw3

kjw3 commented Mar 19, 2026

Copy link
Copy Markdown
Contributor Author

@ericksoa @jacobtomlinson or @liveaverage could I get a review on this to allow curl based uninstalls and a convenience wrapper in nemoclaw cli

Comment thread bin/nemoclaw.js

@liveaverage liveaverage left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ran on Spark and Brev with success. Correctly resolved local uninstall.sh when present and fallback to remote uninstall.sh worked as expected

@kjw3
kjw3 merged commit bf0642c into main Mar 19, 2026
4 checks passed
@kjw3
kjw3 deleted the fix/uninstall-stdin-entrypoint branch March 19, 2026 19:52
Ryuketsukami pushed a commit to Ryuketsukami/NemoClaw that referenced this pull request Mar 24, 2026
* fix uninstall script stdin entrypoint guard

* fix uninstall entrypoint guard when sourced from bash

* fix uninstall cleanup order and tty prompt

* docs add curl uninstall command to readme

* feat add nemoclaw uninstall wrapper

* fix uninstall docs pin and cli exit handling

* docs restore main uninstall url in readme

* docs remove shell prompts from readme commands

* docs match uninstall code fence style
jessesanford pushed a commit to jessesanford/NemoClaw that referenced this pull request Mar 24, 2026
* fix uninstall script stdin entrypoint guard

* fix uninstall entrypoint guard when sourced from bash

* fix uninstall cleanup order and tty prompt

* docs add curl uninstall command to readme

* feat add nemoclaw uninstall wrapper

* fix uninstall docs pin and cli exit handling

* docs restore main uninstall url in readme

* docs remove shell prompts from readme commands

* docs match uninstall code fence style
@wscurran wscurran added the bug-fix PR fixes a bug or regression label Jun 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug-fix PR fixes a bug or regression

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix uninstall.sh when executed via curl pipe to bash

4 participants