File: README.md
The Unified Toolchain for the Web
runtime and package management, create, dev, check, test, build, pack, and monorepo task caching in a single dependency
Vite+ is the unified entry point for local web development. It combines Vite, Vitest, Oxlint, Oxfmt, Rolldown, tsdown, and Vite Task into one zero-config toolchain that also manages runtime and package manager workflows:
vp env: Manage Node.js globally and per projectvp install: Install dependencies with automatic package manager detectionvp dev: Run Vite's fast native ESM dev server with instant HMRvp check: Run formatting, linting, and type checks in one commandvp test: Run tests through bundled Vitestvp build: Build applications for production with Vite + Rolldownvp run: Runpackage.jsonscripts and monorepo tasks with caching and dependency-aware schedulingvp pack: Build libraries for npm publishing or standalone app binariesvp toolchain: Show the versions of Vite+, Vite, Rolldown, Oxc, and other toolsvp create/vp migrate: Scaffold new projects and migrate existing ones
All of this is configured from your project root and works across Vite's framework ecosystem.
Vite+ is fully open-source under the MIT license.
Getting Started
Install Vite+ globally as vp:
For Linux or macOS:
curl -fsSL https://vite.plus | bashFor Windows:
irm https://viteplus.dev/install.ps1 | iexvp handles the full development lifecycle such as package management, development servers, linting, formatting, testing and building for production.
Configuring Vite+
Vite+ can be configured using a single vite.config.ts at the root of your project:
import { defineConfig } from 'vite-plus';
export default defineConfig({
// Standard Vite configuration for dev/build/preview.
plugins: [],
// Vitest configuration.
test: {
include: ['src/**/*.test.ts'],
},
// Oxlint configuration.
lint: {
ignorePatterns: ['dist/**'],
},
// Oxfmt configuration.
fmt: {
semi: true,
singleQuote: true,
},
// Vite Task configuration.
run: {
tasks: {
'generate:icons': {
command: 'node scripts/generate-icons.js',
envs: ['ICON_THEME'],
},
},
},
// `vp staged` configuration.
staged: {
'*': 'vp check --fix',
},
});This lets you keep the configuration for your development server, build, test, lint, format, task runner, and staged-file workflow in one place with type-safe config and shared defaults.
Use vp migrate to migrate to Vite+. It merges tool-specific config files such as .oxlintrc*, .oxfmtrc*, and lint-staged config into vite.config.ts.
CLI Workflows (`vp help`)
Start
- create - Create a new project from a template
- migrate - Migrate an existing project to Vite+
- config - Configure hooks and agent integration
- hooks - Manage the Git hook dispatcher
- staged - Run linters on staged files
- install (
i) - Install dependencies - env - Manage Node.js versions
Develop
- dev - Run the development server
- check - Run format, lint, and type checks
- lint - Lint code
- fmt - Format code
- test - Run tests
Execute
- run - Run monorepo tasks
- exec - Execute a command from local
node_modules/.bin - node - Run a Node.js script with the resolved Vite+ environment
- dlx - Execute a package binary without installing it as a dependency
- cache - Manage the task cache
Build
- build - Build for production
- pack - Build libraries
- preview - Preview production build
Manage Dependencies
Vite+ automatically wraps your package manager (pnpm, npm, Yarn, or Bun) based on packageManager and lockfiles:
- add - Add packages to dependencies
- remove (
rm,un,uninstall) - Remove packages from dependencies - update (
up) - Update packages to latest versions - dedupe - Deduplicate dependencies
- outdated - Check outdated packages
- list (
ls) - List installed packages - why (
explain) - Show why a package is installed - info (
view,show) - View package metadata from the registry - link (
ln) / unlink - Manage local package links - rebuild - Rebuild native modules
- pm - Forward a command to the package manager
Maintain
- toolchain - Show Vite+ tool versions and their relationships
- upgrade - Update
vpitself to the latest version - implode - Remove
vpand all related data
Scaffolding your first Vite+ project
Use vp create to create a new project:
vp createYou can run vp create inside of a project to add new apps or libraries to your project.
Organizations can expose a curated set of templates under their npm scope by
publishing @org/create with a createConfig.templates manifest in its package.json.
Once published, vp create @org opens an interactive picker over those
templates, and setting create: { defaultTemplate: '@org' } invite.config.ts makes it the default for bare vp create. See the
Organization Templates guide
for the authoring workflow andcreate.defaultTemplate for the
config reference.
Migrating an existing project
You can migrate an existing project to Vite+:
vp migrateGitHub Actions
Use the official setup-vp action to install Vite+ in GitHub Actions:
- uses: voidzero-dev/setup-vp@<setup-vp-version>
with:
node-version: '22'
cache: trueSet <setup-vp-version> to an exact version from the setup-vp releases page. You can use a commit SHA instead. Do not use the v1 tag. The v1 tag no longer receives updates.
See Automatic Version Updates to configure Dependabot or Renovate.
Manual Installation & Migration
If you are manually migrating a project to Vite+, install these dev dependencies first:
vp install -D vite-plusAdd package-manager overrides so that other packages use the Vite+ versions. Alias vite to @voidzero-dev/vite-plus-core. Pin vitest to the version from vp toolchain vitest. The project and vp test then use the same Vitest copy. Without the pin, a dependency or workspace package can install a different Vitest version. The two versions can use separate mocks, expect functions, and runner states:
"overrides": {
"vite": "npm:@voidzero-dev/vite-plus-core@latest",
"vitest": "4.1.11"
}If you are using pnpm, add this to your pnpm-workspace.yaml:
overrides:
vite: npm:@voidzero-dev/vite-plus-core@latest
vitest: 4.1.11Or, if you are using Yarn:
"resolutions": {
"vite": "npm:@voidzero-dev/vite-plus-core@latest",
"vitest": "4.1.11"
}Sponsors
Thanks to namespace.so for powering our CI/CD pipelines with fast, free macOS, Linux, and Windows runners.
File: docs/config/build.md
Build Config
vp dev, vp build, and vp preview use the standard Vite configuration, including plugins, aliases, server, build and preview fields.
Example
import { defineConfig } from 'vite-plus';
export default defineConfig({
server: {
port: 3000,
},
build: {
sourcemap: true,
},
preview: {
port: 4173,
},
});File: docs/config/check.md
Check Config
vp check runs format, lint, and type checks together. The check block in vite.config.ts sets defaults for the composite command, mirroring the --no-fmt and --no-lint CLI flags.
This is useful when a project wants to keep most of the toolchain but skip one step by default. For example, a team that lints but does not format can disable check.fmt so a plain vp check (the command agents and contributors run most) only lints, without anyone needing to remember --no-fmt.
Example
import { defineConfig } from 'vite-plus';
export default defineConfig({
check: {
// Skip the format step in `vp check`. Defaults to true.
fmt: false,
// Skip lint rules in `vp check`. Type-check still runs when both
// `lint.options.typeAware` and `lint.options.typeCheck` are enabled.
// Defaults to true.
lint: true,
},
});When a step is disabled here, vp check prints a short note: line so it is clear why the step did not run. With the check.fmt: false config above:
$ vp check
note: Format skipped (check.fmt: false in vite.config.ts)
pass: Found no warnings or lint errors in 1 file (12ms, 8 threads)Scope and precedence
- These options only affect the composite
vp check. Standalonevp fmtandvp lintare unaffected, so you can still run a disabled tool directly when you need it once. Note that anyvp checkinvocation honors these defaults, including one run from a pre-commit hook: if yourstagedtasks callvp check, that step is skipped there too. - A step is skipped if the config disables it or the matching CLI flag is passed. There is no flag to re-enable a step disabled in config; run
vp fmtorvp lintdirectly instead.
File: docs/config/create.md
Create Config
vp create reads the create block in vite.config.ts to set per-repo defaults. See the Creating a Project guide for the full @org template workflow.
`create.defaultTemplate`
When vp create is invoked with no TEMPLATE argument, Vite+ uses this value as if the user had typed it. Typically set to an npm scope whose @scope/create package publishes a createConfig.templates manifest โ so bare vp create drops into the org picker.
import { defineConfig } from 'vite-plus';
export default defineConfig({
create: {
defaultTemplate: '@your-org',
},
});Any value accepted by vp create as a first argument works here: @your-org for an org picker, @your-org:web for a direct manifest entry, vite:application for a built-in, or the name of a local create.templates entry (see below).
`create.templates`
Declare local templates available to vp create inside a monorepo. Each entry is listed in the vp create picker, and selecting it (or passing its name as the template argument) runs the resolved template.
import { defineConfig } from 'vite-plus';
export default defineConfig({
create: {
templates: [
{
name: 'component',
template: './tools/create-component',
},
{ name: 'service', description: 'Backend service', template: 'service-generator' },
],
},
});Each entry has:
| Field | Required | Notes |
|---|---|---|
name |
yes | Identifier shown in the picker and accepted as vp create <name>. Must be unique within the array. The vite: prefix is reserved for built-in templates. |
description |
yes | One-line description shown in the picker. |
template |
yes | A workspace package name, a relative ./path to a local package's directory (resolved against the workspace root), a vite:* built-in, a GitHub URL, or a full npm package name (e.g. create-foo). It is run as-is (not shorthand-expanded). |
create.templates is the source of truth for local templates: only entries listed here appear in the picker. Vite+ does not infer templates from package.json keywords. A create.templates entry whose template does not match any workspace package, or resolves to a local package without a bin, is reported as an error rather than falling through to an unrelated npm package.
vp create vite:generator adds an entry here automatically (idempotently, preserving defaultTemplate); you can also edit the list by hand.
create.defaultTemplate can name a local entry, so bare vp create opens it directly.
Precedence
CLI argument > create.defaultTemplate > the standard built-in picker.
Explicit specifiers always win, so scripts and CI can bypass the configured default:
# Uses create.defaultTemplate
vp create
# Explicitly ignores the default
vp create vite:libraryThe org picker also appends a trailing "Vite+ built-in templates" entry โ selecting it routes to the vite:monorepo / vite:application / vite:library / vite:generator flow, so built-ins stay reachable interactively even when a default is configured.
File: docs/config/fmt.md
Format Config
vp fmt and vp check read Oxfmt settings from the fmt block in vite.config.ts. See Oxfmt's configuration for details.
Example
import { defineConfig } from 'vite-plus';
export default defineConfig({
fmt: {
ignorePatterns: ['dist/**'],
singleQuote: true,
semi: true,
sortPackageJson: true,
},
});For package-specific formatting settings in a workspace, use fmt.overrides from the root vite.config.ts.
File: docs/config/index.md
Configuring Vite+
Vite+ keeps project configuration in one place: vite.config.ts, allowing you to consolidate many top-level configuration files in a single file. You can keep using your Vite configuration such as server or build, and add Vite+ blocks for the rest of your workflow:
import { defineConfig } from 'vite-plus';
export default defineConfig({
server: {},
build: {},
preview: {},
create: {},
run: {},
fmt: {},
lint: {},
check: {},
test: {},
pack: {},
staged: {},
});Vite+ Specific Configuration
Vite+ extends the basic Vite configuration with these additions:
createfor project and template scaffolding defaultsrunfor Vite Taskfmtfor Oxfmtlintfor Oxlintcheckforvp checkdefaultstestfor Vitestpackfor tsdownstagedfor staged-file checksdefaultPackagefor the default target of bare app commands at a workspace root
defaultPackage
Default target directory for vp dev / vp build / vp preview / vp pack when you invoke them bare in the directory containing the config, an implicit vp -C <dir>:
export default {
defaultPackage: './frontend',
};vp reads the values without executing the config, so defaultPackage also works at repository roots with no vite-plus dependency (for example a Laravel or Rails repo whose Vite app lives in frontend/, with vite-plus installed only there). That static read is why the values must stay plain string literals rather than expressions. An explicit -C or positional target always wins over the config.
File: docs/config/lint.md
Lint Config
vp lint and vp check read Oxlint settings from the lint block in vite.config.ts. See Oxlint's configuration for details.
Example
import { defineConfig } from 'vite-plus';
export default defineConfig({
lint: {
ignorePatterns: ['dist/**'],
options: {
typeAware: true,
typeCheck: true,
},
rules: {
'no-console': ['error', { allow: ['error'] }],
},
},
});We recommend enabling both options.typeAware and options.typeCheck so vp lint and vp check can use the full type-aware path.
For package-specific lint rules in a workspace, use lint.overrides from the root vite.config.ts.
File: docs/config/pack.md
Pack Config
vp pack reads tsdown settings from the pack block in vite.config.ts. See tsdown's configuration for details.
Example
import { defineConfig } from 'vite-plus';
export default defineConfig({
pack: {
dts: true,
format: ['esm', 'cjs'],
sourcemap: true,
},
});