---
title: "Upgrade and Codemods"
description: "The @next/codemod package provides automated AST transformation pipelines and upgrade tooling designed to modernize Next.js codebases, update deprecated configurations, and safely migrate dependenc..."
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/upgrade-and-codemods"
---

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

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

- [packages/next-codemod/bin/transform.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/bin/transform.ts)
- [packages/next-codemod/bin/upgrade.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/bin/upgrade.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-codemod/transforms/next-lint-to-eslint-cli.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/next-lint-to-eslint-cli.ts)
- [packages/next-codemod/transforms/next-image-experimental.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/next-image-experimental.ts)
- [packages/next-codemod/transforms/url-to-withrouter.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/url-to-withrouter.ts)
- [packages/next-codemod/transforms/cra-to-next.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/cra-to-next.ts)
- [packages/next-codemod/lib/utils.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/lib/utils.ts)
- [packages/next-codemod/transforms/next-image-to-legacy-image.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/next-image-to-legacy-image.ts)
- [packages/next-codemod/transforms/middleware-to-proxy.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/middleware-to-proxy.ts)
- [packages/next-codemod/transforms/next-experimental-turbo-to-turbopack.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/next-experimental-turbo-to-turbopack.ts)
- [packages/next-codemod/transforms/remove-unstable-prefix.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/remove-unstable-prefix.ts)
- [packages/next-codemod/lib/run-jscodeshift.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/lib/run-jscodeshift.ts)
- [packages/next-codemod/transforms/new-link.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/new-link.ts)
- [packages/next/src/cli/next-upgrade.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-upgrade.ts)
- [packages/next-codemod/transforms/lib/async-request-api/index.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/lib/async-request-api/index.ts)
- [packages/next-codemod/transforms/next-async-request-api.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/next-async-request-api.ts)
- [packages/next-codemod/transforms/lib/async-request-api/next-async-dynamic-prop.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/lib/async-request-api/next-async-dynamic-prop.ts)
- [packages/next-codemod/transforms/next-og-import.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/next-og-import.ts)
- [packages/next-codemod/package.json](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/package.json)
- [packages/next-codemod/transforms/built-in-next-font.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/built-in-next-font.ts)
- [packages/next/src/build/duration-to-string.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/build/duration-to-string.ts)
- [packages/next/src/server/config.ts](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/server/config.ts)
</details>

## Overview

The `@next/codemod` package provides automated AST transformation pipelines and upgrade tooling designed to modernize Next.js codebases, update deprecated configurations, and safely migrate dependencies across major framework releases. By combining programmatic Abstract Syntax Tree (AST) manipulation via `jscodeshift` with interactive CLI workflows, it eliminates manual refactoring overhead when adopting breaking changes [packages/next-codemod/bin/next-codemod.ts:12-47](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/bin/next-codemod.ts#L12-L47), [packages/next-codemod/bin/transform.ts:25-242](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/bin/transform.ts#L25-L242).

Sources: [packages/next-codemod/bin/next-codemod.ts:12-47](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/bin/next-codemod.ts#L12-L47), [packages/next-codemod/bin/transform.ts:25-242](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/bin/transform.ts#L25-L242)]

## Upgrade CLI and Telemetry Orchestration

### Call-Chain Execution Walkthrough

Project upgrades and automated telemetry reporting are orchestrated through CLI entrypoints that spawn child processes, validate project structures, and load user configurations without strict schema validation against current Next.js rules [packages/next/src/cli/next-upgrade.ts:143-150](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-upgrade.ts#L143-L150). The `spawnNextUpgrade` function bootstraps the upgrade flow by validating dependencies, resolving project paths, and optionally handling agent-driven upgrades [packages/next/src/cli/next-upgrade.ts:177-184](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-upgrade.ts#L177-L184). Upgrade telemetry events track invocation outcomes, metadata failures, guide preparations, and agent results through bounded identifiers and status codes [packages/next/src/cli/next-upgrade.ts:23-30](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-upgrade.ts#L23-30), [packages/next/src/cli/next-upgrade.ts:639-652](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-upgrade.ts#L639-L652).

Sources: [packages/next/src/cli/next-upgrade.ts:23-30](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-upgrade.ts#L23-L30), [packages/next/src/cli/next-upgrade.ts:143-150](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-upgrade.ts#L143-L150), [packages/next/src/cli/next-upgrade.ts:177-184](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-upgrade.ts#L177-L184), [packages/next/src/cli/next-upgrade.ts:639-652](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-upgrade.ts#L639-L652)]

The upgrade result reporting and configuration loading pipeline follows a strict execution sequence from incoming telemetry handlers down to low-level duration string formatting and React version inspection.

1. `reportAgentUpgradeAgentResult` — Validates the upgrade run UUID against `UUID_PATTERN` and checks that the result is strictly `success` or `failure` before initializing telemetry [packages/next/src/cli/next-upgrade.ts:699-712](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-upgrade.ts#L699-L712).
2. `loadAgentUpgradeConfig` — Invokes configuration loading with `PHASE_PRODUCTION_BUILD` and raw config flags enabled [packages/next/src/cli/next-upgrade.ts:143-150](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-upgrade.ts#L143-L150).
3. `loadConfig` — Measures high-resolution timing via BigInt nanoseconds when logging is enabled and calls the underlying implementation [packages/next/src/server/config.ts:1938-1962](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/server/config.ts#L1938-L1962).
4. `loadConfigImpl` — Resolves cache keys using `getCacheKey`, checks `configCache`, loads environment configs, and applies validation rules [packages/next/src/server/config.ts:1980-2089](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/server/config.ts#L1980-L2089).
5. `finalizeConfig` — Applies post-processing mutations for experimental features, output hashes, and asset token support [packages/next/src/server/config.ts:1813-1862](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/server/config.ts#L1813-L1862).

Sources: [packages/next/src/cli/next-upgrade.ts:143-150](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-upgrade.ts#L143-L150), [packages/next/src/cli/next-upgrade.ts:699-712](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-upgrade.ts#L699-L712), [packages/next/src/server/config.ts:1813-1862](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/server/config.ts#L1813-L1862), [packages/next/src/server/config.ts:1938-1962](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/server/config.ts#L1938-L1962), [packages/next/src/server/config.ts:1980-2089](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/server/config.ts#L1980-L2089)]

> [!NOTE]
> `reportAgentUpgradeAgentResult` validates that project details and error text never enter telemetry payloads, accepting only a bounded run UUID and binary success or failure outcomes [packages/next/src/cli/next-upgrade.ts:703-711](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-upgrade.ts#L703-L711).

An alternative execution path executes duration formatting and package version inspections during initialization:

1. `reportAgentUpgradeAgentResult` — Receives the run identifier and completion status [packages/next/src/cli/next-upgrade.ts:699-702](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-upgrade.ts#L699-L702).
2. `loadAgentUpgradeConfig` — Reads raw configuration without enforcing current schema constraints [packages/next/src/cli/next-upgrade.ts:143-150](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-upgrade.ts#L143-L150).
3. `loadConfig` — Wraps implementation execution and computes configuration load duration [packages/next/src/server/config.ts:1938-1972](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/server/config.ts#L1938-L1972).
4. `hrtimeBigIntDurationToString` — Converts high-resolution BigInt nanosecond durations into human-readable strings [packages/next/src/build/duration-to-string.ts:86-88](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/build/duration-to-string.ts#L86-L88).
5. `durationToStringWithNanoseconds` — Determines the magnitude tier (minutes, seconds, or milliseconds) and formats precision accordingly [packages/next/src/build/duration-to-string.ts:53-66](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/build/duration-to-string.ts#L53-L66).

Sources: [packages/next/src/cli/next-upgrade.ts:143-150](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-upgrade.ts#L143-L150), [packages/next/src/cli/next-upgrade.ts:699-702](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-upgrade.ts#L699-L702), [packages/next/src/build/duration-to-string.ts:53-66](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/build/duration-to-string.ts#L53-L66), [packages/next/src/build/duration-to-string.ts:86-88](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/build/duration-to-string.ts#L86-L88), [packages/next/src/server/config.ts:1938-1972](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/server/config.ts#L1938-L1972)]

A third trace branch handles React deprecation checks during configuration loading:

1. `reportAgentUpgradeAgentResult` — Initiates the telemetry reporting sequence [packages/next/src/cli/next-upgrade.ts:699-702](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-upgrade.ts#L699-L702).
2. `loadAgentUpgradeConfig` — Loads the unconstrained app configuration [packages/next/src/cli/next-upgrade.ts:143-150](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-upgrade.ts#L143-L150).
3. `loadConfig` — Calls `loadConfigImpl` and subsequently triggers React version warnings [packages/next/src/server/config.ts:1938-1964](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/server/config.ts#L1938-L1964).
4. `warnIfReact18IsInstalled` — Inspects [development server](https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/development/development-server) or production build phases for React 18 installations [packages/next/src/server/config.ts:81-98](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/server/config.ts#L81-L98).
5. `getInstalledPackageVersion` — Resolves the package.json path using `createRequire` and extracts the installed version string [packages/next/src/server/config.ts:72-79](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/server/config.ts#L72-L79).

Sources: [packages/next/src/cli/next-upgrade.ts:143-150](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-upgrade.ts#L143-L150), [packages/next/src/cli/next-upgrade.ts:699-702](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-upgrade.ts#L699-L702), [packages/next/src/server/config.ts:72-79](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/server/config.ts#L72-L79), [packages/next/src/server/config.ts:81-98](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/server/config.ts#L81-L98), [packages/next/src/server/config.ts:1938-1964](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/server/config.ts#L1938-L1964)]

```mermaid
sequenceDiagram
  participant next-upgrade.ts
  participant config.ts
  participant duration-to-string.ts
  next-upgrade.ts->>config.ts: reportAgentUpgradeAgentResult() → loadAgentUpgradeConfig() → loadConfig()
  config.ts->>duration-to-string.ts: hrtimeBigIntDurationToString() → durationToStringWithNanoseconds()
```

Sources: [packages/next/src/cli/next-upgrade.ts:143-150](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-upgrade.ts#L143-L150), [packages/next/src/cli/next-upgrade.ts:699-702](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/cli/next-upgrade.ts#L699-L702), [packages/next/src/build/duration-to-string.ts:53-88](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/build/duration-to-string.ts#L53-L88), [packages/next/src/server/config.ts:1938-1964](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next/src/server/config.ts#L1938-L1964)]

## Interactive Upgrade Assistant Flow

### Semantic Revision Resolution and Version Inspection

The upgrade assistant inspects installed project versions by parsing local `package.json` files and invoking package resolution helpers. `getInstalledNextVersion()` and `getInstalledReactVersion()` resolve package paths relative to the current working directory (`cwd`), extracting version strings from `next/package.json` and `react/package.json`. If version detection fails, a `BadInput` error prompts users running inside monorepos to execute commands directly from the Next.js app directory.

```typescript
function getInstalledNextVersion(): string {
  try {
    return require(
      require.resolve('next/package.json', {
        paths: [cwd],
      })
    ).version
  } catch (error) {
    throw new BadInput(
      `Failed to get the installed Next.js version at "${cwd}".\nIf you're using a monorepo, please run this command from the Next.js app directory.`,
      {
        cause: error,
      }
    )
  }
}

function getInstalledReactVersion(): string {
  try {
    return require(
      require.resolve('react/package.json', {
        paths: [cwd],
      })
    ).version
  } catch (error) {
    throw new BadInput(
      `Failed to detect the installed React version in "${cwd}".\nIf you're working in a monorepo, please run this command from the Next.js app directory.`,
      {
        cause: error,
      }
    )
  }
}
```

Sources: [packages/next-codemod/bin/upgrade.ts:558-590](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/bin/upgrade.ts#L558-L590)

Semantic version keywords supplied via the CLI revision argument are mapped through `resolveSemanticRevision()` to generate explicit npm version queries based on the currently installed major and minor version numbers.

| Revision Keyword | Resolution Behavior | Generated Query |
| :--- | :--- | :--- |
| `patch` | Targets the latest patch within the current minor version | `~${installedMajor}.${installedMinor}.0` |
| `minor` | Targets the latest minor within the current major version | `^${installedMajor}.0.0` |
| `major` | Targets the latest stable release | `latest` |
| *custom/other* | Preserves the provided revision string verbatim | `revision` |

```typescript
function resolveSemanticRevision(
  revision: string,
  installedVersion: string
): string {
  const installedMajor = major(installedVersion)
  const installedMinor = minor(installedVersion)

  switch (revision) {
    case 'patch':
      // ~15.0.0 matches >=15.0.0 <15.1.0
      return `~${installedMajor}.${installedMinor}.0`
    case 'minor':
      // ^15.0.0 matches >=15.0.0 <16.0.0
      return `^${installedMajor}.0.0`
    case 'major':
      return 'latest'
    default:
      return revision
  }
}
```

Sources: [packages/next-codemod/bin/upgrade.ts:93-112](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/bin/upgrade.ts#L93-L112)

> [!NOTE]
> `loadHighestNPMVersionMatching()` executes synchronous `npm view` queries with JSON output enabled to validate React and Next.js compatibility ranges, sorting matching versions with semver comparison utilities to select the highest valid release.

```typescript
async function loadHighestNPMVersionMatching(query: string) {
  const versionsJSON = execSync(
    `npm --silent view "${query}" --json --field version`,
    { encoding: 'utf-8' }
  )
  const versionOrVersions = JSON.parse(versionsJSON)
  if (versionOrVersions.length < 1) {
    throw new Error(
      `Found no React versions matching "${query}". This is a bug in the upgrade tool.`
    )
  }
  // npm-view returns an array if there are multiple versions matching the query.
  if (Array.isArray(versionOrVersions)) {
    // The last entry will be the latest version published.
    // But we want the highest version.
    versionOrVersions.sort(compareVersions)
    return versionOrVersions[versionOrVersions.length - 1]
  }
  return versionOrVersions
}
```

Sources: [packages/next-codemod/bin/upgrade.ts:46-65](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/bin/upgrade.ts#L46-L65)

### Turbopack and Codemod Heuristics

Project upgrade flows evaluate directory structures and script definitions using automated heuristics. `isUsingPagesDir()` and `isUsingAppDir()` check for the presence of `pages` or `app` directories at the project root or inside `src/`.

```typescript
function isUsingPagesDir(projectPath: string): boolean {
  return (
    fs.existsSync(path.resolve(projectPath, 'pages')) ||
    fs.existsSync(path.resolve(projectPath, 'src/pages'))
  )
}
function isUsingAppDir(projectPath: string): boolean {
  return (
    fs.existsSync(path.resolve(projectPath, 'app')) ||
    fs.existsSync(path.resolve(projectPath, 'src/app'))
  )
}
```

Sources: [packages/next-codemod/bin/upgrade.ts:592-603](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/bin/upgrade.ts#L592-L603)

Turbopack adoption is guided by inspecting the `dev` script in `package.json`. Depending on the target Next.js version, the assistant selects between `--turbo` and `--turbopack` flags based on the `15.0.1-canary.3` release threshold.

```typescript
async function suggestTurbopack(
  packageJson: any,
  targetNextVersion: string,
  nonInteractive: boolean
): Promise<void> {
  const devScript: string | undefined = packageJson.scripts?.['dev']
  // Turbopack flag was changed from `--turbo` to `--turbopack` in v15.0.1-canary.3
  // PR: https://github.com/vercel/next.js/pull/71657
  // Release: https://github.com/vercel/next.js/releases/tag/v15.0.1-canary.3
  const isAfterTurbopackFlagChange =
    compareVersions(targetNextVersion, '15.0.1-canary.3') >= 0
  const turboPackFlag = isAfterTurbopackFlagChange ? '--turbopack' : '--turbo'
```

Sources: [packages/next-codemod/bin/upgrade.ts:616-627](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/bin/upgrade.ts#L616-L627)

> [!CAUTION]
> The Turbopack CLI flag was renamed from `--turbo` to `--turbopack` starting in version `15.0.1-canary.3`; target version comparisons ensure backward-compatible script generation.

```typescript
// Turbopack flag was changed from `--turbo` to `--turbopack` in v15.0.1-canary.3
// PR: https://github.com/vercel/next.js/pull/71657
// Release: https://github.com/vercel/next.js/releases/tag/v15.0.1-canary.3
const isAfterTurbopackFlagChange =
  compareVersions(targetNextVersion, '15.0.1-canary.3') >= 0
const turboPackFlag = isAfterTurbopackFlagChange ? '--turbopack' : '--turbo'
```

Sources: [packages/next-codemod/bin/upgrade.ts:622-627](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/bin/upgrade.ts#L622-L627)

Available codemods and framework migrations are enumerated in `TRANSFORMER_INQUIRER_CHOICES`, tracking specific target versions and adoption flags across releases ranging from legacy URL transforms to modern cache component configurations.

```typescript
export const TRANSFORMER_INQUIRER_CHOICES = [
  {
    title:
      'Transform the deprecated automatically injected url property on top level pages to using withRouter',
    value: 'url-to-withrouter',
    version: '6.0.0',
  },
  {
    title:
      'Transforms anonymous components into named components to make sure they work with Fast Refresh',
    value: 'name-default-component',
    version: '9.0.0',
  },
  {
    title:
      'Transforms files that do not import `React` to include the import in order for the new React JSX transform',
    value: 'add-missing-react-import',
    version: '10.0.0',
  },
  {
    title:
      'Automatically migrates a Create React App project to Next.js (experimental)',
    value: 'cra-to-next',
    version: '11.0.0',
  },
  {
    title: 'Ensures your <Link> usage is backwards compatible',
    value: 'new-link',
    version: '13.0.0',
  },
  {
    title:
      'Dangerously migrates from `next/legacy/image` to the new `next/image` by adding inline styles and removing unused props (experimental)',
    value: 'next-image-experimental',
    version: '13.0.0',
  },
  {
    title:
      'Safely migrate Next.js 10, 11, 12 applications importing `next/image` to the renamed `next/legacy/image` import in Next.js 13',
    value: 'next-image-to-legacy-image',
    version: '13.0.0',
  },
  {
    title: 'Uninstall `@next/font` and transform imports to `next/font`',
    value: 'built-in-next-font',
    version: '13.2.0',
  },
  {
    title:
      'Migrates certain viewport related metadata from the `metadata` export to a new `viewport` export',
    value: 'metadata-to-viewport-export',
    version: '14.0.0',
  },
  {
    title:
      'Transforms imports from `next/server` to `next/og` for usage of Dynamic OG Image Generation',
    value: 'next-og-import',
    version: '14.0.0',
  },
  {
    title:
      'Install `@vercel/functions` to replace `geo` and `ip` properties on `NextRequest`',
    value: 'next-request-geo-ip',
    version: '15.0.0-canary.153',
  },
  {
    title: 'Transforms usage of Next.js async Request APIs',
    value: 'next-async-request-api',
    version: '15.0.0-canary.171',
  },
  {
    title:
      'Transform App Router Route Segment Config `runtime` value from `experimental-edge` to `edge`',
    value: 'app-dir-runtime-config-experimental-edge',
    version: '15.0.0-canary.179',
  },
  {
    title: 'Updates `next.config.js` to use the new `turbopack` configuration',
    value: 'next-experimental-turbo-to-turbopack',
    version: '15.4.2-canary.21',
```

Sources: [packages/next-codemod/lib/utils.ts:47-163](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/lib/utils.ts#L47-L163)

## Codemod Runner and Execution Pipeline

### Git Working Tree Validation and Path Expansion

The execution pipeline initializes by validating the state of the local git working tree via `checkGitStatus()`. Unless the `--dry` or `--force` flags are active, `isGitClean.sync()` inspects the working directory to confirm there are no uncommitted changes. If the repository is dirty and force validation is omitted, the process terminates immediately with an exit code of `1`.

```typescript
if (!options.dry) {
  checkGitStatus(options.force)
}
```

```typescript
export function checkGitStatus(force) {
  let clean = false
  let errorMessage = 'Unable to determine if git directory is clean'
  try {
    clean = isGitClean.sync(process.cwd())
    errorMessage = 'Git directory is not clean'
  } catch (err) {
    if (err && err.stderr && err.stderr.includes('Not a git repository')) {
      clean = true
    }
  }

  if (!clean) {
    if (force) {
      console.log(`WARNING: ${errorMessage}. Forcibly continuing.`)
    } else {
      console.log('Thank you for using @next/codemod!')
      console.log(
        yellow(
          '\nBut before we continue, please stash or commit your git changes.'
        )
      )
      console.log(
        '\nYou may use the --force flag to override this safety check.'
      )
      process.exit(1)
    }
  }
}
```

Sources: [packages/next-codemod/bin/transform.ts:33-35](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/bin/transform.ts#L33-L35), [packages/next-codemod/lib/utils.ts:7-35](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/lib/utils.ts#L7-L35)

> [!WARNING]
> If a directory is not a valid git repository, `checkGitStatus()` catches the `Not a git repository` error from standard error streams and treats the directory as clean, allowing execution to proceed outside version control.

```typescript
} catch (err) {
  if (err && err.stderr && err.stderr.includes('Not a git repository')) {
    clean = true
  }
}
```

Sources: [packages/next-codemod/lib/utils.ts:13-17](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/lib/utils.ts#L13-L17)

When file paths or glob patterns are supplied to `runTransform()`, `expandFilePathsIfNeeded()` inspects the argument array for wildcard characters (`*`). If found, it invokes synchronous `globby.sync()` to expand paths into concrete file targets across the disk.

```typescript
function expandFilePathsIfNeeded(filesBeforeExpansion) {
  const shouldExpandFiles = filesBeforeExpansion.some((file) =>
    file.includes('*')
  )
  return shouldExpandFiles
    ? globby.sync(filesBeforeExpansion)
    : filesBeforeExpansion
}
```

Sources: [packages/next-codemod/bin/transform.ts:13-20](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/bin/transform.ts#L13-L20)

### JSCodeshift Invocation and Output Parsing

Codemods that do not execute custom handlers directly are delegated to the `jscodeshift` executable via `execa`. `runTransform()` assembles command-line arguments based on user-supplied options, applying standard parsers, ignore patterns, and file extensions.

| Option Flag | Argument Value Generated | Purpose |
| :--- | :--- | :--- |
| `dry` | `--dry` | Simulates the transform without modifying files |
| `print` | `--print` | Outputs transformed file contents directly to `stdout` |
| `runInBand` | `--run-in-band` | Serializes transform execution across files |
| `verbose` | `--verbose=2` | Increases logging verbosity level |
| *default* | `--parser=tsx` | Sets default AST parser to `tsx` |
| *default* | `--ignore-pattern=**/node_modules/**` | Excludes dependency directories |
| *default* | `--ignore-pattern=**/.next/**` | Excludes build output directories |
| *default* | `--extensions=tsx,ts,jsx,js,mjs` | Restricts transformation targets to JS/TS extensions |

```typescript
const { dry, print, runInBand, jscodeshift, verbose } = options

if (dry) {
  args.push('--dry')
}
if (print) {
  args.push('--print')
}
if (runInBand) {
  args.push('--run-in-band')
}
if (verbose) {
  args.push('--verbose=2')
}
args.push('--parser=tsx')

args.push('--ignore-pattern=**/node_modules/**')
args.push('--ignore-pattern=**/.next/**')

args.push('--extensions=tsx,ts,jsx,js,mjs')

```

Sources: [packages/next-codemod/bin/transform.ts:123-143](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/bin/transform.ts#L123-L143)

During execution, `execaChildProcess.stdout` streams character chunks into a sliding window buffer (`lastThreeLineBreaks`) retaining the last three line breaks. This buffer isolates the final success summary line matching the pattern `N ok`.

```typescript
execaChildProcess.stdout.on('data', (chunk) => {
  lastThreeLineBreaks += chunk.toString('utf-8')

  let cutoff = lastThreeLineBreaks.length

  // Note: the stdout ends with "\n".
  // "foo\n" + "bar\n" + "baz\n" -> "\nbar\nbaz\n"
  // "\n" + "foo\n" + "bar\n" -> "\nfoo\nbar\n"

  for (let i = 0; i < 3; i++) {
    cutoff = lastThreeLineBreaks.lastIndexOf('\n', cutoff) - 1
  }

  if (cutoff > 0 && cutoff < lastThreeLineBreaks.length) {
    lastThreeLineBreaks = lastThreeLineBreaks.slice(cutoff + 1)
  }
})
```

Sources: [packages/next-codemod/bin/transform.ts:173-189](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/bin/transform.ts#L173-L189)

```typescript
const targetOkLine = lastThreeLineBreaks.split('\n').at(-3)

if (!targetOkLine.endsWith('ok')) {
  throw new Error(
    `Failed to parse the successful transformation count "${targetOkLine}". This is a bug in the codemod tool.`
  )
}

const stripped = stripAnsi(targetOkLine)
// "N ok" -> "N"
const parsedNum = parseInt(stripped.split(' ')[0], 10)
const hasChanges = parsedNum > 0
```

Sources: [packages/next-codemod/bin/transform.ts:204-215](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/bin/transform.ts#L204-L215)

## Async Request API Migration Transforms

### Dynamic Property and API Transformation Pipeline

The async request API transform orchestrator executes a sequential pipeline composed of dynamic property transforms and dynamic API transforms. Given a source file and an `API` instance from `jscodeshift`, the runner reduces over the transformation functions, passing the file path and updating the source string incrementally when changes occur.

```typescript
export default function transform(file: FileInfo, api: API) {
  const transforms = [transformDynamicProps, transformDynamicAPI]

  return transforms.reduce<string>((source, transformFn) => {
    const result = transformFn(source, api, file.path)
    if (!result) {
      return source
    }
    return result
  }, file.source)
}
```

Sources: [packages/next-codemod/transforms/lib/async-request-api/index.ts:5-15](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/lib/async-request-api/index.ts#L5-L15)

```typescript
export { default } from './lib/async-request-api/index'
```

Sources: [packages/next-codemod/transforms/next-async-request-api.ts:1-1](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/next-async-request-api.ts#L1-L1)

### Member Access Awaiting and React Use Integration

For dynamic properties, `awaitMemberAccessOfProp()` scans the target function body for member expressions matching identifier names like `props`. When an access matches target property names, the transform checks parent scopes and expressions to determine if an `await` expression can be inserted. If a member access parent scope is synchronous and distinct from the function itself, conversion is blocked and an error comment prefix (`NEXT_CODEMOD_ERROR_PREFIX`) is injected into the node to warn the developer.

```typescript
function awaitMemberAccessOfProp(
  propIdName: string,
  path: ASTPath<FunctionScope>,
  j: API['jscodeshift']
) {
  // search the member access of the prop
  const functionBody = findFunctionBody(path)
  const memberAccess = j(functionBody).find(j.MemberExpression, {
    object: {
      type: 'Identifier',
      name: propIdName,
    },
  })

  let hasAwaited = false
  // await each member access
  memberAccess.forEach((memberAccessPath) => {
    const member = memberAccessPath.value

    const memberProperty = member.property
    const isAccessingMatchedProperty =
      j.Identifier.check(memberProperty) &&
      TARGET_PROP_NAMES.has(memberProperty.name)

    if (!isAccessingMatchedProperty) {
      return
    }

    if (isParentPromiseAllCallExpression(memberAccessPath, j)) {
      return
    }

    // check if it's already awaited
    if (memberAccessPath.parentPath?.value.type === 'AwaitExpression') {
      return
    }

    const parentScopeOfMemberAccess = findClosetParentFunctionScope(
      memberAccessPath,
      j
    )

    // When the parent scope is sync, and it's also not the function itself, which means it's not able to convert to async.
    if (
      parentScopeOfMemberAccess &&
      !parentScopeOfMemberAccess.value?.async &&
      parentScopeOfMemberAccess.node !== path.node
    ) {
      // If it's not able to convert, add a comment to the prop access to warn the user
      // e.g. the parent scope is sync, await keyword can't be applied
      const comment = ` ${NEXT_CODEMOD_ERROR_PREFIX} '${propIdName}.${memberProperty.name}' is accessed without awaiting.`
      insertCommentOnce(member, j, comment)
      return
    }

    const awaitedExpr = j.awaitExpression(member)

    const awaitMemberAccess = wrapParentheseIfNeeded(true, j, awaitedExpr)
    memberAccessPath.replace(awaitMemberAccess)
    hasAwaited = true
  })
```

Sources: [packages/next-codemod/transforms/lib/async-request-api/next-async-dynamic-prop.ts:37-97](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/lib/async-request-api/next-async-dynamic-prop.ts#L37-L97)

> [!WARNING]
> If a parent function scope is synchronous and cannot be converted to `async`, `awaitMemberAccessOfProp()` skips replacement and injects a warning comment directly into the source code rather than throwing an unhandled exception.

```typescript
const parentScopeOfMemberAccess = findClosetParentFunctionScope(
  memberAccessPath,
  j
)

// When the parent scope is sync, and it's also not the function itself, which means it's not able to convert to async.
if (
  parentScopeOfMemberAccess &&
  !parentScopeOfMemberAccess.value?.async &&
  parentScopeOfMemberAccess.node !== path.node
) {
  // If it's not able to convert, add a comment to the prop access to warn the user
  // e.g. the parent scope is sync, await keyword can't be applied
  const comment = ` ${NEXT_CODEMOD_ERROR_PREFIX} '${propIdName}.${memberProperty.name}' is accessed without awaiting.`
  insertCommentOnce(member, j, comment)
  return
}
```

Sources: [packages/next-codemod/transforms/lib/async-request-api/next-async-dynamic-prop.ts:74-90](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/lib/async-request-api/next-async-dynamic-prop.ts#L74-L90)

Alternatively, `applyUseAndRenameAccessedProp()` rewrites synchronous property accesses to leverage React's `use()` hook. It traverses member expressions on the property identifier, records accessed member names, replaces member expressions with their property identifiers, and unshifts a `const` variable declaration invoking `use()` on the accessed property directly into the function body scope.

```typescript
function applyUseAndRenameAccessedProp(
  propIdName: string,
  path: ASTPath<FunctionScope>,
  j: API['jscodeshift']
) {
  // search the member access of the prop, and rename the member access to the member value
  // e.g.
  // props.params => params
  // props.params.foo => params.foo
  // props.searchParams.search => searchParams.search
  let modified = false
  const functionBody = findFunctionBody(path)
  const memberAccess = j(functionBody).find(j.MemberExpression, {
    object: {
      type: 'Identifier',
      name: propIdName,
    },
  })

  const accessedNames: string[] = []
  // rename each member access
  memberAccess.forEach((memberAccessPath) => {
    // If the member access expression is first argument of `use()`, we skip
    if (isParentUseCallExpression(memberAccessPath, j)) {
      return
    }

    const member = memberAccessPath.value
    const memberProperty = member.property
    if (j.Identifier.check(memberProperty)) {
      accessedNames.push(memberProperty.name)
    } else if (j.MemberExpression.check(memberProperty)) {
      let currentMember = memberProperty
      if (j.Identifier.check(currentMember.object)) {
        accessedNames.push(currentMember.object.name)
      }
    }
    memberAccessPath.replace(memberProperty)
  })

  // If there's any renamed member access, need to call `use()` onto member access
  // e.g. ['params'] => insert `const params = use(props.params)`
  if (accessedNames.length > 0) {
    const accessedPropId = j.identifier(propIdName)
    const accessedProp = j.memberExpression(
      accessedPropId,
      j.identifier(accessedNames[0])
    )

    const useCall = j.callExpression(j.identifier('use'), [accessedProp])
    const useDeclaration = j.variableDeclaration('const', [
      j.variableDeclarator(j.identifier(accessedNames[0]), useCall),
    ])

    if (functionBody) {
      functionBody.unshift(useDeclaration)
    }

    modified = true
  }
  return modified
}
```

Sources: [packages/next-codemod/transforms/lib/async-request-api/next-async-dynamic-prop.ts:114-175](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/lib/async-request-api/next-async-dynamic-prop.ts#L114-L175)

## Core Next.js Configuration Transforms

### Middleware Route Proxy and Configuration Mapping

Next.js codemods automate the renaming of legacy middleware configuration properties, type imports, and file structures to their proxy equivalents. The `middleware-to-proxy` transform scans configuration files, middleware modules, and files importing from `next/server` to replace deprecated identifiers. Specifically, `CONFIG_PROPERTY_MAP` translates four legacy configuration properties, while `MIDDLEWARE_TYPE_IMPORT_MAP` maps server types to their updated counterparts.

| Legacy Property | New Proxy Property | Sources |
| :--- | :--- | :--- |
| `middlewarePrefetch` | `proxyPrefetch` | [packages/next-codemod/transforms/middleware-to-proxy.ts:21-21](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/middleware-to-proxy.ts#L21-L21) |
| `middlewareClientMaxBodySize` | `proxyClientMaxBodySize` | [packages/next-codemod/transforms/middleware-to-proxy.ts:22-22](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/middleware-to-proxy.ts#L22-L22) |
| `externalMiddlewareRewritesResolve` | `externalProxyRewritesResolve` | [packages/next-codemod/transforms/middleware-to-proxy.ts:23-23](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/middleware-to-proxy.ts#L23-L23) |
| `skipMiddlewareUrlNormalize` | `skipProxyUrlNormalize` | [packages/next-codemod/transforms/middleware-to-proxy.ts:24-24](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/middleware-to-proxy.ts#L24-L24) |

Sources: [packages/next-codemod/transforms/middleware-to-proxy.ts:19-25](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/middleware-to-proxy.ts#L19-L25)

| Legacy Type Import | New Type Import | Sources |
| :--- | :--- | :--- |
| `NextMiddleware` | `NextProxy` | [packages/next-codemod/transforms/middleware-to-proxy.ts:29-29](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/middleware-to-proxy.ts#L29-L29) |
| `MiddlewareConfig` | `ProxyConfig` | [packages/next-codemod/transforms/middleware-to-proxy.ts:30-30](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/middleware-to-proxy.ts#L30-L30) |

Sources: [packages/next-codemod/transforms/middleware-to-proxy.ts:27-31](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/middleware-to-proxy.ts#L27-L31)

> [!WARNING]
> When processing a middleware file, the transformer removes runtime segment configurations entirely and unlinks the original middleware file after writing the new proxy file output.

Sources: [packages/next-codemod/transforms/middleware-to-proxy.ts:63-86](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/middleware-to-proxy.ts#L63-L86)

### Turbopack Options and Unstable Cache Transforms

Configuration transforms also migrate experimental Turbopack options and unstable prefix APIs. The `next-experimental-turbo-to-turbopack` codemod shifts properties from `experimental.turbo` to the top-level `turbopack` configuration object. Special options are mapped to `experimental.turbopack*` properties, while unsupported memory limits are dropped. Similarly, the `remove-unstable-prefix` codemod updates stable caching imports from `next/cache`.

| Renamed Experimental Property | New Experimental Target | Sources |
| :--- | :--- | :--- |
| `minify` | `turbopackMinify` | [packages/next-codemod/transforms/next-experimental-turbo-to-turbopack.ts:30-30](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/next-experimental-turbo-to-turbopack.ts#L30-L30) |
| `treeShaking` | `turbopackModuleFragments` | [packages/next-codemod/transforms/next-experimental-turbo-to-turbopack.ts:31-31](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/next-experimental-turbo-to-turbopack.ts#L31-L31) |
| `sourceMaps` | `turbopackSourceMaps` | [packages/next-codemod/transforms/next-experimental-turbo-to-turbopack.ts:32-32](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/next-experimental-turbo-to-turbopack.ts#L32-L32) |

Sources: [packages/next-codemod/transforms/next-experimental-turbo-to-turbopack.ts:28-33](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/next-experimental-turbo-to-turbopack.ts#L28-L33)

> [!CAUTION]
> The `memoryLimit` option is entirely unsupported and is deleted from both `experimental.turbo.memoryLimit` and `experimental.turbopackMemoryLimit` during the transformation pass.

Sources: [packages/next-codemod/transforms/next-experimental-turbo-to-turbopack.ts:35-40](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/next-experimental-turbo-to-turbopack.ts#L35-L40)

| Unstable API | Stable Counterpart | Sources |
| :--- | :--- | :--- |
| `unstable_cacheTag` | `cacheTag` | [packages/next-codemod/transforms/remove-unstable-prefix.ts:7-7](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/remove-unstable-prefix.ts#L7-L7) |
| `unstable_cacheLife` | `cacheLife` | [packages/next-codemod/transforms/remove-unstable-prefix.ts:8-8](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/remove-unstable-prefix.ts#L8-L8) |

Sources: [packages/next-codemod/transforms/remove-unstable-prefix.ts:6-9](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/remove-unstable-prefix.ts#L6-L9)

## Component and Tooling Codemods

### Image and Link Component Transformers

Next.js provides automated AST transforms to upgrade legacy components, font packages, OpenGraph generation imports, tool configurations, and entire application structures. These codemods handle syntax migrations for images, links, fonts, `ImageResponse`, ESLint flat configurations, and Create React App migrations.

The image codemods convert between `next/image`, `next/legacy/image`, and `next/future/image`. The `next-image-to-legacy-image` transformer replaces standard and future image imports with `next/legacy/image` and `next/future/image` imports with `next/image` across ES modules, dynamic `import()` expressions, and CommonJS `require()` calls. Conversely, `next-image-experimental` migrates legacy image elements and loader configurations by parsing layout props (`intrinsic`, `responsive`, `fill`, `fixed`) and mapping them to inline styles, sizes attributes, and custom loaders.

| Legacy Image Import Source | Upgraded Target Source | Sources |
| :--- | :--- | :--- |
| `next/image` | `next/legacy/image` | [packages/next-codemod/transforms/next-image-to-legacy-image.ts:15-20](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/next-image-to-legacy-image.ts#L15-L20) |
| `next/future/image` | `next/image` | [packages/next-codemod/transforms/next-image-to-legacy-image.ts:37-43](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/next-image-to-legacy-image.ts#L37-L43) |

Sources: [packages/next-codemod/transforms/next-image-to-legacy-image.ts:12-43](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/next-image-to-legacy-image.ts#L12-L43)

The `new-link` codemod updates `next/link` usages by stripping deprecated `legacyBehavior` and `passHref` attributes. If a `<Link>` wraps an `<a>` child element, the transformer lifts unique anchor attributes directly to the `<Link>` element and unwraps the child anchor tag.

> [!WARNING]
> If a `<Link>` uses removed `legacyBehavior` and contains a child that cannot be verified as an anchor element, the codemod bails out of lifting child properties and injects an error comment block into the JSX children.

Sources: [packages/next-codemod/transforms/new-link.ts:71-86](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/new-link.ts#L71-L86)

### Font, OpenGraph, and ESLint Migrations

Additional transforms modernize font package imports, OpenGraph utilities, and project linting setups. The `built-in-next-font` codemod shifts scoped font imports from `@next/font`, `@next/font/google`, and `@next/font/local` to their built-in `next/font`, `next/font/google`, and `next/font/local` counterparts. The `next-og-import` transformer extracts `ImageResponse` imports from `next/server` into dedicated `next/og` declarations.

| Legacy Font Package | Modernized Font Import | Sources |
| :--- | :--- | :--- |
| `@next/font` | `next/font` | [packages/next-codemod/transforms/built-in-next-font.ts:16-22](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/built-in-next-font.ts#L16-L22) |
| `@next/font/google` | `next/font/google` | [packages/next-codemod/transforms/built-in-next-font.ts:26-33](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/built-in-next-font.ts#L26-L33) |
| `@next/font/local` | `next/font/local` | [packages/next-codemod/transforms/built-in-next-font.ts:37-44](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/built-in-next-font.ts#L37-L44) |

Sources: [packages/next-codemod/transforms/built-in-next-font.ts:13-45](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/built-in-next-font.ts#L13-L45)

The `next-lint-to-eslint-cli` transformer scans `package.json` scripts for `next lint` execution. When detected, it detects TypeScript configuration via `tsconfig.json` existence, searches for legacy configuration files (`.eslintrc.js`, `.eslintrc.cjs`, `.eslintrc.yaml`, `.eslintrc.yml`, `.eslintrc.json`, `.eslintrc`), and runs `@eslint/migrate-config` to generate ESLint flat configuration files (`eslint.config.mjs`, `eslint.config.js`, `eslint.config.cjs`, `eslint.config.ts`, `eslint.config.mts`, `eslint.config.cts`).

> [!NOTE]
> When no existing ESLint configuration is found, the transformer automatically generates an `eslint.config.mjs` file incorporating `eslint-config-next/core-web-vitals` alongside `eslint-config-next/typescript` if TypeScript is detected.

Sources: [packages/next-codemod/transforms/next-lint-to-eslint-cli.ts:62-64](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/next-lint-to-eslint-cli.ts#L62-L64)

Sources: [packages/next-codemod/transforms/next-lint-to-eslint-cli.ts:1088-1094](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/next-lint-to-eslint-cli.ts#L1088-L1094)

The `cra-to-next` project migrator inspects project root structures for `react-scripts` or `vite` dependencies. It validates `src/index` entry points, converts root render calls into Next.js component wrappers, extracts global CSS imports into `_app`, and generates `_app`, `_document`, and catch-all dynamic page routes (`[[...slug]]`).

Sources: [packages/next-codemod/transforms/cra-to-next.ts:55-79](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/cra-to-next.ts#L55-L79)

Sources: [packages/next-codemod/transforms/cra-to-next.ts:196-200](https://github.com/blade47/next.js/blob/d8c1c1b0002db8ccb63b58095f338e8bf423fa99/packages/next-codemod/transforms/cra-to-next.ts#L196-L200)

## Related

- [CLI Commands](https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/cli-telemetry/cli-commands)


## Sitemap

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