Skip to content

v4.0.0 - #1482

Draft
github-actions[bot] wants to merge 2 commits into
mainfrom
release/v4.0.0
Draft

v4.0.0#1482
github-actions[bot] wants to merge 2 commits into
mainfrom
release/v4.0.0

Conversation

@github-actions

@github-actions github-actions Bot commented Aug 24, 2026 •

Copy link
Copy Markdown
Contributor

v4.0.0 is the next major release.

👀 Highlights

Nuxt CLI v4 is a performance, feature and DX-focused release.

It ships alongside Nuxt 4.6, and alongside resolving almost all of the open issues, we've focused on the nuxt dev experience: how quickly it starts, the information it shows you, and what happens when something goes wrong.

It's also a lot smaller. 😁

There's quite a bit to cover (more than 200 commits since v3.37), so here are just some of the things that we're particularly excited about! 🎉

🐞 Better dev-time errors with my-bad

Dev-time errors are now rendered with my-bad, which replaces youch (#1518).

A Vue error rendered by my-bad, showing the original source frame in app/pages/broken.vue

When a page fails to render, you get your own page's error state along with a small overlay in the corner. Expanding it shows the source-mapped code frame in your file, the call stack (with framework frames folded away by default), the Vue component trace, the request and environment, and the server logs that led up to the error.

The collapsed my-bad overlay in the corner of a Nuxt error page

There's a Copy error button with a few formats, including a prompt you can hand straight to an agent:

The my-bad copy menu: copy as Markdown, copy prompt for an agent, copy structured JSON

The CLI now also hosts a single live error channel, mounted at devServer.errorChannel (default /__nuxt_dev__/error). Because it lives in the CLI rather than inside Nuxt, it survives restarts of the process serving your app, and it can report errors that happen before Nuxt is up at all. So if your nuxt.config has a syntax error, or a module can't be loaded, you get a proper error page in the browser, which reloads by itself once you've fixed it:

my-bad showing a build error for a missing @nuxt/image module

Each error is rendered once, rather than at several levels (Vite plugin, Nuxt error handler, h3). The terminal gets the same treatment, with a code frame and folded dependency frames:

[request error] [GET] /broken

  ✖ TypeError (500): Cannot read properties of null (reading 'name')

    <nuxt-root> › <app> › <NuxtPage> › <RouterView> › <RouteProvider> › <broken>

      1 │ <script setup lang="ts">
      2 │ const user = { profile: null as null | { name: string } }
    › 3 │ const name = user.profile!.name.toUpperCase()
        │                            ^
      4 │ </script>

    at setup app/pages/broken.vue:3:28
    … 9 dependency frames

Note

The in-app overlay, source-mapped SSR stack traces and component traces need Nuxt 4.6 (nuxt/nuxt#36258). With an older Nuxt, the CLI still renders errors it sees itself (such as startup and config failures) with my-bad, but other errors will be rendered as before with youch.

The error channel is only served in full to loopback peers. If you expose your dev server to the network, remote peers get a scoped view without request details or error history (#1547, #1552, #1554).

🖥️ An interactive terminal UI for nuxt dev

I am very excited about this one. In an interactive terminal, nuxt dev now renders a panel pinned to the bottom of the screen with your URLs, live startup progress, the current status and a row of shortcuts, while logs fold away above it (#1463).

nuxt dev with the interactive terminal UI

Everything is a single keypress away:

Key Action
r / shift-r Restart the dev server (optionally with a cleared cache)
o Open the app in your browser
y Copy the server URL to the clipboard
i Versions, URLs, QR code and session info
l / e Browse the log history, or jump to the last error
n Browse served requests
p Browse pages and server routes
c Clear logs, requests and the console
? Show all shortcuts
q Quit

Every request the dev server forwards is now tagged with an id, so logs and errors are attributed to the request that caused them, and you can drill into a request from the n view to see what it logged (2d9f1a8, #1557, #1558, #1474).

When something inside the dev server needs your input (for example, useScript() offering to install @nuxt/scripts), the panel steps aside and lets you answer it (#1488):

nuxt dev prompting to install a module from the interactive UI

This also adds three primitives for modules that want to play nicely with the new UI: withTerminal() to borrow the terminal, startTask() for a spinner on the status line, and notify() for a notice that lands in the log history. (To use this, make sure your module has @nuxt/kit v4.6 as a dependency...)

Tip

The UI falls back to a plain stream of logs when the output isn't a terminal, in CI, when a debugger is attached, or when the terminal is too small. Pass --no-tui (or set NUXT_TUI=plain for good) if you prefer the classic output.

We've also tried to make the dev server surface more information about what it's doing:

nuxt dev reporting which nuxt.config keys changed on restart

⚡️ Faster startup, smaller install

As mentioned above, we've spent a lot of time on the size and startup time of the CLI and have cleared a way a lot of unnecessary, old and deprecated dependencies.

@nuxt/cli has gone from 70 packages to 31 and from 13.1 MB to 3.5 MB installed, and the global nuxi package from 6.0 MB to 0.8 MB. We've swapped out a number of dependencies for Node built-ins or smaller alternatives (picocolors for node:util styleText, semver for verkit, fuse.js for fuzzysort, magicast for oxc, ofetch for native fetch, source-map-js for Node's SourceMap), stopped bundling jiti, and kept youch, registry lookups and the update check off the startup path (#1379, #1409, #1413, #1416, #1425, #1430, #1443).

v3.37.0 v4.0.0
@nuxt/cli install size 13.1 MB 3.5 MB -73%
@nuxt/cli dependencies 70 31 -56%
nuxi install size 6.0 MB 0.8 MB -87%
nuxt --help 108 ms 73 ms -32%
nuxi --help (global) 88 ms 49 ms -44%
nuxt dev: first paint 330 ms 50 ms 6.6x faster
nuxt dev: port bound 338 ms 104 ms 3.2x faster
nuxt dev: first page served 3.2 s 2.6 s -19%
nuxt dev: memory at rest (Linux) 630 MB 440 MB -30%
SCR-20260925-ueok

Note

This was measured on a minimal pnpm create nuxt app with Nuxt 4.5.2, Node 24.15 on arm64 Linux, median of 10 runs.

A few of the changes behind this:

🤖 Friendlier to agents (and to people with too many terminals)

A running dev server now records itself in a lock file in .nuxt/. That means a second nuxt dev for the same project reports the server that is already running rather than racing it for a port, and can take it over when that makes sense (#1414):

  • If an agent starts nuxt dev while another non-interactive server is running, it takes over (loudly).
  • If the running server is one you started in a terminal, a non-interactive nuxt dev refuses and tells the agent where your server is.
  • Pass --takeover to force it.

The lock file also powers two new commands that talk to the running server without you needing to know the port (#1417, #1432):

nuxt curl /api/hello
nuxt curl /api/users -X POST -d '{"name":"daniel"}'

nuxt task list
nuxt task run db:migrate --payload.force=true

nuxt curl pretty-printing a JSON response

nuxt curl pretty-prints and highlights responses in a terminal, and exits with 22 on HTTP errors, just like curl --fail. When nuxt dev runs non-interactively, it suggests using nuxt curl (#1464).

nuxt info (82fe2d6), nuxt module search and nuxt task list all gain --json output (da95c8b).

📚 nuxt docs

You can now search the Nuxt documentation from your terminal (f2dbd8c):

nuxt docs "server routes"

It searches the docs for the Nuxt version your project actually depends on, and opens the best match in your browser (or lets you pick, if there are several).

✨ Lots of smaller things

The CLI docs now live in this repository (#1465), alongside a terminal capture harness that produces the recordings you see above (#1461).

✅ Upgrading

@nuxt/cli is a dependency of nuxt, and your project runs whichever version nuxt depends on. The way to get v4 is to upgrade to Nuxt 4.6, which depends on it:

npx nuxt upgrade --dedupe

If you'd like to try CLI v4 before upgrading Nuxt, you can override the version nuxt depends on. With pnpm, in pnpm-workspace.yaml:

overrides:
  '@nuxt/cli': ^4.0.0

With npm (or bun), in package.json:

{
  "overrides": {
    "@nuxt/cli": "^4.0.0"
  }
}

With yarn, use resolutions instead of overrides. Then reinstall, and check with npx nuxt --version.

Note

Installing @nuxt/cli directly, or updating a global nuxi, isn't enough on its own. A global nuxi hands off to your project's own @nuxt/cli (v3.26 or later), so each project runs its own CLI version.

⚠️ Breaking changes

If you're getting CLI v4 by upgrading to Nuxt 4.6, there should be nothing for you to change. 🎉

This is a major release only because it drops support for some older setups. These changes only matter if you override @nuxt/cli on an older version of Nuxt, or use a global nuxi with older projects:

  • Node.js v22.19+, v24.11+ or v26+ is now required, so the CLI can rely on native TypeScript type stripping (4360712). This matches what Nuxt 4.5 already requires, but Nuxt 3 projects on Node 20 will need a newer Node to use CLI v4.
  • Nuxt 2 and @nuxt/bridge are no longer supported, as Nuxt 2 has been EOL for some time now (perf(nuxi)!: defer to project cli + drop nuxt <3.26 support #1410).
  • A global nuxi only hands off to a project @nuxt/cli of v3.26 or later (perf(nuxi)!: defer to project cli + drop nuxt <3.26 support #1410). Every Nuxt 4 release (and Nuxt 3.18+) depends on a compatible version, so this only affects projects with an older lockfile, which will run the global nuxi's own commands instead.
  • nuxt init has moved out of @nuxt/cli. We consider it an edge case to use an already-installed Nuxt to create another one, so instead just use npm create nuxt@latest (or npx nuxi init). This saves around 220 KB in every Nuxt project (fix(init)!: drop init command from @nuxt/cli #1420).

There are also a couple of other changes you'll notice, though they shouldn't need any action:

  • nuxt dev shows the interactive UI by default in an interactive terminal. Scripts and CI are unaffected, and --no-tui or NUXT_TUI=plain restores the previous output.
  • Dev-time errors are rendered with my-bad instead of youch (feat(dev): render dev-time errors with my-bad #1518).

👉 Changelog

compare changes

🚀 Enhancements

🔥 Performance

🩹 Fixes

💅 Refactors

✅ Tests

🤖 CI

❤️ Contributors

@danielroe danielroe closed this Aug 24, 2026
@danielroe danielroe reopened this Aug 24, 2026
@pkg-pr-new

pkg-pr-new Bot commented Aug 24, 2026 •

Copy link
Copy Markdown
  • nuxt-cli-playground

    npm i https://pkg.pr.new/create-nuxt@1482
    
    npm i https://pkg.pr.new/nuxi@1482
    
    npm i https://pkg.pr.new/@nuxt/cli@1482
    

commit: 77c7361

@github-actions

github-actions Bot commented Aug 24, 2026 •

Copy link
Copy Markdown
Contributor Author

CLI benchmark

@nuxt/cli v4.0.0-alpha.1 (baseline) vs v4.0.0 (this PR)

Metric baseline v4.0.0-alpha.1 head v4.0.0 Delta
nuxt --version wall time (median) 41 ms 40 ms -3.9%
nuxt --help wall time (median) 81 ms 82 ms +1.3%
nuxt dev --help wall time (median) 63 ms 62 ms -1.1%
nuxt --version modules loaded 38 38 0.0%
nuxt --help modules loaded 144 144 0.0%
nuxt dev --help modules loaded 63 63 0.0%
Installed node_modules 2.39 MB 2.39 MB -0.0%
Published tarball (packed) 236.0 kB 236.0 kB -0.0%
Full report

@nuxt/cli v4.0.0-alpha.1 (baseline) vs v4.0.0 (head)

Setting Value
Baseline ref:11226dacafa9e0506c123073464ea4e0a4515e54 (v4.0.0-alpha.1)
Head local packages/nuxt-cli at c3bfdc9 (v4.0.0)
Node v24.21.0
OS Linux 6.17.0 (kernel 6.17.0-1022-azure)
CPU AMD EPYC 9V45 96-Core Processor x 4
Memory 15.6 GB
Load average at start 1.01, 0.27, 0.09
Run started 2026-09-25T23:10:25.097Z

Cold CLI startup

Median of 15 interleaved runs per command, one warmup discarded.

Command baseline v4.0.0-alpha.1 median head v4.0.0 median Delta baseline v4.0.0-alpha.1 min / p95 head v4.0.0 min / p95
nuxt --version 41 ms 40 ms -3.9% 39 ms / 44 ms 38 ms / 42 ms
nuxt --version (first output byte) 38 ms 36 ms -4.6% 36 ms / 40 ms 35 ms / 39 ms
nuxt --help 81 ms 82 ms +1.3% 77 ms / 83 ms 79 ms / 88 ms
nuxt --help (first output byte) 77 ms 78 ms +1.5% 73 ms / 79 ms 75 ms / 84 ms
nuxt dev --help 63 ms 62 ms -1.1% 60 ms / 68 ms 58 ms / 65 ms
nuxt dev --help (first output byte) 59 ms 58 ms -1.4% 56 ms / 64 ms 54 ms / 61 ms
nuxt &lt;unknown-command> (no-op) 88 ms 88 ms -0.1% 83 ms / 97 ms 85 ms / 101 ms
nuxt &lt;unknown-command> (no-op) (first output byte) 84 ms 84 ms +0.1% 79 ms / 93 ms 81 ms / 96 ms

Module load cost

Counted with a module.registerHooks load hook, compile cache disabled. Counts every JS module actually evaluated on that code path (built-ins excluded, native addons excluded).

Command baseline v4.0.0-alpha.1 modules head v4.0.0 modules Delta baseline v4.0.0-alpha.1 source bytes head v4.0.0 source bytes Delta
nuxt --version 38 38 0.0% 296.7 kB 296.7 kB -0.0%
nuxt --help 144 144 0.0% 958.9 kB 958.9 kB -0.0%
nuxt dev --help 63 63 0.0% 449.8 kB 449.8 kB -0.0%

Install footprint and published tarball

Each version installed on its own into an empty project with nothing but @nuxt/cli as a dependency, so the tree is exactly the CLI and its transitive dependencies. npm cache is warm and the registry is only consulted for metadata, so install wall time is indicative, not a network benchmark.

Metric baseline v4.0.0-alpha.1 head v4.0.0 Delta
Direct dependencies of @nuxt/cli 22 22 0.0%
Packages in the installed tree (unique name@version) 38 38 0.0%
Unique package names 38 38 0.0%
Package directories on disk (cross-check) 31 31 0.0%
Installed node_modules on disk 2.39 MB 2.39 MB -0.0%
Installed files 420 420 0.0%
Install wall time (warm npm cache, median of 3) 737 ms 736 ms -0.2%
Published tarball (packed) 236.0 kB 236.0 kB -0.0%
Published tarball (unpacked) 769.0 kB 769.0 kB -0.0%
Files in tarball 97 97 0.0%

Interleaved runs on a shared runner: trust the deltas, not the absolute timings. The dev, restart and build suites run locally via pnpm bench:cli.

@codspeed

codspeed Bot commented Aug 24, 2026 •

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 2 untouched benchmarks


Comparing release/v4.0.0 (77c7361) with main (11226da)

Open in CodSpeed

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant