Notes collected while migrating a pnpm monorepo (Astro + Nuxt 4 workspace) to nub as the package manager. Recording these for future reference and upstream bug reports.
- nub
v0.2.7(homebrew,/opt/homebrew/bin/nub) - node
v26.4.0 - macOS Darwin
25.5.0arm64 - Repo: pnpm workspace (
pnpm-workspace.yamlwithcatalog:usingnpm:aliases,overrides,peerDependencyRules,allowBuilds,patchedDependencies,.pnpmfile.cjs)
nub exec <bin> never returns and prints nothing, even with stdin redirected from /dev/null.
nub exec eslint --version < /dev/null # hangs indefinitely, zero output
nub exec -F skylence-landing astro --version # sameControls that prove it is nub exec specifically:
./node_modules/.bin/eslint --version # => v9.39.4 (instant)
nub exec --help # prints help fine
nub run free-ports # nub run executes scripts fine
nub install / nub install --frozen-lockfile # both succeedLeft two nub exec eslint --version processes running for minutes with no output and no exit; had to kill them. nub --verbose exec ... also produced no output before being killed.
Impact: breaks anything built on nub exec:
- CI:
nub exec -F skylence-landing playwright install chromium --with-deps - Playwright
webServer.command:nub exec astro preview
Workaround being considered: call bins through package scripts via nub run instead of nub exec.
nub run -F skylence-landing
# => prints the ROOT package.json scripts, not skylence-landing'sExpected: list the filtered package's scripts (or error). Minor, but misleading when exploring a workspace.
nub pm use --help
# Error: unsupported package manager "--help", nub pm use takes npm, pnpm, yarn, bun, or nub--help is parsed as the positional PM argument. Have to use nub help pm. Minor UX.
nub pm use nub reported every file it touched (great):
package.json: packageManager = nub@0.2.7
package.json: devEngines.packageManager = {...}
package.json: workspaces (packages + catalogs) migrated from pnpm-workspace.yaml
package.json: top-level overrides migrated
package.json: top-level patchedDependencies migrated
package.json: top-level allowBuilds migrated
package.json: pnpm namespace removed (unread under nub identity)
lock.yaml: renamed from pnpm-lock.yaml (bytes unchanged, still pnpm-v9 format)
pnpm-workspace.yaml: deleted
.npmrc: + peer-dependency-rules=...
.npmrc: + shell-emulator=true
.npmrc: + trust-policy=no-downgrade
...but it never mentions .pnpmfile.cjs, which is NOT read under nub identity. Its readPackage hook silently becomes dead code. In our case it was only dropping a few optional peer deps of prettier-plugin-tailwindcss, and removing the file caused no peer fallout, but nub gives no warning that .pnpmfile.cjs is now ignored. A "this file is no longer read" note would help.
pnpm-lock.yaml becomes lock.yaml, content unchanged (lockfileVersion: '9.0'). Round-trips cleanly. Worth knowing for tooling that sniffs lockfile names. nub itself warns about this:
turbo requires a recognized packageManager + lockfile name and will error hosted update bots (Renovate/Dependabot) can't regenerate lock.yaml yet lockfile-sniffing deploy platforms won't auto-detect a PM, run installs with nub in CI
nub's own heads-up after nub pm use nub:
- corepack-enabled shells hard-error on
packageManager: "nub@...", fix:npm i -g @nubjs/nuborcorepack disable - real pnpm refuses to run here (
ERR_PNPM_OTHER_PM_EXPECTED), reverse withnub pm use pnpm
nub installandnub install --frozen-lockfile(CI parity) both succeeded, resolved every workspace package, kept the pnpm-v9 lockfile.nub run <script>andnub run -F <pkg> <script>execute correctly.nub pm use nubmigration of workspaces/catalog/overrides/patchedDependencies/allowBuilds intopackage.json+.npmrcwas accurate.- pnpm
catalog:withnpm:aliases (npm:@voidzero-dev/vite-plus-core@latest) carried over verbatim.
Exit codes captured as ${PIPESTATUS[0]} were always blank here because the shell is zsh (1-indexed $pipestatus), not a nub problem.