Skip to content

Instantly share code, notes, and snippets.

@jonasvanderhaegen
Created June 28, 2026 13:12
Show Gist options
  • Select an option

  • Save jonasvanderhaegen/09fa5992e1c12ea01fbf32eba5e39206 to your computer and use it in GitHub Desktop.

Select an option

Save jonasvanderhaegen/09fa5992e1c12ea01fbf32eba5e39206 to your computer and use it in GitHub Desktop.
Migrating from pnpm (Corepack) to Nub on macOS — uninstall, optimize, and the Laravel Herd nvm question

Migrating from pnpm (Corepack) to Nub on macOS

Notes from replacing pnpm with Nub — the all-in-one Node.js toolkit (runtime + package manager + Node version manager) — on an Apple Silicon Mac running Laravel Herd. Written June 2026, Nub v0.2.7.

TL;DR

  • pnpm installed via Corepack is not an npm/Homebrew package — you "uninstall" it with corepack disable pnpm, then delete its store at ~/Library/pnpm.
  • Install Nub outside any version-managed Node (Homebrew/curl), or it ends up trapped inside a Node it's supposed to manage.
  • Nub can fully replace nvm, but Laravel Herd's bundled nvm can't be cleanly uninstalled as a separate component — Herd owns it. You can only make it dormant.

1. Uninstall pnpm + clear its cache

Check how pnpm got onto your machine first:

ls -la "$(which pnpm)"
# -> .../node/vX/bin/pnpm -> ../lib/node_modules/corepack/dist/pnpm.js

If that symlink points into corepack/dist/pnpm.js, pnpm is a Corepack shim, not a real install. There is no npm/brew package to remove. Disable the shim and clear the content-addressed store:

corepack disable pnpm          # removes the pnpm shim from PATH
rm -rf ~/Library/pnpm          # store (v10/v11), global, bin — often >1 GB

Corepack itself stays, so corepack enable pnpm brings pnpm back if you ever need it.

2. Install Nub

Nub's CLI is flag-for-flag compatible with pnpm and reads/writes native lockfiles (npm/pnpm/Bun round-trip; Yarn read-only), so existing projects keep working — just run nub install.

# Homebrew (recommended on macOS — installs outside any managed Node)
brew install nubjs/tap/nub

# or curl
curl -fsSL https://nubjs.com/install.sh | bash

Avoid npm install -g @nubjs/nub if that npm belongs to a version-managed Node (nvm/Herd/Volta). The nub launcher then execs a native binary that lives inside that Node's node_modules, so deleting the Node deletes Nub. Homebrew/curl avoid this trap.

3. Optimize Nub globally (macOS / Apple Silicon)

Most of "optimize as much as possible" is already handled by defaults on modern hardware:

Factor Optimum Why
Node ≥ 22.15 / 23.5 / 24.0 Fast Tier sync module.registerHooks(), ~2.9× faster startup than tsx
APFS / btrfs filesystem reflink materialization copy-on-write links from store into node_modules, near-zero extra disk
Store on same volume as projects reflink instead of copy reflink only works within one volume

The few knobs worth touching:

  • NUB_CACHE_DIR — global content store (default $XDG_DATA_HOME/nub/store/v1, i.e. ~/.local/share/nub/store/v1). Only change it to keep the store on the same volume as your code if your projects live on a secondary/external disk; otherwise Nub silently falls back to byte-copy.
  • NUB_CONCURRENCY — parallel network/install ops. Auto-tuned; only raise on a fast, unmetered connection (registry rate-limiting can make higher slower).
  • nub install --prefer-offline — skip network revalidation when the store already has everything. Handy as a daily alias:
    alias ni='nub install --prefer-offline'
  • Leave the security defaults on. paranoid (OS build jail), minimumReleaseAge (24h package cooling window), and advisoryCheck (OSV) trade a little speed for real safety — don't disable them to "optimize."
  • Don't set NODE_COMPAT or NODE_EXECUTABLE globally — they're debugging/override escape hatches that disable Nub's augmentation or pin a specific binary.

4. Can Nub replace Laravel Herd's bundled nvm?

Functionally yes — Nub has a built-in Node version manager:

nub node install 24      # provision into Nub's cache
nub node pin <version>   # write the project pin
nub node which           # resolved binary path
nub node ls / uninstall

It auto-provisions Node when running files, honoring (in priority): NODE_EXECUTABLEpackage.json#devEngines.node-version.nvmrcpackage.json#engines.

But you cannot cleanly "uninstall Herd's nvm" as a standalone thing:

  1. Herd owns it. The nvm lives inside Herd's app config (~/Library/Application Support/Herd/config/nvm). Herd's GUI manages versions there and auto-installs the latest by default. There's no supported "remove just the nvm" action, and Herd may re-provision Node.
  2. Shell injection is separate. Herd writes this into ~/.zshrc:
    export NVM_DIR="$HOME/Library/Application Support/Herd/config/nvm"
    [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
    Nub won't be your Node manager until those lines are removed and Nub's shim wins PATH ordering.

Making Herd's nvm dormant (the realistic end state)

  1. Install Nub via Homebrew/curl so it no longer depends on Herd's Node (see §2).
  2. Hand Node to Nub: nub node install 24, verify with nub node which.
  3. Remove the NVM_DIR export + nvm.sh source from ~/.zshrc (keep Herd's PHP lines — that's Herd's actual job). Unset NVM_DIR.
  4. Optional: delete ~/Library/Application Support/Herd/config/nvm/versions/* to reclaim disk. Herd may re-download unless you disable its Node feature in settings.

Herd stays your PHP/nginx environment; its Node subsystem just goes unused and off your PATH. That's the realistic outcome — dormant, not surgically removed.

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment