How does the main entry point work?
How does the main entry point work?
About vercel/next.js · 2 messages · last activity 13 Oct 2026
The CLI's "main entry point" is [packages/next/src/bin/next.ts], which is the executable that runs whenever you type next on the command line (e.g. next dev, next build, next start). Here's how it works end to end:
1. Shebang and bootstrap imports
The file starts with #!/usr/bin/env node so it can be executed directly as a script, and immediately imports ../server/require-hook before anything else, which patches Node's module resolution for Next.js's internal needs [packages/next/src/bin/next.ts:L1-L3]. It then imports commander (Next's vendored copy, next/dist/compiled/commander) along with various CLI option types and helpers like parseValidPositiveInteger and getParsedDebugAddress [packages/next/src/bin/next.ts:L1-L33].
2. A custom Command subclass
Rather than using commander's Command directly, Next defines NextRootCommand extends Command, overriding createCommand so every subcommand gets a shared preAction hook [packages/next/src/bin/next.ts:L88-L141]. That hook runs before any subcommand's action and:
- Warns if
NODE_ENVis set to something non-standard, or used in a way that doesn't match the command (e.g.NODE_ENV=developmentwithnext build) [packages/next/src/bin/next.ts:L94-L107]. - Defaults
NODE_ENVtodevelopmentfordevandproductionotherwise, and always forcesNEXT_RUNTIME = 'nodejs'[packages/next/src/bin/next.ts:L109-L110]. - Detects Apple Silicon Macs running under Rosetta 2 and warns about potential performance issues [packages/next/src/bin/next.ts:L112-L121].
- Rejects the deprecated
--inspectflag for commands other thandev/start[packages/next/src/bin/next.ts:L123-L132].
3. Program/root command setup
A single program = new NextRootCommand() instance is created and configured with the CLI name, description, custom help formatting (formatCliHelpOutput), and version output sourced from process.env.__NEXT_VERSION [packages/next/src/bin/next.ts:L156-L173].
4. Subcommands registered via chained .command(...) calls
Each CLI subcommand (build, dev, start, info, upgrade, experimental-test, and an internal group for debugging tools like trace, query-trace, upload-trace, static-routes-info) is declared by chaining onto program:
devis marked as the default command (program.command('dev', { isDefault: true })), so running barenextlaunches dev mode [packages/next/src/bin/next.ts:L311-L325]. It defines--turbo/--turbopack/--webpack,--port(withPORTenv fallback), and--inspectwith custom address parsing [packages/next/src/bin/next.ts:L325-L341].startsimilarly wires up--port,--hostname, and--inspectfor production mode [packages/next/src/bin/next.ts:L432-L461].upgradedynamically imports../cli/next-upgrade.jsand callsspawnNextUpgrade[packages/next/src/bin/next.ts:L548-L573].internalis a nested command group for undocumented/unstable tooling (not covered by semver) — e.g.trace/turbo-trace-serverstarts a Turbopack trace server, andquery-tracequeries it over an MCP (Model Context Protocol) JSON-RPC endpoint [packages/next/src/bin/next.ts:L569-L661].
5. Lazy-loading command implementations
Almost every .action(...) callback does a dynamic import('../cli/next-*.js') (or occasionally require) rather than importing the implementation up front — e.g. next-info.js, next-post-build.js, internal/upload-trace.js [packages/next/src/bin/next.ts:L429-L431, L702-L727]. This keeps CLI startup fast since only the code for the invoked subcommand gets loaded.
6. The query-trace example of an internal command's actual logic
As a concrete illustration of what a subcommand action ultimately does
Did this answer what you came for?
Want to ask your own question?
Open chat for vercel/next.jsPublic Q&A. Generated by RepoPilot from the actual source of vercel/next.js. AI answers can be incomplete or stale — verify before relying on them.