Skip to content

fix(installer): resolve npm prefix when host nvm is present#485

Merged
cv merged 8 commits intoNVIDIA:mainfrom
afurm:fix/installer-nvm-path-refresh
Apr 22, 2026
Merged

fix(installer): resolve npm prefix when host nvm is present#485
cv merged 8 commits intoNVIDIA:mainfrom
afurm:fix/installer-nvm-path-refresh

Conversation

@afurm
Copy link
Copy Markdown
Contributor

@afurm afurm commented Mar 20, 2026

Summary

Fixes an installer regression where a host nvm environment could override the active npm during PATH refresh, causing nemoclaw to appear missing even after a successful install.

Changes

  • Add a resolve_npm_bin() helper that resolves the npm global bin from the active npm on PATH before falling back to loading nvm.
  • refresh_path() now uses resolve_npm_bin() instead of calling ensure_nvm_loaded() first and using a bare npm config get prefix — this avoids a hostile host nvm.sh overriding the already-working npm.
  • ensure_nemoclaw_shim() uses resolve_npm_bin() for consistent npm bin resolution.
  • verify_nemoclaw() uses resolve_npm_bin() for PATH recovery guidance.
  • Drop obsolete test/install-preflight.test.js (superseded by test/install-preflight.test.ts in main).

Testing

  • make check passes.
  • npm test passes.
  • Shell syntax validated with bash -n on both install.sh and scripts/install.sh.

DCO

Signed-off-by: Andrii Furmanets furmanets.andriy@gmail.com

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 20, 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

Extracted npm global-bin resolution into resolve_npm_bin() used by PATH refresh, shim installation, and verification; installer now prefers an npm already on PATH (sources nvm only if npm is missing) and conditionally uses sudo for NodeSource global installs when the npm prefix's bin/lib/node_modules are not writable. Tests add hermetic env helpers and cover these behaviors.

Changes

Cohort / File(s) Summary
Installer script
scripts/install.sh, install.sh
Added resolve_npm_bin() (queries npm config get prefix, sources nvm only if npm is missing, fails when prefix unavailable) and npm_link_targets_writable(); updated refresh_path(), ensure_nemoclaw_shim(), and verify_nemoclaw() to use resolve_npm_bin(); Nodesource npm link path now checks prefix writability and sets SUDO="sudo" only when targets are not writable.
Tests
test/install-preflight.test.js
Added installerEnv(tmp, fakeBin, extra = {}) helper for hermetic subprocess envs and replaced inline env constructions. Added tests: prefer PATH npm over hostile NVM_DIR npm; verify sudo used for npm link when Nodesource prefix targets are not writable; added fake uname helper for deterministic runtime detection.
Metadata / size
(internal)
Script changes: added helpers and call-site updates; Test changes: new helper and multiple new cases. Lines changed across diff: scripts +~50/-~6, tests +~435/-~30 (approx.).

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Installer
  participant npm
  participant nvm
  participant FS as Filesystem

  User->>Installer: run install script
  Installer->>npm: probe npm on PATH
  alt npm present
    npm-->>Installer: responds
  else npm absent
    Installer->>nvm: source NVM_DIR to load npm
    nvm-->>Installer: nvm loaded
    Installer->>npm: probe npm after loading nvm
    npm-->>Installer: responds or fails
  end
  Installer->>npm: npm config get prefix
  npm-->>Installer: prefix
  Installer->>Installer: compute npm_bin = prefix/bin
  Installer->>FS: ensure npm_bin is in PATH / create shim
  Installer->>FS: check writability of prefix/bin and prefix/lib/node_modules
  alt writable
    Installer->>npm: npm link / npm install -g (no sudo)
  else not writable
    Installer->>FS: invoke sudo for npm link / install
  end
  Installer->>User: emit verification ("Verified: nemoclaw is available")
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I hopped the PATH to find the bin,
I sniffed whether npm was already in,
I woke nvm only if npm hid away,
Resolved the prefix and arranged the way.
If bins were locked — a polite sudo saved the day 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 90.91% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(installer): resolve npm prefix when host nvm is present' clearly and specifically describes the main change—addressing npm prefix resolution issues when host nvm is active, which aligns with the core problem and solution documented in the PR objectives.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@wscurran wscurran added enhancement New feature or request NemoClaw CLI Use this label to identify issues with the NemoClaw command-line interface (CLI). labels Mar 20, 2026
@wscurran
Copy link
Copy Markdown
Contributor

Thanks for tackling the installer issues, especially around npm resolution and PATH refresh - this could make a big difference for users with nvm installed.

@afurm afurm force-pushed the fix/installer-nvm-path-refresh branch from bee4afc to 3ef8fef Compare March 21, 2026 08:06
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 (1)
scripts/install.sh (1)

431-439: Good fix for avoiding unnecessary sudo, with a minor robustness consideration.

The writability check correctly avoids sudo npm link when the npm prefix is writable, fixing the stdin issue in CI pipelines. However, npm link writes to both $npm_prefix/bin and $npm_prefix/lib/node_modules. If these subdirectories have different permissions than the prefix itself, the link could still fail.

For typical nodesource setups or CI containers, checking just the prefix is likely sufficient. If edge cases arise, consider checking $npm_prefix/bin writability as well.

💡 Optional: More precise writability check
   npm_prefix="$(npm config get prefix 2>/dev/null || true)"
-  if [ -z "$npm_prefix" ] || [ ! -w "$npm_prefix" ]; then
+  if [ -z "$npm_prefix" ] || [ ! -w "$npm_prefix/bin" ]; then
     SUDO="sudo"
   fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/install.sh` around lines 431 - 439, The current SUDO detection
(variables NODE_MGR, SUDO, npm_prefix) only checks writability of npm_prefix
which can miss differing permissions on npm_prefix/bin or
npm_prefix/lib/node_modules; update the logic in scripts/install.sh so after
obtaining npm_prefix you test writability of "$npm_prefix/bin" and
"$npm_prefix/lib/node_modules" (falling back to testing npm_prefix if those
paths are missing) and only leave SUDO empty when those target dirs are writable
(otherwise set SUDO="sudo"); ensure the same early-root check (id -u) and
NODE_MGR="nodesource" condition are preserved and reference SUDO, NODE_MGR, and
npm_prefix in your changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@scripts/install.sh`:
- Around line 431-439: The current SUDO detection (variables NODE_MGR, SUDO,
npm_prefix) only checks writability of npm_prefix which can miss differing
permissions on npm_prefix/bin or npm_prefix/lib/node_modules; update the logic
in scripts/install.sh so after obtaining npm_prefix you test writability of
"$npm_prefix/bin" and "$npm_prefix/lib/node_modules" (falling back to testing
npm_prefix if those paths are missing) and only leave SUDO empty when those
target dirs are writable (otherwise set SUDO="sudo"); ensure the same early-root
check (id -u) and NODE_MGR="nodesource" condition are preserved and reference
SUDO, NODE_MGR, and npm_prefix in your changes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 95455142-b500-4be1-a488-c62ece65b323

📥 Commits

Reviewing files that changed from the base of the PR and between bee4afc and 3ef8fef.

📒 Files selected for processing (3)
  • install.sh
  • scripts/install.sh
  • test/install-preflight.test.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/install-preflight.test.js

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

🧹 Nitpick comments (1)
test/install-preflight.test.js (1)

451-595: Test cleanup consideration: read-only directories may persist.

The test sets prefixBin and prefixNodeModules to mode 0o555 (read-only). While the fake npm link restores writability when running under fake sudo, if the test fails early or assertions fail, these directories remain read-only in the temp directory, which could cause issues during cleanup on some systems.

Consider adding a cleanup step or using t.after() to restore permissions:

♻️ Optional: Ensure cleanup restores permissions
// At the start of the test, after creating the directories:
const cleanup = () => {
  try {
    fs.chmodSync(prefixBin, 0o755);
    fs.chmodSync(prefixNodeModules, 0o755);
  } catch (e) { /* ignore */ }
};
// Node test runner cleanup hook would go here if available
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/install-preflight.test.js` around lines 451 - 595, The test "uses sudo
for npm link when nodesource target directories are not writable" leaves
prefixBin and prefixNodeModules as mode 0o555 which can block cleanup on
failures; add a teardown that restores permissions (chmodSync back to 0o755) for
prefixBin and prefixNodeModules and invoke it in a finally block or the test
framework's after/teardown hook (e.g., t.after or equivalent) so permissions are
always reset even if assertions fail.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/install.sh`:
- Around line 126-149: The npm_link_targets_writable function doesn't verify
writability of the intermediate "$npm_prefix/lib" when
"$npm_prefix/lib/node_modules" is absent; update the logic inside
npm_link_targets_writable to check the parent directory of npm_lib_dir (e.g.,
"$npm_prefix/lib") and return failure if that parent exists but is not writable,
so that attempting to create "node_modules" won't later fail; keep existing
checks for npm_bin_dir and npm_prefix and use the variables npm_prefix and
npm_lib_dir to locate and test the intermediate dir.

---

Nitpick comments:
In `@test/install-preflight.test.js`:
- Around line 451-595: The test "uses sudo for npm link when nodesource target
directories are not writable" leaves prefixBin and prefixNodeModules as mode
0o555 which can block cleanup on failures; add a teardown that restores
permissions (chmodSync back to 0o755) for prefixBin and prefixNodeModules and
invoke it in a finally block or the test framework's after/teardown hook (e.g.,
t.after or equivalent) so permissions are always reset even if assertions fail.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: baae8255-8b26-4093-b869-c05cb5223e8a

📥 Commits

Reviewing files that changed from the base of the PR and between 3ef8fef and 99f166e.

📒 Files selected for processing (2)
  • scripts/install.sh
  • test/install-preflight.test.js

Comment thread scripts/install.sh
@afurm
Copy link
Copy Markdown
Contributor Author

afurm commented Mar 21, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 21, 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: 1

🧹 Nitpick comments (1)
test/install-preflight.test.js (1)

451-740: Consider extracting shared fake-runtime setup helpers.

The two new sudo-focused tests duplicate a large setup surface (fake node, git, npm, sudo, docker, openshell, uname). A small fixture builder would reduce drift and make future behavior changes easier to apply consistently.

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

In `@test/install-preflight.test.js` around lines 451 - 740, Both tests duplicate
a large fake runtime setup (creating tmp, fakeBin, prefix, writing
node/git/npm/sudo/docker/openshell/uname via writeExecutable and using
installerEnv), so extract that logic into a small fixture builder (e.g.,
createFakeRuntime or buildFakeBinWithExecutables) that accepts overrides for
permissions and NPM_PREFIX/SUDO_LOG_PATH; update the two tests to call this
helper and only mutate what differs (like chmod on prefix/lib or prefix/bin) and
keep using writeExecutable and installerEnv in the helper to locate the code to
change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@test/install-preflight.test.js`:
- Around line 594-595: The current assertion using
assert.match(fs.readFileSync(sudoLog, "utf-8"), /^npm link$/m) allows "npm link"
to appear anywhere in sudo.log and misses extra sudo commands; update both
occurrences to assert the log equals exactly "npm link" (e.g., read sudoLog,
trim the content and compare with "npm link") so any additional sudo activity
fails the test; locate and replace the assert.match calls that reference sudoLog
in test/install-preflight.test.js accordingly.

---

Nitpick comments:
In `@test/install-preflight.test.js`:
- Around line 451-740: Both tests duplicate a large fake runtime setup (creating
tmp, fakeBin, prefix, writing node/git/npm/sudo/docker/openshell/uname via
writeExecutable and using installerEnv), so extract that logic into a small
fixture builder (e.g., createFakeRuntime or buildFakeBinWithExecutables) that
accepts overrides for permissions and NPM_PREFIX/SUDO_LOG_PATH; update the two
tests to call this helper and only mutate what differs (like chmod on prefix/lib
or prefix/bin) and keep using writeExecutable and installerEnv in the helper to
locate the code to change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ee692bc0-14be-4df9-964b-70f535fe2663

📥 Commits

Reviewing files that changed from the base of the PR and between 3ef8fef and b06c2ed.

📒 Files selected for processing (2)
  • scripts/install.sh
  • test/install-preflight.test.js
✅ Files skipped from review due to trivial changes (1)
  • scripts/install.sh

Comment thread test/install-preflight.test.js Outdated
kjw3 added a commit that referenced this pull request Apr 4, 2026
## Summary
Fixes a CLI install regression where `nemoclaw` was reported as
installed but the command was broken after install completed.

This changes the installer so:
- user shells get a stable `~/.local/bin/nemoclaw` wrapper
- the wrapper prepends the resolved Node bin to `PATH` before execing
the installed CLI
- bootstrap `curl | bash` installs no longer `npm link` a temporary
cloned checkout
- bootstrap payload clones are treated as ephemeral, not as persistent
source checkouts

## Root Cause
There were two installer-side problems:

1. The thin bootstrap `install.sh` cloned the selected ref into a
temporary directory and then executed `scripts/install.sh` from that
clone. The payload installer treated that temp clone as a source
checkout and ran `npm link`, which created a global package symlink into
the temp directory. Once the bootstrap temp directory was cleaned up,
`nemoclaw` was broken.

2. Even when the CLI binary existed, future shells could still fail to
run it because the shebang relied on `node` being on `PATH`. On hosts
using `nvm`, sourcing `nvm.sh` was not sufficient to guarantee that a
Node version was active in later shells.

## Related Issues
Related: #569, #989, #1429

Notes:
- `#569` is the closest installer/runtime-path issue.
- `#989` and `#1429` track the developer-doc path that requires `npm
link`.
- This PR does not update docs, so it does not close `#989` or `#1429`.

## Related Prior Work
This overlaps with earlier installer investigation/work in:
- `#485` by @afurm
- `#517` by @MilanKiele

Those PRs helped surface the same general npm/prefix/PATH fragility from
adjacent angles.

## What Changed
- `install.sh`
- marks bootstrap payload execution as ephemeral via
`NEMOCLAW_BOOTSTRAP_PAYLOAD=1`
- `scripts/install.sh`
  - adds a stable `~/.local/bin/nemoclaw` wrapper
- wrapper exports the resolved Node bin onto `PATH` and execs the
installed `nemoclaw`
  - `is_source_checkout()` now rejects bootstrap payload clones
- `test/install-preflight.test.js`
- adds coverage for source checkout detection and bootstrap payload
handling
  - updates shim expectations to match the wrapper behavior

## Supported Paths
This PR fixes the fully supported installer paths:
- `curl | bash`
- repo checkout + `./install.sh`

Developer repo usage remains:
- `git clone`
- `npm install`
- `npm link`
- `nemoclaw onboard`

Plain `npm install` alone is not treated as a supported CLI install
path.

## Validation
Local:
- `npm test -- test/install-preflight.test.js`

Live:
- `brev-cpu` `kj-nemoclaw-cpu-test`
  - repo checkout + `./install.sh --non-interactive`
  - raw GitHub bootstrap installer equivalent to `curl | bash`
  - verified fresh-shell `command -v nemoclaw` and `nemoclaw --version`
- `spark` `spark-d8c8`
  - reproduced broken pre-fix binary state
  - repo checkout + `./install.sh --non-interactive`
  - verified fresh-shell `command -v nemoclaw` and `nemoclaw --version`

## Notes
I only live-tested non-interactive installs on this branch. Interactive
install behavior was not live-retested here.


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

* **Bug Fixes / Improvements**
* Improved installer reliability and shim creation so the CLI runs
correctly even when Node is outside PATH.
* Installer better distinguishes source checkouts vs non-persistent
payload installs and emits clearer informational messages.
* Uninstaller now recognizes and removes installer-generated wrapper
shims while preserving unrelated user files.

* **Tests**
* Added and updated tests covering shim behavior, uninstall handling,
and installation-type detection.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
@wscurran wscurran added the status: rebase PR needs to be rebased against main before review can continue label Apr 14, 2026
When a host nvm environment is present on the system, sourcing nvm.sh during
installer PATH refresh could switch to a different npm than the one that
performed the install, making nemoclaw appear missing even after a successful
install.

Add a resolve_npm_bin() helper that resolves the npm global bin from the
active npm on PATH before falling back to nvm-loaded npm. Reuse this helper
in refresh_path(), ensure_nemoclaw_shim(), and verify_nemoclaw() for
consistent resolution across all installer code paths.

refresh_path() no longer unconditionally calls ensure_nvm_loaded() first —
it now uses resolve_npm_bin() which respects an already-active npm while
still loading nvm as a fallback when needed.

Drop obsolete test/install-preflight.test.js (replaced by .ts version in main).
@afurm afurm force-pushed the fix/installer-nvm-path-refresh branch from b06c2ed to e1f37cc Compare April 14, 2026 16:03
@afurm
Copy link
Copy Markdown
Contributor Author

afurm commented Apr 14, 2026

Thanks for the review! I've rebased against main and updated the PR description to reflect the actual changes. The diff now adds a resolve_npm_bin() helper that uses the active npm on PATH before falling back to nvm — avoiding the hostile nvm.sh override issue. Also dropped the obsolete test/install-preflight.test.js since main now has the TypeScript version. Ready for another look when you have time.

gemini2026 pushed a commit to gemini2026/NemoClaw that referenced this pull request Apr 14, 2026
## Summary
Fixes a CLI install regression where `nemoclaw` was reported as
installed but the command was broken after install completed.

This changes the installer so:
- user shells get a stable `~/.local/bin/nemoclaw` wrapper
- the wrapper prepends the resolved Node bin to `PATH` before execing
the installed CLI
- bootstrap `curl | bash` installs no longer `npm link` a temporary
cloned checkout
- bootstrap payload clones are treated as ephemeral, not as persistent
source checkouts

## Root Cause
There were two installer-side problems:

1. The thin bootstrap `install.sh` cloned the selected ref into a
temporary directory and then executed `scripts/install.sh` from that
clone. The payload installer treated that temp clone as a source
checkout and ran `npm link`, which created a global package symlink into
the temp directory. Once the bootstrap temp directory was cleaned up,
`nemoclaw` was broken.

2. Even when the CLI binary existed, future shells could still fail to
run it because the shebang relied on `node` being on `PATH`. On hosts
using `nvm`, sourcing `nvm.sh` was not sufficient to guarantee that a
Node version was active in later shells.

## Related Issues
Related: NVIDIA#569, NVIDIA#989, NVIDIA#1429

Notes:
- `NVIDIA#569` is the closest installer/runtime-path issue.
- `NVIDIA#989` and `NVIDIA#1429` track the developer-doc path that requires `npm
link`.
- This PR does not update docs, so it does not close `NVIDIA#989` or `NVIDIA#1429`.

## Related Prior Work
This overlaps with earlier installer investigation/work in:
- `NVIDIA#485` by @afurm
- `NVIDIA#517` by @MilanKiele

Those PRs helped surface the same general npm/prefix/PATH fragility from
adjacent angles.

## What Changed
- `install.sh`
- marks bootstrap payload execution as ephemeral via
`NEMOCLAW_BOOTSTRAP_PAYLOAD=1`
- `scripts/install.sh`
  - adds a stable `~/.local/bin/nemoclaw` wrapper
- wrapper exports the resolved Node bin onto `PATH` and execs the
installed `nemoclaw`
  - `is_source_checkout()` now rejects bootstrap payload clones
- `test/install-preflight.test.js`
- adds coverage for source checkout detection and bootstrap payload
handling
  - updates shim expectations to match the wrapper behavior

## Supported Paths
This PR fixes the fully supported installer paths:
- `curl | bash`
- repo checkout + `./install.sh`

Developer repo usage remains:
- `git clone`
- `npm install`
- `npm link`
- `nemoclaw onboard`

Plain `npm install` alone is not treated as a supported CLI install
path.

## Validation
Local:
- `npm test -- test/install-preflight.test.js`

Live:
- `brev-cpu` `kj-nemoclaw-cpu-test`
  - repo checkout + `./install.sh --non-interactive`
  - raw GitHub bootstrap installer equivalent to `curl | bash`
  - verified fresh-shell `command -v nemoclaw` and `nemoclaw --version`
- `spark` `spark-d8c8`
  - reproduced broken pre-fix binary state
  - repo checkout + `./install.sh --non-interactive`
  - verified fresh-shell `command -v nemoclaw` and `nemoclaw --version`

## Notes
I only live-tested non-interactive installs on this branch. Interactive
install behavior was not live-retested here.


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

* **Bug Fixes / Improvements**
* Improved installer reliability and shim creation so the CLI runs
correctly even when Node is outside PATH.
* Installer better distinguishes source checkouts vs non-persistent
payload installs and emits clearer informational messages.
* Uninstaller now recognizes and removes installer-generated wrapper
shims while preserving unrelated user files.

* **Tests**
* Added and updated tests covering shim behavior, uninstall handling,
and installation-type detection.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
@wscurran wscurran added v0.0.22 Release target and removed status: rebase PR needs to be rebased against main before review can continue labels Apr 15, 2026
@wscurran wscurran requested a review from cv April 21, 2026 19:30
@wscurran
Copy link
Copy Markdown
Contributor

Thanks for the quick turnaround on the rebase and updated PR description — the resolve_npm_bin() helper approach is clean. This is queued for maintainer review; we'll follow up once we've had a chance to look it over.

@cv
Copy link
Copy Markdown
Contributor

cv commented Apr 21, 2026

@afurm can I ask you add the DCO tag to the PR body, please?

@cv cv added v0.0.23 Release target and removed v0.0.22 Release target labels Apr 22, 2026
@afurm
Copy link
Copy Markdown
Contributor Author

afurm commented Apr 22, 2026

@afurm can I ask you add the DCO tag to the PR body, please?

Done, added the DCO sign-off to the PR body.

@cv cv changed the title Fix installer npm prefix resolution when host nvm is present fix(installer): resolve npm prefix when host nvm is present Apr 22, 2026
@cv cv enabled auto-merge (squash) April 22, 2026 09:31
@cv cv merged commit 9b66b63 into NVIDIA:main Apr 22, 2026
14 of 15 checks passed
ericksoa added a commit that referenced this pull request Apr 22, 2026
## Summary
This PR fixes the post-merge main-CI regression introduced after #485 by
making the installer npm-resolution permission test match non-root
installer semantics on root-backed runners. The production installer
logic is unchanged; only the test harness is adjusted so the assertion
no longer depends on root-only writability behavior.

## Changes
- update `test/install-npm-resolution.test.ts` so the
permission-sensitive `npm_link_targets_writable()` assertion runs as
`nobody` on Linux root runners
- keep the temporary fixture directories traversable while making the
lib path the actual unwritable target under test
- preserve existing coverage for active-PATH npm preference, nvm
fallback, and writable target detection without changing installer code

## Type of Change
- [x] 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
- [x] `npx prek run --all-files` passes
- [x] `npm test` passes
- [x] Tests added or updated for new or changed behavior
- [x] No secrets, API keys, or credentials committed
- [ ] Docs updated for user-facing behavior changes
- [ ] `make docs` builds without warnings (doc changes only)
- [ ] 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
- [x] AI-assisted — tool: pi agent

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

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

* **Tests**
* Installer tests now support executing provided snippets "raw" (no
automatic sourcing) so wrappers can control execution.
* Tests simulate privilege-drop execution (running as an unprivileged
user) to validate installer behavior under lowered privileges.
* Improved handling of writable/unwritable install targets with
conditional permission adjustments when running as root.
  * No public interfaces were changed; updates are test-only.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Co-authored-by: Aaron Erickson <aerickson@nvidia.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request NemoClaw CLI Use this label to identify issues with the NemoClaw command-line interface (CLI). v0.0.23 Release target

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants