diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5428fa88f59f..c60d4490700e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,21 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## [Unreleased]
 
+- Nothing yet!
+
+## [4.0.1] - 2025-01-29
+
 ### Added
 
-- Target `:open` in existing `open` variant ([#15349](https://github.com/tailwindlabs/tailwindcss/pull/15349))
+- Include `:open` pseudo-class in existing `open` variant ([#15349](https://github.com/tailwindlabs/tailwindcss/pull/15349))
 
 ### Fixed
 
 - Remove invalid `min-w/h-none` utilities ([#15845](https://github.com/tailwindlabs/tailwindcss/pull/15845))
-- Ensure CSS variable shorthand uses valid CSS variables ([#15738](https://github.com/tailwindlabs/tailwindcss/pull/15738))
-- Ensure font-size utilities with `none` modifier have a line-height set e.g.: `text-sm/none` ([#15921](https://github.com/tailwindlabs/tailwindcss/pull/15921))
+- Discard CSS variable shorthand utilities that don't use valid CSS variables ([#15738](https://github.com/tailwindlabs/tailwindcss/pull/15738))
+- Ensure font-size utilities with `none` modifier have a line-height set e.g. `text-sm/none` ([#15921](https://github.com/tailwindlabs/tailwindcss/pull/15921))
 - Ensure font-size utilities with unknown modifier don't generate CSS ([#15921](https://github.com/tailwindlabs/tailwindcss/pull/15921))
 - Don’t suggest font weight utilities more than once ([#15857](https://github.com/tailwindlabs/tailwindcss/pull/15857))
 - Suggest container query variants ([#15857](https://github.com/tailwindlabs/tailwindcss/pull/15857))
 - Disable bare value suggestions when not using the `--spacing` variable ([#15857](https://github.com/tailwindlabs/tailwindcss/pull/15857))
 - Ensure suggested classes are properly sorted ([#15857](https://github.com/tailwindlabs/tailwindcss/pull/15857))
-- Don’t look at ignore files outside initialized repos ([#15941](https://github.com/tailwindlabs/tailwindcss/pull/15941))
+- Don’t look at .gitignore files outside initialized repos ([#15941](https://github.com/tailwindlabs/tailwindcss/pull/15941))
 - Find utilities when using the Svelte class shorthand syntax across multiple lines ([#15974](https://github.com/tailwindlabs/tailwindcss/pull/15974))
 - Find utilities when using the Angular class shorthand syntax ([#15974](https://github.com/tailwindlabs/tailwindcss/pull/15974))
 - Find utilities when using functions inside arrays ([#15974](https://github.com/tailwindlabs/tailwindcss/pull/15974))
@@ -29,10 +33,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - Ensure that `tailwind-merge` is not scanned when using the Vite plugin ([#16005](https://github.com/tailwindlabs/tailwindcss/pull/16005))
 - Ensure CSS theme variables are available within shadow roots ([#15975](https://github.com/tailwindlabs/tailwindcss/pull/15975))
 - Fix crash when project lives in the `/` directory ([#15988](https://github.com/tailwindlabs/tailwindcss/pull/15988))
-- Ensure `@custom-variant` has a non-empty selector list  ([#16009](https://github.com/tailwindlabs/tailwindcss/pull/16009))
+- Ensure custom variants have a non-empty selector list ([#16009](https://github.com/tailwindlabs/tailwindcss/pull/16009))
 - _Upgrade_: Ensure JavaScript config files on different drives are correctly migrated ([#15927](https://github.com/tailwindlabs/tailwindcss/pull/15927))
 - _Upgrade_: Migrate `leading-[1]` to `leading-none` ([#16004](https://github.com/tailwindlabs/tailwindcss/pull/16004))
-- _Upgrade_: Do not migrate arbitrary leading utilities to bare utilities ([#16004](https://github.com/tailwindlabs/tailwindcss/pull/16004))
+- _Upgrade_: Do not migrate arbitrary leading utilities to bare values ([#16004](https://github.com/tailwindlabs/tailwindcss/pull/16004))
 
 ## [4.0.0] - 2025-01-21
 
@@ -3347,7 +3351,8 @@ No release notes
 
 - Everything!
 
-[unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v4.0.0...HEAD
+[unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v4.0.1...HEAD
+[4.0.1]: https://github.com/tailwindlabs/tailwindcss/compare/v4.0.0...v4.0.1
 [4.0.0]: https://github.com/tailwindlabs/tailwindcss/compare/v4.0.0-beta.10...v4.0.0
 [4.0.0-beta.10]: https://github.com/tailwindlabs/tailwindcss/compare/v4.0.0-beta.9...v4.0.0-beta.10
 [4.0.0-beta.9]: https://github.com/tailwindlabs/tailwindcss/compare/v4.0.0-beta.8...v4.0.0-beta.9
diff --git a/crates/node/npm/android-arm-eabi/package.json b/crates/node/npm/android-arm-eabi/package.json
index d8ec4ab95d00..f786a9acea9e 100644
--- a/crates/node/npm/android-arm-eabi/package.json
+++ b/crates/node/npm/android-arm-eabi/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@tailwindcss/oxide-android-arm-eabi",
-  "version": "4.0.0",
+  "version": "4.0.1",
   "repository": {
     "type": "git",
     "url": "git+https://github.com/tailwindlabs/tailwindcss.git",
diff --git a/crates/node/npm/android-arm64/package.json b/crates/node/npm/android-arm64/package.json
index 5eb9a0fa19d6..adc7a56c43c6 100644
--- a/crates/node/npm/android-arm64/package.json
+++ b/crates/node/npm/android-arm64/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@tailwindcss/oxide-android-arm64",
-  "version": "4.0.0",
+  "version": "4.0.1",
   "repository": {
     "type": "git",
     "url": "git+https://github.com/tailwindlabs/tailwindcss.git",
diff --git a/crates/node/npm/darwin-arm64/package.json b/crates/node/npm/darwin-arm64/package.json
index 619f1c8b779d..2f20b3232fa0 100644
--- a/crates/node/npm/darwin-arm64/package.json
+++ b/crates/node/npm/darwin-arm64/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@tailwindcss/oxide-darwin-arm64",
-  "version": "4.0.0",
+  "version": "4.0.1",
   "repository": {
     "type": "git",
     "url": "git+https://github.com/tailwindlabs/tailwindcss.git",
diff --git a/crates/node/npm/darwin-x64/package.json b/crates/node/npm/darwin-x64/package.json
index 2c7b5ab1a824..3169e58dc9fc 100644
--- a/crates/node/npm/darwin-x64/package.json
+++ b/crates/node/npm/darwin-x64/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@tailwindcss/oxide-darwin-x64",
-  "version": "4.0.0",
+  "version": "4.0.1",
   "repository": {
     "type": "git",
     "url": "git+https://github.com/tailwindlabs/tailwindcss.git",
diff --git a/crates/node/npm/freebsd-x64/package.json b/crates/node/npm/freebsd-x64/package.json
index 6090f34618db..1d7f1390bd64 100644
--- a/crates/node/npm/freebsd-x64/package.json
+++ b/crates/node/npm/freebsd-x64/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@tailwindcss/oxide-freebsd-x64",
-  "version": "4.0.0",
+  "version": "4.0.1",
   "repository": {
     "type": "git",
     "url": "git+https://github.com/tailwindlabs/tailwindcss.git",
diff --git a/crates/node/npm/linux-arm-gnueabihf/package.json b/crates/node/npm/linux-arm-gnueabihf/package.json
index 4c8dc4a44d90..38a82b6baa62 100644
--- a/crates/node/npm/linux-arm-gnueabihf/package.json
+++ b/crates/node/npm/linux-arm-gnueabihf/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@tailwindcss/oxide-linux-arm-gnueabihf",
-  "version": "4.0.0",
+  "version": "4.0.1",
   "repository": {
     "type": "git",
     "url": "git+https://github.com/tailwindlabs/tailwindcss.git",
diff --git a/crates/node/npm/linux-arm64-gnu/package.json b/crates/node/npm/linux-arm64-gnu/package.json
index f70d59c02fac..25f2012c7744 100644
--- a/crates/node/npm/linux-arm64-gnu/package.json
+++ b/crates/node/npm/linux-arm64-gnu/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@tailwindcss/oxide-linux-arm64-gnu",
-  "version": "4.0.0",
+  "version": "4.0.1",
   "repository": {
     "type": "git",
     "url": "git+https://github.com/tailwindlabs/tailwindcss.git",
diff --git a/crates/node/npm/linux-arm64-musl/package.json b/crates/node/npm/linux-arm64-musl/package.json
index 7fd9e903b78d..eec1330699b2 100644
--- a/crates/node/npm/linux-arm64-musl/package.json
+++ b/crates/node/npm/linux-arm64-musl/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@tailwindcss/oxide-linux-arm64-musl",
-  "version": "4.0.0",
+  "version": "4.0.1",
   "repository": {
     "type": "git",
     "url": "git+https://github.com/tailwindlabs/tailwindcss.git",
diff --git a/crates/node/npm/linux-x64-gnu/package.json b/crates/node/npm/linux-x64-gnu/package.json
index d5d66ee0d1a1..8df51808885c 100644
--- a/crates/node/npm/linux-x64-gnu/package.json
+++ b/crates/node/npm/linux-x64-gnu/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@tailwindcss/oxide-linux-x64-gnu",
-  "version": "4.0.0",
+  "version": "4.0.1",
   "repository": {
     "type": "git",
     "url": "git+https://github.com/tailwindlabs/tailwindcss.git",
diff --git a/crates/node/npm/linux-x64-musl/package.json b/crates/node/npm/linux-x64-musl/package.json
index 3e8d92d99259..0013c4b287b5 100644
--- a/crates/node/npm/linux-x64-musl/package.json
+++ b/crates/node/npm/linux-x64-musl/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@tailwindcss/oxide-linux-x64-musl",
-  "version": "4.0.0",
+  "version": "4.0.1",
   "repository": {
     "type": "git",
     "url": "git+https://github.com/tailwindlabs/tailwindcss.git",
diff --git a/crates/node/npm/win32-arm64-msvc/package.json b/crates/node/npm/win32-arm64-msvc/package.json
index b73a264cd1ba..c8721d3ba78c 100644
--- a/crates/node/npm/win32-arm64-msvc/package.json
+++ b/crates/node/npm/win32-arm64-msvc/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@tailwindcss/oxide-win32-arm64-msvc",
-  "version": "4.0.0",
+  "version": "4.0.1",
   "repository": {
     "type": "git",
     "url": "git+https://github.com/tailwindlabs/tailwindcss.git",
diff --git a/crates/node/npm/win32-x64-msvc/package.json b/crates/node/npm/win32-x64-msvc/package.json
index 3119f85b1927..b135728598b5 100644
--- a/crates/node/npm/win32-x64-msvc/package.json
+++ b/crates/node/npm/win32-x64-msvc/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@tailwindcss/oxide-win32-x64-msvc",
-  "version": "4.0.0",
+  "version": "4.0.1",
   "repository": {
     "type": "git",
     "url": "git+https://github.com/tailwindlabs/tailwindcss.git",
diff --git a/crates/node/package.json b/crates/node/package.json
index ac069ef8e1b2..d1588c89247b 100644
--- a/crates/node/package.json
+++ b/crates/node/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@tailwindcss/oxide",
-  "version": "4.0.0",
+  "version": "4.0.1",
   "repository": {
     "type": "git",
     "url": "git+https://github.com/tailwindlabs/tailwindcss.git",
diff --git a/packages/@tailwindcss-browser/package.json b/packages/@tailwindcss-browser/package.json
index aef639cf3f8d..5758c89547eb 100644
--- a/packages/@tailwindcss-browser/package.json
+++ b/packages/@tailwindcss-browser/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@tailwindcss/browser",
-  "version": "4.0.0",
+  "version": "4.0.1",
   "description": "A utility-first CSS framework for rapidly building custom user interfaces.",
   "license": "MIT",
   "main": "./dist/index.global.js",
diff --git a/packages/@tailwindcss-cli/package.json b/packages/@tailwindcss-cli/package.json
index 90ad3b80dcbe..63b35d2fb3c8 100644
--- a/packages/@tailwindcss-cli/package.json
+++ b/packages/@tailwindcss-cli/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@tailwindcss/cli",
-  "version": "4.0.0",
+  "version": "4.0.1",
   "description": "A utility-first CSS framework for rapidly building custom user interfaces.",
   "license": "MIT",
   "repository": {
diff --git a/packages/@tailwindcss-node/package.json b/packages/@tailwindcss-node/package.json
index 1978c69f7935..fb5333b8e72b 100644
--- a/packages/@tailwindcss-node/package.json
+++ b/packages/@tailwindcss-node/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@tailwindcss/node",
-  "version": "4.0.0",
+  "version": "4.0.1",
   "description": "A utility-first CSS framework for rapidly building custom user interfaces.",
   "license": "MIT",
   "repository": {
diff --git a/packages/@tailwindcss-postcss/package.json b/packages/@tailwindcss-postcss/package.json
index 98f23e318c35..00b49bdf5783 100644
--- a/packages/@tailwindcss-postcss/package.json
+++ b/packages/@tailwindcss-postcss/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@tailwindcss/postcss",
-  "version": "4.0.0",
+  "version": "4.0.1",
   "description": "PostCSS plugin for Tailwind CSS, a utility-first CSS framework for rapidly building custom user interfaces",
   "license": "MIT",
   "repository": {
diff --git a/packages/@tailwindcss-standalone/package.json b/packages/@tailwindcss-standalone/package.json
index 8705696e58cb..d45ad2037f5e 100644
--- a/packages/@tailwindcss-standalone/package.json
+++ b/packages/@tailwindcss-standalone/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@tailwindcss/standalone",
-  "version": "4.0.0",
+  "version": "4.0.1",
   "private": true,
   "description": "Standalone CLI for Tailwind CSS",
   "license": "MIT",
diff --git a/packages/@tailwindcss-upgrade/package.json b/packages/@tailwindcss-upgrade/package.json
index b3b7bbedfe9b..2274dd358018 100644
--- a/packages/@tailwindcss-upgrade/package.json
+++ b/packages/@tailwindcss-upgrade/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@tailwindcss/upgrade",
-  "version": "4.0.0",
+  "version": "4.0.1",
   "description": "A utility-first CSS framework for rapidly building custom user interfaces.",
   "license": "MIT",
   "repository": {
diff --git a/packages/@tailwindcss-vite/package.json b/packages/@tailwindcss-vite/package.json
index 2fb5e0e8b046..bd8682a9ddfb 100644
--- a/packages/@tailwindcss-vite/package.json
+++ b/packages/@tailwindcss-vite/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@tailwindcss/vite",
-  "version": "4.0.0",
+  "version": "4.0.1",
   "description": "A utility-first CSS framework for rapidly building custom user interfaces.",
   "license": "MIT",
   "repository": {
diff --git a/packages/tailwindcss/package.json b/packages/tailwindcss/package.json
index 14e47b358d3d..29b92bef2394 100644
--- a/packages/tailwindcss/package.json
+++ b/packages/tailwindcss/package.json
@@ -1,6 +1,6 @@
 {
   "name": "tailwindcss",
-  "version": "4.0.0",
+  "version": "4.0.1",
   "description": "A utility-first CSS framework for rapidly building custom user interfaces.",
   "license": "MIT",
   "repository": {
diff --git a/scripts/version-packages.mjs b/scripts/version-packages.mjs
index 6215c8451437..36f412cc377f 100644
--- a/scripts/version-packages.mjs
+++ b/scripts/version-packages.mjs
@@ -47,108 +47,19 @@ for (let [name, paths] of syncedWorkspaces) {
   }
 }
 
-exec('pnpm --silent --filter=!./playgrounds/* -r exec pwd', async (err, stdout) => {
-  if (err) {
-    console.error(err)
-    process.exit(1)
-  }
-
-  if (version !== null) {
-    for (let pkgPath of stdout
-      .trim()
-      .split('\n')
-      .map((x) => path.resolve(x, 'package.json'))) {
-      let pkg = await fs.readFile(pkgPath, 'utf8').then(JSON.parse)
-      let name = pkg.name
-      if (version !== '') {
-        // Ensure the version is set after the name and before everything else
-        delete pkg.name
-        delete pkg.version
-
-        // This allows us to keep the order of the keys in the package.json
-        pkg = { name, version, ...pkg }
-      }
-
-      await fs.writeFile(
-        pkgPath,
-        await prettier
-          .format(JSON.stringify(pkg, null, 2), { filepath: pkgPath })
-          .then((x) => `${x.trim()}\n`),
-      )
+exec(
+  "pnpm --silent --filter='!./playgrounds/*' --filter='!./integrations' --filter='!./packages/internal-example-plugin' -r exec pwd",
+  async (err, stdout) => {
+    if (err) {
+      console.error(err)
+      process.exit(1)
     }
 
-    console.log('Done.')
-    return
-  }
-
-  let paths = stdout
-    .trim()
-    .split('\n')
-    .map((x) => path.resolve(x, 'package.json'))
-    // Workspaces that are in sync with another workspace should not be updated
-    // manually, they should be updated by updating the main workspace.
-    .filter((x) => !inverseSyncedWorkspaces.has(x))
-
-  let workspaces = new Map()
-
-  // Track all the workspaces
-  for (let path of paths) {
-    let pkg = await fs.readFile(path, 'utf8').then(JSON.parse)
-    if (pkg.private) continue
-    workspaces.set(pkg.name, { version: pkg.version ?? '', path })
-  }
-
-  // Build the editable output
-  let lines = ['# Update the versions of the packages you want to change', '']
-  for (let [name, info] of workspaces) {
-    lines.push(`${name}: ${info.version}`)
-  }
-  let output = lines.join('\n')
-
-  // Edit the file
-  {
-    // Figure out which editor to use.
-    //
-    // In this case we still split on whitespace, because it can happen that the
-    // EDITOR env variable is configured as `code --wait`. This means that we
-    // want `code` as the editor, but `--wait` is one of the arguments.
-    let args = process.env.EDITOR.split(' ')
-    let editor = args.shift()
-
-    // Create a temporary file which will be edited
-    let filepath = path.resolve(tmpdir(), `version-${randomUUID()}.txt`)
-    await fs.writeFile(filepath, output)
-
-    // Edit the file, once the editor is closed, the file will be saved and we
-    // can read the changes
-    spawnSync(editor, [...args, filepath], {
-      stdio: 'inherit',
-    })
-
-    let newOutput = await fs.readFile(filepath, 'utf8').then((x) => x.trim().split('\n'))
-
-    // Cleanup temporary file
-    await fs.unlink(filepath)
-
-    // Update the package.json files
-    for (let line of newOutput) {
-      if (line[0] === '#') continue // Skip comment lines
-      if (line.trim() === '') continue // Skip empty lines
-
-      let [name, version = ''] = line.split(':').map((x) => x.trim())
-
-      // Figure out all the paths to the package.json files that need to be
-      // updated with the new version
-      let paths = [
-        // The package.json file of the main workspace
-        workspaces.get(name).path,
-
-        // The package.json files of the workspaces that are in sync with the
-        // main workspace
-        ...(syncedWorkspaces.get(name) ?? []),
-      ]
-
-      for (let pkgPath of paths) {
+    if (version !== null) {
+      for (let pkgPath of stdout
+        .trim()
+        .split('\n')
+        .map((x) => path.resolve(x, 'package.json'))) {
         let pkg = await fs.readFile(pkgPath, 'utf8').then(JSON.parse)
         let name = pkg.name
         if (version !== '') {
@@ -167,8 +78,100 @@ exec('pnpm --silent --filter=!./playgrounds/* -r exec pwd', async (err, stdout)
             .then((x) => `${x.trim()}\n`),
         )
       }
+
+      console.log('Done.')
+      return
+    }
+
+    let paths = stdout
+      .trim()
+      .split('\n')
+      .map((x) => path.resolve(x, 'package.json'))
+      // Workspaces that are in sync with another workspace should not be updated
+      // manually, they should be updated by updating the main workspace.
+      .filter((x) => !inverseSyncedWorkspaces.has(x))
+
+    let workspaces = new Map()
+
+    // Track all the workspaces
+    for (let path of paths) {
+      let pkg = await fs.readFile(path, 'utf8').then(JSON.parse)
+      if (pkg.private) continue
+      workspaces.set(pkg.name, { version: pkg.version ?? '', path })
     }
-  }
 
-  console.log('Done.')
-})
+    // Build the editable output
+    let lines = ['# Update the versions of the packages you want to change', '']
+    for (let [name, info] of workspaces) {
+      lines.push(`${name}: ${info.version}`)
+    }
+    let output = lines.join('\n')
+
+    // Edit the file
+    {
+      // Figure out which editor to use.
+      //
+      // In this case we still split on whitespace, because it can happen that the
+      // EDITOR env variable is configured as `code --wait`. This means that we
+      // want `code` as the editor, but `--wait` is one of the arguments.
+      let args = process.env.EDITOR.split(' ')
+      let editor = args.shift()
+
+      // Create a temporary file which will be edited
+      let filepath = path.resolve(tmpdir(), `version-${randomUUID()}.txt`)
+      await fs.writeFile(filepath, output)
+
+      // Edit the file, once the editor is closed, the file will be saved and we
+      // can read the changes
+      spawnSync(editor, [...args, filepath], {
+        stdio: 'inherit',
+      })
+
+      let newOutput = await fs.readFile(filepath, 'utf8').then((x) => x.trim().split('\n'))
+
+      // Cleanup temporary file
+      await fs.unlink(filepath)
+
+      // Update the package.json files
+      for (let line of newOutput) {
+        if (line[0] === '#') continue // Skip comment lines
+        if (line.trim() === '') continue // Skip empty lines
+
+        let [name, version = ''] = line.split(':').map((x) => x.trim())
+
+        // Figure out all the paths to the package.json files that need to be
+        // updated with the new version
+        let paths = [
+          // The package.json file of the main workspace
+          workspaces.get(name).path,
+
+          // The package.json files of the workspaces that are in sync with the
+          // main workspace
+          ...(syncedWorkspaces.get(name) ?? []),
+        ]
+
+        for (let pkgPath of paths) {
+          let pkg = await fs.readFile(pkgPath, 'utf8').then(JSON.parse)
+          let name = pkg.name
+          if (version !== '') {
+            // Ensure the version is set after the name and before everything else
+            delete pkg.name
+            delete pkg.version
+
+            // This allows us to keep the order of the keys in the package.json
+            pkg = { name, version, ...pkg }
+          }
+
+          await fs.writeFile(
+            pkgPath,
+            await prettier
+              .format(JSON.stringify(pkg, null, 2), { filepath: pkgPath })
+              .then((x) => `${x.trim()}\n`),
+          )
+        }
+      }
+    }
+
+    console.log('Done.')
+  },
+)