All five channels below are wired up and tested. The GoReleaser config
that produces the binary archives lives in .goreleaser.yaml; the
Homebrew tap cask and Scoop bucket manifest are pushed
automatically on every v*.*.* tag (see .github/workflows/release.yml).
| OS | Architectures | Notes |
|---|---|---|
| macOS | arm64, amd64 | Universal binary if needed |
| Linux | arm64, amd64 | Most distros; glibc-based |
| Windows | amd64 | nvm-windows supported |
Each channel is a deliberate trade between convenience, how
strongly you trust the package manager you already use, and how
much you want nodeup coupled to anything else on your system. Use
the table below to pick — the per-channel sections below it show
exactly what to run.
| Channel | One-line install | Auto-updates? | Lives in… | Best for… | Avoid if… |
|---|---|---|---|---|---|
| Homebrew | brew install dipto0321/tap/nodeup |
Yes — brew upgrade |
/opt/homebrew/bin/ (macOS) or /home/linuxbrew/.linuxbrew/bin/ (Linux) |
macOS / Linux devs already using Homebrew for tooling | You don't have Homebrew and don't want to set it up just for one tool |
| Scoop | scoop install nodeup (after adding the bucket) |
Yes — scoop update |
%USERPROFILE%\scoop\apps\nodeup\ |
Windows devs already using Scoop | You prefer winget / Chocolatey — neither is wired up today |
| npm wrapper | npm install -g nodeupx |
Semi — npm update -g nodeupx only when a wrapper version bumps |
Inside a Node install, on your global node_modules/ path |
JS devs who already treat npm i -g as the source of truth for CLIs; locked-down machines that block system installers but allow npm globals |
You want a CLI that lives completely outside any Node install, or you want to track Go-binary releases the moment they tag (the wrapper lags by one publish). Note: the package is nodeupx, not nodeup — nodeup is taken on npmjs.com. |
| Direct binary | curl … | tar xz |
No — you re-run to update | Wherever you put the extracted binary | CI pipelines, reproducible installs, lock-down environments without npm or brew | You want auto-updates; you'll forget to re-run |
| From source | go install ./cmd/nodeup@latest |
No — re-run against a new tag | $GOBIN or $GOPATH/bin |
nodeup contributors and Go developers who want HEAD |
Anyone who doesn't have Go installed and isn't trying to hack on the tool |
brew install dipto0321/tap/nodeupWho this is for: developers on macOS or Linux who already use
Homebrew for dev tooling (brew is the package manager for
command-line apps, distinct from the App Store). The tap
dipto0321/homebrew-tap
holds the cask and is auto-pushed by GoReleaser on every
v*.*.* tag.
Upgrading from the old formula:
nodeupshipped as a Homebrew formula up to v1.2.1 and switched to a cask in v1.2.2. The command is unchanged (brew install dipto0321/tap/nodeupstill works), but Homebrew treats a formula and a cask as different packages. The tap carries atap_migrations.json, sobrew updateperforms the hand-off for you: it unlinks the old keg, installs the cask, and tells you to runbrew uninstall --formula --force nodeupto clean up the old keg. If you'd rather do it by hand:brew uninstall --formula --force nodeup brew install dipto0321/tap/nodeup
Tradeoffs: upgrades happen via brew upgrade, which all Homebrew
users already run on a schedule. The install lives in Homebrew's
prefix (typically /opt/homebrew/bin on Apple Silicon), completely
independent of any Node install — safe for nvm/fnm/Volta users
who don't want a Node coupling.
scoop bucket add dipto0321 https://github.com/dipto0321/scoop-bucket
scoop install nodeupWho this is for: Windows developers already using Scoop as their
package manager. The bucket
dipto0321/scoop-bucket
holds the manifest and is auto-pushed by GoReleaser.
Tradeoffs: user-level install (no admin shell), upgrades via
scoop update nodeup. Same Node-decoupled shape as Homebrew.
npm install -g nodeupxThe package is published as nodeupx, not nodeup, because
the bare nodeup name on npmjs.com is owned by an unrelated,
dormant 2015 package (romanmt/nodeup — "a simple cluster
implementation for node"). The downloaded binary still installs as
the nodeup CLI on your $PATH.
Who this is for: developers who already treat npm install -g as
the canonical way to install CLIs. Common in JavaScript-heavy
projects where the team's onboarding script already runs npm i -g <tool1> <tool2> …. Also a good fit when system package installs are
blocked but npm globals are allowed.
Tradeoffs:
- Slight version lag. The wrapper pins to the Go-binary version
in its
binaryVersionfield. A new Go release needs a new wrapper publish —npm update -g nodeupxonly gets you a new Go binary after the wrapper version that pins to it ships. To jump to a brand-new release ahead of that, use a direct-binary install. - Coupled to a Node install. The wrapper and binary live inside
a Node install (the one you ran
npm i -gagainst). Fornvm/fnm/Voltausers this means re-installing the wrapper after every Node bump — exactly whatnodeupis supposed to remove. For those users, prefer Homebrew / Scoop / direct-binary. - No Node runtime needed at runtime. The wrapper's
postinstallscript downloads a static Go binary; thenoderuntime is used only during install (for the script itself) and is never invoked bynodeuponce installed.
See nodeup-npm/README.md for the full
install / update / uninstall flow.
Best for CI, locked-down environments, and anyone who wants zero install ceremony. Grab the archive for your OS/arch from the Releases page:
# macOS Apple Silicon
curl -L https://github.com/dipto0321/nodeup/releases/latest/download/nodeup_$(curl -s https://api.github.com/repos/dipto0321/nodeup/releases/latest | grep tag_name | cut -d'"' -f4 | tr -d v)_darwin_arm64.tar.gz | tar xz
sudo mv nodeup /usr/local/bin/
# Linux x86_64
curl -L https://github.com/dipto0321/nodeup/releases/latest/download/nodeup_*_linux_amd64.tar.gz | tar xz
sudo mv nodeup /usr/local/bin/
# Windows (PowerShell)
curl -L https://github.com/dipto0321/nodeup/releases/latest/download/nodeup_$(curl -s https://api.github.com/repos/dipto0321/nodeup/releases/latest | grep tag_name | cut -d'"' -f4 | tr -d v)_windows_amd64.zip -OutFile nodeup.zip
Expand-Archive nodeup.zip -DestinationPath .
# Move nodeup.exe somewhere on $PATHWho this is for: anyone who wants a deterministic install — no
package manager metadata, no postinstall hook, no auto-update. Pin
the URL to a specific tag (not latest) to make the install
reproducible across CI runs.
Tradeoffs: you own the upgrade lifecycle. Re-run the command (or script it) when you want a new version. The binary is fully self-contained — no runtime, no Node, no manager.
On macOS: if you downloaded the archive through a browser, the
extracted binary can carry the Gatekeeper quarantine attribute and
macOS will refuse to run it. Strip it with
xattr -dr com.apple.quarantine nodeup after extracting. See
macOS Gatekeeper
for the full story.
go install github.com/dipto0321/nodeup/cmd/nodeup@latestRequires Go 1.24+ (matches go.mod and the CI pin in .github/workflows/ci.yml + release.yml).
Who this is for: nodeup contributors and Go developers who want
to track main between tagged releases. The binary lands in
$GOBIN (or $GOPATH/bin), which Go is configured to put on
$PATH for you.
Tradeoffs: the slowest to upgrade (you recompile), but the closest to the bleeding edge. Not appropriate for end users — they should pick one of the channels above.
nodeup versionShould print a version, git commit, build date, and Go runtime info.
macOS marks files that came from the internet with an extended
attribute called com.apple.quarantine. Gatekeeper then refuses to
execute an unsigned binary that still carries that attribute —
the kernel kills the process before main() ever runs, so the
command dies with no output at all:
ASP: Security policy would not allow process: 82275, /opt/homebrew/Cellar/nodeup/1.2.1/bin/nodeup
nodeup ships as an unsigned Go binary (no Apple Developer ID
certificate), so this used to hit anyone who installed it through a
channel that let the attribute survive. As of v1.2.2 every
channel strips the attribute as part of the install:
| Channel | How the attribute is removed |
|---|---|
| Homebrew | The cask's postflight_steps hook runs xattr -dr com.apple.quarantine on the staged path after install. |
| npm wrapper | nodeup-npm/scripts/install.js strips the attribute from the extracted binary before it is moved into place. |
| Scoop | Windows only — the attribute does not exist. |
| From source | go install compiles locally — nothing is downloaded, so nothing is quarantined. |
If nodeup dies silently with no output, macOS is blocking it. Strip
the attribute by hand:
xattr -dr com.apple.quarantine "$(command -v nodeup)"If that reports Permission denied, the file is not writable — make
it writable first, then restore the mode:
BIN="$(command -v nodeup)"
chmod u+w "$BIN" && xattr -d com.apple.quarantine "$BIN" && chmod 555 "$BIN"Reinstalling through Homebrew or npm also fixes it, because both channels strip the attribute as part of the install.
Note:
tarandzipextraction both propagate the quarantine attribute to the files they unpack, so a browser-downloaded archive can leave the extracted binary quarantined too. That is why the direct-binary section above is followed by thexattrone-liner whenever the download came through a browser.
You can install via multiple channels at once if you want — they'll
write to different paths and the first one on $PATH wins. To
avoid the version-skew that causes, pick one and use it for upgrades
and uninstalls consistently:
- Homebrew owns upgrades → use
brew upgrade nodeup. - Scoop owns upgrades → use
scoop update nodeup. - npm owns upgrades → use
npm update -g nodeupx. - Direct binary owns upgrades → re-run the curl one-liner (or pin a specific tag in CI).
- From source owns upgrades →
go install -u github.com/dipto0321/nodeup/cmd/nodeup@latest.