@kevinmarrec/create-app — CLI that scaffolds an opinionated Bun & Vue fullstack application.
Invoked via bun create @kevinmarrec/app or bunx @kevinmarrec/create-app.
- Runtime: Bun (v1.3.10+)
- Language: TypeScript (ES modules)
- Build: tsdown →
dist/index.mjs - Test: Vitest with v8 coverage
- Lint: ESLint (@antfu config), Stylelint, Knip (unused exports)
- Types: vue-tsc --noEmit
@clack/prompts— CLI prompts (intro, text, confirm, tasks, note, outro)ansis— Terminal colorspathe— Cross-platform path utilitiestinyexec— Process execution (git, bun install)
src/
├── index.ts # Entry point (shebang, calls run())
├── run.ts # CLI orchestration (parseArgs, prompts, scaffold)
├── scaffold.ts # Template copying logic
└── utils/
├── fs.ts # FS utilities (empty, emptyCheck, exists, ignorePredicate)
└── template.ts # URL resolution, git clone for external templates
test/
├── index.test.ts # Entry point error handling
├── run.test.ts # Integration tests (mocks prompts + tinyexec)
└── template.test.ts # Unit tests for URL resolution + clone
template/ # Built-in opinionated template (copied on scaffold)bun run build— Build with tsdownbun run test— Run tests (vitest)bun run test:coverage— Tests with v8 coveragebun run check— All checks (eslint + stylelint + knip + types)bun run check:eslint— ESLint onlybun run check:types— Type checking (vue-tsc)
- Always run
bun run checkbefore considering work done — all checks (eslint, stylelint, knip, types) must pass - Run
bun run test:coverageto verify tests pass with 100% coverage - Do not add
Co-Authored-Bytrailers to commit messages
- Imports: Use project's
src/utils/fswrapper (re-exportsnode:fs/promises+ custom utils), never importnode:fs/promisesdirectly insrc/ - Ignored files: Use
ignorePredicatefromsrc/utils/fs.tsfor.gitfiltering — never hardcode'.git'string comparisons - CLI options: Keep alphabetically ordered in
parseArgsand help text - Process execution: Use
tinyexec(x()) for shelling out - Error handling: Preserve error cause with
{ cause: error }in Error constructors - Tests: Mock
tinyexecand@clack/promptsviavi.hoisted()+vi.mock(). Usefs.mkdtempfor temp dirs, clean up inafterEach - Coverage: Maintain 100% coverage across statements, branches, functions, and lines
- Style: No emojis in code. ESLint enforces
antfu/consistent-list-newlineandantfu/consistent-chaining
process.exitis mocked to throwError('process.exit(N)'), tested viarejects.toThrowErrorprocess.stdout.writeis spied and mocked to verify CLI outputprocess.cwdis mocked to return a temp directory- Only test long option names (e.g.
--force,--template), not short aliases