Creating a project
Scaffold a new TypeScript-first project — manifest, tsconfig, entry file, git, and installed dev dependencies — in one command.
Running nub init scaffolds a minimal TypeScript project that runs and typechecks immediately. It writes five files, initializes git, and installs TypeScript plus the type packages the editor needs:
$ nub init -y
created my-app
├── package.json
├── tsconfig.json
├── index.ts
├── .gitignore
├── README.md
└── .git/
devDependencies:
+ @nubjs/types@0.4.13
+ @types/node@26.1.1
+ typescript@7.0.2
Your project is ready!
Try running `nub index.ts`The scaffold has zero runtime dependencies — the entry file runs right away:
$ nub index.ts
Hello from NubWhat it writes
The manifest carries the same packageManager pin and devEngines range that nub pm pin writes, plus the dev dependencies:
{
"name": "my-app",
"version": "0.0.1",
"type": "module",
"packageManager": "nub@0.5.0",
"devEngines": {
"packageManager": { "name": "nub", "version": "^0.5.0", "onFail": "ignore" }
},
"scripts": {
"start": "nub index.ts"
},
"devDependencies": {
"@nubjs/types": ">=0.4.13 <=0.5.0",
"@types/node": "^26",
"typescript": "^7"
}
}The @nubjs/types range is capped at the running Nub version, but allows an older release so the default 24-hour cooling window can select the newest mature declarations. The install step resolves the dependencies and writes Nub's neutral lockfile, nub.lock.
The tsconfig targets Node's own TypeScript semantics — nodenext resolution, verbatimModuleSyntax, strict mode, noEmit (Nub transpiles; the installed typescript is for the editor and typechecking) — and wires the installed type packages:
{
"compilerOptions": {
"module": "nodenext",
"moduleResolution": "nodenext",
"target": "es2024",
"lib": ["es2024"],
"types": ["node", "@nubjs/types"],
"strict": true,
"noEmit": true
// ...
}
}The generated project is not locked to Nub: everything runs on plain Node too (the devEngines policy is ignore — a signal to read, not a rule to enforce), and swapping the start script to a plain node invocation is the only change a non-Nub user would make. Plain node runs the TypeScript entry on Node ≥22.18 (type stripping, unflagged in 23.6 and backported to 22.18); on older Node, scaffold with --js instead.
Prompts
In a terminal, nub init asks three questions — project name, TypeScript or JavaScript, and whether to initialize git. Every prompt has a sensible default; -y skips them all. Outside a terminal (CI, piped stdin) the defaults apply automatically, so the command never hangs.
Flags
| Flag | Effect |
|---|---|
-y, --yes | Skip all prompts, take the defaults. |
--js | JavaScript variant: writes index.js, no tsconfig, no devDependencies. |
--name <name> | Project name (default: the directory name, sanitized). Scoped names (@scope/pkg) are preserved. |
--no-git | Skip git init. |
--no-install | Skip the install step. |
--force | Overwrite existing files. |
Existing files
When any target file already exists, init refuses and names the conflicts — nothing is partially written:
$ nub init -y
Error: nub: refusing to overwrite existing files: package.json, tsconfig.json, index.ts, .gitignore, README.md
(pass --force to overwrite)Passing --force overwrites the listed files. An existing .git/ is never touched — init skips git init inside an existing repository.
Templates
Framework templates are not init's job — they belong to nub create. It resolves the ecosystem's create-* convention (vue → create-vue, @scope/foo → @scope/create-foo), fetches the scaffolder, and runs it. Scaffolders that detect the invoking package manager answer with Nub commands:
$ nub create vue my-app --default
└ Done. Now run:
cd my-app
nub install
nub run devEverything after the template name is passed through to the scaffolder, so each create-* tool's own flags work unchanged.
Read the full docs for pnpm create on pnpm.io.
Passing a template to init points you the same way:
$ nub init vite
Error: nub: `init` does not accept arguments (got "vite")
(to scaffold from a template: nubx create-vite)Compiling executables
Package a TypeScript or JavaScript entry into a target-specific executable that either embeds Node or locates it on the target machine, provisioning a copy when needed.
Package manager
Nub's install engine — the package.json fields and config keys that shape dependency resolution, plus lockfile compatibility with npm, pnpm, Bun, and Yarn.