@gowhiteleaf/nextdoctor
v0.3.0
Published
Diagnose, auto-fix, and watchdog memory usage of Next.js dev servers
Maintainers
Readme
nextdoctor
The memory monitor for Next.js development — diagnose, auto-tune, and watch memory usage of your dev server, in one command.
Next.js dev servers hold onto memory for every route and page you visit — exactly how much depends on your Next.js version, bundler, and config (Turbopack, the default since Next.js 15, added eviction in 16.3, but plenty of projects are on older versions, on webpack, or just want visibility into what's actually happening). nextdoctor gives you that visibility, one-command tuning, and a live dashboard you can keep open all day.
Try it on one project first (no install)
cd into the Next.js project you want to check, then run it straight from
npm — nothing gets installed anywhere, and nothing is added to that
project's package.json:
cd /path/to/your-nextjs-project
npx @gowhiteleaf/nextdoctor diagnoseThat's it — this downloads and runs nextdoctor just for this one command.
Try fix and dev the same way (swap diagnose for fix or dev) before
deciding whether to install it properly.
Note:
nextdoctor(unscoped) was already taken on npm, so the package is published as@gowhiteleaf/nextdoctor— but the command it gives you is still justnextdoctor, as shown below.
Install once you're happy with it
Two options, either works:
Global install (recommended if you'll use it across many projects) —
one install, then nextdoctor is available everywhere:
npm install -g @gowhiteleaf/nextdoctor
nextdoctor diagnosePer-project install (keeps it scoped to just this project, e.g. if you don't want a global CLI):
npm install --save-dev @gowhiteleaf/nextdoctor
npx nextdoctor diagnoseTo upgrade later, re-run the same install command — it won't auto-update.
Contributing / running from source
Only needed if you're modifying nextdoctor itself, not for using it:
git clone https://github.com/jasswhiteleaf/nextdoctor.git
cd nextdoctor
npm install
npm run build
npm link # makes your local build available globally as `nextdoctor`,
# taking over from any npm-installed version until you `npm unlink`Releasing
Every push runs a build check (.github/workflows/ci.yml). Pushes to
main also run .github/workflows/publish.yml, which publishes to npm
automatically — but only if package.json's version is actually new;
otherwise it's a harmless no-op, so there's no separate release/tag step.
To ship a new version:
# bump "version" in package.json, then:
git add package.json && git commit -m "Bump version to x.y.z"
git pushRequires an NPM_TOKEN repo secret — a Classic → Automation npm token
specifically (not the default Granular Access Token), since only that type
bypasses the interactive 2FA prompt that a normal npm publish would need.
Commands
nextdoctor init
Generates a nextdoctor.config.json with your preferred settings so you
don't have to remember or retype flags every time. In a real terminal it
asks a few quick questions (dev command, memory threshold, sampling
interval, auto-restart) — just press Enter to accept the default for any
of them. Pass -y to skip the questions entirely and write sensible
defaults instead. Safe to run anytime: it won't overwrite an existing
config without asking (or without -y).
nextdoctor initYou can hand-edit the generated file anytime, or re-run nextdoctor init
to regenerate it.
nextdoctor diagnose
Static scan of the current project. Checks:
- Next.js version + whether you're on Turbopack without memory eviction
onDemandEntriestuning (or lack of it)next.configpresence and known risky flags- Monorepo detection (turbo/nx/pnpm workspaces)
nextdoctor fix
Applies the safe fixes from diagnose — adds onDemandEntries tuning,
removes an accidentally-disabled turbopackMemoryEviction: false, etc.
Always backs up your next.config first (next.config.js.nextdoctor-backup-<timestamp>)
and shows you what it's about to change before writing. Pass -y to skip
the confirmation prompt (e.g. in CI or a setup script). Refuses to run if
the working tree (when inside a git repo) has uncommitted changes, so its
diff stays easy to review in isolation — pass --allow-dirty to override.
nextdoctor dev
Wraps your actual dev command (default npm run dev) and shows a live
memory dashboard for the whole process tree (Next.js dev spawns worker
processes, so this isn't just the root PID). In a real terminal this is a
full-screen TUI — gauge, memory sparkline, per-process breakdown, and a
scrolling log tail of the wrapped dev server's own output. Piped/non-TTY
output (CI, | cat, log files) falls back to a plain-text renderer instead.
nextdoctor dev --command "next dev" --threshold 6144 --auto-restart--threshold <mb>— warn (and optionally restart) above this many MB (default 4096)--interval <ms>— how often to sample (default 5000)--auto-restart— kill and relaunch the dev server when the threshold is hit, instead of just warning- In the dashboard:
←/→switch focus between apps,rmanually restarts the focused app,qquits
Watching multiple apps at once
Useful for monorepos (turbo/nx/pnpm workspaces) where several dev servers run side by side — each app gets its own pane, sampled and restarted independently, so one app crashing or breaching its threshold doesn't disturb the others.
Either point at a config file:
nextdoctor dev --config nextdoctor.config.json{
"threshold": 4096,
"apps": [
{ "id": "web", "cwd": "apps/web", "command": "npm run dev" },
{ "id": "admin", "cwd": "apps/admin", "command": "npm run dev", "threshold": 2048 }
]
}(nextdoctor.config.json in the current directory is picked up automatically if --config isn't passed.)
Or pass --app repeatedly for a quick one-off, no file needed:
nextdoctor dev --app "web=apps/web:npm run dev" --app "admin=apps/admin:npm run dev"Troubleshooting
"Could not start the interactive dashboard" / a React-related crash on dev.
This happens when nextdoctor is installed as a per-project dependency
(npm install --save-dev) inside a project that already has a different
major React version installed (e.g. any Next.js 15+/16+ project, which ships
React 19) — npm can hoist the dashboard's UI library onto the host project's
React instead of nextdoctor's own, and the two aren't binary-compatible.
diagnose and fix are unaffected either way. If you hit this on dev,
run it via npx @gowhiteleaf/nextdoctor dev or a global install instead —
neither shares a node_modules tree with the target project, so there's
nothing to collide with. (As of 0.1.1, this now degrades to plain-text
output with a clear message instead of crashing.)
Notes / next steps
- This is a v1 scaffold — the
fixcommand does conservative text-insertion intonext.configrather than a full AST rewrite, specifically so diffs stay obvious and reviewable. Worth revisiting with a proper codemod (e.g.jscodeshift) if you want more aggressive rewrites later. - The watchdog currently restarts the whole
next devprocess on breach. A future version could instead prompt Turbopack to evict its cache without a full restart, once/if Next.js exposes that as a signal. - No telemetry, no network calls — everything runs locally against the project(s) you point it at.
- The dashboard captures the wrapped dev server's stdout/stderr line-by-line
to render them in a log pane, instead of passing the raw stream straight
through to your terminal. One consequence: output that relies on in-place
\rupdates (like some progress spinners) renders as one line per update rather than overwriting in place.
