vite-plus 0.1.0-alpha.0 → 0.1.1-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/AGENTS.md +41 -21
  2. package/README.md +104 -29
  3. package/dist/bin.d.ts +1 -1
  4. package/dist/bin.js +55 -18
  5. package/dist/config/agent.d.ts +9 -0
  6. package/dist/config/agent.js +190 -0
  7. package/dist/config/bin.d.ts +1 -0
  8. package/dist/config/bin.js +79 -0
  9. package/dist/config/hooks.d.ts +6 -0
  10. package/dist/config/hooks.js +101 -0
  11. package/dist/global/browser-CY4NBwxR.js +6500 -0
  12. package/dist/global/browser-DFpJ6sKb.js +3 -0
  13. package/dist/global/chunk-CtfvYSle.js +48 -0
  14. package/dist/global/cli-truncate-BxinOqz5.js +187 -0
  15. package/dist/global/{init.js → config.js} +212 -56
  16. package/dist/global/create.js +35 -11
  17. package/dist/global/{help-DeHOTK5z.js → json-Bfvtp2rL.js} +20 -71
  18. package/dist/global/lib-CibYHP32.js +99 -0
  19. package/dist/global/log-update-DdU6_LCN.js +583 -0
  20. package/dist/global/migrate.js +47 -18
  21. package/dist/global/package-Pq2biU7_.js +47 -0
  22. package/dist/global/{agent-BQgTGptV.js → prompts-CAIahN1u.js} +274 -149
  23. package/dist/global/slice-ansi-BhwAwMdF.js +144 -0
  24. package/dist/global/src-C6aLHRsS.js +331 -0
  25. package/dist/global/staged.js +9036 -0
  26. package/dist/global/strip-ansi-BL-dgd7n.js +245 -0
  27. package/dist/global/terminal-Cb-NuRkb.js +102 -0
  28. package/dist/global/version.js +35 -13
  29. package/dist/global/{workspace-DxLkU2Bw.js → workspace-De4OKHV7.js} +606 -6913
  30. package/dist/global/wrap-ansi-BJxjUEQR.js +4 -0
  31. package/dist/global/wrap-ansi-Iww6Ak1s.js +208 -0
  32. package/dist/index.d.ts +2 -0
  33. package/dist/init-config.d.ts +20 -0
  34. package/dist/init-config.js +210 -0
  35. package/dist/pack-bin.js +2 -2
  36. package/dist/resolve-vite-config.d.ts +4 -0
  37. package/dist/resolve-vite-config.js +11 -4
  38. package/dist/staged/bin.d.ts +1 -0
  39. package/dist/staged/bin.js +183 -0
  40. package/dist/staged-config.d.ts +1 -0
  41. package/dist/staged-config.js +0 -0
  42. package/dist/utils/agent.d.ts +2 -1
  43. package/dist/utils/agent.js +21 -11
  44. package/dist/utils/prompts.d.ts +5 -1
  45. package/dist/utils/prompts.js +29 -2
  46. package/package.json +12 -11
  47. package/rules/vite-prepare.yml +8 -0
  48. package/rules/vite-tools.yml +10 -0
  49. package/dist/global/terminal-dIO5Uf8n.js +0 -96
package/AGENTS.md CHANGED
@@ -2,43 +2,62 @@
2
2
 
3
3
  # Using Vite+, the Unified Toolchain for the Web
4
4
 
5
- This project is using Vite+, a modern toolchain built on top of Vite, Rolldown, Vitest, tsdown, Oxlint, and Oxfmt. Vite+ wraps these tools and package manager commands in a single, global CLI called `vp`. Vite+ is distinct from Vite, but it invokes Vite through `vp dev` and `vp build`.
5
+ This project is using Vite+, a unified toolchain built on top of Vite, Rolldown, Vitest, tsdown, Oxlint, Oxfmt, and Vite Task. Vite+ wraps runtime management, package management, and frontend tooling in a single global CLI called `vp`. Vite+ is distinct from Vite, but it invokes Vite through `vp dev` and `vp build`.
6
6
 
7
7
  ## Vite+ Workflow
8
8
 
9
9
  `vp` is a global binary that handles the full development lifecycle. Run `vp help` to print a list of commands and `vp <command> --help` for information about a specific command.
10
10
 
11
- ### Vite+ Commands
11
+ ### Start
12
+
13
+ - create - Create a new project from a template
14
+ - migrate - Migrate an existing project to Vite+
15
+ - config - Configure hooks and agent integration
16
+ - staged - Run linters on staged files
17
+ - install (`i`) - Install dependencies
18
+ - env - Manage Node.js versions
19
+
20
+ ### Develop
12
21
 
13
22
  - dev - Run the development server
14
- - build - Build for production
23
+ - check - Run format, lint, and TypeScript type checks
15
24
  - lint - Lint code
16
- - test - Run tests
17
25
  - fmt - Format code
18
- - check - Run format, lint, and type checks
19
- - lib - Build library
20
- - migrate - Migrate an existing project to Vite+
21
- - create - Create a new monorepo package (in-project) or a new project (global)
22
- - exec - Execute a command in workspace packages (supports `--filter`, `-r`, `--parallel`)
23
- - run - Run tasks from `package.json` scripts
26
+ - test - Run tests
24
27
 
25
- These commands map to their corresponding tools. For example, `vp dev --port 3000` runs Vite's dev server and works the same as Vite. `vp test` runs JavaScript tests through the bundled Vitest. The version of all tools can be checked using `vp --version`. This is useful when researching documentation, features, and bugs.
28
+ ### Execute
29
+
30
+ - run - Run monorepo tasks
31
+ - exec - Execute a command from local `node_modules/.bin`
32
+ - dlx - Execute a package binary without installing it as a dependency
33
+ - cache - Manage the task cache
34
+
35
+ ### Build
26
36
 
27
- ### Package Manager Commands
37
+ - build - Build for production
38
+ - pack - Build libraries
39
+ - preview - Preview production build
40
+
41
+ ### Manage Dependencies
28
42
 
29
43
  Vite+ automatically detects and wraps the underlying package manager such as pnpm, npm, or Yarn through the `packageManager` field in `package.json` or package manager-specific lockfiles.
30
44
 
31
- - install - Install all dependencies, or add packages if package names are provided
32
45
  - add - Add packages to dependencies
33
- - remove - Remove packages from dependencies
34
- - dlx - Execute a package binary without installing it as a dependency
35
- - info - View package information from the registry, including latest versions
36
- - link - Link packages for local development
46
+ - remove (`rm`, `un`, `uninstall`) - Remove packages from dependencies
47
+ - update (`up`) - Update packages to latest versions
48
+ - dedupe - Deduplicate dependencies
37
49
  - outdated - Check for outdated packages
50
+ - list (`ls`) - List installed packages
51
+ - why (`explain`) - Show why a package is installed
52
+ - info (`view`, `show`) - View package information from the registry
53
+ - link (`ln`) / unlink - Manage local package links
38
54
  - pm - Forward a command to the package manager
39
- - unlink - Unlink packages
40
- - update - Update packages to their latest versions
41
- - why - Show why a package is installed
55
+
56
+ ### Maintain
57
+
58
+ - upgrade - Update `vp` itself to the latest version
59
+
60
+ These commands map to their corresponding tools. For example, `vp dev --port 3000` runs Vite's dev server and works the same as Vite. `vp test` runs JavaScript tests through the bundled Vitest. The version of all tools can be checked using `vp --version`. This is useful when researching documentation, features, and bugs.
42
61
 
43
62
  ## Common Pitfalls
44
63
 
@@ -46,11 +65,12 @@ Vite+ automatically detects and wraps the underlying package manager such as pnp
46
65
  - **Always use Vite commands to run tools:** Don't attempt to run `vp vitest` or `vp oxlint`. They do not exist. Use `vp test` and `vp lint` instead.
47
66
  - **Running scripts:** Vite+ commands take precedence over `package.json` scripts. If there is a `test` script defined in `scripts` that conflicts with the built-in `vp test` command, run it using `vp run test`.
48
67
  - **Do not install Vitest, Oxlint, Oxfmt, or tsdown directly:** Vite+ wraps these tools. They must not be installed directly. You cannot upgrade these tools by installing their latest versions. Always use Vite+ commands.
68
+ - **Use Vite+ wrappers for one-off binaries:** Use `vp dlx` instead of package-manager-specific `dlx`/`npx` commands.
49
69
  - **Import JavaScript modules from `vite-plus`:** Instead of importing from `vite` or `vitest`, all modules should be imported from the project's `vite-plus` dependency. For example, `import { defineConfig } from 'vite-plus';` or `import { expect, test, vi } from 'vite-plus/test';`. You must not install `vitest` to import test utilities.
50
70
  - **Type-Aware Linting:** There is no need to install `oxlint-tsgolint`, `vp lint --type-aware` works out of the box.
51
71
 
52
72
  ## Review Checklist for Agents
53
73
 
54
74
  - [ ] Run `vp install` after pulling remote changes and before getting started.
55
- - [ ] Run `vp lint`, `vp fmt`, and `vp test` to validate changes.
75
+ - [ ] Run `vp check` and `vp test` to validate changes.
56
76
  <!--VITE PLUS END-->
package/README.md CHANGED
@@ -1,22 +1,26 @@
1
1
  # VITE+(⚡︎) Local CLI
2
2
 
3
3
  **The Unified Toolchain for the Web**
4
- _dev, build, test, lint, format, monorepo caching & more in a single dependency, built for scale, speed, and sanity_
4
+ _runtime and package management, create, dev, check, test, build, pack, and monorepo task caching in a single dependency_
5
5
 
6
6
  This package provides the project-local version of Vite+. The global `vite` command automatically delegates to this package for all project-specific tasks.
7
7
 
8
8
  ---
9
9
 
10
- Vite+ 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), [tsdown](https://tsdown.dev/) and [Rolldown](https://rolldown.rs/) as a single zero-config toolchain:
10
+ 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:
11
11
 
12
- - **Dev Server:** Powered by Vite's fast development experience with native ES modules and instant HMR
13
- - **Build Tool:** Optimized production builds using Rolldown and Oxc
14
- - **Testing:** Seamless Vitest integration with fast feedback loops
15
- - **Linting:** Ships with Oxlint for quick code quality checks
16
- - **Task Runner:** Monorepo task execution with automated caching and dependency resolution
17
- - **Package Management:** Vite+ wraps package managers to provide a unified interface
12
+ - **`vp env`:** Manage Node.js globally and per project
13
+ - **`vp install`:** Install dependencies with automatic package manager detection
14
+ - **`vp dev`:** Run Vite's fast native ESM dev server with instant HMR
15
+ - **`vp check`:** Run formatting, linting, and type checks in one command
16
+ - **`vp test`:** Run tests through bundled Vitest
17
+ - **`vp build`:** Build applications for production with Vite + Rolldown
18
+ - **`vp run`:** Execute monorepo tasks with caching and dependency-aware scheduling
19
+ - **`vp pack`:** Build libraries for npm publishing or standalone app binaries
20
+ - **`vp create` / `vp migrate`:** Scaffold new projects and migrate existing ones
18
21
 
19
- Vite+ is built to scale with your codebase while reducing your devtools to a single dependency.
22
+ All of this is configured from your project root and works across Vite's framework ecosystem.
23
+ Vite+ is fully open-source under the MIT license.
20
24
 
21
25
  ## Getting Started
22
26
 
@@ -25,44 +29,115 @@ Install Vite+ globally as `vp`:
25
29
  For Linux or macOS:
26
30
 
27
31
  ```bash
28
- curl -fsSL https://staging.viteplus.dev/install.sh | bash
32
+ curl -fsSL https://viteplus.dev/install.sh | bash
29
33
  ```
30
34
 
31
35
  For Windows:
32
36
 
33
37
  ```bash
34
- irm https://staging.viteplus.dev/install.ps1 | iex
38
+ irm https://viteplus.dev/install.ps1 | iex
35
39
  ```
36
40
 
37
41
  `vp` handles the full development lifecycle such as package management, development servers, linting, formatting, testing and building for production.
38
42
 
39
- ### Vite+ Commands
43
+ ## Configuring Vite+
44
+
45
+ Vite+ can be configured using a single `vite.config.ts` at the root of your project:
46
+
47
+ ```ts
48
+ import { defineConfig } from 'vite-plus';
49
+
50
+ export default defineConfig({
51
+ // Standard Vite configuration for dev/build/preview.
52
+ plugins: [],
53
+
54
+ // Vitest configuration.
55
+ test: {
56
+ include: ['src/**/*.test.ts'],
57
+ },
58
+
59
+ // Oxlint configuration.
60
+ lint: {
61
+ ignorePatterns: ['dist/**'],
62
+ },
63
+
64
+ // Oxfmt configuration.
65
+ fmt: {
66
+ semi: true,
67
+ singleQuote: true,
68
+ },
69
+
70
+ // Vite Task configuration.
71
+ run: {
72
+ tasks: {
73
+ 'generate:icons': {
74
+ command: 'node scripts/generate-icons.js',
75
+ envs: ['ICON_THEME'],
76
+ },
77
+ },
78
+ },
79
+
80
+ // `vp staged` configuration.
81
+ staged: {
82
+ '*': 'vp check --fix',
83
+ },
84
+ });
85
+ ```
86
+
87
+ 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.
88
+
89
+ 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`.
90
+
91
+ ### CLI Workflows (`vp help`)
92
+
93
+ #### Start
94
+
95
+ - **create** - Create a new project from a template
96
+ - **migrate** - Migrate an existing project to Vite+
97
+ - **config** - Configure hooks and agent integration
98
+ - **staged** - Run linters on staged files
99
+ - **install** (`i`) - Install dependencies
100
+ - **env** - Manage Node.js versions
101
+
102
+ #### Develop
40
103
 
41
104
  - **dev** - Run the development server
42
- - **build** - Build for production
105
+ - **check** - Run format, lint, and type checks
43
106
  - **lint** - Lint code
44
- - **test** - Run tests
45
107
  - **fmt** - Format code
46
- - **lib** - Build library
47
- - **migrate** - Migrate an existing project to Vite+
48
- - **create** - Create a new monorepo package (in-project) or a new project (global)
49
- - **run** - Run tasks from `package.json` scripts
108
+ - **test** - Run tests
109
+
110
+ #### Execute
111
+
112
+ - **run** - Run monorepo tasks
113
+ - **exec** - Execute a command from local `node_modules/.bin`
114
+ - **dlx** - Execute a package binary without installing it as a dependency
115
+ - **cache** - Manage the task cache
116
+
117
+ #### Build
50
118
 
51
- ### Package Manager Commands
119
+ - **build** - Build for production
120
+ - **pack** - Build libraries
121
+ - **preview** - Preview production build
122
+
123
+ #### Manage Dependencies
52
124
 
53
- Vite+ automatically detects and wraps the underlying package manager such as pnpm, npm, or Yarn through the `packageManager` field in `package.json` or package manager-specific lockfiles.
125
+ Vite+ automatically wraps your package manager (pnpm, npm, or Yarn) based on `packageManager` and lockfiles:
54
126
 
55
- - **install** - Install all dependencies, or add packages if package names are provided
56
127
  - **add** - Add packages to dependencies
57
- - **remove** - Remove packages from dependencies
58
- - **dlx** - Execute a package binary without installing it as a dependency
59
- - **info** - View package information from the registry, including latest versions
60
- - **link** - Link packages for local development
61
- - **outdated** - Check for outdated packages
128
+ - **remove** (`rm`, `un`, `uninstall`) - Remove packages from dependencies
129
+ - **update** (`up`) - Update packages to latest versions
130
+ - **dedupe** - Deduplicate dependencies
131
+ - **outdated** - Check outdated packages
132
+ - **list** (`ls`) - List installed packages
133
+ - **why** (`explain`) - Show why a package is installed
134
+ - **info** (`view`, `show`) - View package metadata from the registry
135
+ - **link** (`ln`) / **unlink** - Manage local package links
62
136
  - **pm** - Forward a command to the package manager
63
- - **unlink** - Unlink packages
64
- - **update** - Update packages to their latest versions
65
- - **why** - Show why a package is installed
137
+
138
+ #### Maintain
139
+
140
+ - **upgrade** - Update `vp` itself to the latest version
66
141
 
67
142
  ### Scaffolding your first Vite+ project
68
143
 
package/dist/bin.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Unified entry point for both the local CLI (via bin/vp) and the global CLI (via Rust vp binary).
3
3
  *
4
- * Global commands (create, migrate, init, mcp, --version) are handled by rolldown-bundled modules.
4
+ * Global commands (create, migrate, config, mcp, staged, --version) are handled by rolldown-bundled modules.
5
5
  * All other commands are delegated to the Rust core through NAPI bindings, which
6
6
  * uses JavaScript tool resolver functions to locate tool binaries.
7
7
  *
package/dist/bin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Unified entry point for both the local CLI (via bin/vp) and the global CLI (via Rust vp binary).
3
3
  *
4
- * Global commands (create, migrate, init, mcp, --version) are handled by rolldown-bundled modules.
4
+ * Global commands (create, migrate, config, mcp, staged, --version) are handled by rolldown-bundled modules.
5
5
  * All other commands are delegated to the Rust core through NAPI bindings, which
6
6
  * uses JavaScript tool resolver functions to locate tool binaries.
7
7
  *
@@ -9,7 +9,9 @@
9
9
  * vite-plus installation using oxc_resolver and runs its dist/bin.js directly.
10
10
  * If no local installation is found, this global dist/bin.js is used as fallback.
11
11
  */
12
+ import path from 'node:path';
12
13
  import { run } from '../binding/index.js';
14
+ import { applyToolInitConfigToViteConfig, inspectInitCommand } from './init-config.js';
13
15
  import { doc } from './resolve-doc.js';
14
16
  import { fmt } from './resolve-fmt.js';
15
17
  import { lint } from './resolve-lint.js';
@@ -17,6 +19,7 @@ import { pack } from './resolve-pack.js';
17
19
  import { test } from './resolve-test.js';
18
20
  import { resolveUniversalViteConfig } from './resolve-vite-config.js';
19
21
  import { vite } from './resolve-vite.js';
22
+ import { accent, log } from './utils/terminal.js';
20
23
  // Parse command line arguments
21
24
  let args = process.argv.slice(2);
22
25
  // Transform `vp help [command]` into `vp [command] --help`
@@ -35,9 +38,9 @@ else if (command === 'migrate') {
35
38
  // @ts-ignore — rolldown output
36
39
  await import('./global/migrate.js');
37
40
  }
38
- else if (command === 'init') {
41
+ else if (command === 'config') {
39
42
  // @ts-ignore — rolldown output
40
- await import('./global/init.js');
43
+ await import('./global/config.js');
41
44
  }
42
45
  else if (command === 'mcp') {
43
46
  // @ts-ignore — rolldown output
@@ -47,23 +50,57 @@ else if (command === '--version' || command === '-V') {
47
50
  // @ts-ignore — rolldown output
48
51
  await import('./global/version.js');
49
52
  }
53
+ else if (command === 'staged') {
54
+ // @ts-ignore — rolldown output
55
+ await import('./global/staged.js');
56
+ }
50
57
  else {
51
58
  // All other commands — delegate to Rust core via NAPI binding
52
- run({
53
- lint,
54
- pack,
55
- fmt,
56
- vite,
57
- test,
58
- doc,
59
- resolveUniversalViteConfig,
60
- args: process.argv.slice(2),
61
- })
62
- .then((exitCode) => {
63
- process.exit(exitCode);
64
- })
65
- .catch((err) => {
59
+ try {
60
+ const initInspection = inspectInitCommand(command, args.slice(1));
61
+ if (initInspection.handled &&
62
+ initInspection.configKey &&
63
+ initInspection.hasExistingConfigKey &&
64
+ initInspection.existingViteConfigPath) {
65
+ log(`Skipped initialization: '${accent(initInspection.configKey)}' already exists in '${accent(path.basename(initInspection.existingViteConfigPath))}'.`);
66
+ process.exit(0);
67
+ }
68
+ const exitCode = await run({
69
+ lint,
70
+ pack,
71
+ fmt,
72
+ vite,
73
+ test,
74
+ doc,
75
+ resolveUniversalViteConfig,
76
+ args: process.argv.slice(2),
77
+ });
78
+ let finalExitCode = exitCode;
79
+ if (exitCode === 0) {
80
+ try {
81
+ const result = await applyToolInitConfigToViteConfig(command, args.slice(1));
82
+ if (result.handled &&
83
+ result.action === 'added' &&
84
+ result.configKey &&
85
+ result.viteConfigPath) {
86
+ log(`Added '${accent(result.configKey)}' to '${accent(path.basename(result.viteConfigPath))}'.`);
87
+ }
88
+ if (result.handled &&
89
+ result.action === 'skipped-existing' &&
90
+ result.configKey &&
91
+ result.viteConfigPath) {
92
+ log(`Skipped initialization: '${accent(result.configKey)}' already exists in '${accent(path.basename(result.viteConfigPath))}'.`);
93
+ }
94
+ }
95
+ catch (err) {
96
+ console.error('[Vite+] Failed to initialize config in vite.config.ts:', err);
97
+ finalExitCode = 1;
98
+ }
99
+ }
100
+ process.exit(finalExitCode);
101
+ }
102
+ catch (err) {
66
103
  console.error('[Vite+] run error:', err);
67
104
  process.exit(1);
68
- });
105
+ }
69
106
  }
@@ -0,0 +1,9 @@
1
+ import { type AgentConfig } from '../utils/agent.js';
2
+ export interface AgentSetupSelection {
3
+ instructionFilePath: 'CLAUDE.md' | 'AGENTS.md';
4
+ agents: AgentConfig[];
5
+ }
6
+ export declare function resolveAgentSetup(root: string, interactive: boolean): Promise<AgentSetupSelection>;
7
+ export declare function hasExistingAgentInstructions(root: string): boolean;
8
+ export declare function injectAgentBlock(root: string, filePath: string): void;
9
+ export declare function setupMcpConfig(root: string, selectedAgents: AgentConfig[]): void;
@@ -0,0 +1,190 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+ import * as prompts from '@voidzero-dev/vite-plus-prompts';
4
+ import { detectAgents, getAgentById, } from '../utils/agent.js';
5
+ import { writeJsonFile, readJsonFile } from '../utils/json.js';
6
+ import { pkgRoot } from '../utils/path.js';
7
+ function detectInstructionFilePath(root, agentConfigs) {
8
+ if (agentConfigs.some((a) => a.skillsDir === '.claude/skills')) {
9
+ return 'CLAUDE.md';
10
+ }
11
+ if (existsSync(join(root, 'CLAUDE.md'))) {
12
+ return 'CLAUDE.md';
13
+ }
14
+ return 'AGENTS.md';
15
+ }
16
+ async function pickAgentWhenUndetected() {
17
+ const choice = await prompts.select({
18
+ message: 'Could not detect your coding agent. Which one are you using?',
19
+ options: [
20
+ { value: 'claude-code', label: 'Claude Code' },
21
+ { value: 'cursor', label: 'Cursor' },
22
+ { value: 'codex', label: 'Codex' },
23
+ { value: 'gemini-cli', label: 'Gemini CLI' },
24
+ { value: 'generic', label: 'Generic' },
25
+ ],
26
+ });
27
+ if (prompts.isCancel(choice)) {
28
+ prompts.cancel('Setup cancelled.');
29
+ process.exit(0);
30
+ }
31
+ if (choice === 'generic') {
32
+ return {
33
+ instructionFilePath: 'AGENTS.md',
34
+ agents: [],
35
+ };
36
+ }
37
+ const selected = getAgentById(choice);
38
+ if (!selected) {
39
+ return {
40
+ instructionFilePath: 'AGENTS.md',
41
+ agents: [],
42
+ };
43
+ }
44
+ return {
45
+ instructionFilePath: choice === 'claude-code' ? 'CLAUDE.md' : 'AGENTS.md',
46
+ agents: [selected],
47
+ };
48
+ }
49
+ export async function resolveAgentSetup(root, interactive) {
50
+ const detected = detectAgents(root);
51
+ if (detected.length > 0 || !interactive) {
52
+ return {
53
+ instructionFilePath: detectInstructionFilePath(root, detected),
54
+ agents: detected,
55
+ };
56
+ }
57
+ return pickAgentWhenUndetected();
58
+ }
59
+ // --- Version and template reading ---
60
+ function getOwnVersion() {
61
+ const pkg = JSON.parse(readFileSync(join(pkgRoot, 'package.json'), 'utf-8'));
62
+ if (typeof pkg.version !== 'string') {
63
+ throw new Error('vite-plus package.json is missing a "version" field');
64
+ }
65
+ return pkg.version;
66
+ }
67
+ function readAgentPrompt() {
68
+ return readFileSync(join(pkgRoot, 'AGENTS.md'), 'utf-8');
69
+ }
70
+ // --- Versioned injection ---
71
+ const MARKER_OPEN_RE = /<!--injected-by-vite-plus-v([\w.+-]+)-->/;
72
+ const MARKER_CLOSE = '<!--/injected-by-vite-plus-->';
73
+ const MARKER_BLOCK_RE = /<!--injected-by-vite-plus-v[\w.+-]+-->\n[\s\S]*?<!--\/injected-by-vite-plus-->/;
74
+ export function hasExistingAgentInstructions(root) {
75
+ for (const file of ['AGENTS.md', 'CLAUDE.md']) {
76
+ const fullPath = join(root, file);
77
+ if (existsSync(fullPath)) {
78
+ const content = readFileSync(fullPath, 'utf-8');
79
+ if (MARKER_OPEN_RE.test(content)) {
80
+ return true;
81
+ }
82
+ }
83
+ }
84
+ return false;
85
+ }
86
+ export function injectAgentBlock(root, filePath) {
87
+ const fullPath = join(root, filePath);
88
+ const version = getOwnVersion();
89
+ const promptContent = readAgentPrompt();
90
+ const openMarker = `<!--injected-by-vite-plus-v${version}-->`;
91
+ const block = `${openMarker}\n${promptContent}\n${MARKER_CLOSE}`;
92
+ if (existsSync(fullPath)) {
93
+ const existing = readFileSync(fullPath, 'utf-8');
94
+ const match = existing.match(MARKER_OPEN_RE);
95
+ if (match) {
96
+ if (match[1] === version) {
97
+ prompts.log.info(`${filePath} already has Vite+ instructions (v${version})`);
98
+ return;
99
+ }
100
+ // Replace existing block with updated version
101
+ const updated = existing.replace(MARKER_BLOCK_RE, block);
102
+ if (updated === existing) {
103
+ // Closing marker is missing or malformed — append fresh block
104
+ const separator = existing.endsWith('\n') ? '\n' : '\n\n';
105
+ writeFileSync(fullPath, existing + separator + block + '\n');
106
+ prompts.log.warn(`Existing Vite+ block in ${filePath} was malformed; appended fresh block`);
107
+ }
108
+ else {
109
+ writeFileSync(fullPath, updated);
110
+ prompts.log.success(`Updated Vite+ instructions in ${filePath} (v${match[1]} → v${version})`);
111
+ }
112
+ }
113
+ else {
114
+ // Append block to end of file
115
+ const separator = existing.endsWith('\n') ? '\n' : '\n\n';
116
+ writeFileSync(fullPath, existing + separator + block + '\n');
117
+ prompts.log.success(`Added Vite+ instructions to ${filePath}`);
118
+ }
119
+ }
120
+ else {
121
+ writeFileSync(fullPath, block + '\n');
122
+ prompts.log.success(`Created ${filePath} with Vite+ instructions`);
123
+ }
124
+ }
125
+ // --- MCP config ---
126
+ function writeMcpConfigForTarget(root, target) {
127
+ const fullPath = join(root, target.filePath);
128
+ let existing = {};
129
+ if (existsSync(fullPath)) {
130
+ try {
131
+ existing = readJsonFile(fullPath);
132
+ }
133
+ catch {
134
+ prompts.log.warn(`Could not parse ${target.filePath} — skipping MCP config. Please add the config manually.`);
135
+ return;
136
+ }
137
+ }
138
+ if (!existing[target.rootKey]) {
139
+ existing[target.rootKey] = {};
140
+ }
141
+ if (existing[target.rootKey]['vite-plus']) {
142
+ prompts.log.info(`${target.filePath} already has vite-plus MCP config`);
143
+ return;
144
+ }
145
+ existing[target.rootKey]['vite-plus'] = {
146
+ command: 'npx',
147
+ args: ['vp', 'mcp'],
148
+ ...target.extraFields,
149
+ };
150
+ mkdirSync(dirname(fullPath), { recursive: true });
151
+ writeJsonFile(fullPath, existing);
152
+ prompts.log.success(`Added vite-plus MCP server to ${target.filePath}`);
153
+ }
154
+ function pickMcpTarget(root, targets) {
155
+ if (targets.length === 1) {
156
+ return targets[0];
157
+ }
158
+ return targets.find((t) => existsSync(join(root, t.filePath))) ?? targets[0];
159
+ }
160
+ export function setupMcpConfig(root, selectedAgents) {
161
+ if (selectedAgents.length === 0) {
162
+ prompts.note(JSON.stringify({
163
+ 'vite-plus': {
164
+ command: 'npx',
165
+ args: ['vp', 'mcp'],
166
+ },
167
+ }, null, 2), 'Add this MCP server config to your agent');
168
+ return;
169
+ }
170
+ const mcpAgents = [];
171
+ const hintAgents = [];
172
+ for (const agent of selectedAgents) {
173
+ if (agent.mcpConfig) {
174
+ mcpAgents.push({ agent, targets: agent.mcpConfig });
175
+ }
176
+ else if (agent.mcpHint) {
177
+ hintAgents.push({ agent, hint: agent.mcpHint });
178
+ }
179
+ }
180
+ // Print hints for agents without project-level config
181
+ for (const { agent, hint } of hintAgents) {
182
+ prompts.log.info(`${agent.displayName}: ${hint}`);
183
+ }
184
+ // Write config for agents with project-level support
185
+ for (const { agent, targets } of mcpAgents) {
186
+ const target = pickMcpTarget(root, targets);
187
+ prompts.log.info(`${agent.displayName} MCP target: ${target.filePath}`);
188
+ writeMcpConfigForTarget(root, target);
189
+ }
190
+ }
@@ -0,0 +1 @@
1
+ export {};