Watch mode
Restart-on-change for files and scripts, driven by the resolved dependency graph plus your .env*, tsconfig.json, and package.json — no glob hygiene required.
Watch mode (nub watch) runs your entry point and restarts it whenever something it actually depends on changes. The engine underneath is Node's own --watch, with Nub-side glue that reports the in-memory-transpiled dependency graph — plus the off-graph files that still invalidate a process — back to Node's watcher. The result is a watcher that Just Works for TypeScript projects, with no glob list to maintain.
This page is a cookbook. For how nub runs files in the first place, see Running files; for scripts, Running scripts.
Watch and restart a file
Point nub watch at an entry file. It runs the file, then restarts the process on any change to the file or anything in its resolved import graph.
nub watch src/server.tsTypeScript, JSX, .env* loading, tsconfig.json paths — everything nub <file> gives you is active here too, because nub watch runs the same augmented Node underneath.
--watch
Flag and subcommand are aliases: nub --watch <file> dispatches to the exact same code path as nub watch <file> — same defaults, same behavior. The flag form exists so node --watch script.ts muscle memory lands in Nub's improved experience without surprise.
nub --watch src/server.tsWatching a script
The watcher takes a file, not a script: point nub watch at the entry your dev script runs.
nub watch src/server.tsA --watch placed after a script name is forwarded to the script like any other argument — nub run test --watch runs your test tool's own watch mode, it does not invoke Nub's watcher. See nub run → Forward arguments.
Preserve output
Nub preserves terminal output by default and prints a restart banner, rather than clearing the screen. The previous run's error message is usually the most important thing on screen, so wiping it on every restart is the wrong default.
nub watch src/server.ts
# ── restart [14:32:08] ──If you prefer Node's clear-on-restart behavior, opt in:
nub watch --clear src/server.tsWhat triggers a restart
The watch set is loader-instrumented, not glob-based: nub watch only watches files that were actually loaded as part of the run, plus a small set of off-graph files that invalidate the process when they change. Concretely, a restart fires on a change to:
- Any file in the resolved dependency graph of the entry — including
.ts/.tsxfiles transpiled in-memory throughmodule.registerHooks()that Node never sees on disk. - Your
.env*files in their normal precedence (.env,.env.local,.env.<NODE_ENV>, …) — these are read once at boot and aren't in any import graph, so Nub reports them to the watcher explicitly. - The
tsconfig.jsonextends chain — editing a tsconfig (for example, changing apathsmapping) restarts the process even though tsconfig isn't imported by anything. package.json.
This is why a plain node --watch silently goes stale on a tsconfig edit, and why Nub reports those off-graph files over Node's internal WATCH_REPORT_DEPENDENCIES channel.
What doesn't trigger a restart
Because the watch set is the import graph rather than a directory glob, files that nothing in the run actually loads are simply not watched. A rebuild that emits dist/foo.js doesn't trigger a restart unless something in the run imported dist/foo.js.
nub watch src/server.ts
# editing dist/** or coverage/** does not restart —
# they aren't in the loaded dependency graphThere is no ignore list to maintain. Most of the ignore / restart-loop-guard hygiene that glob-based watchers require is unnecessary in a loader-instrumented model.
Plain Node --watch
Nub's watch mode is intentionally not byte-for-byte Node — it adds the banner, preserve-output default, and off-graph reporting described above. When you want vanilla Node --watch with no Nub-side glue at all, type node --watch directly in your shell.
node --watch script.jsNub's PATH shim is per-invocation: it only affects descendants of an active nub ... call, so the node in your shell is always your real Node. There is no --node compat flag on nub watch — for strict-Node watch behavior, this is the path. See the --node flag for where compat mode does and doesn't apply.
Related
- Running files — how
nub <file>executes TypeScript and JSX. - Running scripts —
nub runand its workspace surface. - nubx — running local CLIs from
node_modules/.bin. - FAQ — short answers across the whole surface.
File runnernub <file>
Run TypeScript and JSX files directly — a flag-for-flag drop-in for the node command, with module resolution, data-format loaders, automatic .env loading, and modern globals.
Script runnernub run
Use nub run as a drop-in for npm run / pnpm run — lifecycle hooks, npm_* env vars, arg forwarding, and pnpm-style workspace filters, an order of magnitude faster on the cold path.