15 releases
| 0.2.0 | Jun 24, 2026 |
|---|---|
| 0.1.13 | Jun 22, 2026 |
| 0.1.12 | Apr 11, 2026 |
| 0.1.8 | Mar 22, 2026 |
#900 in Parser implementations
460KB
12K
SLoC
nodeup
nodeup is a Rust-based Node.js version manager with rustup-like commands, deterministic runtime resolution, and managed alias dispatch for node, npm, npx, yarn, and pnpm.
Overview
- Manage multiple Node.js runtimes from one CLI.
- Resolve active runtime consistently with explicit, override, and default selectors.
- Use human-friendly output for operators and JSON output for automation.
- Run
node,npm,npx,yarn, andpnpmthrough one binary by executable-name dispatch.
Install
Tag contract:
nodeup@v<semver>
Package manager:
- macOS/Linux:
brew install delinoio/tap/nodeup
Direct installers:
Install cosign first and leave it on PATH; the installers require it to verify SHA256SUMS entries and Sigstore bundle sidecars (*.sigstore.json). Missing cosign is reported before release artifact download as a prerequisite failure. Use Homebrew or cargo-binstall instead if you do not want to manage that prerequisite directly.
brew install cosign
On Linux without Homebrew, follow the Sigstore cosign installation guide. On Windows, use winget install sigstore.cosign or scoop install cosign.
macOS and Linux:
(
installer_url="https://raw.githubusercontent.com/delinoio/oss/refs/heads/main/scripts/install/nodeup.sh"
tmp_dir="$(mktemp -d)"
trap 'rm -rf "$tmp_dir"' EXIT
if ! curl -fsSL "$installer_url" -o "$tmp_dir/nodeup.sh"; then
exit 1
fi
bash "$tmp_dir/nodeup.sh" --version latest --method direct
)
Windows PowerShell:
$InstallerUrl = "https://raw.githubusercontent.com/delinoio/oss/refs/heads/main/scripts/install/nodeup.ps1"
$Installer = Join-Path ([System.IO.Path]::GetTempPath()) ("nodeup-install-" + [System.Guid]::NewGuid().ToString("N") + ".ps1")
try {
Invoke-WebRequest -Uri $InstallerUrl -OutFile $Installer -UseBasicParsing
Unblock-File -LiteralPath $Installer -ErrorAction SilentlyContinue
$PowerShell = (Get-Process -Id $PID).Path
& $PowerShell -NoProfile -ExecutionPolicy Bypass -File $Installer -Version latest -Method direct
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}
}
finally {
Remove-Item -LiteralPath $Installer -Force -ErrorAction SilentlyContinue
}
These commands fetch the current first-party installer scripts from delinoio/oss. For reproducible automation, pin the same raw URL paths to a reviewed commit or repository tag instead of refs/heads/main, and replace latest with an explicit Nodeup semver.
Canonical in-repo installer paths for maintainer workflows:
scripts/install/nodeup.shscripts/install/nodeup.ps1
cargo-binstall:
cargo binstall nodeup --no-confirm
cargo-binstall resolves first-party GitHub Release assets only:
nodeup-linux-amd64.tar.gznodeup-linux-arm64.tar.gznodeup-darwin-amd64.tar.gznodeup-darwin-arm64.tar.gznodeup-windows-amd64.zipnodeup-windows-arm64.zip
Third-party quick-install and compile fallback strategies are disabled. Unsupported hosts or missing release assets fail instead of compiling from source; use Homebrew, the direct installer with cosign, or a supported x64/arm64 host with a complete Nodeup release.
GitHub Actions:
- uses: taiki-e/install-action@v2
with:
tool: cargo-binstall
- run: cargo binstall nodeup --no-confirm
Direct installers support bundle-enabled releases only.
Direct installers place the binary in ~/.local/bin by default and do not modify your shell PATH. Add that directory before running nodeup, or pass --install-dir / -InstallDir with a directory already on PATH.
macOS and Linux:
export PATH="$HOME/.local/bin:$PATH"
Windows PowerShell:
$env:Path = "$HOME\.local\bin;$env:Path"
Quick Command Reference
nodeup toolchain list [--quiet|--verbose]nodeup toolchain install <runtime>...nodeup toolchain uninstall <runtime>...nodeup toolchain link <name> <path>nodeup toolchain unlink <name>...nodeup default [runtime]nodeup show active-runtimenodeup show homenodeup update [runtime]...nodeup checknodeup override listnodeup override set <runtime> [--path <path>]nodeup override unset [--path <path> | --nonexistent]nodeup which [--runtime <runtime>] <command>nodeup run [--install] <runtime> <command>...nodeup shim setup [--dir <path>]nodeup self updatenodeup self uninstallnodeup self upgrade-datanodeup completions <shell> [command]
nodeup override unset --path <path> and nodeup override unset --nonexistent are mutually exclusive. Use --path for one override target, or --nonexistent for global stale-entry cleanup.
Runtime Resolution Precedence
Runtime resolution follows a stable order:
- Explicit selector (
run <runtime>,which --runtime <runtime>) - Directory override (
override set) - Global default (
default)
If no selector resolves, commands fail with deterministic not-found errors.
Linked Runtimes
nodeup toolchain link <name> <path> registers an external runtime directory
without copying or owning that directory. The runtime must provide a runnable
Node executable under bin/: bin/node on Unix-like hosts or bin/node.exe
when Windows platform behavior is selected. Unix hosts require an executable
permission bit on bin/node.
Linked runtime names cannot be reserved channel selectors (lts, current,
latest) or case variants such as LTS, Current, or LATEST. Use distinct
names such as local-lts or work-node.
Successful link output separates the required runnable node check from
optional managed shim availability. Missing package-manager shims (npm,
npx, yarn, or pnpm) are reported at link time but do not make linking
fail.
nodeup toolchain unlink <name>... removes linked runtime records from nodeup
settings and tracked selectors without deleting external runtime directories.
Unlinking fails with conflict when the linked name is the current default or
is referenced by a directory override; change the default or remove/update the
override before unlinking. Conflict diagnostics include blocker details,
remediation commands, and retry commands. Missing linked names fail with
deterministic not-found errors.
packageManager Support
nodeup resolves package.json from the current working directory upward and supports
the packageManager field for yarn and pnpm commands.
- Supported format:
<manager>@<exact-semver> - Supported managers:
yarn,pnpm - Strict behavior:
- if
packageManagerexists, requested command must match manager - mismatches fail with
conflict - malformed values fail with
invalid-input
- if
- Corepack is not used;
nodeupuses the selected runtime'snpm exec.
Mapping rules:
pnpm@x.y.z->npm exec --package pnpm@x.y.z -- pnpm ...yarn@1.x.y->npm exec --package yarn@1.x.y -- yarn ...yarn@2+->npm exec --package @yarnpkg/cli-dist@x.y.z -- yarn ...
Fallback rules when packageManager is absent:
- if runtime provides
bin/yarnorbin/pnpm, run it directly - otherwise run through
npm execwith defaults:yarn->@yarnpkg/cli-distpnpm->pnpm
Managed Shims
nodeup shim setup creates or repairs managed aliases for node, npm, npx, yarn, and pnpm.
- Default shim directory:
NODEUP_SHIM_DIR, otherwise$HOME/.local/bin - macOS/Linux: symlink aliases
- Windows: copied
.exealiases - Conflicts report the existing path, ownership classification, and remediation; unrelated commands are not replaced
- PATH activation remains manual by default; output includes shell- and OS-aware current-session commands, profile persistence hints, and verification commands
- JSON output includes
action,status,shim_dir,nodeup_binary,path_active,path_instruction,detected_shell,operating_system,path_next_steps,verification_commands, and per-aliasshims
Re-run the command after moving the Nodeup binary or when an alias is stale.
Self Uninstall Boundary
nodeup self uninstall removes Nodeup-owned data, cache, and config roots only. It does not remove the running binary, managed shims, shell profile entries, or user PATH values. Configured roots that are not clearly Nodeup-owned are refused without deletion and reported separately.
Human output separates removed Nodeup-owned data/cache/config roots from remaining manual binary, shim, shell-profile, and PATH cleanup. JSON output includes removed_paths, manual_leftover_paths, ownership_refused_paths, cleanup_boundaries, remaining_manual_steps, detected_shell, operating_system, manual_cleanup_commands, verification_commands, and likely_leftover_paths.
Output and Logging
- Global output mode:
--output human|json(default:human) humanmode:- command results are written to stdout for operators
- default log filter is
nodeup=warnfor management commands
jsonmode:- success payloads are written to stdout as JSON
- handled failures are written to stderr as JSON envelopes
- fields:
kind,message,exit_code messagefollows<cause>. Hint: <next action>for actionable recovery guidance
- fields:
- logging stays off so Nodeup JSON payloads remain parseable
runredirects delegated command stdout to stderr so stdout can carry the Nodeup JSON response; do not parserunstderr as a JSON-only stream
completionscommand:- always writes raw completion script text to stdout
- does not wrap completion output in JSON, even when
--output jsonis set - still reports invalid shells and unsupported scopes as JSON error envelopes
on stderr when
--output jsonis set
- logs are written to stderr when enabled
Script-safe output patterns:
- Structured automation:
nodeup --output json <command> - Runtime identifier loops:
nodeup toolchain list --quiet - Completion redirection:
nodeup completions <shell> >file - Human output without logs: set
RUST_LOG=off, then runnodeup <command> - Explicit tracing: set
RUST_LOG=nodeup=debugor another tracing filter; logs stay on stderr
Human output color control:
- Global color mode for human output:
--color auto|always|never(default:auto) - Environment override for human output:
NODEUP_COLOR=auto|always|never - Precedence:
--color>NODEUP_COLOR>NO_COLOR>auto autoenables ANSI styles per stream only when the stream is a terminalnodeup show colorreports effective human stdout, human stderr, and log color decisions, includingNO_COLORconflicts- Invalid
NODEUP_COLORvalues are ignored, warned about in human mode, and reported bynodeup show color --output jsonnever injects ANSI styles into JSON payloadscompletionsoutput remains raw shell script text even when--color alwaysis set
Log color control:
NODEUP_LOG_COLOR=always|auto|never(defaultalways)NO_COLORdisables color whenNODEUP_LOG_COLORis unset orauto- Invalid
NODEUP_LOG_COLORvalues are ignored, warned about in human mode, and reported bynodeup show color
Mirror overrides:
NODEUP_INDEX_URL=https://mirror.example/download/release/index.json
NODEUP_DOWNLOAD_BASE_URL=https://mirror.example/download/release
Checksum mismatch errors include sanitized mirror diagnostics when a mirror override is configured. Credentials, query strings, and fragments are stripped from reported URLs.
Completions
nodeup completions generates shell completion scripts for:
bashzshfishpowershellelvish
Scope filtering:
nodeup completions <shell>generates completions for all top-level commands.nodeup completions <shell> <command>generates a script scoped to one top-level command:toolchain,default,show,update,check,override,which,run,shim,self,completions
- Nested subcommand scopes such as
toolchain installare not supported. They fail withinvalid-inputand suggest the nearest valid top-level scope, such asnodeup completions bash toolchain. - With
--output json, invalid shell and unsupported scope failures are written as JSON error envelopes on stderr. Successful completion scripts remain raw text on stdout. - Completion generation defaults Nodeup logging off so redirection examples stay script-safe without
RUST_LOG=off. ExplicitRUST_LOGfilters still enable tracing on stderr.
Testing Strategy
nodeup validation combines unit tests and end-to-end CLI integration tests.
- Unit tests cover selectors, resolver, release index cache behavior, logging mode selection, and installer helpers.
- CLI integration tests cover command contracts, JSON error envelopes, selector precedence, override lifecycle, update/check branches, self-management commands, alias dispatch (
node,npm,npx,yarn,pnpm), andpackageManager-aware execution planning. nodeup updatetreats exact-version selectors as immutable pins, reportsskipped-exact-version, and canonicalizes tracked exact selectors such as22.1.0andv22.1.0to onev<semver>entry. To move from one exact runtime to another, install or select the newer exact version withnodeup toolchain install <version>,nodeup default <version>, ornodeup override set <version> --path <path>.- Multi-selector
toolchain installand explicitupdateinvocations preflight all selectors before channel resolution, runtime download, extraction, tracking, or install mutation.
Run locally from repository root:
cargo fmt --all
cargo test -p nodeup
cargo test
Troubleshooting
- Runtime not installed:
- use
nodeup toolchain install <runtime>ornodeup run --install <runtime> ...
- use
- No selector resolved:
- set one with
nodeup default <runtime>ornodeup override set <runtime>
- set one with
- Linked runtime failures:
- verify
<path>/bin/nodeexists and is executable beforetoolchain link - use
nodeup toolchain unlink <name>to remove a stale linked runtime record
- verify
- JSON parsing issues in automation:
- use
--output jsonand keepRUST_LOGunset (oroff) to keep stdout JSON-only - use
nodeup toolchain list --quietfor newline-delimited runtime identifiers andnodeup completions <shell> >filefor raw completion scripts; both default Nodeup logging off
- use
- Error troubleshooting:
- follow the
Hint:action in the error message first, then rerun withRUST_LOG=nodeup=debugwhen deeper diagnostics are needed
- follow the
Documentation Links
- Project index:
docs/project-nodeup.md - Runtime contract:
docs/crates-nodeup-foundation.md - Dedicated docs app:
apps/nodeup-docs(https://nodeup.delino.io)
Dependencies
~18–31MB
~518K SLoC