create-packkit 2.4.0 → 2.6.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.
package/README.md CHANGED
@@ -28,29 +28,114 @@ Then `cd`, and you already have a working project — `build`, `test`, and `lint
28
28
 
29
29
  No install needed: **[danmat.github.io/create-packkit](https://danmat.github.io/create-packkit/)** — tick the options, preview the file tree, and **download a zip** (or copy the equivalent `npx create-packkit` command). Everything runs in your browser.
30
30
 
31
- ## What you can pick
32
-
33
- | Area | Options |
34
- |---|---|
35
- | **Language** | TypeScript (strict) · JavaScript (ESM) |
36
- | **Module format** | **ESM-only (default)** · dual (ESM + CJS) · CJS — proper `exports` map |
37
- | **Target** | Library · CLI tool · **HTTP service (Hono)** · **App (Vite SPA)** · any combination |
38
- | **Framework** | None · **React** · **Vue** · **Svelte** (component libraries or apps) |
39
- | **Storybook** | optional, for React / Vue / Svelte component libraries |
40
- | **Bundler** | tsup · tsdown · unbuild · rollup · none (tsc) · optional **minify** |
41
- | **Tests** | Vitest · Jest · node:test · none (+ coverage) |
42
- | **Lint/format** | ESLint + Prettier · Biome · oxlint · none |
43
- | **Git hooks** | simple-git-hooks · husky + lint-staged · lefthook · none |
44
- | **Release** | Changesets · release-it · np · none |
45
- | **GitHub Actions** | CI · npm publish (provenance) · Pages · CodeQL · Codecov · stale bot |
46
- | **Deps** | Renovate · Dependabot · none |
47
- | **Repo** | LICENSE · community files · **AGENTS.md + CLAUDE.md** · VS Code · `.editorconfig` |
48
- | **Monorepo** | optional pnpm/npm/yarn workspace with **Turborepo** + Changesets + example packages |
49
- | **Package manager** | npm · pnpm · yarn · bun |
31
+ ## Options reference
32
+
33
+ Every flag, its values (**default** in bold), and what it's for. Prefer the interactive [web configurator](https://danmat.github.io/create-packkit/) — the same descriptions appear as you hover. _This table is generated from the schema (`npm run gen:reference`)._
34
+
35
+ <!-- OPTIONS:START -->
36
+
37
+ ### Package
38
+
39
+ | Flag | Values | What it does |
40
+ |---|---|---|
41
+ | `--name` | | The npm package name. Scoped names like `@you/pkg` are fine. |
42
+ | `--description` | | One-line summary used in package.json and the README heading. |
43
+ | `--author` | | Your name (and optionally email/URL). Populates package.json + LICENSE. |
44
+ | `--keywords` | | Comma-separated npm keywords to help people discover the package. |
45
+ | `--repo` | | Git repository URL. Wires up repository/bugs/homepage links and CI badges. |
46
+
47
+ ### Core
48
+
49
+ | Flag | Values | What it does |
50
+ |---|---|---|
51
+ | `--language` | **ts** · js | TypeScript (strict, recommended) or plain ESM JavaScript. TS gives you types, editor help, and generated .d.ts for consumers. |
52
+ | `--module` | **esm** · dual · cjs | How the package is consumed. ESM-only (default) is the modern, leanest choice — Node 20.19+/22.12+ can `require()` ESM. Pick dual only if you must support older CJS-only consumers; cjs-only is rarely needed. |
53
+ | `--server` | **hono** · fastify · express | For the service target: Hono (fast, web-standard, tiny — default), Fastify (batteries-included, plugins, schema validation), or Express (ubiquitous, huge ecosystem). |
54
+ | `--target` | **library** · cli · service · app | What you are building — mix and match: a library (importable package), a CLI (ships a bin), an HTTP service, or an app (Vite SPA). |
55
+ | `--monorepo` | on / off (default: **off**) | Generate a pnpm + Turborepo workspace with two linked example packages and Changesets. Only worth it when ≥2 packages share code. |
56
+ | `--framework` | **none** · react · vue · svelte | UI framework for component libraries and apps: React, Vue, or Svelte (or none for a plain package). |
57
+ | `--pm` | **npm** · pnpm · yarn · bun | Which package manager the scripts, lockfile, and CI target: npm, pnpm, yarn, or bun. |
58
+ | `--node` | 22 · **24** · 26 | Minimum Node line to support. Choices track Node’s own release schedule (Active LTS is the default); this sets engines + .nvmrc. |
59
+
60
+ ### Build
61
+
62
+ | Flag | Values | What it does |
63
+ |---|---|---|
64
+ | `--bundler` | **tsup** · tsdown · unbuild · rollup · none | How the library is built. tsup (default, esbuild-fast) and tsdown suit most libs; unbuild for zero-config; rollup for full control; none = tsc-only (or no build). |
65
+ | `--minify` | on / off (default: **off**) | Minify the build output. Best for CLIs and browser bundles; usually unnecessary for libraries (consumers minify). |
66
+ | `--no-sourcemaps` | on / off (default: **on**) | Ship source + JS/declaration maps so consumers can step into and go-to-definition on your original code when debugging. On by default for libraries. |
67
+
68
+ ### Quality
69
+
70
+ | Flag | Values | What it does |
71
+ |---|---|---|
72
+ | `--test` | **vitest** · jest · node · none | Test runner: Vitest (fast, Vite-native, default), Jest (classic, huge ecosystem), or Node’s built-in node:test (zero deps). |
73
+ | `--no-coverage` | on / off (default: **on**) | Collect code-coverage reports (v8) and add a `coverage` script. Pairs with the Codecov workflow. |
74
+ | `--storybook` | on / off (default: **off**) | Add Storybook to develop and document components in isolation. Component libraries only. |
75
+ | `--e2e` | on / off (default: **off**) | Add Playwright end-to-end tests for app targets: a config that boots your dev server, an example spec, and a CI job. |
76
+ | `--env` | on / off (default: **off**) | Type-safe environment variables: a Zod-validated `src/env.ts` that fails fast on misconfig, plus a `.env.example`. For services and CLIs. |
77
+ | `--pkg-checks` | on / off (default: **off**) | Verify the published package is correct with publint + are-the-types-wrong (exports map, types resolution, ESM/CJS). Highly recommended for libraries. |
78
+ | `--knip` | on / off (default: **off**) | Find unused files, dependencies, and exports so the project doesn’t accumulate dead weight. |
79
+ | `--size-limit` | on / off (default: **off**) | Add a bundle-size budget (size-limit) that measures your built entry and fails CI if it exceeds the limit — catches accidental bloat. |
80
+ | `--doctor` | on / off (default: **off**) | Add an env doctor (`npm run doctor`) that warns when the local Node / package manager don’t match what the project expects. Warn-only. |
81
+ | `--lint` | **eslint-prettier** · biome · oxlint · none | Linter + formatter: ESLint + Prettier (default, most compatible), Biome (one fast tool for both), or oxlint (Rust-fast linting). |
82
+ | `--hooks` | **simple-git-hooks** · husky · lefthook · none | Pre-commit hooks that run lint-staged: simple-git-hooks (tiny, default), husky (popular), or lefthook (fast, parallel). |
83
+
84
+ ### Release
85
+
86
+ | Flag | Values | What it does |
87
+ |---|---|---|
88
+ | `--canary` | on / off (default: **off**) | Add a workflow that publishes snapshot builds (x.y.z-canary-<hash>) to a `canary` dist-tag so people can test unreleased changes. Requires Changesets. |
89
+ | `--release` | **changesets** · release-it · np · none | How you version + publish: Changesets (default, great for libraries and monorepos), release-it, np, or none. |
90
+ | `--jsr` | on / off (default: **off**) | Also publish to JSR, the TypeScript-first registry. For plain ESM TypeScript libraries. |
91
+
92
+ ### CI / CD
93
+
94
+ | Flag | Values | What it does |
95
+ |---|---|---|
96
+ | `--workflows` | **ci** · **npm-publish** · pages · codeql · codecov · stale | GitHub Actions to include: ci (lint/test/build), npm-publish (provenance), pages (deploy Storybook/site), codeql (security), codecov (coverage), stale. |
97
+ | `--deps` | **renovate** · dependabot · none | Automated dependency updates: Renovate (default, powerful) or Dependabot (built into GitHub). |
98
+
99
+ ### Repository
100
+
101
+ | Flag | Values | What it does |
102
+ |---|---|---|
103
+ | `--license` | **MIT** · Apache-2.0 · ISC · none | Open-source license for the LICENSE file and package.json (MIT recommended), or none. |
104
+ | `--no-community` | on / off (default: **on**) | Community health files: CONTRIBUTING, CODE_OF_CONDUCT, SECURITY, and issue/PR templates. |
105
+ | `--no-agents` | on / off (default: **on**) | AI-agent instructions (AGENTS.md + CLAUDE.md) so coding agents know how to build, test, and work in the repo. |
106
+ | `--no-vscode` | on / off (default: **on**) | VS Code workspace settings + recommended-extensions so the repo is set up consistently on open. |
107
+ | `--no-editorconfig` | on / off (default: **on**) | An .editorconfig so every editor uses the same indentation and line endings. |
108
+ | `--no-git` | on / off (default: **on**) | Run `git init` and make an initial commit after scaffolding. |
109
+ | `--no-install` | on / off (default: **on**) | Install dependencies automatically after scaffolding. |
110
+
111
+ <!-- OPTIONS:END -->
50
112
 
51
113
  ## Presets
52
114
 
53
- `ts-lib` · `js-lib` · `ts-cli` / `cli` · `react-lib` · `react-lib-js` · `react-app` · `vue-lib` · `vue-app` · `svelte-lib` · `svelte-app` · `node-service` · `monorepo` · `oss` · `minimal` · `full` — named bundles of the options above. See the [roadmap](ROADMAP.md) for what's next.
115
+ Named bundles of the options above `npx packkit <preset> <name> -y`.
116
+
117
+ <!-- PRESETS:START -->
118
+
119
+ | Preset | Shortcut | What you get |
120
+ |---|---|---|
121
+ | `ts-lib` | `lib` | TypeScript library — ESM-only, tsup, Vitest, ESLint. |
122
+ | `js-lib` | `jslib` | JavaScript (ESM) library — tsup, Vitest, ESLint. |
123
+ | `ts-cli` | — | TypeScript CLI + library — ESM, ships a bin. |
124
+ | `cli` | — | TypeScript CLI tool — ESM, ships a bin. |
125
+ | `react-lib` | `rlib` | React component library (TS) — JSX, peer deps, jsdom tests. |
126
+ | `react-lib-js` | — | React component library (JS) — JSX, peer deps, jsdom tests. |
127
+ | `react-app` | `rapp` | React SPA — Vite dev server, build, Testing Library. |
128
+ | `vue-lib` | `vlib` | Vue component library — Vite lib build (SFCs), ESM + types. |
129
+ | `vue-app` | `vapp` | Vue SPA — Vite dev server, build, Testing Library. |
130
+ | `svelte-lib` | `slib` | Svelte component library — ships source, peer svelte, jsdom tests. |
131
+ | `svelte-app` | `sapp` | Svelte SPA — Vite dev server, build, Testing Library. |
132
+ | `node-service` | `svc`, `service` | Node HTTP service (Hono) — tsx dev, tsup build, Dockerfile. |
133
+ | `monorepo` | — | pnpm + Turborepo workspace — two example packages, Changesets, CI. |
134
+ | `oss` | — | Full open-source library — coverage, CodeQL, Codecov, Renovate, Changesets. |
135
+ | `minimal` | — | Bare TS library — tsup only, no tests/lint/CI. |
136
+ | `full` | — | Everything on — library + CLI, all workflows and extras. |
137
+
138
+ <!-- PRESETS:END -->
54
139
 
55
140
  **Team profiles:** save a partial config as `packkit.config.json` (or any file) and reuse it with `npx create-packkit my-lib --from ./packkit.config.json` — flags still override the file.
56
141
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-packkit",
3
- "version": "2.4.0",
3
+ "version": "2.6.0",
4
4
  "description": "Highly configurable scaffolder for modern npm packages and CLIs — pick your stack (TS/JS, bundler, tests, linter, CI, releases) from a CLI or a web configurator.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -27,7 +27,8 @@
27
27
  "check:deps": "node scripts/check-template-deps.mjs",
28
28
  "integration": "node scripts/integration.mjs",
29
29
  "build:web": "esbuild src/core/index.js --bundle --format=esm --outfile=docs/packkit-core.js",
30
- "update:node": "node scripts/update-node-versions.mjs"
30
+ "update:node": "node scripts/update-node-versions.mjs",
31
+ "gen:reference": "node scripts/gen-reference.mjs"
31
32
  },
32
33
  "repository": {
33
34
  "type": "git",
package/src/cli/args.js CHANGED
@@ -56,6 +56,7 @@ export function parseCliArgs(argv) {
56
56
  'pkg-checks': { type: 'boolean' },
57
57
  knip: { type: 'boolean' },
58
58
  'size-limit': { type: 'boolean' },
59
+ doctor: { type: 'boolean' },
59
60
  jsr: { type: 'boolean' },
60
61
  help: { type: 'boolean', short: 'h' },
61
62
  version: { type: 'boolean', short: 'v' },
@@ -86,6 +87,7 @@ export function parseCliArgs(argv) {
86
87
  if (values['pkg-checks']) overrides.pkgChecks = true;
87
88
  if (values.knip) overrides.knip = true;
88
89
  if (values['size-limit']) overrides.sizeLimit = true;
90
+ if (values.doctor) overrides.doctor = true;
89
91
  if (values.jsr) overrides.jsr = true;
90
92
  for (const [flag, key] of Object.entries(NEGATABLE)) {
91
93
  if (values[flag]) overrides[key] = false;
package/src/cli/index.js CHANGED
@@ -2,7 +2,7 @@ import { resolve, basename } from 'node:path';
2
2
  import { readFileSync, existsSync } from 'node:fs';
3
3
  import { fileURLToPath } from 'node:url';
4
4
  import * as p from '@clack/prompts';
5
- import { generate, fromPreset, normalizeConfig, PRESET_NAMES, OPTIONS, PRESET_INFO, PRESET_ALIASES } from '../core/index.js';
5
+ import { generate, fromPreset, normalizeConfig, PRESET_NAMES, OPTIONS, OPTION_HELP, PRESET_INFO, PRESET_ALIASES } from '../core/index.js';
6
6
  import { engineFloor, meetsNodeFloor } from '../core/node.js';
7
7
  import { parseCliArgs } from './args.js';
8
8
  import { runWizard } from './wizard.js';
@@ -18,48 +18,75 @@ const pkgVersion = () => {
18
18
  };
19
19
 
20
20
  const HELP = `
21
- packkit — scaffold a modern npm package or CLI
21
+ packkit — scaffold a modern npm package, CLI, service, or app
22
22
 
23
23
  Usage:
24
24
  npm create packkit@latest [name] [options]
25
25
  npx packkit [preset] [name] [options]
26
26
 
27
- Presets: ${PRESET_NAMES.join(', ')}
28
-
29
- Options:
30
- --preset <name> Use a preset (skips the wizard)
31
- --from <file> Load defaults from a JSON profile (or packkit.config.json)
32
- --name <name> Package name
33
- --here Scaffold into the current directory
34
- -y, --yes Accept defaults / preset, no prompts (one-shot)
35
- --recommended Alias for --yes — recommended defaults in one command
36
- --monorepo Generate a pnpm/Turborepo workspace
37
- --no-install Skip dependency install
38
- --no-git Skip git init
39
- --pm <manager> npm | pnpm | yarn | bun
40
- --language <ts|js> --module <esm|cjs|dual> --framework <none|react|vue|svelte>
41
- --target <library|cli|service|app> (repeatable) --storybook
42
- --server <hono|fastify|express> (HTTP service framework)
43
- --bundler <tsup|tsdown|unbuild|rollup|none> --minify
44
- --test <vitest|jest|node|none> --e2e (Playwright, for apps)
45
- --env (type-safe env validation, services/CLIs) --no-sourcemaps
27
+ Run with no options for an interactive wizard, or add -y for recommended
28
+ defaults in one shot. Every option is documented (with why-you'd-use-it) at:
29
+ https://danmat.github.io/create-packkit/ · and in the README reference.
30
+
31
+ Presets:
32
+ ${PRESET_NAMES.join(' ')}
33
+ shortcuts: lib jslib rlib rapp vlib vapp slib sapp svc
34
+
35
+ Getting started:
36
+ --preset <name> Start from a preset (skips the wizard)
37
+ --from <file> Load defaults from a JSON profile (or packkit.config.json)
38
+ -y, --yes Accept defaults / preset, no prompts (one-shot)
39
+ --recommended Alias for -y
40
+ --here Scaffold into the current directory
41
+ --no-install Skip dependency install
42
+ --no-git Skip git init
43
+
44
+ Stack:
45
+ --language <ts|js>
46
+ --module <esm|cjs|dual> ESM-only is the default
47
+ --framework <none|react|vue|svelte>
48
+ --target <library|cli|service|app> repeatable
49
+ --server <hono|fastify|express> HTTP service framework
50
+ --pm <npm|pnpm|yarn|bun>
51
+ --monorepo pnpm + Turborepo workspace
52
+
53
+ Build & test:
54
+ --bundler <tsup|tsdown|unbuild|rollup|none>
55
+ --minify Minify the build output
56
+ --no-sourcemaps Don't ship source / sourcemaps
57
+ --test <vitest|jest|node|none>
58
+ --e2e Playwright end-to-end tests (apps)
59
+ --size-limit Bundle-size budget + CI gate (libs)
60
+
61
+ Quality:
46
62
  --lint <eslint-prettier|biome|oxlint|none>
47
- --hooks <simple-git-hooks|husky|lefthook|none> --release <changesets|release-it|np|none>
48
- --workflows <ci|npm-publish|pages|codeql|codecov|stale> (repeatable)
49
- --deps <renovate|dependabot|none> --license <MIT|Apache-2.0|ISC|none>
50
- --pkg-checks (publint + are-the-types-wrong) --knip --jsr --canary
51
- --size-limit (bundle-size budget, libraries)
63
+ --hooks <simple-git-hooks|husky|lefthook|none>
64
+ --pkg-checks publint + are-the-types-wrong
65
+ --knip Find unused files / deps / exports
66
+ --doctor Warn on Node / pm mismatch
67
+ --env Type-safe env validation (services/CLIs)
68
+
69
+ Release & CI:
70
+ --release <changesets|release-it|np|none>
71
+ --canary Snapshot/canary release workflow
72
+ --jsr Also publish to JSR
73
+ --workflows <ci|npm-publish|pages|codeql|codecov|stale> repeatable
74
+ --deps <renovate|dependabot|none>
75
+
76
+ Repo & extras:
77
+ --license <MIT|Apache-2.0|ISC|none>
78
+ --storybook Storybook (component libraries)
52
79
  --no-coverage --no-community --no-agents --no-vscode --no-editorconfig
53
- --schema Print the full option/preset schema as JSON (for tools/agents)
54
- -h, --help Show this help
55
- -v, --version Show version
56
80
 
57
- Preset shortcuts: lib, jslib, rlib, rapp, vlib, vapp, slib, sapp, svc
81
+ Other:
82
+ --schema Print the full option/preset schema as JSON (for agents)
83
+ -h, --help Show this help -v, --version Show version
58
84
 
59
85
  Examples:
60
- npx packkit ts-lib my-lib
61
- npm create packkit@latest my-cli -- --preset cli
62
- npx packkit --preset full my-pkg --pm pnpm
86
+ npx packkit ts-lib my-lib -y
87
+ npx packkit react-app my-app --e2e
88
+ npx packkit node-service api --server fastify --env
89
+ npm create packkit@latest my-pkg -- --preset oss --pm pnpm
63
90
  `;
64
91
 
65
92
  export async function run(argv = process.argv.slice(2)) {
@@ -68,7 +95,7 @@ export async function run(argv = process.argv.slice(2)) {
68
95
  if (args.version) return void console.log(pkgVersion());
69
96
  if (args.schema) {
70
97
  // Machine-readable interface for tools/agents: every option, preset, and alias.
71
- return void console.log(JSON.stringify({ version: pkgVersion(), options: OPTIONS, presets: PRESET_INFO, aliases: PRESET_ALIASES }, null, 2));
98
+ return void console.log(JSON.stringify({ version: pkgVersion(), options: OPTIONS, optionHelp: OPTION_HELP, presets: PRESET_INFO, aliases: PRESET_ALIASES }, null, 2));
72
99
  }
73
100
 
74
101
  // Only prompt when the user gave nothing to go on — a preset, --yes, a
@@ -0,0 +1,54 @@
1
+ // A tiny environment doctor: checks the local Node and package manager match
2
+ // what this project expects, and warns (never fails) otherwise. `npm run doctor`
3
+ // runs it any time; for private projects it also runs on postinstall. It is NOT
4
+ // wired to postinstall for publishable packages — that would run in every
5
+ // consumer's install.
6
+
7
+ export default {
8
+ id: 'doctor',
9
+ active: (cfg) => cfg.doctor && !cfg.monorepo,
10
+ apply(cfg) {
11
+ const files = { 'scripts/doctor.mjs': script(cfg) };
12
+ const pkg = { scripts: { doctor: 'node scripts/doctor.mjs' } };
13
+ if (!cfg.publishable) pkg.scripts.postinstall = 'node scripts/doctor.mjs';
14
+ return { files, pkg };
15
+ },
16
+ };
17
+
18
+ function script(cfg) {
19
+ return [
20
+ `/* global process, console, URL */`,
21
+ `// Checks your environment matches this project. Warns only — never fails.`,
22
+ `import { readFileSync } from 'node:fs';`,
23
+ ``,
24
+ `const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));`,
25
+ `const gte = (a, b) => {`,
26
+ `\tconst pa = String(a).split('.').map(Number);`,
27
+ `\tconst pb = String(b).split('.').map(Number);`,
28
+ `\tfor (let i = 0; i < 3; i++) if ((pa[i] || 0) !== (pb[i] || 0)) return (pa[i] || 0) > (pb[i] || 0);`,
29
+ `\treturn true;`,
30
+ `};`,
31
+ ``,
32
+ `let issues = 0;`,
33
+ `const floor = (pkg.engines?.node || '').replace(/[^0-9.]/g, '');`,
34
+ `const node = process.versions.node;`,
35
+ `if (floor && !gte(node, floor)) {`,
36
+ "\tconsole.warn(`⚠ Node ${node} is below the required >=${floor} — run: nvm install ${floor.split('.')[0]}`);",
37
+ `\tissues++;`,
38
+ `} else {`,
39
+ "\tconsole.log(`✓ Node ${node}`);",
40
+ `}`,
41
+ ``,
42
+ `const expectedPm = '${cfg.packageManager}';`,
43
+ `const usingPm = (process.env.npm_config_user_agent || '').split('/')[0];`,
44
+ `if (usingPm && usingPm !== expectedPm) {`,
45
+ "\tconsole.warn(`⚠ This project uses ${expectedPm}, but you ran ${usingPm}.`);",
46
+ `\tissues++;`,
47
+ `} else {`,
48
+ "\tconsole.log(`✓ Package manager: ${expectedPm}`);",
49
+ `}`,
50
+ ``,
51
+ `if (issues) console.warn('\\nSee the README "Requirements" section to fix these.');`,
52
+ ``,
53
+ ].join('\n');
54
+ }
@@ -22,6 +22,7 @@ import storybook from './storybook.js';
22
22
  import community from './community.js';
23
23
  import agents from './agents.js';
24
24
  import vscode from './vscode.js';
25
+ import doctor from './doctor.js';
25
26
  import gitfiles from './gitfiles.js';
26
27
 
27
28
  export default [
@@ -46,5 +47,6 @@ export default [
46
47
  community,
47
48
  agents,
48
49
  vscode,
50
+ doctor,
49
51
  gitfiles,
50
52
  ];
package/src/core/index.js CHANGED
@@ -2,14 +2,14 @@
2
2
  // generate(config) -> { config, files: { path: contents }, postCommands, summary }
3
3
  // The CLI writes `files` to disk; the web configurator zips them.
4
4
 
5
- import { normalizeConfig, OPTIONS, GROUPS, defaultConfig } from './options.js';
5
+ import { normalizeConfig, OPTIONS, GROUPS, OPTION_HELP, defaultConfig } from './options.js';
6
6
  import { deepMerge, toJson } from './render.js';
7
7
  import { finalizePackageJson } from './pkg.js';
8
8
  import features from './features/index.js';
9
9
  import { buildMonorepo } from './monorepo.js';
10
10
  import { PRESETS, PRESET_NAMES, PRESET_INFO, PRESET_ALIASES, resolvePreset } from './presets.js';
11
11
 
12
- export { OPTIONS, GROUPS, defaultConfig, normalizeConfig, PRESETS, PRESET_NAMES, PRESET_INFO, PRESET_ALIASES, resolvePreset };
12
+ export { OPTIONS, GROUPS, OPTION_HELP, defaultConfig, normalizeConfig, PRESETS, PRESET_NAMES, PRESET_INFO, PRESET_ALIASES, resolvePreset };
13
13
 
14
14
  /** Apply a named preset (or alias) over the defaults, returning a full config. */
15
15
  export function fromPreset(name, overrides = {}) {
@@ -111,6 +111,7 @@ export const OPTIONS = {
111
111
  pkgChecks: { group: 'quality', type: 'boolean', label: 'Package checks (publint + are-the-types-wrong)', default: false },
112
112
  knip: { group: 'quality', type: 'boolean', label: 'Knip (unused files / deps / exports)', default: false },
113
113
  sizeLimit: { group: 'quality', type: 'boolean', label: 'size-limit (bundle-size budget, libraries)', default: false },
114
+ doctor: { group: 'quality', type: 'boolean', label: 'Env doctor (warn on Node / package-manager mismatch)', default: false },
114
115
 
115
116
  // ---- lint / format ----
116
117
  lint: {
@@ -196,6 +197,50 @@ export const GROUPS = [
196
197
  { id: 'repo', label: 'Repository' },
197
198
  ];
198
199
 
200
+ // Plain-English "what it is / why you'd pick it" for every option. One source
201
+ // of truth for the web tooltips, the README reference, and `--schema` (agents).
202
+ export const OPTION_HELP = {
203
+ name: 'The npm package name. Scoped names like `@you/pkg` are fine.',
204
+ description: 'One-line summary — used in package.json and the README heading.',
205
+ author: 'Your name (and optionally email/URL). Populates package.json + LICENSE.',
206
+ keywords: 'Comma-separated npm keywords to help people discover the package.',
207
+ repo: 'Git repository URL. Wires up repository/bugs/homepage links and CI badges.',
208
+ language: 'TypeScript (strict, recommended) or plain ESM JavaScript. TS gives you types, editor help, and generated .d.ts for consumers.',
209
+ moduleFormat: 'How the package is consumed. ESM-only (default) is the modern, leanest choice — Node 20.19+/22.12+ can `require()` ESM. Pick dual only if you must support older CJS-only consumers; cjs-only is rarely needed.',
210
+ target: 'What you are building — mix and match: a library (importable package), a CLI (ships a bin), an HTTP service, or an app (Vite SPA).',
211
+ serviceFramework: 'For the service target: Hono (fast, web-standard, tiny — default), Fastify (batteries-included, plugins, schema validation), or Express (ubiquitous, huge ecosystem).',
212
+ monorepo: 'Generate a pnpm + Turborepo workspace with two linked example packages and Changesets. Only worth it when ≥2 packages share code.',
213
+ framework: 'UI framework for component libraries and apps: React, Vue, or Svelte (or none for a plain package).',
214
+ packageManager: 'Which package manager the scripts, lockfile, and CI target: npm, pnpm, yarn, or bun.',
215
+ nodeVersion: 'Minimum Node line to support. Choices track Node’s own release schedule (Active LTS is the default); this sets engines + .nvmrc.',
216
+ bundler: 'How the library is built. tsup (default, esbuild-fast) and tsdown suit most libs; unbuild for zero-config; rollup for full control; none = tsc-only (or no build).',
217
+ minify: 'Minify the build output. Best for CLIs and browser bundles; usually unnecessary for libraries (consumers minify).',
218
+ sourcemaps: 'Ship source + JS/declaration maps so consumers can step into and go-to-definition on your original code when debugging. On by default for libraries.',
219
+ test: 'Test runner: Vitest (fast, Vite-native, default), Jest (classic, huge ecosystem), or Node’s built-in node:test (zero deps).',
220
+ coverage: 'Collect code-coverage reports (v8) and add a `coverage` script. Pairs with the Codecov workflow.',
221
+ storybook: 'Add Storybook to develop and document components in isolation. Component libraries only.',
222
+ e2e: 'Add Playwright end-to-end tests for app targets: a config that boots your dev server, an example spec, and a CI job.',
223
+ sizeLimit: 'Add a bundle-size budget (size-limit) that measures your built entry and fails CI if it exceeds the limit — catches accidental bloat.',
224
+ doctor: 'Add an env doctor (`npm run doctor`) that warns when the local Node / package manager don’t match what the project expects. Warn-only.',
225
+ env: 'Type-safe environment variables: a Zod-validated `src/env.ts` that fails fast on misconfig, plus a `.env.example`. For services and CLIs.',
226
+ pkgChecks: 'Verify the published package is correct with publint + are-the-types-wrong (exports map, types resolution, ESM/CJS). Highly recommended for libraries.',
227
+ knip: 'Find unused files, dependencies, and exports so the project doesn’t accumulate dead weight.',
228
+ lint: 'Linter + formatter: ESLint + Prettier (default, most compatible), Biome (one fast tool for both), or oxlint (Rust-fast linting).',
229
+ gitHooks: 'Pre-commit hooks that run lint-staged: simple-git-hooks (tiny, default), husky (popular), or lefthook (fast, parallel).',
230
+ release: 'How you version + publish: Changesets (default, great for libraries and monorepos), release-it, np, or none.',
231
+ canary: 'Add a workflow that publishes snapshot builds (x.y.z-canary-<hash>) to a `canary` dist-tag so people can test unreleased changes. Requires Changesets.',
232
+ jsr: 'Also publish to JSR, the TypeScript-first registry. For plain ESM TypeScript libraries.',
233
+ workflows: 'GitHub Actions to include: ci (lint/test/build), npm-publish (provenance), pages (deploy Storybook/site), codeql (security), codecov (coverage), stale.',
234
+ deps: 'Automated dependency updates: Renovate (default, powerful) or Dependabot (built into GitHub).',
235
+ license: 'Open-source license for the LICENSE file and package.json (MIT recommended), or none.',
236
+ community: 'Community health files: CONTRIBUTING, CODE_OF_CONDUCT, SECURITY, and issue/PR templates.',
237
+ agents: 'AI-agent instructions (AGENTS.md + CLAUDE.md) so coding agents know how to build, test, and work in the repo.',
238
+ vscode: 'VS Code workspace settings + recommended-extensions so the repo is set up consistently on open.',
239
+ editorconfig: 'An .editorconfig so every editor uses the same indentation and line endings.',
240
+ gitInit: 'Run `git init` and make an initial commit after scaffolding.',
241
+ install: 'Install dependencies automatically after scaffolding.',
242
+ };
243
+
199
244
  /** Build a default config from the schema. */
200
245
  export function defaultConfig() {
201
246
  const cfg = {};