## 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](https://vite.dev/), [Vitest](https://vitest.dev/), [Oxlint](https://oxc.rs/docs/guide/usage/linter.html), [Oxfmt](https://oxc.rs/docs/guide/usage/formatter.html), [Rolldown](https://rolldown.rs/), [tsdown](https://tsdown.dev/), and [Vite Task](https://github.com/voidzero-dev/vite-task) into one zero-config toolchain that also manages runtime and package manager workflows:

- **`vp env`:** Manage Node.js globally and per project
- **`vp install`:** Install dependencies with automatic package manager detection
- **`vp dev`:** Run Vite's fast native ESM dev server with instant HMR
- **`vp check`:** Run formatting, linting, and type checks in one command
- **`vp test`:** Run tests through bundled Vitest
- **`vp build`:** Build applications for production with Vite + Rolldown
- **`vp run`:** Run `package.json` scripts and monorepo tasks with caching and dependency-aware scheduling
- **`vp pack`:** Build libraries for npm publishing or standalone app binaries
- **`vp toolchain`:** Show the versions of Vite+, Vite, Rolldown, Oxc, and other tools
- **`vp 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:

```bash
curl -fsSL https://vite.plus | bash
```

For Windows:

```bash
irm https://viteplus.dev/install.ps1 | iex
```

`vp` 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:

```ts
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 `vp` itself to the latest version
- **implode** - Remove `vp` and all related data

### Scaffolding your first Vite+ project

Use `vp create` to create a new project:

```bash
vp create
```

You 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' }` in
`vite.config.ts` makes it the default for bare `vp create`. See the
[Organization Templates guide](https://viteplus.dev/guide/create#organization-templates)
for the authoring workflow and
[`create.defaultTemplate`](https://viteplus.dev/config/create) for the
config reference.

### Migrating an existing project

You can migrate an existing project to Vite+:

```bash
vp migrate
```

### GitHub Actions

Use the official [`setup-vp`](https://github.com/voidzero-dev/setup-vp) action to install Vite+ in GitHub Actions:

```yaml
- uses: voidzero-dev/setup-vp@<setup-vp-version>
  with:
    node-version: '22'
    cache: true
```

Set `<setup-vp-version>` to an exact version from the [`setup-vp` releases page](https://github.com/voidzero-dev/setup-vp/releases). You can use a commit SHA instead. Do not use the `v1` tag. The `v1` tag no longer receives updates.

See [Automatic Version Updates](https://viteplus.dev/guide/ci#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:

```bash
vp install -D vite-plus
```

Add 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:

```json
"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`:

```yaml
overrides:
  vite: npm:@voidzero-dev/vite-plus-core@latest
  vitest: 4.1.11
```

Or, if you are using Yarn:

```json
"resolutions": {
  "vite": "npm:@voidzero-dev/vite-plus-core@latest",
  "vitest": "4.1.11"
}
```

## Sponsors

Thanks to [namespace.so](https://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](https://vite.dev/config/), including [plugins](https://vite.dev/guide/using-plugins), [aliases](https://vite.dev/config/shared-options#resolve-alias), [`server`](https://vite.dev/config/server-options), [`build`](https://vite.dev/config/build-options) and [`preview`](https://vite.dev/config/preview-options) fields.

## Example

```ts [vite.config.ts]
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

```ts [vite.config.ts]
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:

```bash
$ 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`. Standalone [`vp fmt`](/config/fmt) and [`vp lint`](/config/lint) are unaffected, so you can still run a disabled tool directly when you need it once. Note that any `vp check` invocation honors these defaults, including one run from a pre-commit hook: if your [`staged`](/config/staged) tasks call `vp 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 fmt` or `vp lint` directly 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](/guide/create#organization-templates) 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.

```ts
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`.

```ts
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`](/guide/create#code-generators) 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:

```bash
# Uses create.defaultTemplate
vp create

# Explicitly ignores the default
vp create vite:library
```

The 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](https://oxc.rs/docs/guide/usage/formatter/config.html) for details.

## Example

```ts [vite.config.ts]
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`](/guide/monorepo#format-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:

```ts [vite.config.ts]
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:

- [`create`](/config/create) for project and template scaffolding defaults
- [`run`](/config/run) for Vite Task
- [`fmt`](/config/fmt) for Oxfmt
- [`lint`](/config/lint) for Oxlint
- [`check`](/config/check) for `vp check` defaults
- [`test`](/config/test) for Vitest
- [`pack`](/config/pack) for tsdown
- [`staged`](/config/staged) for staged-file checks
- [`defaultPackage`](#defaultpackage) for 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>`](/guide/monorepo#app-commands):

```ts [vite.config.ts]
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](https://oxc.rs/docs/guide/usage/linter/config.html) for details.

## Example

```ts [vite.config.ts]
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`](/guide/monorepo#root-config-with-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](https://tsdown.dev/options/config-file) for details.

## Example

```ts [vite.config.ts]
import { defineConfig } from 'vite-plus';

export default defineConfig({
  pack: {
    dts: true,
    format: ['esm', 'cjs'],
    sourcemap: true,
  },
});
```