Nub: A Rust-Powered Node.js Toolkit That Replaces npm, npx, and nvm
The fast all-in-one Node.js toolkit. Script runner, nub run A drop-in for npm run and pnpm run.
At a glance
- What is it?
- Nub is an all-in-one Node.js toolkit written in Rust that runs TypeScript files, dispatches scripts, installs dependencies, and manages Node versions. It aims to be a drop-in replacement for npm, pnpm, npx, nvm, and tsx, with performance claims that are worth verifying.
- Who is it for?
- Adopt Nub if you manage multiple Node projects and want a single tool for running files, scripts, installs, and Node versions, especially if you value TypeScript support without a build step and automatic Node provisioning. Do not adopt it if you need a stable, production-hardened runtime with a mature ecosystem, since Nub is in canary releases and relies on Node's experimental extension surfaces.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 14, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The Problem Nub Solves: Toolchain Fragmentation
Node.js developers juggle multiple tools: node or tsx to run TypeScript, npm run or pnpm run to dispatch scripts, npx to execute packages, nvm or fnm to manage Node versions, nodemon for watch mode, and corepack for package manager shims. Each tool has its own configuration, startup overhead, and quirks. Nub collapses this into a single binary. The README positions it as 'a Bun-like DX on top of stock node, written in Rust.' That means you get a unified command surface: nub <file>, nub run, nubx, nub install, nub watch, nub node, and nub pm. The target audience is developers who want the convenience of Bun or Deno but are unwilling to abandon the Node ecosystem or adopt a new runtime. Nub is not a runtime; it augments stock Node with preloads, transpilation, and polyfills. This is a meaningful distinction: you keep compatibility with existing Node packages and APIs, but you gain a faster, more ergonomic front end.
How Nub Works: Node Extension Surfaces and Rust Core
Nub's mechanism is visible in the README's 'How it works' section. It relies on Node extension surfaces that were not available when Deno and Bun were built. Specifically, it uses --import and --require preloads to inject its behavior, module.registerHooks() to intercept transpilation and resolution, and N-API native addons to embed the oxc transpiler for pre-transpilation. This means Nub does not fork Node or create a new runtime; it wraps it. When you run nub index.ts, Nub resolves the Node version your project expects, based on NODE_EXECUTABLE, package.json#devEngines, .node-version, .nvmrc, or package.json#engines, in that precedence order. If the required Node version is not installed, Nub installs it automatically. Then it runs your file with that Node binary, using its preloads to handle TypeScript, JSX, decorators, and other modern syntax. The Rust core handles command dispatch and startup, which is why nub run can claim a 24x speedup over pnpm run: the Rust binary has no JavaScript startup of its own. This architecture is clever, but it also means Nub is only as stable as Node's experimental hooks.
Getting Started: Installation and Commands
You can install Nub via a curl script for macOS and Linux, a PowerShell script for Windows, Homebrew, Nix flakes, mise, or npm. The README gives concrete commands: curl -fsSL https://nubjs.com/install.sh | bash, irm https://nubjs.com/install.ps1 | iex, brew install nubjs/tap/nub, nix run github:nubjs/nub, mise use -g nub, or npm install -g @nubjs/nub. For GitHub Actions, you replace actions/setup-node with nubjs/setup-nub. The core commands are straightforward: nub index.ts runs a TypeScript file, nub run dev dispatches a package.json script, nubx prisma generate runs a package like npx, nub install installs dependencies, nub watch src/server.ts watches and restarts, nub pm shim creates Corepack-style shims, and nub node install 26 installs a specific Node version. The README claims nubx is 19x faster than npx and nub install is 18x faster than pnpm install. These are bold claims, and you should verify them on your own hardware before relying on them.
File Runner Capabilities and Modern API Support
The nub <file> command supports .js, .ts, .mjs, .cjs, .mts, .cts, .jsx, and .tsx. It is described as 'flag-for-flag and var-for-var drop-in compatible with node (mostly via passthrough).' That 'mostly' is an honest caveat; not every Node flag is guaranteed to pass through. Nub augments stock Node with TypeScript support including enum and namespace, extensionless imports, tsconfig.json#paths resolution, JSX, decorators, and emitDecoratorMetadata. It also automatically loads .env* files, matching Next.js and Vite behavior. Built-in loaders handle .yaml, .toml, .jsonc, .json5, and .txt. The README claims 2.9x faster startup than tsx. Modern APIs are handled in three ways: polyfilled below certain Node versions, unflagged when experimental, or downleveled in the transpiler. For example, Temporal is polyfilled below Node 26, URLPattern below Node 24, and node:sqlite is unflagged from Node 22.5. This is a pragmatic approach, but it creates a matrix of behavior that varies by Node version. You need to know which Node version you are running to predict whether a given API is native, polyfilled, or downleveled.
Watch Mode and Dependency Tracking
Nub's watch mode is not a simple file watcher. The README states it is 'driven by the resolved dependency graph plus the off-graph files that still invalidate a run.' That means nub watch src/server.ts watches not only the entry file but also its resolved imports, and it also watches off-graph invalidators like .env* files, the tsconfig.json extends chain, and package.json. This avoids maintaining a glob list, which is a common pain point with nodemon. It runs on Node's own --watch engine, preserving output by default. The implementation uses Node's --watch, which is a stable feature, but the dependency graph tracking depends on Nub's module.registerHooks() resolution. If a file is loaded dynamically via a non-standard mechanism, the graph might miss it. The README does not document this limitation, but it is a realistic failure mode for any dependency-graph-based watcher.
Script Runner and Package Execution: nub run and nubx
The script runner is a drop-in for npm run and pnpm run. It supports --filter for monorepos, as shown in nub run -r --filter "@org/*" test. The performance claim is a 24x speedup over pnpm run, attributed to the Rust binary having no JavaScript startup. This is plausible because npm and pnpm are JavaScript-based and incur interpreter startup. nubx is the npx replacement, claiming 19x faster. The README does not detail how nubx resolves packages or handles authentication for private registries. If your workflow relies on npx's interactive prompts or specific registry configurations, you need to test nubx against your use cases. The same applies to nub install; it replaces npm install and pnpm install, but the README does not describe its lockfile handling or whether it supports pnpm's workspace protocols. For a monorepo using pnpm workspaces, you should verify that nub install produces the same node_modules structure and respects your workspace settings.
Node Version Management and Corepack Shims
Nub includes a Node version manager via nub node install 26. It resolves the expected Node version from your project files, as described earlier, and auto-installs it when needed. The README shows an example where running nub hello.ts with a .node-version file containing 26 outputs 'Using Node.js 26.3.0 (resolved from .node-version)' and 'Installed in 9.8s.' This is a significant convenience, as it removes the need for nvm or fnm. However, the version resolution precedence is specific: NODE_EXECUTABLE, then package.json#devEngines, then .node-version, then .nvmrc, then package.json#engines. If you use a different convention, such as a .tool-versions file from mise or asdf, Nub will not pick it up. The nub pm shim command creates Corepack-style shims, which is useful for pinning package manager versions. But the README does not explain how these shims interact with existing package manager installations. If you already have corepack or nvm in your CI, you need to decide whether to replace them entirely or run them side by side.
Limitations and Trade-offs: Experimental Surfaces and Canary Releases
The most obvious limitation is that Nub is in canary releases. The recent releases are all v0.8.0-canary.*, with dates in August 2026. That indicates the project is pre-1.0 and likely unstable. The README does not state a stable release date. Another limitation is Nub's reliance on Node's experimental extension surfaces: module.registerHooks() and --import preloads. These are not guaranteed to be stable across Node versions. If a future Node release changes these APIs, Nub could break. The README acknowledges this by saying it takes advantage of surfaces that 'mostly didn't exist when Deno and Bun were built,' but that also means Nub is tied to Node's development roadmap. The 'mostly via passthrough' caveat for node compatibility is another limitation: not every Node flag or behavior is guaranteed. If you rely on obscure Node flags or edge-case semantics, you may encounter differences. Finally, the performance claims are not independently verified. The README states 24x, 19x, 18x, and 2.9x improvements, but these are likely benchmark results from the maintainers. You should measure on your own workloads before assuming they hold.
Alternatives: Bun, Deno, and the Traditional Toolchain
The closest alternative is Bun, which is a full runtime written in Zig. Bun includes its own JavaScript engine, package manager, and test runner, and it can run TypeScript natively. However, Bun is not Node; it has its own API surface and can have compatibility gaps with Node packages. Nub explicitly avoids that by building on stock Node. Deno is another alternative, but it is also a separate runtime with its own module system and permissions model. If you want to stay on Node, the traditional toolchain of tsx, npm, nvm, and nodemon is the baseline. Nub's advantage is consolidation and speed, but it comes with the risk of depending on a less mature project. The README compares Nub to tsx, ts-node, dotenv-cli, npm run, pnpm run, npx, nodemon, nvm, fnm, and corepack, positioning Nub as a replacement for all of them. The key difference is that Bun and Deno are new runtimes, while Nub is a wrapper around Node. That is the core distinction: Nub offers Bun-like DX without the runtime replacement.
Maintenance and Upgrade Cost, and License
Nub is licensed under MIT, which is permissive and imposes no copyleft obligations. You can use it in commercial projects without legal concerns, though you should review the license text for any specifics. The maintenance cost is twofold. First, Nub itself is in canary releases, so you need to track updates and expect breaking changes. The release cadence is high, with multiple canary releases per day, which suggests active development but also instability. Second, Nub depends on Node's internal APIs, so you need to watch Node release notes for changes to module.registerHooks() or --import behavior. Upgrading Node might break Nub, and upgrading Nub might change behavior. The README mentions nub upgrade for self-update, which is convenient, but it does not describe a rollback mechanism. You should pin Nub to a specific version in CI and test before upgrading, just as you would with any tool. The setup-nub GitHub Action is designed to be a drop-in replacement for actions/setup-node, which simplifies CI migration, but you need to verify that it handles your Node version resolution correctly.
Editorial conclusion
Adopt Nub if you manage multiple Node projects and want a single tool for running files, scripts, installs, and Node versions, especially if you value TypeScript support without a build step and automatic Node provisioning. Do not adopt it if you need a stable, production-hardened runtime with a mature ecosystem, since Nub is in canary releases and relies on Node's experimental extension surfaces. Before adopting, verify the performance claims on your own machine, test the transpilation edge cases with your codebase, and confirm the Node version resolution works with your CI setup.
Community notes