---
title: "CLI Commands"
description: "The command-line interface infrastructure of Next.js provides the primary entrypoint for managing application lifecycles, development workflows, production builds, and diagnostic reporting. Rooted ..."
last_updated: "2026-10-12T06:38:56.875594+00:00"
canonical_url: "https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/cli-telemetry/cli-commands"
---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [packages/next/src/bin/next.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/bin/next.ts)
- [packages/next/src/build/index.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/build/index.ts)
- [packages/next/src/cli/next-dev.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-dev.ts)
- [packages/next/taskfile.js](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/taskfile.js)
- [packages/next/src/cli/next-build.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-build.ts)
- [packages/next-codemod/bin/next-codemod.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/bin/next-codemod.ts)
- [packages/next/src/cli/next-info.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-info.ts)
- [packages/next/src/server/lib/start-server.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/server/lib/start-server.ts)
- [packages/create-next-app/index.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/create-next-app/index.ts)
- [packages/next/src/cli/next-start.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-start.ts)
- [packages/next/src/server/lib/utils.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/server/lib/utils.ts)
- [packages/next/src/cli/internal/static-routes-info.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/internal/static-routes-info.ts)
- [packages/next/src/cli/next-analyze.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-analyze.ts)
- [packages/next/src/cli/internal/turbo-trace-server.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/internal/turbo-trace-server.ts)
- [packages/next/src/server/next-server.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/server/next-server.ts)
- [packages/next/src/build/utils.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/build/utils.ts)
- [packages/next/src/cli/next-request-insights.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-request-insights.ts)
- [packages/devlow-bench/src/cli.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/devlow-bench/src/cli.ts)
- [packages/next/src/cli/next-test.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-test.ts)
- [packages/next/src/cli/next-export.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-export.ts)
- [packages/next/src/server/next.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/server/next.ts)
- [packages/next/src/lib/bundler.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/lib/bundler.ts)
- [package.json](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/package.json)
- [packages/next/src/lib/upgrade/nudge.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/lib/upgrade/nudge.ts)
- [packages/next/src/lib/upgrade/prompt-output.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/lib/upgrade/prompt-output.ts)
- [packages/next/src/telemetry/agent-name.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/telemetry/agent-name.ts)
- [packages/next/src/telemetry/storage.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/telemetry/storage.ts)
</details>

## Overview

The command-line interface infrastructure of Next.js provides the primary entrypoint for managing application lifecycles, development workflows, production builds, and diagnostic reporting. Rooted in the main binary dispatcher, the CLI parses subcommands and flags to coordinate execution flows across development and production environments.

Sources: [packages/next/src/bin/next.ts:390-578](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/bin/next.ts#L390-L578)

## Entrypoint routing and command dispatch

### Subcommand definitions and action bindings

The primary CLI entrypoint configures commands and option parsers for subcommands including `dev`, `start`, `info`, and `export`. The `dev` command is designated as the default subcommand and accepts an optional `[directory]` argument alongside configuration flags.

```typescript
program
  .command('dev', { isDefault: true })
  .description(
    'Starts Next.js in development mode with hot-code reloading, error reporting, and more.'
  )
  .argument(
    '[directory]',
    `A directory on which to build the application. ${italic(
      'If no directory is provided, the current directory will be used.'
    )}`
  )
  .addOption(
    new Option(
      '--inspect [[host:]port]',
      'Allows inspecting server-side code. See https://nextjs.org/docs/app/guides/debugging#server-side-code'
    ).argParser(parseValidInspectAddress)
  )
  .option('--turbo', 'Starts development mode using Turbopack.')
  .option('--turbopack', 'Starts development mode using Turbopack.')
  .option('--webpack', 'Starts development mode using the bundled webpack.')
  .option(
    '--custom-webpack',
    'Starts development mode using your project-installed webpack.'
  )
  .addOption(
    new Option(
      '-p, --port <port>',
      'Specify a port number on which to start the application.'
    )
      .argParser(parseValidPositiveInteger)
      .default(3000)
      .env('PORT')
  )
  .option(
    '-H, --hostname <hostname>',
    'Specify a hostname on which to start the application (default: 0.0.0.0).'
  )
  .option(
    '--disable-source-maps',
    "Don't start the Dev server with `--enable-source-maps`.",
    false
  )
  .option(
    '--experimental-https',
    'Starts the server with HTTPS and generates a self-signed certificate.'
  )
  .option('--experimental-https-key, <path>', 'Path to a HTTPS key file.')
  .option(
    '--experimental-https-cert, <path>',
    'Path to a HTTPS certificate file.'
  )
  .option(
    '--experimental-https-ca, <path>',
    'Path to a HTTPS certificate authority file.'
  )
  // `--server-fast-refresh` is hidden because it's the default behavior and
  // only needs to be explicitly passed to override a
  // `experimental.turbopackServerFastRefresh: false` in next.config. The
  // `--no-server-fast-refresh` negation is the meaningful user-facing flag.
  .addOption(new Option('--server-fast-refresh').default(undefined).hideHelp())
  .addOption(
    new Option('--no-server-fast-refresh', 'Disable server-side Fast Refresh')
  )
  .option(
    '--experimental-upload-trace, <traceUrl>',
    'Reports a subset of the debugging trace to a remote HTTP URL. Includes sensitive data.'
  )
  .option(
    '--experimental-next-config-strip-types',
    'Use Node.js native TypeScript resolution for next.config.(ts|mts)'
  )
  .option(
    '--experimental-cpu-prof',
    'Enable CPU profiling. Profiles are saved to .next-profiles/ on exit.'
  )
  .addOption(
    new Option(
      '--internal-trace [level]',
      'Enable Turbopack tracing. "all" (default) enables turbo-tasks level tracing, "overview" enables overview tracing.'
    )
```
Sources: [packages/next/src/bin/next.ts:390-501](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/bin/next.ts#L390-L501)

The `start` subcommand configures production startup parameters, port resolution, and debugger bindings.

```typescript
program
  .command('start')
  .description(
    'Starts Next.js in production mode. The application should be compiled with `next build` first.'
  )
  .argument(
    '[directory]',
    `A directory on which to start the application. ${italic(
      'If no directory is provided, the current directory will be used.'
    )}`
  )
  .addOption(
    new Option(
      '-p, --port <port>',
      'Specify a port number on which to start the application.'
    )
      .argParser(parseValidPositiveInteger)
      .default(3000)
      .env('PORT')
  )
  .option(
    '-H, --hostname <hostname>',
    'Specify a hostname on which to start the application (default: 0.0.0.0).'
  )
  .addOption(
    new Option(
      '--inspect [[host:]port]',
      'Allows inspecting server-side code. See https://nextjs.org/docs/app/guides/debugging#server-side-code'
    ).argParser(parseValidInspectAddress)
  )
  .addOption(
    new Option(
      '--keepAliveTimeout <keepAliveTimeout>',
      'Specify the maximum amount of milliseconds to wait before closing inactive connections.'
    ).argParser(parseValidPositiveInteger)
  )
  .option(
    '--experimental-next-config-strip-types',
    'Use Node.js native TypeScript resolution for next.config.(ts|mts)'
  )
  .option(
    '--experimental-cpu-prof',
    'Enable CPU profiling. Profiles are saved to .next-profiles/ on exit.'
  )
  .action((directory: string, options: NextStartOptions) => {
    if (options.experimentalNextConfigStripTypes) {
      process.env.__NEXT_NODE_NATIVE_TS_LOADER_ENABLED = 'true'
    }
    if (options.experimentalCpuProf) {
      process.env.NEXT_CPU_PROF = '1'
      process.env.__NEXT_PRIVATE_CPU_PROFILE = 'start-main'
    }
    setupProfilesDir(directory || process.cwd())
    return import('../cli/next-start.js').then((mod) =>
      mod.nextStart(options, directory)
    )
  })
  .usage('[directory] [options]')
```
Sources: [packages/next/src/bin/next.ts:521-578](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/bin/next.ts#L521-L578)

### Argument and environment option parsing

Utility functions support tokenizing argument strings, parsing environment variables like `NODE_OPTIONS`, and handling option constraints. Repeatable Node.js CLI arguments are preserved via specific type definitions.

```typescript
const REPEATABLE_OPTIONS: Record<string, { type: 'string'; multiple: true }> = {
  require: { type: 'string', multiple: true },
  import: { type: 'string', multiple: true },
}

const parseNodeArgs = (args: string[]): NodeOptions => {
  const parsed = parseArgs({
    args,
    strict: false,
    tokens: true,
    options: REPEATABLE_OPTIONS,
  })
  const values: NodeOptions = parsed.values
  const tokens = parsed.tokens

  // For the `NODE_OPTIONS`, we support arguments with values without the `=`
  // sign. We need to parse them manually.
  let orphan = null
  for (let i = 0; i < tokens.length; i++) {
    const token = tokens[i]

    if (token.kind === 'option-terminator') {
      break
    }

    // When we encounter an option, if it's value is undefined, we should check
    // to see if the following tokens are positional parameters. If they are,
    // then the option is orphaned, and we can assign it.
    if (token.kind === 'option') {
      orphan = typeof token.value === 'undefined' ? token : null
      continue
    }

    // If the token isn't a positional one, then we can't assign it to the found
    // orphaned option.
    if (token.kind !== 'positional') {
      orphan = null
      continue
    }

    // If we don't have an orphan, then we can skip this token.
    if (!orphan) {
      continue
    }

    const name = orphan.name

    // If the option is repeatable, accumulate each occurrence instead of
    // collapsing them into a single value.
    if (name in REPEATABLE_OPTIONS) {
      if (Array.isArray(values[name])) {
        values[name].push(token.value)
      } else if (typeof values[name] === 'string') {
        values[name] = [values[name], token.value]
      } else {
        values[name] = token.value
      }
      continue
    }

    // If the token is a positional one, and it has a value, so add it to the
    // values object. If it already exists, append it with a space.
    if (name in values && typeof values[name] === 'string') {
      values[name] += ` ${token.value}`
    } else {
      values[name] = token.value
    }
  }

  return values
}
```
Sources: [packages/next/src/server/lib/utils.ts:26-96](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/server/lib/utils.ts#L26-L96)

> [!NOTE]
> Repeatable arguments such as `--require` and `--import` are accumulated into arrays rather than collapsed into single string values during `NODE_OPTIONS` parsing.

```typescript
export const tokenizeArgs = (input: string): string[] => {
  let args: string[] = []
  let isInString = false
  let willStartNewArg = true

  for (let i = 0; i < input.length; i++) {
    let char = input[i]

    // Skip any escaped characters in strings.
    if (char === '\\' && isInString) {
      // Ensure we don't have an escape character at the end.
      if (input.length === i + 1) {
        throw new Error('Invalid escape character at the end.')
      }

      // Skip the next character.
      char = input[++i]
    }
    // If we find a space outside of a string, we should start a new argument.
    else if (char === ' ' && !isInString) {
      willStartNewArg = true
      continue
    }

    // If we find a quote, we should toggle the string flag.
    else if (char === '"') {
      isInString = !isInString
      continue
    }

    // If we're starting a new argument, we should add it to the array.
    if (willStartNewArg) {
      args.push(char)
      willStartNewArg = false
    }
    // Otherwise, add it to the last argument.
    else {
      args[args.length - 1] += char
    }
  }

  if (isInString) {
    throw new Error('Unterminated string')
  }

  return args
}
```
Sources: [packages/next/src/server/lib/utils.ts:106-152](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/server/lib/utils.ts#L106-L152)

Flags restricted to direct `execArgv` usage are validated against a predefined set of inspection options.

```typescript
const EXEC_ARGV_ONLY_OPTIONS = new Set([
  'experimental-network-inspection',
  'experimental-storage-inspection',
  'experimental-worker-inspection',
  'experimental-inspector-network-resource',
])

```
Sources: [packages/next/src/server/lib/utils.ts:214-220](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/server/lib/utils.ts#L214-L220)

## Development server CLI bootstrapping

### Bundler resolution and options parsing

The [development server](https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/development/development-server) determines its active compiler through `parseBundlerArgs`, which processes flags such as `--turbo`, `--turbopack`, `--webpack`, and `--custom-webpack` alongside environment variables like `TURBOPACK`, `IS_TURBOPACK_TEST`, `IS_WEBPACK_TEST`, `NEXT_RSPACK`, and `NEXT_TEST_USE_RSPACK`. If multiple conflicting bundler flags are supplied, Next.js logs an error and terminates execution with exit code `1`. When no bundler flags are provided, Turbopack is selected by default by setting `process.env.TURBOPACK = 'auto'`.

```typescript
export function parseBundlerArgs(options: {
  turbo?: boolean
  turbopack?: boolean
  webpack?: boolean
  customWebpack?: boolean
}): Bundler {
  const bundlerFlags = new Map<Bundler, string[]>()
  const setBundlerFlag = (bundler: Bundler, flag: string) => {
    bundlerFlags.set(bundler, (bundlerFlags.get(bundler) ?? []).concat(flag))
  }
  // What turbo flag was set? We allow multiple to be set, which is silly but not ambiguous, just pick the most relevant one.
  if (options.turbopack) {
    setBundlerFlag(Bundler.Turbopack, '--turbopack')
  }
  if (options.turbo) {
    setBundlerFlag(Bundler.Turbopack, '--turbo')
  } else if (process.env.TURBOPACK) {
    // We don't really want to support this but it is trivial and not really confusing.
    // If we don't support it and someone sets it, we would have inconsistent behavior
    // since some parts of next would read the return value of this function and other
    // parts will read the env variable.
    setBundlerFlag(Bundler.Turbopack, `TURBOPACK=${process.env.TURBOPACK}`)
  } else if (process.env.IS_TURBOPACK_TEST) {
    setBundlerFlag(
      Bundler.Turbopack,
      `IS_TURBOPACK_TEST=${process.env.IS_TURBOPACK_TEST}`
    )
  }
  if (options.webpack) {
    setBundlerFlag(Bundler.Webpack, '--webpack')
  }
  if (options.customWebpack) {
    setBundlerFlag(Bundler.Webpack, '--custom-webpack')
  }

  if (process.env.IS_WEBPACK_TEST) {
    setBundlerFlag(
      Bundler.Webpack,
      `IS_WEBPACK_TEST=${process.env.IS_WEBPACK_TEST}`
    )
  }

  // Mostly this is set via the NextConfig but it can also be set via the command line which is
  // common for testing.
  if (process.env.NEXT_RSPACK) {
    setBundlerFlag(Bundler.Rspack, `NEXT_RSPACK=${process.env.NEXT_RSPACK}`)
  }
  if (process.env.NEXT_TEST_USE_RSPACK) {
    setBundlerFlag(
      Bundler.Rspack,
      `NEXT_TEST_USE_RSPACK=${process.env.NEXT_TEST_USE_RSPACK}`
    )
  }

  if (
    bundlerFlags.size > 1 ||
    (options.webpack === true && options.customWebpack === true)
  ) {
    console.error(
      `Multiple bundler flags set: ${Array.from(bundlerFlags.values()).flat().join(', ')}.

Edit your command or your package.json script to configure only one bundler.`
    )
    process.exit(1)
  }
  // The default is turbopack when nothing is configured.
  if (bundlerFlags.size === 0) {
    process.env.TURBOPACK = 'auto'
    return Bundler.Turbopack
  }
  if (bundlerFlags.has(Bundler.Turbopack)) {
    // Only conditionally assign to the environment variable, preserving already set values.
    // If it was set to 'auto' because no flag was set and this function is called a second time we
    // would upgrade to '1' but we don't really want that.
    process.env.TURBOPACK ??= '1'
    return Bundler.Turbopack
  }
  // Otherwise it is one of rspack or webpack. At this point there must be exactly one key in the map.
  return bundlerFlags.keys().next().value!
}
```
Sources: [packages/next/src/lib/bundler.ts:41-120](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/lib/bundler.ts#L41-L120)

| Bundler Option / Flag | Environment Variable | Target Bundler |
| :--- | :--- | :--- |
| `--turbopack` / `--turbo` | `TURBOPACK`, `IS_TURBOPACK_TEST` | `Bundler.Turbopack` |
| `--webpack` / `--custom-webpack` | `IS_WEBPACK_TEST` | `Bundler.Webpack` |
| *(None configured)* | `NEXT_RSPACK`, `NEXT_TEST_USE_RSPACK` | `Bundler.Rspack` |

Sources: [packages/next/src/lib/bundler.ts:24-93](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/lib/bundler.ts#L24-L93)

> [!WARNING]
> Setting multiple distinct bundler flags simultaneously triggers a fatal exit code `1` after listing all activated flag arguments.

```typescript
  if (
    bundlerFlags.size > 1 ||
    (options.webpack === true && options.customWebpack === true)
  ) {
    console.error(
      `Multiple bundler flags set: ${Array.from(bundlerFlags.values()).flat().join(', ')}.

Edit your command or your package.json script to configure only one bundler.`
    )
    process.exit(1)
  }
```
Sources: [packages/next/src/lib/bundler.ts:95-105](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/lib/bundler.ts#L95-L105)

### Worker handoff and watchpack management

When executing as an internal worker (`process.env.NEXT_PRIVATE_WORKER`), the server listens for parent messages containing `nextWorkerOptions`. It initializes tracing infrastructure via `trace('start-dev-server')` combined with heap statistics, CPU counts, free memory metrics, and parent-provided environment flags, eventually invoking `startServer`.

```typescript
if (process.env.NEXT_PRIVATE_WORKER && process.send) {
  // Output is piped to the CLI to hold it while the upgrade menu is open.
  if (process.env.NEXT_PRIVATE_PROMPT_OUTPUT === '1') {
    blockOnOutputWrites()
  }
  process.addListener('message', async (msg: any) => {
    if (
      msg &&
      typeof msg === 'object' &&
      msg.nextWorkerOptions &&
      process.send
    ) {
      let enabledFeaturesFromParent = {}
      if (process.env.NEXT_PRIVATE_ENABLED_FEATURES) {
        const parsed = JSON.parse(process.env.NEXT_PRIVATE_ENABLED_FEATURES)
        enabledFeaturesFromParent = Object.fromEntries(
          Object.entries(parsed).map(([key, value]) => [
            `feature.${key}`,
            value,
          ])
        )
      }

      let rageRestartAttrsFromParent = {}
      if (process.env.NEXT_PRIVATE_DEV_SPAN_ATTRS) {
        rageRestartAttrsFromParent = JSON.parse(
          process.env.NEXT_PRIVATE_DEV_SPAN_ATTRS
        )
      }

      startServerSpan = trace('start-dev-server', undefined, {
        cpus: String(os.cpus().length),
        platform: os.platform(),
        'memory.freeMem': String(os.freemem()),
        'memory.totalMem': String(os.totalmem()),
        'memory.heapSizeLimit': String(v8.getHeapStatistics().heap_size_limit),
        ...enabledFeaturesFromParent,
        ...rageRestartAttrsFromParent,
      })

      initializeTraceState({
        ...exportTraceState(),
        defaultParentSpanId: startServerSpan.getId(),
      })

      const result = await startServerSpan.traceAsyncFn(() =>
        startServer(msg.nextWorkerOptions)
      )
      const memoryUsage = process.memoryUsage()
      startServerSpan.setAttribute('memory.rss', String(memoryUsage.rss))
      startServerSpan.setAttribute(
        'memory.heapTotal',
        String(memoryUsage.heapTotal)
      )
      startServerSpan.setAttribute(
        'memory.heapUsed',
        String(memoryUsage.heapUsed)
      )
      process.send({
        nextServerReady: true,
        port: process.env.PORT,
        distDir: result.distDir,
      })
    }
  })
  process.send({ nextWorkerReady: true })
}
```
Sources: [packages/next/src/server/lib/start-server.ts:634-700](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/server/lib/start-server.ts#L634-L700)

During development startup, Watchpack monitors project configuration files and distribution directory ancestors. Any modification to configuration files or deletion of watched path ancestors forces the server to exit with `RESTART_EXIT_CODE`.

```typescript
// Watch config files for changes and distDir ancestors for deletion.
if (isDev) {
  // Note: dir is absolute and normalized (`..` segments removed), `absDistDir`
  // is also normalized because `path.join()` performs normalization. `distDir`
  // does not have to be inside of `dir`!
  const absDistDir = path.join(dir, distDir)
  // always watch dir and absDistDir
  const dirWatchPaths: string[] = [dir, absDistDir]
  // also watch ancestors of absDistDir that are inside of dir.
  let prevAncestor = absDistDir
  while (true) {
    const nextAncestor = path.dirname(prevAncestor)
    // note: `dirname('/') === '/'` if we happen to reach the FS root
    if (
      !nextAncestor.startsWith(dir + path.sep) ||
      nextAncestor === prevAncestor
    ) {
      break
    }
    dirWatchPaths.push(nextAncestor)
    prevAncestor = nextAncestor
  }

  const configFiles = CONFIG_FILES.map((file) => path.join(dir, file))
  const Watchpack =
    require('next/dist/compiled/watchpack') as typeof import('next/dist/compiled/watchpack').default
  const wp = new Watchpack()
  wp.watch({
    files: configFiles,
    missing: dirWatchPaths,
  })
  wp.on('change', async (filename) => {
    if (!configFiles.includes(filename)) {
      return
    }
    Log.warn(
      `Found a change in ${path.basename(
        filename
      )}. Restarting the server to apply the changes...`
    )
    process.exit(RESTART_EXIT_CODE)
  })
  wp.on('remove', (removedPath: string) => {
    if (dirWatchPaths.includes(removedPath)) {
      Log.error(
        `The directory at "${removedPath}" was deleted.\n\n` +
          'Deleting this directory removes caches and will cause slower ' +
          'performance.\n\n' +
          'Deleting this directory while Next.js is running can lead to ' +
          'undefined behavior. Restarting the server to recover...'
      )
      process.exit(RESTART_EXIT_CODE)
    }
  })
}
```
Sources: [packages/next/src/server/lib/start-server.ts:575-629](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/server/lib/start-server.ts#L575-L629)

> [!NOTE]
> The threshold window for identifying a rapid user restart as a "rage restart" spans 90,000 milliseconds (`RAGE_RESTART_THRESHOLD_MS`).

```typescript
// If the user restarts the dev server within this window we count it as a "rage restart".
const RAGE_RESTART_THRESHOLD_MS = 90_000
```
Sources: [packages/next/src/cli/next-dev.ts:102-103](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-dev.ts#L102-L103)

## Production build invocation and child process management

### Child process execution and output interception

When executing `[[Build Pipeline]]` via `next build`, execution begins inside `nextBuild` where the process title is updated and signal handlers are attached for `SIGTERM` and `SIGINT` to safely invoke `saveCpuProfile` and exit with status codes `143` and `130` respectively. If `process.env.NEXT_PRIVATE_UPGRADE_BUILD_CHILD` is set to `'1'`, output writes are blocked via `blockOnOutputWrites`. Otherwise, `shouldBuildInChild` evaluates whether debuggers, profilers, or AI coding agents are active.

```typescript
const nextBuild = async (options: NextBuildOptions, directory?: string) => {
  process.title = `next-build (v${process.env.__NEXT_VERSION})`

  // To show the upgrade menu without pausing the build, run the build in a
  // child and keep the menu here.
  if (process.env.NEXT_PRIVATE_UPGRADE_BUILD_CHILD === '1') {
    blockOnOutputWrites()
  } else if (await shouldBuildInChild()) {
    return buildInChild()
  }

```
Sources: [packages/next/src/cli/next-build.ts:57-67](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-build.ts#L57-L67)

```typescript
const onTerminate = () => {
  saveCpuProfile()
  process.exit(143)
}
const onInterrupt = () => {
  saveCpuProfile()
  process.exit(130)
}
process.on('SIGTERM', onTerminate)
process.on('SIGINT', onInterrupt)

```
Sources: [packages/next/src/cli/next-build.ts:68-78](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-build.ts#L68-L78)

If building in a child process is approved, `buildInChild` forks the current script with `process.argv` and configures `stdio` with `['inherit', 'pipe', 'pipe', 'ipc']`, passing `NEXT_PRIVATE_UPGRADE_BUILD_CHILD: '1'` and environment variables from `getPromptOutputEnv`. The child process output is captured and managed through `createPromptOutput`, which attaches data listeners to `child.stdout` and `child.stderr`.

```typescript
async function buildInChild(): Promise<never> {
  // Rerun the same command as a child, with its output piped to us.
  const child = fork(process.argv[1], process.argv.slice(2), {
    stdio: ['inherit', 'pipe', 'pipe', 'ipc'],
    env: {
      ...process.env,
      ...getPromptOutputEnv(),
      NEXT_PRIVATE_UPGRADE_BUILD_CHILD: '1',
    },
  })
  const exited = once(child, 'exit') as Promise<
    [number | null, NodeJS.Signals | null]
  >
  const output = createPromptOutput()
  output.attach(child)

```
Sources: [packages/next/src/cli/next-build.ts:215-230](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-build.ts#L215-L230)

```typescript
export function createPromptOutput() {
  // print: show now. hold: keep for later. drop: throw away.
  let mode: 'print' | 'hold' | 'drop' = 'print'
  // One list for stdout and stderr keeps their order.
  let held: Array<[NodeJS.WriteStream, Buffer]> = []
  let heldBytes = 0
  let droppedBytes = 0

  function forward(destination: NodeJS.WriteStream) {
    return (chunk: Buffer) => {
      if (mode === 'print') {
        destination.write(chunk)
      } else if (mode === 'hold') {
        held.push([destination, chunk])
        heldBytes += chunk.length
        // Over the limit: drop the oldest output.
        while (heldBytes > MAX_HELD_BYTES && held.length > 1) {
          const [, oldest] = held.shift()!
          heldBytes -= oldest.length
          droppedBytes += oldest.length
        }
      }
    }
  }
```
Sources: [packages/next/src/lib/upgrade/prompt-output.ts:25-48](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/lib/upgrade/prompt-output.ts#L25-L48)

> [!WARNING]
> Held output bytes are bounded by `MAX_HELD_BYTES` (`10 * 1024 * 1024` bytes). When exceeded while the upgrade menu is open, the oldest chunks are dropped and a warning is logged upon release.

```typescript
// Keep at most this much while the menu is open, so a menu left open doesn't
// grow memory without bound.
const MAX_HELD_BYTES = 10 * 1024 * 1024
```
Sources: [packages/next/src/lib/upgrade/prompt-output.ts:19-21](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/lib/upgrade/prompt-output.ts#L19-L21)

```typescript
heldBytes += chunk.length
// Over the limit: drop the oldest output.
while (heldBytes > MAX_HELD_BYTES && held.length > 1) {
  const [, oldest] = held.shift()!
  heldBytes -= oldest.length
  droppedBytes += oldest.length
}
```
Sources: [packages/next/src/lib/upgrade/prompt-output.ts:39-45](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/lib/upgrade/prompt-output.ts#L39-L45)

### Call-chain execution walkthroughs

The execution paths governing build isolation, output forwarding, and agent evaluation follow strict step-by-General call orders:

1. `nextBuild` invokes `buildInChild` when child execution is required.
2. `buildInChild` executes `showUpgradeMenu` to display upgrade prompts alongside the running process.
3. `showUpgradeMenu` initializes and invokes `flush` on the telemetry storage instance.

```typescript
} else if (await shouldBuildInChild()) {
  return buildInChild()
}
```
Sources: [packages/next/src/cli/next-build.ts:64-66](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-build.ts#L64-L66)

```typescript
export async function showUpgradeMenu(
  output: PromptOutput,
  options: {
    dir: string
    context: UpgradeContext
    command: 'dev' | 'build'
    signal: AbortSignal
    initialAssessment: Promise<UpgradeReminder | null> | null
    // The child's NEXT_TELEMETRY_DISABLED. It loaded .env; this process did
    // not.
    telemetryDisabled: string | undefined
  }
): Promise<UpgradeMenuResult> {
```
Sources: [packages/next/src/lib/upgrade/prompt-output.ts:124-136](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/lib/upgrade/prompt-output.ts#L124-L136)

```typescript
pendingTelemetry = telemetry.flush()

```
Sources: [packages/next/src/lib/upgrade/prompt-output.ts:169-170](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/lib/upgrade/prompt-output.ts#L169-L170)

Sources: [packages/next/src/telemetry/storage.ts:226-228](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/telemetry/storage.ts#L226-L228)

1. `nextBuild` triggers `buildInChild` to fork execution.
2. `buildInChild` calls `createPromptOutput` to instantiate output control buffers.
3. `createPromptOutput` returns handlers including `forward` to route data streams.

```typescript
} else if (await shouldBuildInChild()) {
  return buildInChild()
}
```
Sources: [packages/next/src/cli/next-build.ts:64-66](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-build.ts#L64-L66)

```typescript
const output = createPromptOutput()
output.attach(child)
```
Sources: [packages/next/src/cli/next-build.ts:228-229](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-build.ts#L228-L229)

```typescript
export function createPromptOutput() {
  // print: show now. hold: keep for later. drop: throw away.
  let mode: 'print' | 'hold' | 'drop' = 'print'
  // One list for stdout and stderr keeps their order.
  let held: Array<[NodeJS.WriteStream, Buffer]> = []
  let heldBytes = 0
  let droppedBytes = 0

  function forward(destination: NodeJS.WriteStream) {
```
Sources: [packages/next/src/lib/upgrade/prompt-output.ts:25-33](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/lib/upgrade/prompt-output.ts#L25-L33)

1. `nextBuild` evaluates `shouldBuildInChild`.
2. `shouldBuildInChild` calls `shouldPromptForUpgrade`.
3. `shouldPromptForUpgrade` checks terminal capabilities and calls `getAgentName`.

```typescript
} else if (await shouldBuildInChild()) {
```
Sources: [packages/next/src/cli/next-build.ts:64-64](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-build.ts#L64-L64)

```typescript
async function shouldBuildInChild() {
  const nodeOptions = getParsedNodeOptions()
  if (
    process.env.NEXT_CPU_PROF ||
    getNodeDebugType(nodeOptions) ||
    ['inspect-wait', 'cpu-prof', 'heap-prof', 'prof'].some(
      (flag) => nodeOptions[flag]
    )
  ) {
    return false
  }
  const { shouldPromptForUpgrade } = await import('../lib/upgrade/nudge.js')
  return shouldPromptForUpgrade()
}
```
Sources: [packages/next/src/cli/next-build.ts:199-212](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-build.ts#L199-L212)

```typescript
export async function shouldPromptForUpgrade(): Promise<boolean> {
  return (
    canPromptForUpgrade() &&
    (isTerminalForcedForTesting() || !(await getAgentName()))
  )
}
```
Sources: [packages/next/src/lib/upgrade/nudge.ts:527-532](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/lib/upgrade/nudge.ts#L527-L532)

Sources: [packages/next/src/telemetry/agent-name.ts:17-25](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/telemetry/agent-name.ts#L17-L25)

```mermaid
sequenceDiagram
    participant next-build.ts
    participant prompt-output.ts
    participant nudge.ts
    participant agent-name.ts
    participant storage.ts

    next-build.ts->>next-build.ts: nextBuild
    next-build.ts->>next-build.ts: buildInChild
    next-build.ts->>prompt-output.ts: createPromptOutput
    prompt-output.ts->>prompt-output.ts: forward
    next-build.ts->>prompt-output.ts: showUpgradeMenu
    prompt-output.ts->>storage.ts: flush
    next-build.ts->>next-build.ts: shouldBuildInChild
    next-build.ts->>nudge.ts: shouldPromptForUpgrade
    nudge.ts->>agent-name.ts: getAgentName
```

Sources: [packages/next/src/cli/next-build.ts:57-230](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-build.ts#L57-L230)

Sources: [packages/next/src/lib/upgrade/prompt-output.ts:25-180](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/lib/upgrade/prompt-output.ts#L25-L180)

Sources: [packages/next/src/lib/upgrade/nudge.ts:527-532](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/lib/upgrade/nudge.ts#L527-L532)

Sources: [packages/next/src/telemetry/agent-name.ts:17-25](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/telemetry/agent-name.ts#L17-L25)

Sources: [packages/next/src/telemetry/storage.ts:226-228](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/telemetry/storage.ts#L226-L228)

### Build options and configuration validation

Command-line options parsed into `NextBuildOptions` dictate compiler parameters, feature flags, and diagnostic toggles. Options such as `--analyze` require Turbopack and will terminate via `printAndExit` if combined with other bundlers.

```typescript
export type NextBuildOptions = {
  analyze?: boolean
  experimentalAnalyze?: boolean
  debug?: boolean
  debugPrerender?: boolean
  profile?: boolean
  mangling: boolean
  turbo?: boolean
  turbopack?: boolean
  webpack?: boolean
  customWebpack?: boolean
  experimentalDebugMemoryUsage: boolean
  experimentalAppOnly?: boolean
  experimentalTurbo?: boolean
  experimentalBuildMode: 'default' | 'compile' | 'generate' | 'generate-env'
  experimentalUploadTrace?: string
  experimentalNextConfigStripTypes?: boolean
  debugBuildPaths?: string
  experimentalCpuProf?: boolean
  internalTrace?: string | boolean
}
```
Sources: [packages/next/src/cli/next-build.ts:35-55](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-build.ts#L35-L55)

```typescript
const bundler = parseBundlerArgs(options)

if ((analyze || experimentalAnalyze) && bundler !== Bundler.Turbopack) {
  printAndExit('--analyze is only compatible with the Turbopack bundler.')
}
```
Sources: [packages/next/src/cli/next-build.ts:98-102](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-build.ts#L98-L102)

| Option Property | CLI Flag / Source | Default / Behavior |
| :--- | :--- | :--- |
| `analyze` / `experimentalAnalyze` | `--analyze` / `--experimental-analyze` | Compatible only with Turbopack bundler |
| `mangling` | `--no-mangling` | Emits a warning when disabled for debugging |
| `profile` | `--profile` | Enables build performance profiling |
| `debugPrerender` | `--debug-prerender` | Forces `NODE_ENV='development'` during prerendering |
| `experimentalDebugMemoryUsage` | `--experimental-debug-memory-usage` | Enables memory debugging startup/shutdown routines |
| `experimentalBuildMode` | `--experimental-build-mode` | Restricted to `'default'`, `'compile'`, `'generate'`, or `'generate-env'` |

Sources: [packages/next/src/cli/next-build.ts:35-55](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-build.ts#L35-L55)

Sources: [packages/next/src/cli/next-build.ts:98-168](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-build.ts#L98-L168)

> [!TIP]
> Debugger and profiler executions (such as `--inspect-wait`, `--cpu-prof`, `--heap-prof`, or `NEXT_CPU_PROF`) bypass child process nesting and run directly in the parent process to prevent port collisions or duplicate profiling outputs.

```typescript
// Debugger and profiler runs stay in one process and skip the menu. Otherwise
// the debugger would attach to the wrong process, or there would be two
// profiles.
async function shouldBuildInChild() {
  const nodeOptions = getParsedNodeOptions()
  if (
    process.env.NEXT_CPU_PROF ||
    getNodeDebugType(nodeOptions) ||
    ['inspect-wait', 'cpu-prof', 'heap-prof', 'prof'].some(
      (flag) => nodeOptions[flag]
    )
  ) {
    return false
  }
  const { shouldPromptForUpgrade } = await import('../lib/upgrade/nudge.js')
  return shouldPromptForUpgrade()
}
```
Sources: [packages/next/src/cli/next-build.ts:196-212](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-build.ts#L196-L212)

## Production server CLI initialization

### Options Sanitization and Port Verification

The `nextStart` function coordinates initialization for production server execution. It validates project directories via `getProjectDir`, verifies missing React dependencies, and enforces reserved port checks using `isPortIsReserved` and `getReservedPortExplanation`.

```typescript
const nextStart = async (options: NextStartOptions, directory?: string) => {
  const dir = getProjectDir(directory)
  warnMissingReactDependencies(dir)
  const hostname = options.hostname
  const inspect = options.inspect
  const port = options.port
  const keepAliveTimeout = options.keepAliveTimeout

  if (isPortIsReserved(port)) {
    printAndExit(getReservedPortExplanation(port), 1)
  }
```
Sources: [packages/next/src/cli/next-start.ts:43-53](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-start.ts#L43-L53)

| Option Property | CLI Flag / Source | Description |
| :--- | :--- | :--- |
| `port` | `--port`, `-p` | Target port number for the production server |
| `hostname` | `--hostname`, `-H` | Hostname interface to bind the server against |
| `inspect` | `--inspect` / `--inspect-brk` | Node.js inspector connection parameters |
| `keepAliveTimeout` | `--keep-alive-timeout` | Server keep-alive timeout configuration |
| `experimentalCpuProf` | `--experimental-cpu-prof` | Enables CPU profiling on exit signals |

Sources: [packages/next/src/cli/next-start.ts:27-35](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-start.ts#L27-L35)

> [!CAUTION]
> If a requested port is designated as reserved by system conventions, `printAndExit` terminates process execution with an exit code of `1` before any runtime server instance can be spun up.

```typescript
if (isPortIsReserved(port)) {
  printAndExit(getReservedPortExplanation(port), 1)
}
```
Sources: [packages/next/src/cli/next-start.ts:51-53](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-start.ts#L51-L53)

### Runtime Server Handoff

When debugger inspection options are passed, `nextStart` queries the `inspector` module. If the debug port is already occupied, a warning is emitted; otherwise, `inspector.open` starts the debugger agent on the parsed address before passing configurations to `startServer`.

```typescript
if (inspect) {
  const inspector = await import('inspector')
  const isInspecting = inspector.url() !== undefined
  if (isInspecting) {
    Log.warn(
      `The Node.js debugger port is already open at ${process.debugPort}. Ignoring '--inspect${inspect === true ? '' : `="${formatDebugAddress(inspect)}"`}'.`
    )
  } else {
    const inspectAddress: DebugAddress =
      inspect === true ? getParsedDebugAddress(true) : inspect
    // TODO: Implement --inspect-wait
    const wait = false
    try {
      inspector.open(inspectAddress.port, inspectAddress.host, wait)
    } catch (error) {
      console.error(
        `Failed to start the Node.js inspector with --inspect="${formatDebugAddress(inspectAddress)}":`,
        error
      )
      return process.exit(1)
    }
  }
}
```
Sources: [packages/next/src/cli/next-start.ts:55-77](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-start.ts#L55-L77)

> [!IMPORTANT]
> The `NextServer` class acts as the wrapper server implementation for `next start`, holding internal references to `NextNodeServer` through asynchronous factory loaders while exposing standard request handlers, host properties, and port parameters.

```typescript
/** The wrapper server used by `next start` */
export class NextServer implements NextWrapperServer {
  private serverPromise?: Promise<NextNodeServer>
  private server?: NextNodeServer
  private reqHandler?: NodeRequestHandler
  private reqHandlerPromise?: Promise<NodeRequestHandler>
  private preparedAssetPrefix?: string

  public options: NextServerOptions

  constructor(options: NextServerOptions) {
    this.options = options
  }

  get hostname() {
    return this.options.hostname
  }

  get port() {
    return this.options.port
  }
```
Sources: [packages/next/src/server/next.ts:178-198](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/server/next.ts#L178-L198)

## Diagnostic and deprecated utility commands

### Diagnostic Execution with Next Info

The `next info` CLI command gathers diagnostic information about the host environment, installed packages, and runtime binaries. It supports a `verbose` option to collect deep environmental data. When executing verbose checks, it verifies that the operating system platform is one of the supported environments: `win32`, `linux`, or `darwin`.

```typescript
export type NextInfoOptions = {
  verbose?: boolean
}
```
Sources: [packages/next/src/cli/next-info.ts:14-16](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-info.ts#L14-L16)

```typescript
async function printVerboseInfo() {
  const fs = require('fs') as typeof import('fs')
  const currentPlatform = os.platform()

  if (
    currentPlatform !== 'win32' &&
    currentPlatform !== 'linux' &&
    currentPlatform !== 'darwin'
  ) {
    console.log(
      'Unsupported platform, only win32, linux, darwin are supported.'
    )
    return
  }
```
Sources: [packages/next/src/cli/next-info.ts:257-270](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-info.ts#L257-L270)

The verbose diagnostic routine executes a series of system and application verification tasks, outputting reports for host properties, package versions, and binary installations.

| Diagnostic Task Title | Target Platform | Description |
| :--- | :--- | :--- |
| `Host system information` | Default (`win32`, `linux`, `darwin`) | Collects WSL status, Docker environment checks, and CI environment detection via `ci-info`. |
| `Next.js installation` | Default (`win32`, `linux`, `darwin`) | Reports active Node, npm, Yarn, and pnpm versions alongside related package versions (`next`, `eslint-config-next`, `react`, `react-dom`, `typescript`) and config output fields. |
| `Node.js diagnostic report` | Default (`win32`, `linux`, `darwin`) | Queries `process.report?.getReport()` while sanitizing sensitive header fields such as `cwd`, `commandLine`, `host`, `cpus`, and `networkInterfaces`. |
| `next-swc installation` | Default (`win32`, `linux`, `darwin`) | Validates SWC native bindings via `loadBindings` target retrieval, falling back to resolving platform architecture triples or checking local `next-swc-fallback` directories. |

Sources: [packages/next/src/cli/next-info.ts:273-462](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-info.ts#L273-L462)

> [!WARNING]
> If the Node.js diagnostic report API is unavailable on the current runtime, the diagnostic task flags a failure status and reports that the Node.js diagnostic report is missing rather than crashing the CLI process.

```typescript
title: 'Node.js diagnostic report',
scripts: {
  default: async () => {
    const report = process.report?.getReport()

    if (!report) {
      return {
        messages: 'Node.js diagnostic report is not available.',
        result: 'fail',
      }
    }
```
Sources: [packages/next/src/cli/next-info.ts:335-345](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-info.ts#L335-L345)

### Deprecation Flow of Next Export

The deprecated `next export` command has been fully removed from the active CLI runtime in favor of configuration-driven static exports. When invoked, it writes an error log instructing users to migrate to the `output: 'export'` property inside `next.config.js` and immediately terminates the process with an exit code of `1`.

```typescript
const nextExport = () => {
  error(`
    \`next export\` has been removed in favor of 'output: export' in next.config.js.\nLearn more: ${cyan(
      'https://nextjs.org/docs/app/building-your-application/deploying/static-exports'
    )}
  `)

  process.exit(1)
}
```
Sources: [packages/next/src/cli/next-export.ts:4-12](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-export.ts#L4-L12)

## Related

- [Build Pipeline](https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/build-system/build-pipeline)
- [Development Server](https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/development/development-server)
- [Upgrade and Codemods](https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/cli-telemetry/upgrade-and-codemods)


## Sitemap

See the full [sitemap](https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/llms.txt) for all pages in this wiki.
