create-quiver 0.8.0 → 0.9.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.
@@ -39,7 +39,14 @@
39
39
  "Bash(NPM_TOKEN=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 npm publish --access public)",
40
40
  "Bash(NPM_TOKEN=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 npm publish --access public)",
41
41
  "Bash(npm info *)",
42
- "Bash(npm publish *)"
42
+ "Bash(npm publish *)",
43
+ "Bash(rm -rf /tmp/quiver-skip-test)",
44
+ "Bash(mkdir -p /tmp/quiver-skip-test)",
45
+ "Bash(echo '{\"name\":\"test\",\"scripts\":{}}')",
46
+ "Bash(ls /tmp/quiver-skip-test/node_modules/create-quiver)",
47
+ "Bash(rm -rf /tmp/quiver-install-test)",
48
+ "Bash(mkdir -p /tmp/quiver-install-test)",
49
+ "Bash(npm config *)"
43
50
  ]
44
51
  }
45
52
  }
package/CHANGELOG.md CHANGED
@@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.9.0] - 2026-05-14
8
+
9
+ ### Added
10
+
11
+ - Auto-install `create-quiver` as a dev dependency after `init` and `migrate` — detects yarn/pnpm/bun/npm via lockfiles and runs the appropriate install command
12
+ - `--skip-install` flag to suppress the dev dependency install step (useful for CI environments)
13
+
7
14
  ## [0.8.0] - 2026-05-13
8
15
 
9
16
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-quiver",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "private": false,
5
5
  "description": "Quiver CLI for scaffolding projects from the packaged template",
6
6
  "license": "MIT",
@@ -0,0 +1,19 @@
1
+ # Quiver v19 — Evidence Report
2
+
3
+ **Spec:** quiver-v19-self-install-dev-dep
4
+ **Date:** 2026-05-14
5
+ **Status:** In Progress
6
+
7
+ ## Slice Evidence
8
+
9
+ | Slice | Status | Evidence |
10
+ |-------|--------|----------|
11
+ | slice-01 | Ready | — |
12
+
13
+ ## Required Final Evidence
14
+
15
+ - `npx create-quiver --name "test-project" --dir /tmp/test-project` → `cat /tmp/test-project/package.json | grep create-quiver` returns a devDependency entry
16
+ - `ls /tmp/test-project/node_modules/create-quiver` → directory exists
17
+ - `npx create-quiver plan` inside `/tmp/test-project` → exits 0 without `@version`
18
+ - `npx create-quiver --skip-install --name "ci-project" --dir /tmp/ci-project` → no `node_modules/create-quiver`
19
+ - `node --test tests/**/*.test.js` → all pass
@@ -0,0 +1,51 @@
1
+ # Quiver v19 — Self-Install as Dev Dependency
2
+
3
+ **Date:** 2026-05-14
4
+ **Status:** Active
5
+
6
+ Slice numbering resets here. This spec starts at `slice-01`.
7
+
8
+ ## Problem
9
+
10
+ `npx create-quiver` uses the global npx cache. After init, commands like `quiver:plan`, `quiver:graph`, and `quiver:next` in the target project may silently run the cached version instead of the latest — or fail entirely if the version in cache predates those commands. The user has no `create-quiver` in their `node_modules` unless they install it manually.
11
+
12
+ ## Objective
13
+
14
+ After `npx create-quiver --name "foo"` (init) or `npx create-quiver migrate`, the target project's `package.json` has `create-quiver` in `devDependencies` and it is installed in `node_modules`. Subsequent `npx create-quiver` invocations in that project resolve to the local version — no cache issues, reproducible across machines.
15
+
16
+ ## Scope
17
+
18
+ ### Included
19
+
20
+ - Detect the package manager in use (yarn, pnpm, bun, npm) by checking lockfiles
21
+ - Run the appropriate install command (`npm install -D`, `yarn add -D`, `pnpm add -D`, `bun add -d`) with the exact running version
22
+ - Skip if `create-quiver` is already present in `devDependencies`
23
+ - Skip gracefully if no `package.json` exists in the target project
24
+ - Add `--skip-install` flag to the CLI for CI environments
25
+ - Apply to both `init` and `migrate` flows
26
+ - Tests for `detectPackageManager` and `installSelfAsDevDep`
27
+
28
+ ### Excluded
29
+
30
+ - Changing any other part of the init/migrate scaffold output
31
+ - Supporting non-standard registries or private npm configurations
32
+ - Auto-updating an existing create-quiver devDependency to a newer version
33
+
34
+ ## Acceptance Criteria
35
+
36
+ 1. After init, `cat package.json | jq .devDependencies` shows `"create-quiver": "^X.Y.Z"`
37
+ 2. `node_modules/create-quiver` exists in the target project after init
38
+ 3. `npx create-quiver plan` (no `@version`) works immediately after init
39
+ 4. If target project has no `package.json` → no crash, warning printed, init continues
40
+ 5. If `create-quiver` already in `devDependencies` → step skipped, no duplicate install
41
+ 6. `npx create-quiver --skip-install --name "foo"` → installs Quiver docs but skips npm install
42
+ 7. `npx create-quiver migrate --skip-install` → same skip behavior
43
+ 8. yarn/pnpm/bun projects get the right install command
44
+ 9. If install fails (no network, etc.) → warning printed, init completes without crashing
45
+ 10. `node --test tests/**/*.test.js` passes
46
+
47
+ ## Slices
48
+
49
+ | Slice | Title | Status |
50
+ |-------|-------|--------|
51
+ | slice-01 | Auto-install create-quiver as dev dependency | Ready |
@@ -0,0 +1,20 @@
1
+ # Quiver v19 — Status
2
+
3
+ **Spec:** quiver-v19-self-install-dev-dep
4
+ **Last updated:** 2026-05-14
5
+
6
+ ## Status
7
+
8
+ | Slice | Title | Status | PR | Estimated hours | Actual hours |
9
+ |-------|-------|--------|----|-----------------|--------------|
10
+ | slice-01 | Auto-install create-quiver as dev dependency | Ready | — | 1.5 | — |
11
+
12
+ ## Progress
13
+
14
+ - Completed slices: 0 / 1
15
+ - Estimated hours: 1.5
16
+ - Actual hours: —
17
+
18
+ ## Blockers
19
+
20
+ None.
@@ -0,0 +1,29 @@
1
+ # CLOSURE BRIEF — slice-01: Auto-install create-quiver as dev dependency
2
+
3
+ **Spec:** quiver-v19-self-install-dev-dep
4
+ **Slice:** slice-01-auto-install-dev-dep
5
+
6
+ ---
7
+
8
+ ## Checklist antes de abrir el PR
9
+
10
+ - [ ] `node --test tests/**/*.test.js` → exit 0, todos los tests pasan incluyendo los 7 nuevos en `init-docs.test.js`
11
+ - [ ] Smoke con `--skip-install` → `node_modules/create-quiver` NO existe en el proyecto destino
12
+ - [ ] Smoke sin `--skip-install` → `node_modules/create-quiver` SÍ existe y `npx create-quiver plan` funciona sin `@version`
13
+ - [ ] Smoke con `devDependencies` preexistente → el step se saltea, no hay doble install
14
+ - [ ] `git diff --stat HEAD` muestra exactamente 3 archivos: `src/create-quiver/lib/init-docs.js`, `src/create-quiver/index.js`, `tests/lib/init-docs.test.js`
15
+
16
+ ## Checklist del PR
17
+
18
+ - [ ] Branch: `feature/QUIVER-01-auto-install-dev-dep` → `main`
19
+ - [ ] Título: `feat(QUIVER-01): auto-install create-quiver as dev dependency after init`
20
+ - [ ] Body sigue las secciones del `docs/GITFLOW_PR_GUIDE.md.template`
21
+ - [ ] En "Evidence": output del smoke test mostrando `node_modules/create-quiver` creado y `npx create-quiver plan` funcionando
22
+ - [ ] En "Risks / Notes": mencionar que en entornos sin red el install falla silenciosamente (expected behavior) y documentar el `--skip-install` flag
23
+
24
+ ## Post-merge
25
+
26
+ - [ ] Actualizar `specs/quiver-v19-self-install-dev-dep/STATUS.md`: slice-01 → `Completed`, agregar PR y `actual_hours`
27
+ - [ ] Actualizar `specs/quiver-v19-self-install-dev-dep/EVIDENCE_REPORT.md`: registrar evidencia
28
+ - [ ] Actualizar `slice.json`: `status: completed`, `actual_hours`, timestamps
29
+ - [ ] Evaluar si se publica `0.9.0` o si se acumula con otros cambios
@@ -0,0 +1,287 @@
1
+ # EXECUTION BRIEF — slice-01: Auto-install create-quiver as dev dependency
2
+
3
+ **Spec:** quiver-v19-self-install-dev-dep
4
+ **Slice:** slice-01-auto-install-dev-dep
5
+ **Branch:** `feature/QUIVER-01-auto-install-dev-dep` from `main`
6
+ **Estimated time:** 1.5h
7
+
8
+ ---
9
+
10
+ ## Contexto
11
+
12
+ `npx create-quiver` no instala el paquete en `node_modules` del proyecto destino. Después del init, comandos como `quiver:plan` fallan o usan la versión cacheada globalmente. La solución es correr el package manager del proyecto destino para instalar `create-quiver` como dev dependency inmediatamente después del init/migrate.
13
+
14
+ ---
15
+
16
+ ## Archivos a modificar
17
+
18
+ 1. `src/create-quiver/lib/init-docs.js` — agregar `detectPackageManager` e `installSelfAsDevDep`
19
+ 2. `src/create-quiver/index.js` — agregar `--skip-install` al parser, llamar a `installSelfAsDevDep` en init y migrate
20
+ 3. `tests/lib/init-docs.test.js` — nuevo archivo de tests
21
+
22
+ No toques ningún otro archivo.
23
+
24
+ ---
25
+
26
+ ## Parte A — `src/create-quiver/lib/init-docs.js`
27
+
28
+ ### Paso 1: Agregar import de `execSync`
29
+
30
+ Al inicio del archivo, después de los requires existentes (`fs`, `path`, `writeState`), agregar:
31
+
32
+ ```js
33
+ const { execSync } = require('child_process');
34
+ ```
35
+
36
+ ### Paso 2: Agregar las dos funciones nuevas
37
+
38
+ Agregar antes del `module.exports` al final del archivo:
39
+
40
+ ```js
41
+ function detectPackageManager(projectRoot) {
42
+ if (fs.existsSync(path.join(projectRoot, 'bun.lockb'))) return 'bun';
43
+ if (fs.existsSync(path.join(projectRoot, 'pnpm-lock.yaml'))) return 'pnpm';
44
+ if (fs.existsSync(path.join(projectRoot, 'yarn.lock'))) return 'yarn';
45
+ return 'npm';
46
+ }
47
+
48
+ function installSelfAsDevDep(projectRoot, version) {
49
+ const packageJsonPath = path.join(projectRoot, 'package.json');
50
+ if (!fs.existsSync(packageJsonPath)) {
51
+ return 'skipped-no-package-json';
52
+ }
53
+
54
+ const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
55
+ if (pkg.devDependencies && pkg.devDependencies['create-quiver']) {
56
+ return 'skipped-already-present';
57
+ }
58
+
59
+ const pm = detectPackageManager(projectRoot);
60
+ const commands = {
61
+ npm: `npm install -D create-quiver@${version}`,
62
+ yarn: `yarn add -D create-quiver@${version}`,
63
+ pnpm: `pnpm add -D create-quiver@${version}`,
64
+ bun: `bun add -d create-quiver@${version}`,
65
+ };
66
+
67
+ try {
68
+ execSync(commands[pm], { cwd: projectRoot, stdio: 'inherit' });
69
+ return 'installed';
70
+ } catch {
71
+ return 'failed';
72
+ }
73
+ }
74
+ ```
75
+
76
+ ### Paso 3: Exportar las funciones nuevas
77
+
78
+ Encontrá el `module.exports` actual y agregá las dos funciones nuevas:
79
+
80
+ ```js
81
+ module.exports = {
82
+ // ... exports existentes ...
83
+ detectPackageManager,
84
+ installSelfAsDevDep,
85
+ };
86
+ ```
87
+
88
+ ---
89
+
90
+ ## Parte B — `src/create-quiver/index.js`
91
+
92
+ ### Paso 1: Importar `installSelfAsDevDep`
93
+
94
+ En la línea 10 donde se importa `runInitDocs`, extender el destructuring para incluir la función nueva:
95
+
96
+ ```js
97
+ // Antes (aproximado):
98
+ const { runInitDocs } = require('./lib/init-docs');
99
+
100
+ // Después:
101
+ const { runInitDocs, installSelfAsDevDep } = require('./lib/init-docs');
102
+ ```
103
+
104
+ ### Paso 2: Agregar `--skip-install` al parser de args
105
+
106
+ Dentro de la función `parseArgs`, en el bloque donde se manejan los flags (el loop que analiza `arg`), agregar el caso nuevo junto a los otros flags booleanos (`--yes`, etc.):
107
+
108
+ ```js
109
+ if (arg === '--skip-install') {
110
+ result.skipInstall = true;
111
+ continue;
112
+ }
113
+ ```
114
+
115
+ ### Paso 3: Llamar a `installSelfAsDevDep` en el flujo de init
116
+
117
+ El flujo init en index.js (cerca de la línea 1416) actualmente es:
118
+
119
+ ```js
120
+ runInitDocs(targetDir, projectName);
121
+ console.log(`Installed Quiver into ${targetDir}`);
122
+ printInitNextSteps(targetDir, projectName);
123
+ ```
124
+
125
+ Reemplazarlo por:
126
+
127
+ ```js
128
+ runInitDocs(targetDir, projectName);
129
+
130
+ if (!args.skipInstall) {
131
+ const installResult = installSelfAsDevDep(targetDir, CLI_VERSION);
132
+ if (installResult === 'installed') {
133
+ console.log(`Added create-quiver@${CLI_VERSION} as dev dependency`);
134
+ } else if (installResult === 'failed') {
135
+ console.warn(`Warning: could not install create-quiver automatically. Run: npm install -D create-quiver@${CLI_VERSION}`);
136
+ }
137
+ }
138
+
139
+ console.log(`Installed Quiver into ${targetDir}`);
140
+ printInitNextSteps(targetDir, projectName);
141
+ ```
142
+
143
+ Nota: `CLI_VERSION` ya existe en `index.js` — no lo reimportes.
144
+
145
+ ### Paso 4: Llamar a `installSelfAsDevDep` en el flujo de migrate
146
+
147
+ Buscá el flujo de migrate en index.js (buscar `runInitDocs` con `migrateMode: true` o similar). Aplicar el mismo patrón después del call de init/migrate.
148
+
149
+ ---
150
+
151
+ ## Parte C — `tests/lib/init-docs.test.js` (archivo nuevo)
152
+
153
+ Crear este archivo con el patrón del repo (`node:test`, `node:assert/strict`):
154
+
155
+ ```js
156
+ const assert = require('node:assert/strict');
157
+ const fs = require('node:fs');
158
+ const os = require('node:os');
159
+ const path = require('node:path');
160
+ const test = require('node:test');
161
+
162
+ const { detectPackageManager, installSelfAsDevDep } = require('../../src/create-quiver/lib/init-docs');
163
+
164
+ function makeTmpDir() {
165
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'quiver-init-test-'));
166
+ return { dir, cleanup: () => fs.rmSync(dir, { recursive: true, force: true }) };
167
+ }
168
+
169
+ test('detectPackageManager returns npm when no lockfile exists', () => {
170
+ const { dir, cleanup } = makeTmpDir();
171
+ try {
172
+ assert.equal(detectPackageManager(dir), 'npm');
173
+ } finally {
174
+ cleanup();
175
+ }
176
+ });
177
+
178
+ test('detectPackageManager returns yarn when yarn.lock exists', () => {
179
+ const { dir, cleanup } = makeTmpDir();
180
+ try {
181
+ fs.writeFileSync(path.join(dir, 'yarn.lock'), '');
182
+ assert.equal(detectPackageManager(dir), 'yarn');
183
+ } finally {
184
+ cleanup();
185
+ }
186
+ });
187
+
188
+ test('detectPackageManager returns pnpm when pnpm-lock.yaml exists', () => {
189
+ const { dir, cleanup } = makeTmpDir();
190
+ try {
191
+ fs.writeFileSync(path.join(dir, 'pnpm-lock.yaml'), '');
192
+ assert.equal(detectPackageManager(dir), 'pnpm');
193
+ } finally {
194
+ cleanup();
195
+ }
196
+ });
197
+
198
+ test('detectPackageManager returns bun when bun.lockb exists', () => {
199
+ const { dir, cleanup } = makeTmpDir();
200
+ try {
201
+ fs.writeFileSync(path.join(dir, 'bun.lockb'), '');
202
+ assert.equal(detectPackageManager(dir), 'bun');
203
+ } finally {
204
+ cleanup();
205
+ }
206
+ });
207
+
208
+ test('installSelfAsDevDep returns skipped-no-package-json when no package.json', () => {
209
+ const { dir, cleanup } = makeTmpDir();
210
+ try {
211
+ const result = installSelfAsDevDep(dir, '0.8.0');
212
+ assert.equal(result, 'skipped-no-package-json');
213
+ } finally {
214
+ cleanup();
215
+ }
216
+ });
217
+
218
+ test('installSelfAsDevDep returns skipped-already-present when create-quiver in devDeps', () => {
219
+ const { dir, cleanup } = makeTmpDir();
220
+ try {
221
+ fs.writeFileSync(path.join(dir, 'package.json'), JSON.stringify({
222
+ name: 'test',
223
+ devDependencies: { 'create-quiver': '^0.7.0' },
224
+ }));
225
+ const result = installSelfAsDevDep(dir, '0.8.0');
226
+ assert.equal(result, 'skipped-already-present');
227
+ } finally {
228
+ cleanup();
229
+ }
230
+ });
231
+
232
+ test('installSelfAsDevDep returns failed when install command fails', () => {
233
+ const { dir, cleanup } = makeTmpDir();
234
+ try {
235
+ fs.writeFileSync(path.join(dir, 'package.json'), JSON.stringify({ name: 'test' }));
236
+ // Force failure: set PATH to empty so no package manager can be found
237
+ const original = process.env.PATH;
238
+ process.env.PATH = '';
239
+ const result = installSelfAsDevDep(dir, '0.8.0');
240
+ process.env.PATH = original;
241
+ assert.equal(result, 'failed');
242
+ } finally {
243
+ cleanup();
244
+ }
245
+ });
246
+ ```
247
+
248
+ ---
249
+
250
+ ## Verificaciones
251
+
252
+ ```bash
253
+ # Tests
254
+ node --test tests/**/*.test.js
255
+
256
+ # Smoke: --skip-install no instala
257
+ mkdir -p /tmp/quiver-skip-test && echo '{"name":"test","scripts":{}}' > /tmp/quiver-skip-test/package.json
258
+ node bin/create-quiver.js --skip-install --name test --dir /tmp/quiver-skip-test
259
+ ls /tmp/quiver-skip-test/node_modules/create-quiver 2>/dev/null && echo "FAIL: se instaló igual" || echo "OK: no instaló"
260
+
261
+ # Smoke: sin --skip-install sí instala (requiere red)
262
+ mkdir -p /tmp/quiver-install-test && echo '{"name":"test","scripts":{}}' > /tmp/quiver-install-test/package.json
263
+ node bin/create-quiver.js --name test --dir /tmp/quiver-install-test
264
+ ls /tmp/quiver-install-test/node_modules/create-quiver && echo "OK: instalado" || echo "FAIL"
265
+ ```
266
+
267
+ ---
268
+
269
+ ## Restricciones
270
+
271
+ - No toques `mergePackageJson` — la lógica de install va en `installSelfAsDevDep`, no en el merge de package.json
272
+ - No hagas `npm install` general — solo `npm install -D create-quiver@VERSION`
273
+ - No elimines ni renombres ningún export existente de `init-docs.js`
274
+ - No agregues dependencias externas — solo `child_process` (built-in de Node)
275
+ - Un solo commit con los tres archivos
276
+
277
+ ## Mensaje de commit sugerido
278
+
279
+ ```
280
+ feat(QUIVER-01): auto-install create-quiver as dev dependency after init
281
+
282
+ After init or migrate, detect the target project's package manager
283
+ (yarn/pnpm/bun/npm) and install create-quiver as a dev dependency.
284
+ Skippable with --skip-install for CI environments.
285
+ Resolves the npx cache issue: subsequent quiver commands in the project
286
+ resolve to the local version without requiring @version suffix.
287
+ ```
@@ -0,0 +1,56 @@
1
+ {
2
+ "slice_id": "slice-01-auto-install-dev-dep",
3
+ "ticket": "QUIVER-01",
4
+ "type": "feature",
5
+ "title": "Auto-install create-quiver as dev dependency after init/migrate",
6
+ "objective": "After `npx create-quiver` init or migrate, the target project has create-quiver in devDependencies and installed in node_modules. Uses the correct package manager. Skippable via --skip-install.",
7
+ "description": "Add two functions to init-docs.js: detectPackageManager (checks lockfiles) and installSelfAsDevDep (runs the appropriate install command). Call installSelfAsDevDep from the init and migrate flows in index.js after runInitDocs. Add --skip-install flag to the CLI arg parser.",
8
+ "git": {
9
+ "branch_type": "feature",
10
+ "base_branch": "main",
11
+ "branch_slug": "auto-install-dev-dep",
12
+ "branch_name": "feature/QUIVER-01-auto-install-dev-dep"
13
+ },
14
+ "files": [
15
+ "src/create-quiver/lib/init-docs.js",
16
+ "src/create-quiver/index.js",
17
+ "tests/lib/init-docs.test.js"
18
+ ],
19
+ "depends_on": [],
20
+ "must": [
21
+ "detectPackageManager(projectRoot) returns 'bun'|'pnpm'|'yarn'|'npm' based on lockfile presence",
22
+ "installSelfAsDevDep(projectRoot, version) runs the correct install command for the detected pm",
23
+ "installSelfAsDevDep skips if no package.json exists (returns 'skipped-no-package-json')",
24
+ "installSelfAsDevDep skips if create-quiver already in devDependencies (returns 'skipped-already-present')",
25
+ "installSelfAsDevDep catches install errors and returns 'failed' without throwing",
26
+ "--skip-install flag parsed in index.js and passed through to suppress the install step",
27
+ "Both init and migrate flows call installSelfAsDevDep unless --skip-install is set",
28
+ "Init output prints 'Added create-quiver@X.Y.Z as dev dependency' on success or a warning on skip/fail",
29
+ "node --test tests/**/*.test.js passes"
30
+ ],
31
+ "not_included": [
32
+ "Auto-updating an existing create-quiver version in devDependencies",
33
+ "Supporting private registries or custom npm configs",
34
+ "Changing the scaffold output beyond the install step message"
35
+ ],
36
+ "acceptance": [
37
+ "After init: package.json has create-quiver in devDependencies",
38
+ "After init: node_modules/create-quiver exists",
39
+ "npx create-quiver plan works without @version in a freshly initialized project",
40
+ "--skip-install suppresses the install in both init and migrate",
41
+ "yarn/pnpm/bun projects use the right install command",
42
+ "Install failure prints a warning but does not crash the init",
43
+ "node --test tests/**/*.test.js exits 0"
44
+ ],
45
+ "tests": [
46
+ "node --test tests/**/*.test.js",
47
+ "npx create-quiver --skip-install --name test --dir /tmp/quiver-test-skip && ls /tmp/quiver-test-skip/node_modules/create-quiver 2>/dev/null && echo FAIL || echo OK"
48
+ ],
49
+ "estimated_hours": 1.5,
50
+ "actual_hours": null,
51
+ "status": "ready",
52
+ "blocked_reason": null,
53
+ "ready_at": "2026-05-14T00:00:00Z",
54
+ "started_at": null,
55
+ "completed_at": null
56
+ }
@@ -7,7 +7,7 @@ const { collectDoctorWarnings } = require('./lib/doctor');
7
7
  const { runGraph } = require('./commands/graph');
8
8
  const { runNext } = require('./commands/next');
9
9
  const { runPlan } = require('./commands/plan');
10
- const { initializeProjectDocs } = require('./lib/init-docs');
10
+ const { initializeProjectDocs, installSelfAsDevDep } = require('./lib/init-docs');
11
11
  const { checkPrReadiness, checkScope, checkSliceReadiness } = require('./lib/readiness');
12
12
  const { cleanupSlice, refreshActiveSlicesBoard, startSlice } = require('./lib/lifecycle');
13
13
  const { relativePosixPath, resolveTargetRoot } = require('./lib/paths');
@@ -144,6 +144,11 @@ function parseArgs(argv) {
144
144
  continue;
145
145
  }
146
146
 
147
+ if (arg === '--skip-install') {
148
+ result.skipInstall = true;
149
+ continue;
150
+ }
151
+
147
152
  if (arg === '--doctor') {
148
153
  result.mode = 'doctor';
149
154
  continue;
@@ -1160,6 +1165,15 @@ function runMigrate(targetDir) {
1160
1165
  });
1161
1166
  updateStateForMigrate(projectRoot, projectName, CLI_VERSION);
1162
1167
 
1168
+ if (!args.skipInstall) {
1169
+ const installResult = installSelfAsDevDep(projectRoot, CLI_VERSION);
1170
+ if (installResult === 'installed') {
1171
+ console.log(`Added create-quiver@${CLI_VERSION} as dev dependency`);
1172
+ } else if (installResult === 'failed') {
1173
+ console.warn(`Warning: could not install create-quiver automatically. Run: npm install -D create-quiver@${CLI_VERSION}`);
1174
+ }
1175
+ }
1176
+
1163
1177
  console.log(`Quiver migration completed for ${projectRoot}`);
1164
1178
  console.log('Missing workflow files were restored without overwriting existing project files.');
1165
1179
  } finally {
@@ -1415,6 +1429,15 @@ async function run(argv) {
1415
1429
  copyTemplate(templateRoot, targetDir);
1416
1430
  runInitDocs(targetDir, projectName);
1417
1431
 
1432
+ if (!args.skipInstall) {
1433
+ const installResult = installSelfAsDevDep(targetDir, CLI_VERSION);
1434
+ if (installResult === 'installed') {
1435
+ console.log(`Added create-quiver@${CLI_VERSION} as dev dependency`);
1436
+ } else if (installResult === 'failed') {
1437
+ console.warn(`Warning: could not install create-quiver automatically. Run: npm install -D create-quiver@${CLI_VERSION}`);
1438
+ }
1439
+ }
1440
+
1418
1441
  console.log(`Installed Quiver into ${targetDir}`);
1419
1442
  printInitNextSteps(targetDir, projectName);
1420
1443
  } finally {
@@ -1,5 +1,6 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
+ const { execSync } = require('child_process');
3
4
  const { writeState } = require('./state');
4
5
 
5
6
  function ensureDir(dirPath) {
@@ -667,8 +668,44 @@ function initializeProjectDocs(options) {
667
668
  };
668
669
  }
669
670
 
671
+ function detectPackageManager(projectRoot) {
672
+ if (fs.existsSync(path.join(projectRoot, 'bun.lockb'))) return 'bun';
673
+ if (fs.existsSync(path.join(projectRoot, 'pnpm-lock.yaml'))) return 'pnpm';
674
+ if (fs.existsSync(path.join(projectRoot, 'yarn.lock'))) return 'yarn';
675
+ return 'npm';
676
+ }
677
+
678
+ function installSelfAsDevDep(projectRoot, version) {
679
+ const packageJsonPath = path.join(projectRoot, 'package.json');
680
+ if (!fs.existsSync(packageJsonPath)) {
681
+ return 'skipped-no-package-json';
682
+ }
683
+
684
+ const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
685
+ if (pkg.devDependencies && pkg.devDependencies['create-quiver']) {
686
+ return 'skipped-already-present';
687
+ }
688
+
689
+ const pm = detectPackageManager(projectRoot);
690
+ const commands = {
691
+ npm: `npm install -D create-quiver@${version}`,
692
+ yarn: `yarn add -D create-quiver@${version}`,
693
+ pnpm: `pnpm add -D create-quiver@${version}`,
694
+ bun: `bun add -d create-quiver@${version}`,
695
+ };
696
+
697
+ try {
698
+ execSync(commands[pm], { cwd: projectRoot, stdio: 'inherit' });
699
+ return 'installed';
700
+ } catch {
701
+ return 'failed';
702
+ }
703
+ }
704
+
670
705
  module.exports = {
671
706
  initializeProjectDocs,
672
707
  writeFrontMatter,
673
708
  toProjectSlug,
709
+ detectPackageManager,
710
+ installSelfAsDevDep,
674
711
  };