Nub 0.5.0 ships nub init — a TypeScript-first project scaffold — alongside a batch of package-manager correctness fixes and faster Node installs.
nub init
One command scaffolds a minimal TypeScript project that runs and typechecks immediately:
nub init
nub index.tsIt writes five files, initializes git, and runs the install:
my-app/
├── package.json
├── tsconfig.json
├── index.ts
├── README.md
├── .gitignore
├── nub.lock
├── node_modules/
└── .git/
- TypeScript 7 by default. The scaffold pins
typescript@^7— the native compiler — alongside@types/node@^26and@nubjs/types. Nub transpiles at run time, sotscexists purely to typecheck (noEmit) and the project has zero runtime dependencies. - Node types without
"dom".libstays["es2024"]; the globals Nub polyfills (Worker, …) are typed by@nubjs/types, sowindowanddocumentnever leak into a Node project. - Real
.tsimports.verbatimModuleSyntaxandallowImportingTsExtensions: import specifiers say./thing.tsand resolve exactly as Node and Nub do. - Strict from the first file.
strictplusnoUncheckedIndexedAccessandexactOptionalPropertyTypes,nodenextresolution,es2024target.
The generated tsconfig.json
{
"compilerOptions": {
"module": "nodenext",
"moduleResolution": "nodenext",
"target": "es2024",
"lib": ["es2024"],
"types": ["node", "@nubjs/types"],
"moduleDetection": "force",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"isolatedModules": true,
"noUncheckedSideEffectImports": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"skipLibCheck": true,
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"noEmit": true
}
}In a terminal, init asks three questions — name, TypeScript or JavaScript, git — each with a sensible default; -y skips them, non-interactive environments auto-default, and existing files are never overwritten without --force.
Full details in the docs. (#499, #526)
nub create
nub create <template> resolves the ecosystem's create-* convention (vue → create-vue) and runs the scaffolder. As of this release the scaffolder can tell Nub is calling — #529 exports the npm_config_user_agent these tools read — so scaffolders with Nub detection respond with Nub commands. Working today:
nub create vue my-app
nub create vite my-app
nub create nuxt my-app$ nub create vue my-app --default
└ Done. Now run:
cd my-app
nub install
nub run devDetection PRs are open across the ecosystem — track them to see your framework land:
- vercel/next.js#95331 — create-next-app
- honojs/create-hono#124 — create-hono
- t3-oss/create-t3-app#2237 — create-t3-app
- payloadcms/payload#17163 — create-payload-app
- strapi/strapi#26864 — create-strapi-app
- medusajs/medusa#15898 — create-medusa-app
- QwikDev/qwik#8786 — create-qwik
- unjs/std-env#197 — std-env runtime detection
Already merged upstream: create-vue, Nuxt, solid-cli, react-router, create-cloudflare, and package-manager-detector (the detection library behind many of them). create-vite needs no patch — it reads the user agent directly.
Package manager
Top-level packageExtensions in the root manifest is now honored in Nub-native projects (it was already supported in pnpm- and npm-compatibility mode), plus a batch of correctness fixes:
| Area | What changed | PR |
|---|---|---|
packageExtensions |
Top-level packageExtensions is honored in Nub-native projects, enforced and role-scoped |
#507, #509 |
dlx / create |
Children see the role-aware npm_config_user_agent, so create-* scaffolders detect Nub |
#529 |
nub update |
Accepts dist-tag specs (nub update pkg@beta) |
#516 |
| Hoisted linker | Workspace-spanning hoisted planning for nodeLinker=hoisted |
#511 |
approve-builds |
Runs the approved build scripts instead of only recording approval | #503 |
dedupe |
Workspace link packages no longer appear in the dedupe diff | #502 |
| Identity detection | Walk-up is clamped to Nub's cache root for internal scratch installs | #513 |
publish |
Scope is preserved in the publish attachment key and tarball URI | #478 |
| Registry traffic | Dist-tag resolution is cached and metadata fetches slimmed | #505 |
nubx
nubx <name> no longer tries file and script resolution first — it resolves the node_modules/.bin chain and falls back to the registry on a miss, exactly as npx does. Files are nub <file>, scripts are nub run <script>. The consent gate on first registry fetch is unchanged. (#525)
Process management and watch
| Area | What changed | PR |
|---|---|---|
| Spawn | The parent-death watcher verb dispatches above argv0 detection | #517 |
| Spawn (macOS) | A group-reaper watcher prevents SIGKILL of Nub's process group from orphaning the workload | #504 |
nub watch |
An explicit --env-file is forwarded to the watched Node so restarts re-read it |
#510 |
| node-gyp | The __node-gyp-bootstrap verb is honored under every argv0 |
7621113 |
Platforms and Node installs
nub upgradesupports the self-owned channel on Windows (#506).- Node installs stream extraction during download and overlap the checksum fetch (#508).
- Source builds work on Android/Termux without a JVM (#501).
Internals
- The vendored aube engine is synced to upstream v1.32.0 (#519).
- Dead code removed and visibility tightened via cargo-hawk (#514).
- Benchmark, docs, and tooling updates.
What's Changed
- fix(publish): preserve scope in publish attachment key and tarball URI by @pullfrog[bot] in #478
- Fall back to webpki roots and system DNS on Android (no-JVM builds) by @colinhacks in #501
- feat(init): ship nub init — TypeScript-first project scaffold by @colinhacks in #499
- upgrade: support the self-owned channel on Windows by @colinhacks in #506
- pm: run approved build scripts during approve-builds by @colinhacks in #503
- fix(spawn): macOS group-reaper watcher so SIGKILL of the nub process group can't orphan the workload by @colinhacks in #504
- pm: exclude workspace link packages from dedupe diff by @colinhacks in #502
- fix(pm): clamp identity walk-up to nub's cache root for internal scratch installs by @colinhacks in #513
- fix(pm): cache dist-tag resolution and slim registry metadata fetches by @colinhacks in #505
- node install: stream extraction during download, overlap checksum fetch by @colinhacks in #508
- linker: workspace-spanning hoisted planning for nodeLinker=hoisted by @colinhacks in #511
- feat(pm): sanction top-level packageExtensions under nub identity by @colinhacks in #507
- fix(pm): enforce + role-scope packageExtensions under nub identity by @colinhacks in #509
- pm: accept dist-tag specs in update args by @colinhacks in #516
- chore: remove dead code and tighten visibility via cargo-hawk by @colinhacks in #514
- fix(watch): forward explicit --env-file to the watched Node so restarts re-read it by @colinhacks in #510
- fix(spawn): dispatch the parent-death watcher verb above argv0 detection by @colinhacks in #517
- aube: sync vendored engine to upstream v1.32.0 by @colinhacks in #519
- revert(nubx): drop the unified file/script tiers, back to npx parity by @colinhacks in #525
- init: scaffold typescript ^7 as a devDependency by @colinhacks in #526
- fix(pm): export npm_config_user_agent to dlx/create/exec children by @colinhacks in #529
Full Changelog: v0.4.13...v0.5.0