diff --git a/.github/workflows/publish-preview.yml b/.github/workflows/publish-preview.yml
index 3c3896ece1..13c82745bc 100644
--- a/.github/workflows/publish-preview.yml
+++ b/.github/workflows/publish-preview.yml
@@ -98,6 +98,15 @@ jobs:
- name: Install dependencies
run: pnpm install
+ # The registry bridge rewrites dependencies by package name. Stamp core
+ # before pnpm pack so the dependency named `vite` already aliases the
+ # preview version. Keep the CLI manifest aligned with its built dist too.
+ - name: Set preview package versions
+ run: |
+ for package in cli core; do
+ pnpm exec json-edit "packages/$package/package.json" '_.version = process.env.VERSION'
+ done
+
- name: Download cli dist
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/check-api.mjs b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/check-api.mjs
new file mode 100644
index 0000000000..573b1212d6
--- /dev/null
+++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/check-api.mjs
@@ -0,0 +1,29 @@
+import assert from 'node:assert/strict';
+import { createRequire } from 'node:module';
+
+import * as vite from 'vite';
+import { ModuleRunner } from 'vite/module-runner';
+import * as vp from 'vite-plus';
+import { ModuleRunner as VpModuleRunner } from 'vite-plus/module-runner';
+import pkg from 'vite-plus/package.json' with { type: 'json' };
+
+const require = createRequire(import.meta.url);
+const cjsVite = require('vite');
+const cjsVp = require('vite-plus');
+for (const name of [
+ 'createServer',
+ 'DevEnvironment',
+ 'mergeConfig',
+ 'isRunnableDevEnvironment',
+ 'isFetchableDevEnvironment',
+]) {
+ assert.equal(vite[name], vp[name], name);
+ assert.equal(cjsVite[name], cjsVp[name], name);
+ assert.equal(vite[name], cjsVite[name], name);
+}
+assert.equal(ModuleRunner, VpModuleRunner);
+const config = {};
+assert.equal(vite.defineConfig(config), config);
+assert.equal(pkg.dependencies.vite, `npm:@voidzero-dev/vite-plus-core@${pkg.version}`);
+assert.equal(pkg.dependencies['@voidzero-dev/vite-plus-core'], undefined);
+console.log('Packed alias, ESM, CommonJS, and module-runner identity passed');
diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/check-bundled.mjs b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/check-bundled.mjs
new file mode 100644
index 0000000000..119a23c051
--- /dev/null
+++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/check-bundled.mjs
@@ -0,0 +1,12 @@
+import assert from 'node:assert/strict';
+import { createRequire } from 'node:module';
+
+import { createServer } from 'vite-plus';
+import { build } from 'vite-plus/pack';
+
+const require = createRequire(import.meta.url);
+const cliRequire = createRequire(require.resolve('vite-plus/package.json'));
+assert.equal(createServer, cliRequire('vite').createServer);
+assert.equal(build, cliRequire('vite/pack').build);
+assert.equal(require('./package.json').devDependencies.vite, undefined);
+console.log('Bundled APIs resolve without a project Vite dependency');
diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/entry.js b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/entry.js
new file mode 100644
index 0000000000..1bbe700ce9
--- /dev/null
+++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/entry.js
@@ -0,0 +1 @@
+export const message = 'Core identity regression';
diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/identity.test.js b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/identity.test.js
new file mode 100644
index 0000000000..86f3a9ca4f
--- /dev/null
+++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/identity.test.js
@@ -0,0 +1,11 @@
+import { expect, test } from 'vite-plus/test';
+import { createServer, isRunnableDevEnvironment } from 'vite-plus';
+
+test('the public guard accepts an environment created by the bundled server', async () => {
+ const server = await createServer({ configFile: false, server: { middlewareMode: true } });
+ try {
+ expect(isRunnableDevEnvironment(server.environments.ssr)).toBe(true);
+ } finally {
+ await server.close();
+ }
+});
diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/index.html b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/index.html
new file mode 100644
index 0000000000..bd571f1923
--- /dev/null
+++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/index.html
@@ -0,0 +1,3 @@
+
+
Core identity regression
+
diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/package.json b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/package.json
new file mode 100644
index 0000000000..bb31f79399
--- /dev/null
+++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/package.json
@@ -0,0 +1,13 @@
+{
+ "name": "core-module-identity",
+ "private": true,
+ "type": "module",
+ "packageManager": "bun@1.4.2",
+ "devDependencies": {
+ "vite": "npm:@voidzero-dev/vite-plus-core@latest",
+ "vite-plus": "latest"
+ },
+ "overrides": {
+ "vite": "npm:@voidzero-dev/vite-plus-core@latest"
+ }
+}
diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/snapshots.toml b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/snapshots.toml
new file mode 100644
index 0000000000..b487006a95
--- /dev/null
+++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/snapshots.toml
@@ -0,0 +1,109 @@
+[[case]]
+name = "core_module_identity_bun"
+vp = "global"
+local-registry = true
+steps = [
+ { argv = ["vp", "install", "--ignore-scripts"], snapshot = false },
+ ["node", "check-api.mjs"],
+ ["vp", "dev"],
+]
+
+[[case]]
+name = "core_module_identity_repackaged_version"
+vp = "global"
+local-registry = true
+comment = "CI can stamp the package version after building the CLI. The resolver must compare installed manifests rather than an inlined build-time version."
+steps = [
+ { argv = ["vp", "install", "--ignore-scripts"], snapshot = false },
+ { argv = ["vpt", "json-edit", "node_modules/vite-plus/package.json", "version", "0.0.0"], snapshot = false },
+ { argv = ["vpt", "json-edit", "node_modules/vite-plus/package.json", "dependencies.vite", "npm:@voidzero-dev/vite-plus-core@0.0.0"], snapshot = false },
+ { argv = ["vpt", "json-edit", "node_modules/vite/package.json", "version", "0.0.0"], snapshot = false },
+ ["node", "check-api.mjs"],
+ ["vp", "dev"],
+ ["vp", "build"],
+ ["vp", "pack", "entry.js"],
+]
+
+[[case]]
+name = "core_module_identity_yarn"
+vp = "global"
+local-registry = true
+steps = [
+ { argv = ["vpt", "json-edit", "package.json", "packageManager", "yarn@4.10.3"], snapshot = false },
+ { argv = ["vpt", "json-edit", "package.json", "resolutions.vite", "npm:@voidzero-dev/vite-plus-core@latest"], snapshot = false },
+ { argv = ["vpt", "write-file", ".yarnrc.yml", "nodeLinker: node-modules\nenableScripts: false\n"], snapshot = false },
+ { argv = ["vp", "install"], timeout = 120000, snapshot = false },
+ ["node", "check-api.mjs"],
+ ["vp", "dev"],
+]
+
+[[case]]
+name = "core_module_identity_npm"
+vp = "global"
+local-registry = true
+steps = [
+ { argv = ["vpt", "json-edit", "package.json", "packageManager", "npm@11.11.0"], snapshot = false },
+ { argv = ["vp", "install", "--ignore-scripts"], snapshot = false },
+ ["node", "check-api.mjs"],
+ ["vp", "dev"],
+]
+
+[[case]]
+name = "core_module_identity_pnpm"
+vp = "global"
+local-registry = true
+steps = [
+ { argv = ["vpt", "json-edit", "package.json", "packageManager", "pnpm@11.24.0"], snapshot = false },
+ { argv = ["vpt", "write-file", "pnpm-workspace.yaml", "overrides:\n vite: npm:@voidzero-dev/vite-plus-core@latest\nminimumReleaseAge: 0\n"], snapshot = false },
+ { argv = ["vp", "install", "--ignore-scripts"], snapshot = false },
+ ["node", "check-api.mjs"],
+ ["vp", "dev"],
+]
+
+[[case]]
+name = "core_module_identity_without_project_alias"
+vp = "global"
+local-registry = true
+steps = [
+ { argv = ["vpt", "write-file", "package.json", "{\"name\":\"core-module-identity\",\"private\":true,\"type\":\"module\",\"devDependencies\":{\"vite-plus\":\"latest\"},\"packageManager\":\"pnpm@11.24.0\"}\n"], snapshot = false },
+ { argv = ["vpt", "write-file", "pnpm-workspace.yaml", "hoist: false\nminimumReleaseAge: 0\noverrides:\n vite: npm:@voidzero-dev/vite-plus-core@latest\n"], snapshot = false },
+ { argv = ["vpt", "replace-file-content", "vite.config.ts", "from 'vite';", "from 'vite-plus';"], snapshot = false },
+ { argv = ["vp", "install", "--ignore-scripts"], snapshot = false },
+ ["node", "check-bundled.mjs"],
+ ["vp", "dev"],
+ ["vp", "build"],
+ ["vp", "test", "run"],
+ ["vp", "pack", "entry.js"],
+]
+
+[[case]]
+name = "core_module_identity_pnpm_global_store"
+vp = "global"
+local-registry = true
+steps = [
+ { argv = ["vpt", "json-edit", "package.json", "packageManager", "pnpm@11.24.0"], snapshot = false },
+ { argv = ["vpt", "write-file", "pnpm-workspace.yaml", "enableGlobalVirtualStore: true\noverrides:\n vite: npm:@voidzero-dev/vite-plus-core@latest\nminimumReleaseAge: 0\n"], snapshot = false },
+ { argv = ["vp", "install", "--ignore-scripts"], snapshot = false },
+ ["node", "check-api.mjs"],
+ ["vp", "dev"],
+]
+
+[[case]]
+name = "core_module_identity_pnpm_peer_contexts"
+vp = "global"
+local-registry = true
+steps = [
+ { argv = ["vpt", "json-edit", "package.json", "packageManager", "pnpm@11.24.0"], snapshot = false },
+ { argv = ["vpt", "write-file", "pnpm-workspace.yaml", "packages:\n - packages/*\nresolvePeersFromWorkspaceRoot: false\noverrides:\n vite: npm:@voidzero-dev/vite-plus-core@latest\nminimumReleaseAge: 0\n"], snapshot = false },
+ { argv = ["vpt", "write-file", "packages/a/package.json", "{\"name\":\"app-a\",\"private\":true,\"type\":\"module\",\"devDependencies\":{\"vite\":\"npm:@voidzero-dev/vite-plus-core@latest\",\"vite-plus\":\"latest\",\"@types/node\":\"22.20.1\"}}\n"], snapshot = false },
+ { argv = ["vpt", "write-file", "packages/b/package.json", "{\"name\":\"app-b\",\"private\":true,\"type\":\"module\",\"devDependencies\":{\"vite\":\"npm:@voidzero-dev/vite-plus-core@latest\",\"vite-plus\":\"latest\",\"@types/node\":\"24.10.3\"}}\n"], snapshot = false },
+ { argv = ["vpt", "cp", "check-api.mjs", "packages/a/check-api.mjs"], snapshot = false },
+ { argv = ["vpt", "cp", "check-api.mjs", "packages/b/check-api.mjs"], snapshot = false },
+ { argv = ["vpt", "cp", "vite.config.ts", "packages/a/vite.config.ts"], snapshot = false },
+ { argv = ["vpt", "cp", "vite.config.ts", "packages/b/vite.config.ts"], snapshot = false },
+ { argv = ["vp", "install", "--ignore-scripts"], timeout = 120000, snapshot = false },
+ { argv = ["node", "check-api.mjs"], cwd = "packages/a" },
+ { argv = ["vp", "dev"], cwd = "packages/a" },
+ { argv = ["node", "check-api.mjs"], cwd = "packages/b" },
+ { argv = ["vp", "dev"], cwd = "packages/b" },
+]
diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/snapshots/core_module_identity_bun.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/snapshots/core_module_identity_bun.md
new file mode 100644
index 0000000000..62e7688c85
--- /dev/null
+++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/snapshots/core_module_identity_bun.md
@@ -0,0 +1,21 @@
+# core_module_identity_bun
+
+## `vp install --ignore-scripts`
+
+
+## `node check-api.mjs`
+
+```
+Packed alias, ESM, CommonJS, and module-runner identity passed
+```
+
+## `vp dev`
+
+```
+
+ VITE+
+
+ ➜ Local: http://127.0.0.1:/
+ ➜ press h + enter to show help
+SSR environment identity and HTTP response passed
+```
diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/snapshots/core_module_identity_npm.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/snapshots/core_module_identity_npm.md
new file mode 100644
index 0000000000..7d894496cf
--- /dev/null
+++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/snapshots/core_module_identity_npm.md
@@ -0,0 +1,24 @@
+# core_module_identity_npm
+
+## `vpt json-edit package.json packageManager npm@11.11.0`
+
+
+## `vp install --ignore-scripts`
+
+
+## `node check-api.mjs`
+
+```
+Packed alias, ESM, CommonJS, and module-runner identity passed
+```
+
+## `vp dev`
+
+```
+
+ VITE+
+
+ ➜ Local: http://127.0.0.1:/
+ ➜ press h + enter to show help
+SSR environment identity and HTTP response passed
+```
diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/snapshots/core_module_identity_pnpm.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/snapshots/core_module_identity_pnpm.md
new file mode 100644
index 0000000000..060f920f18
--- /dev/null
+++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/snapshots/core_module_identity_pnpm.md
@@ -0,0 +1,30 @@
+# core_module_identity_pnpm
+
+## `vpt json-edit package.json packageManager pnpm@11.24.0`
+
+
+## `vpt write-file pnpm-workspace.yaml 'overrides:
+ vite: npm:@voidzero-dev/vite-plus-core@latest
+minimumReleaseAge: 0
+'`
+
+
+## `vp install --ignore-scripts`
+
+
+## `node check-api.mjs`
+
+```
+Packed alias, ESM, CommonJS, and module-runner identity passed
+```
+
+## `vp dev`
+
+```
+
+ VITE+
+
+ ➜ Local: http://127.0.0.1:/
+ ➜ press h + enter to show help
+SSR environment identity and HTTP response passed
+```
diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/snapshots/core_module_identity_pnpm_global_store.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/snapshots/core_module_identity_pnpm_global_store.md
new file mode 100644
index 0000000000..9a56d9db06
--- /dev/null
+++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/snapshots/core_module_identity_pnpm_global_store.md
@@ -0,0 +1,31 @@
+# core_module_identity_pnpm_global_store
+
+## `vpt json-edit package.json packageManager pnpm@11.24.0`
+
+
+## `vpt write-file pnpm-workspace.yaml 'enableGlobalVirtualStore: true
+overrides:
+ vite: npm:@voidzero-dev/vite-plus-core@latest
+minimumReleaseAge: 0
+'`
+
+
+## `vp install --ignore-scripts`
+
+
+## `node check-api.mjs`
+
+```
+Packed alias, ESM, CommonJS, and module-runner identity passed
+```
+
+## `vp dev`
+
+```
+
+ VITE+
+
+ ➜ Local: http://127.0.0.1:/
+ ➜ press h + enter to show help
+SSR environment identity and HTTP response passed
+```
diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/snapshots/core_module_identity_pnpm_peer_contexts.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/snapshots/core_module_identity_pnpm_peer_contexts.md
new file mode 100644
index 0000000000..a956d9a999
--- /dev/null
+++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/snapshots/core_module_identity_pnpm_peer_contexts.md
@@ -0,0 +1,70 @@
+# core_module_identity_pnpm_peer_contexts
+
+## `vpt json-edit package.json packageManager pnpm@11.24.0`
+
+
+## `vpt write-file pnpm-workspace.yaml 'packages:
+ - packages/*
+resolvePeersFromWorkspaceRoot: false
+overrides:
+ vite: npm:@voidzero-dev/vite-plus-core@latest
+minimumReleaseAge: 0
+'`
+
+
+## `vpt write-file packages/a/package.json '{"name":"app-a","private":true,"type":"module","devDependencies":{"vite":"npm:@voidzero-dev/vite-plus-core@latest","vite-plus":"latest","@types/node":"22.20.1"}}
+'`
+
+
+## `vpt write-file packages/b/package.json '{"name":"app-b","private":true,"type":"module","devDependencies":{"vite":"npm:@voidzero-dev/vite-plus-core@latest","vite-plus":"latest","@types/node":"24.10.3"}}
+'`
+
+
+## `vpt cp check-api.mjs packages/a/check-api.mjs`
+
+
+## `vpt cp check-api.mjs packages/b/check-api.mjs`
+
+
+## `vpt cp vite.config.ts packages/a/vite.config.ts`
+
+
+## `vpt cp vite.config.ts packages/b/vite.config.ts`
+
+
+## `vp install --ignore-scripts`
+
+
+## `cd packages/a && node check-api.mjs`
+
+```
+Packed alias, ESM, CommonJS, and module-runner identity passed
+```
+
+## `cd packages/a && vp dev`
+
+```
+
+ VITE+
+
+ ➜ Local: http://127.0.0.1:/
+ ➜ press h + enter to show help
+SSR environment identity and HTTP response passed
+```
+
+## `cd packages/b && node check-api.mjs`
+
+```
+Packed alias, ESM, CommonJS, and module-runner identity passed
+```
+
+## `cd packages/b && vp dev`
+
+```
+
+ VITE+
+
+ ➜ Local: http://127.0.0.1:/
+ ➜ press h + enter to show help
+SSR environment identity and HTTP response passed
+```
diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/snapshots/core_module_identity_repackaged_version.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/snapshots/core_module_identity_repackaged_version.md
new file mode 100644
index 0000000000..cb2e5d51f3
--- /dev/null
+++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/snapshots/core_module_identity_repackaged_version.md
@@ -0,0 +1,58 @@
+# core_module_identity_repackaged_version
+
+CI can stamp the package version after building the CLI. The resolver must compare installed manifests rather than an inlined build-time version.
+
+## `vp install --ignore-scripts`
+
+
+## `vpt json-edit node_modules/vite-plus/package.json version 0.0.0`
+
+
+## `vpt json-edit node_modules/vite-plus/package.json dependencies.vite npm:@voidzero-dev/vite-plus-core@0.0.0`
+
+
+## `vpt json-edit node_modules/vite/package.json version 0.0.0`
+
+
+## `node check-api.mjs`
+
+```
+Packed alias, ESM, CommonJS, and module-runner identity passed
+```
+
+## `vp dev`
+
+```
+
+ VITE+
+
+ ➜ Local: http://127.0.0.1:/
+ ➜ press h + enter to show help
+SSR environment identity and HTTP response passed
+```
+
+## `vp build`
+
+```
+VITE+ - The Unified Toolchain for the Web
+
+✓ 4 modules transformed.
+computing gzip size...
+dist/index.html kB │ gzip: kB
+dist/assets/index-.js kB │ gzip: kB
+
+✓ built in
+```
+
+## `vp pack entry.js`
+
+```
+VITE+ - The Unified Toolchain for the Web
+
+ℹ entry: entry.js
+ℹ Build start
+ℹ Cleaning files
+ℹ dist/entry.mjs kB │ gzip: kB
+ℹ 1 files, total: kB
+✔ Build complete in
+```
diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/snapshots/core_module_identity_without_project_alias.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/snapshots/core_module_identity_without_project_alias.md
new file mode 100644
index 0000000000..121227e830
--- /dev/null
+++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/core_module_identity/snapshots/core_module_identity_without_project_alias.md
@@ -0,0 +1,77 @@
+# core_module_identity_without_project_alias
+
+## `vpt write-file package.json '{"name":"core-module-identity","private":true,"type":"module","devDependencies":{"vite-plus":"latest"},"packageManager":"pnpm@11.24.0"}
+'`
+
+
+## `vpt write-file pnpm-workspace.yaml 'hoist: false
+minimumReleaseAge: 0
+overrides:
+ vite: npm:@voidzero-dev/vite-plus-core@latest
+'`
+
+
+## `vpt replace-file-content vite.config.ts 'from '\''vite'\'';' 'from '\''vite-plus'\'';'`
+
+
+## `vp install --ignore-scripts`
+
+
+## `node check-bundled.mjs`
+
+```
+Bundled APIs resolve without a project Vite dependency
+```
+
+## `vp dev`
+
+```
+
+ VITE+
+
+ ➜ Local: http://127.0.0.1:/
+ ➜ press h + enter to show help
+SSR environment identity and HTTP response passed
+```
+
+## `vp build`
+
+```
+VITE+ - The Unified Toolchain for the Web
+
+✓ 4 modules transformed.
+computing gzip size...
+dist/index.html kB │ gzip: kB
+dist/assets/index-.js kB │ gzip: kB
+
+✓ built in
+```
+
+## `vp test run`
+
+```
+VITE+ - The Unified Toolchain for the Web
+
+ RUN
+
+ ✓ identity.test.js (1 test)
+ ✓ the public guard accepts an environment created by the bundled server
+
+ Test Files 1 passed (1)
+ Tests 1 passed (1)
+ Start at