GitHub - nubjs/nub: The fast all-in-one Node.js toolkit

A fast all-in-one toolkit that augments Node.js instead of replacing it

A Bun-like DX on top of stock `node`, written in Rust.
nub index.ts # TypeScript-first Node.js runtime nub run dev # 24ร faster pnpm run nubx prisma generate # 19ร faster npx nub install # 2.5ร faster pnpm install nub watch src/server.ts # native watch mode nub pm shim # built-in Corepack-style shims nub node install 26 # Node version manager nub upgrade # self update
One tool to run your files and scripts, install dependencies, and manage Node itself. No new runtime, no vendor-specific API surface, no lock-in.
| Nub | Instead of | | --- | --- | | `nub <file>` | `node`, `tsx`, `ts-node`, `dotenv-cli` | | `nub run <script>` | `npm run`, `pnpm run` | | `nubx` | `npx`, `pnpm dlx / exec` | | `nub install` | `npm`, `pnpm` | | `nub watch` | `nodemon`, `node --watch`, `tsx watch` | | `nub node` | `nvm`, `fnm`, `n`, `volta` | | `nub pm` | `corepack` |
Install
[](https://github.com/nubjs/nub#install)
macOS / Linux
curl -fsSL https://nubjs.com/install.sh | bash
Windows (PowerShell)
irm https://nubjs.com/install.ps1 | iex
Homebrew (macOS / Linux)
brew install nubjs/tap/nub
Nix (flakes)
nix run github:nubjs/nub
mise
mise use -g nub
Or via npm (pnpm / yarn global add work too)
npm install -g --ignore-scripts=false @nubjs/nub
For GitHub Actions, use `nubjs/setup-nub` in place of `actions/setup-node`. It's one-to-one compatible.
- - uses: actions/setup-node@v4
+ - uses: nubjs/setup-nub@v0
File runner โ `nub <file>`
[](https://github.com/nubjs/nub#file-runner--nub-file) Run a file. Supports `.js`, `.ts`, `.mjs`, `.cjs`, `.mts`, `.cts`, `.jsx`, and `.tsx`. Flag-for-flag and var-for-var drop-in compatible with `node` (mostly via passthrough).
nub index.ts # TypeScript, JSX, no build step nub --watch app.ts # same path, restart-on-change
It augments stock Node with some of Bun/Deno's best features:
- ๐ฆ Full TypeScript support, including `enum`, `namespace`
- ๐งญ TypeScript-friendly resolution: extensionless imports, `tsconfig.json#paths`
- โ๏ธ JSX / TSX
- ๐ Decorators and `emitDecoratorMetadata`
- ๐ Modern syntax like `using` (downleveled in transpiler when needed)
- ๐ Automatic `.env*` loading โ Next.js/Vite parity
- ๐๏ธ Built-in loaders for common data formats โ `.yaml`, `.toml`, `.jsonc`, `.json5`, `.txt`
- ๐ Polyfills for `Temporal`, `Worker`, `URLPattern` (when needed)
- ๐ฅ Unflags experimental features like`node:sqlite`, `vm.Module`, `localStorage`, `WebSocket`, `EventSource`
- โก 2.9ร faster startup than `tsx`
> **How it works** โNub takes advantage of Node extension surfaces that mostly didn't exist when Deno and Bun were built: > > > * `--import`/`--require` preloads > * `module.registerHooks()` for transpilation and resolution > * N-API native addons: Nub embeds oxc for pre-transpilation
Node provisioning
[](https://github.com/nubjs/nub#node-provisioning) When you run a file with nub, it infers the version of Node your project expects and auto-installs it if needed. It respects (in precedence order):
- `NODE_EXECUTABLE` (override)
- `package.json#devEngines`
- `.node-version`
- `.nvmrc`
- `package.json#engines`
This resolved version of Node is installed and your file is executed with it (with Nub's augmentations).
$ echo 26 > .node-version $ nub hello.ts Using Node.js 26.3.0 (resolved from .node-version) Installed in 9.8s Hello world!
Modern APIs
[](https://github.com/nubjs/nub#modern-apis) Modern API work out of the box under Nub. Node.js experimental APIs are unflagged, others are auto-polyfilled (e.g. `Temporal` on Node 25 and earlier), and others are downleveled in the transpiler (`using`).
| API | How | | --- | --- | | `Temporal` | polyfilled below Node 26, native above | | `URLPattern` | polyfilled below Node 24, native above | | `RegExp.escape` | polyfilled below Node 24, native above | | `Error.isError` | polyfilled below Node 24, native above | | `Promise.try` | polyfilled below Node 24, native above | | `Float16Array` | polyfilled below Node 24, native above | | `navigator.locks` | polyfilled below Node 24.5, native above | | `reportError` | polyfilled | | `vm.Module` | unflagged | | `ShadowRealm` | unflagged | | `Wasm module imports` | unflagged below Node 24.5 (22.19 on the 22.x line), native above | | `WebSocket` | unflagged from Node 20.10, native from Node 22 | | `EventSource` | unflagged from Node 20.18, native above | | `node:sqlite` | unflagged from Node 22.5, native from Node 22.13 | | `addon imports` | unflagged from Node 22.20, never native |
Watch mode
[](https://github.com/nubjs/nub#watch-mode) Restart-on-change driven by the resolved dependency graph plus the off-graph files that still invalidate a run โ no glob list to maintain:
nub watch src/server.ts nub --watch src/server.ts # same path
- ๐ Tracks the resolved dependency graph automatically
- ๐งท Also watches the off-graph invalidators โ `.env*`, the `tsconfig.json` extends chain, `package.json`
- โ๏ธ Runs on Node's own `--watch` engine, preserving output by default
View the full runtime docs ๐.
Script runner โ `nub run`
[](https://github.com/nubjs/nub#script-runner--nub-run) A drop-in for `npm run` and `pnpm run`. The runner is a Rust binary with no JavaScript startup of its own, so it dispatches a warm script roughly 24ร faster than `pnpm run`:
nub run build nub run -r --filter "@org/*" test # supports --filter
It's fast compared to existing JavaScript-based script runners.
| Command | Time | Relative | | --- | --- | --- | | `nub run` | 14.7 ms | โ | | `npm run` | 329.9 ms | 22ร | | `pnpm run` | 442.7 ms | 30ร |
> script dispatch ยท warm ยท 50 runs ยท macOS โ view benchmark
- ๐ Feels instantaneous โ 14ms vs a detectable 300ms+ lag for npm/pnpm
- ๐ Full lifecycle support โ `pre`/`post` hooks and the complete `npm_*` environment
- ๐งฐ Local `node_modules/.bin` on `PATH`, with args forwarded without the `--` separator
- ๐๏ธ The full pnpm workspace surface โ `-r`, `--filter`, `--parallel`, `--workspace-concurrency`, `--resume-from`, `--stream`
- ๐ฏ pnpm's `--filter` grammar verbatim โ graph (`...@org/web`) and changed-since (`[main]`) selectors
View the full script runner docs ๐.
Package runner โ `nubx` / `nub dlx`
[](https://github.com/nubjs/nub#package-runner--nubx--nub-dlx) A drop-in for `npx` and `pnpm dlx`. Local-first with a download-and-execute registry fallback (same as `npx`). Eliminating the double-Node.js-spawn performance penalty paid by JavaScript-based tools like `npx` and `pnpm`.
nubx eslint . --fix nubx -y cowsay@1.5.0 "hi" # fetched from the registry (auto-approved via -y)
| Command | Time | Relative | | --- | --- | --- | | `nubx esbuild --version` | 11 ms | โ | | `pnpm exec esbuild --version` | 191 ms | 17ร | | `npx esbuild --version` | 226 ms | 19ร |
> esbuild --version ยท macOS โ view benchmark
- โก Runs a local bin ~19ร faster than `npx`, with no Node in the wrapper
- ๐ Resolves `node_modules/.bin` regardless of which package manager installed it
- ๐ Registry fallback for uninstalled bins โ fetched, run, then discarded
- ๐งฉ Full `pnpm exec` / `pnpm dlx` flag parity, shell mode included
- ๐ช Walks the resolution chain โ member `.bin`, then workspace root, then ancestors
View the full package runner docs ๐.
Package manager โ `nub install`
[](https://github.com/nubjs/nub#package-manager--nub-install) Nub is a package manager powered by the Aube engine. The CLI is flag-for-flag compatible with `pnpm` for muscle memory, but
nub install nub ci nub add -E -D --save-catalog react nub remove lodash nub update nub dedupe
It's fast โ avoids the per-command Node.js bootstrap lag incurred by JS-based package managers.
| Tool | Time | Relative | | --- | --- | --- | | `nub` | 1122 ms | โ | | `bun` | 1444 ms | 29% slower | | `pnpm` | 2847 ms | 2.5ร | | `npm` | 4163 ms | 3.7ร |
> warm frozen install ยท create-t3-app ยท 222 deps ยท macOS โ view benchmark
Security
[](https://github.com/nubjs/nub#security)
- ๐ก๏ธ Blocks postinstall by default
- ๐ฆ Checks osv.dev for known-malicious package versions during resolution by default
- ๐ป Refuses provenance downgrades by default
- โณ 24-hour `minimumReleaseAge` by default
Compatibility
[](https://github.com/nubjs/nub#compatibility)
When you run `nub install` inside a project, it detects the _incumbent_ package manager (based on your `package.json#packageManager` or any detected lockfiles). It then runs in **compat-mode**, respecting the config files and environment variables for that package manager.
Under each incumbent, Nub reads that tool's branded config and no other's; the neutral `.npmrc` cascade and `npm_config_*` are read under every one.
| Incumbent | Config it reads | | --- | --- | | **npm** | `package-lock.json`, `.npmrc`, `overrides`, `workspaces`, `engines`/`os`/`cpu`/`libc` | | **pnpm** | `pnpm-lock.yaml`, `pnpm-workspace.yaml`, `.pnpmfile.cjs`, `package.json#pnpm`, `resolutions`, `catalog:`, `.npmrc` | | **Yarn** (read-only) | `yarn.lock`, a `.yarnrc.yml` / `.yarnrc` subset, `YARN_*`, `resolutions`, `packageExtensions`, `.npmrc` | | **Bun** | `bun.lock`, `bunfig.toml``[install]`, `trustedDependencies`, `overrides`, `patchedDependencies`, `catalog:`, `.npmrc` | | **Nub** | neutral only โ `.npmrc`, `npm_config_*`, `overrides` / `resolutions` / `catalog` / `workspaces` |
View the full package manager docs ๐.
Package meta-manager โ `nub pm`
[](https://github.com/nubjs/nub#package-meta-manager--nub-pm) Corepack's job, in native Rust: provision and run the exact pnpm / npm / yarn your project pins:
nub pm shim # registers global shims (Corepack-style)
Like `corepack enable`, this registers global shims for `npm`, `yarn`, and `pnpm`. When you run a command using one of these shim aliases anywhere on your file system, the shim will:
- Detect the version used in your project
- Install that version if needed
- Run the command using the proper version
Nub provides this functionality as a convenience for users who prefer to keep their current package manager. Corepack itself was unbundled from Node itself in v25.
View the full `nub pm` docs ๐.
Node version manager โ `nub node`
[](https://github.com/nubjs/nub#node-version-manager--nub-node) Though Node.js versions will generally be auto-installed and cached as needed, you can manage versions manually as well.
$ nub node -h nub node โ manage Node versions
Usage: nub node <command>
Commands: which print the resolved Node binary path (why โ stderr) install [<version>...] provision version(s) into nub's cache ls list versions in nub's cache uninstall <version> remove a version from nub's cache pin <version> write the project's Node pin
View the full `nub node` docs ๐.
License
[](https://github.com/nubjs/nub#license) MIT
> _โญ๏ธ If you read this far, consider starring the repo :) โญ๏ธ_