claude-toolkit 0.16.0 → 0.17.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 (68) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +54 -13
  3. package/bin/cli.ts +75 -19
  4. package/package.json +6 -7
  5. package/src/generator.ts +64 -26
  6. package/src/refresh-hint.ts +95 -0
  7. package/bin/postinstall.mjs +0 -69
  8. package/docs/README.md +0 -59
  9. package/docs/agents/code-reviewer.md +0 -76
  10. package/docs/agents/github-workflow.md +0 -98
  11. package/docs/best-practices/capacitor/README.md +0 -64
  12. package/docs/best-practices/capacitor/capacitor-8.md +0 -60
  13. package/docs/best-practices/capacitor/capgo-setup.md +0 -151
  14. package/docs/best-practices/capacitor/channels-and-rollouts.md +0 -101
  15. package/docs/best-practices/capacitor/live-updates-ota.md +0 -75
  16. package/docs/best-practices/capacitor/security-encryption.md +0 -68
  17. package/docs/best-practices/solidjs/README.md +0 -43
  18. package/docs/best-practices/solidjs/anti-patterns.md +0 -166
  19. package/docs/best-practices/solidjs/component-patterns.md +0 -131
  20. package/docs/best-practices/solidjs/context-and-global-state.md +0 -131
  21. package/docs/best-practices/solidjs/control-flow.md +0 -124
  22. package/docs/best-practices/solidjs/data-fetching.md +0 -205
  23. package/docs/best-practices/solidjs/effects-and-lifecycle.md +0 -113
  24. package/docs/best-practices/solidjs/performance.md +0 -100
  25. package/docs/best-practices/solidjs/props-patterns.md +0 -100
  26. package/docs/best-practices/solidjs/reactivity-model.md +0 -104
  27. package/docs/best-practices/solidjs/signals-and-state.md +0 -78
  28. package/docs/best-practices/solidjs/stores-and-nested-state.md +0 -111
  29. package/docs/best-practices/solidjs/typescript-integration.md +0 -186
  30. package/docs/best-practices/testing/README.md +0 -84
  31. package/docs/best-practices/testing/playwright-e2e.md +0 -649
  32. package/docs/best-practices/testing/storybook-interaction.md +0 -455
  33. package/docs/best-practices/testing/vitest-unit.md +0 -451
  34. package/docs/best-practices/typescript/README.md +0 -45
  35. package/docs/best-practices/typescript/any-and-unknown.md +0 -73
  36. package/docs/best-practices/typescript/deriving-vs-decoupling.md +0 -83
  37. package/docs/best-practices/typescript/discriminated-unions.md +0 -75
  38. package/docs/best-practices/typescript/enums-alternatives.md +0 -72
  39. package/docs/best-practices/typescript/essential-patterns.md +0 -119
  40. package/docs/best-practices/typescript/generics-patterns.md +0 -105
  41. package/docs/best-practices/typescript/micro-opinions.md +0 -87
  42. package/docs/best-practices/typescript/runtime-validation.md +0 -62
  43. package/docs/best-practices/typescript/satisfies-operator.md +0 -100
  44. package/docs/best-practices/typescript/tsconfig-cheat-sheet.md +0 -160
  45. package/docs/best-practices/typescript/type-organization.md +0 -64
  46. package/docs/best-practices/typescript/type-vs-interface.md +0 -80
  47. package/docs/commands/code-quality.md +0 -36
  48. package/docs/commands/onboard.md +0 -63
  49. package/docs/commands/pr-review.md +0 -91
  50. package/docs/commands/pr-summary.md +0 -50
  51. package/docs/commands/proto-check.md +0 -59
  52. package/docs/commands/ticket.md +0 -56
  53. package/docs/skills/code-style.md +0 -26
  54. package/docs/skills/systematic-debugging.md +0 -70
  55. package/docs/skills/testing-patterns.md +0 -140
  56. package/docs/skills/typescript-conventions.md +0 -283
  57. package/docs/skills/verification-before-completion.md +0 -103
  58. package/docs/stacks/capacitor-ota.md +0 -145
  59. package/docs/stacks/cloudflare-d1-kv.md +0 -144
  60. package/docs/stacks/esnext-idioms.md +0 -25
  61. package/docs/stacks/i18n-typesafe.md +0 -141
  62. package/docs/stacks/playwright-patterns.md +0 -179
  63. package/docs/stacks/protobuf-contracts.md +0 -85
  64. package/docs/stacks/rust-wasm-patterns.md +0 -106
  65. package/docs/stacks/solidjs-patterns.md +0 -110
  66. package/docs/stacks/storybook-patterns.md +0 -177
  67. package/docs/stacks/vanilla-extract-patterns.md +0 -115
  68. package/docs/stacks/vite-vitest-patterns.md +0 -485
@@ -1,485 +0,0 @@
1
- # Vite + Vitest Patterns
2
-
3
- > Vite build tooling and Vitest unit/integration testing patterns.
4
-
5
- **Type:** Stack Skill (requires `vite` stack)
6
- **Source:** [`stacks/vite/skills/ct-vite-vitest-patterns/SKILL.md`](../../stacks/vite/skills/ct-vite-vitest-patterns/SKILL.md)
7
- **Directory Mappings:** `vite.config.ts`, `vitest.config.ts`, `src/**/*.test.ts`, `tests/`
8
- **File Extensions:** `.test.ts`, `.test.tsx`, `.spec.ts`, `.spec.tsx`
9
-
10
- ## Overview
11
-
12
- Vite is the build tool; Vitest is its native test runner. They share a unified config -- aliases, plugins, and `define` values work identically in both. This is the primary advantage over separate build/test toolchains.
13
-
14
- ## Vite Configuration
15
-
16
- ### Config Structure
17
-
18
- ```typescript
19
- import { defineConfig } from 'vite'
20
-
21
- export default defineConfig({
22
- base: '/',
23
- plugins: [],
24
- envPrefix: 'VITE_',
25
-
26
- resolve: {
27
- alias: { '@': '/src' },
28
- conditions: [],
29
- },
30
-
31
- css: {
32
- transformer: 'postcss', // or 'lightningcss'
33
- modules: {},
34
- preprocessorOptions: {},
35
- },
36
-
37
- oxc: {}, // Oxc transformer (replaces esbuild in Vite 8)
38
-
39
- server: {
40
- port: 5173,
41
- proxy: {},
42
- warmup: { clientFiles: [] }, // pre-transform hot files for faster cold starts
43
- },
44
-
45
- build: {
46
- target: 'baseline-widely-available',
47
- outDir: 'dist',
48
- sourcemap: false,
49
- minify: 'oxc', // 'oxc' (default) | 'terser' | false
50
- rolldownOptions: {}, // Rolldown bundler config (replaces rollupOptions in Vite 8)
51
- },
52
-
53
- ssr: {
54
- target: 'node',
55
- noExternal: [],
56
- external: [],
57
- },
58
- })
59
- ```
60
-
61
- ### Conditional Config
62
-
63
- ```typescript
64
- export default defineConfig(({ command, mode, isSsrBuild }) => {
65
- if (command === 'serve') return { /* dev-specific */ }
66
- return { /* build-specific */ }
67
- })
68
- ```
69
-
70
- ### Environment Variables
71
-
72
- Loading order (later overrides earlier): `.env` > `.env.local` > `.env.[mode]` > `.env.[mode].local`.
73
-
74
- Built-in `import.meta.env`: `MODE`, `BASE_URL`, `PROD`, `DEV`, `SSR`.
75
-
76
- **Security:** Never put secrets in `VITE_*` variables -- they are embedded in client bundles.
77
-
78
- TypeScript declarations (`src/vite-env.d.ts`):
79
-
80
- ```typescript
81
- /// <reference types="vite/client" />
82
-
83
- interface ImportMetaEnv {
84
- readonly VITE_API_URL: string
85
- }
86
- interface ImportMeta {
87
- readonly env: ImportMetaEnv
88
- }
89
- ```
90
-
91
- ### Plugin System
92
-
93
- ```typescript
94
- export default defineConfig({
95
- plugins: [
96
- solidPlugin(),
97
- process.env.ANALYZE && visualizer(), // conditional (falsy ignored)
98
- { ...myPlugin(), enforce: 'pre' }, // before Vite core transforms
99
- { ...myPlugin(), apply: 'build' }, // build only
100
- ],
101
- })
102
- ```
103
-
104
- Key hooks (execution order): `config` > `configResolved` > `configureServer` > `transformIndexHtml` > `resolveId` > `load` > `transform` > `handleHotUpdate`.
105
-
106
- ### Library Mode
107
-
108
- ```typescript
109
- import { resolve } from 'node:path'
110
-
111
- export default defineConfig({
112
- build: {
113
- lib: {
114
- entry: resolve(import.meta.dirname, 'lib/main.ts'),
115
- name: 'MyLib',
116
- fileName: 'my-lib',
117
- formats: ['es', 'cjs'],
118
- },
119
- rolldownOptions: {
120
- external: ['solid-js', 'solid-js/web'], // always externalize peer deps
121
- },
122
- },
123
- })
124
- ```
125
-
126
- ### SSR
127
-
128
- ```json
129
- {
130
- "build:client": "vite build --outDir dist/client",
131
- "build:server": "vite build --outDir dist/server --ssr src/entry-server.ts"
132
- }
133
- ```
134
-
135
- Use `middlewareMode: true` + `appType: 'custom'` for framework SSR integration.
136
-
137
- ### Build Performance
138
-
139
- 1. **Avoid barrel files** -- import directly from source modules, not re-export `index.ts`
140
- 2. **Use explicit extensions** -- `import './Component.tsx'` not `import './Component'`
141
- 3. **Warm up hot files** -- `server.warmup.clientFiles: ['./src/main.tsx']`
142
- 4. **Prefer native CSS** -- CSS nesting is supported natively; avoid Sass when possible
143
- 5. **Narrow resolve.extensions** -- remove extensions you don't use
144
-
145
- ## Vitest Configuration
146
-
147
- ### Standalone Config
148
-
149
- ```typescript
150
- import { defineConfig } from 'vitest/config'
151
-
152
- export default defineConfig({
153
- test: {
154
- include: ['**/*.{test,spec}.{ts,tsx}'],
155
- environment: 'node', // 'node' | 'jsdom' | 'happy-dom'
156
- globals: false,
157
- setupFiles: [],
158
- testTimeout: 5000,
159
- pool: 'forks', // 'forks' | 'threads' | 'vmThreads'
160
-
161
- restoreMocks: true, // auto vi.restoreAllMocks() after each test
162
- clearMocks: true,
163
-
164
- coverage: {
165
- provider: 'v8',
166
- include: ['src/**/*.{ts,tsx}'],
167
- exclude: ['**/*.test.*', '**/*.d.ts', 'src/types/**'],
168
- reporter: ['text', 'html', 'lcov'],
169
- thresholds: { lines: 80, branches: 80, functions: 80, statements: 80 },
170
- },
171
-
172
- snapshotSerializers: [],
173
- },
174
- })
175
- ```
176
-
177
- ### Integrated with Vite Config
178
-
179
- ```typescript
180
- /// <reference types="vitest/config" />
181
- import { defineConfig } from 'vite'
182
-
183
- export default defineConfig({
184
- plugins: [solidPlugin()],
185
- resolve: { alias: { '@': '/src' } }, // shared: works in both app and tests
186
- test: {
187
- environment: 'jsdom',
188
- setupFiles: ['./tests/setup.ts'],
189
- },
190
- })
191
- ```
192
-
193
- Vite's `resolve.alias`, `plugins`, and `define` are automatically inherited by Vitest. Never duplicate them.
194
-
195
- ### Merging Separate Configs
196
-
197
- ```typescript
198
- import { defineConfig, mergeConfig } from 'vitest/config'
199
- import viteConfig from './vite.config'
200
-
201
- export default mergeConfig(viteConfig, defineConfig({
202
- test: { environment: 'jsdom' },
203
- }))
204
- ```
205
-
206
- ### Workspace / Projects (Vitest 3+)
207
-
208
- Use `test.projects` for monorepos or mixed environments:
209
-
210
- ```typescript
211
- export default defineConfig({
212
- test: {
213
- projects: [
214
- 'packages/*',
215
- {
216
- test: {
217
- name: 'unit',
218
- include: ['src/**/*.test.ts'],
219
- environment: 'node',
220
- },
221
- },
222
- {
223
- test: {
224
- name: 'components',
225
- include: ['src/**/*.test.tsx'],
226
- environment: 'jsdom',
227
- },
228
- },
229
- ],
230
- },
231
- })
232
- ```
233
-
234
- ## Mocking
235
-
236
- ### Mock Functions
237
-
238
- ```typescript
239
- const fn = vi.fn()
240
- fn.mockReturnValue(42)
241
- fn.mockResolvedValue({ data: [] })
242
- fn.mockImplementation((x) => x * 2)
243
-
244
- expect(fn).toHaveBeenCalledWith('arg')
245
- expect(fn).toHaveBeenCalledTimes(1)
246
- ```
247
-
248
- ### Module Mocking
249
-
250
- `vi.mock` is hoisted above imports automatically:
251
-
252
- ```typescript
253
- vi.mock('./api', () => ({
254
- fetchUser: vi.fn().mockResolvedValue({ id: 1, name: 'Test' }),
255
- }))
256
-
257
- // Access original implementation inside mock
258
- vi.mock('./utils', async (importOriginal) => {
259
- const actual = await importOriginal<typeof import('./utils')>()
260
- return { ...actual, format: vi.fn() }
261
- })
262
- ```
263
-
264
- **Hoisting caveat:** Variables defined before `vi.mock()` are not accessible inside the factory. Use `vi.hoisted()` for shared variables:
265
-
266
- ```typescript
267
- const { mockFetch } = vi.hoisted(() => ({
268
- mockFetch: vi.fn(),
269
- }))
270
-
271
- vi.mock('./api', () => ({ fetch: mockFetch }))
272
- ```
273
-
274
- ### Spying
275
-
276
- ```typescript
277
- const spy = vi.spyOn(console, 'warn').mockImplementation(() => {})
278
- expect(spy).toHaveBeenCalledWith('expected warning')
279
- spy.mockRestore()
280
- ```
281
-
282
- ### Timer Mocking
283
-
284
- ```typescript
285
- vi.useFakeTimers()
286
- vi.setSystemTime(new Date('2026-01-01'))
287
-
288
- setTimeout(callback, 1000)
289
- vi.advanceTimersByTime(1000)
290
- expect(callback).toHaveBeenCalled()
291
-
292
- vi.useRealTimers()
293
- ```
294
-
295
- ### Environment Stubs
296
-
297
- ```typescript
298
- vi.stubGlobal('__VERSION__', '1.0.0')
299
- vi.stubEnv('VITE_API_URL', 'http://test.example.com')
300
-
301
- afterEach(() => {
302
- vi.unstubAllGlobals()
303
- vi.unstubAllEnvs()
304
- })
305
- ```
306
-
307
- ## Snapshot Testing
308
-
309
- ```typescript
310
- // File snapshots (stored in __snapshots__/)
311
- expect(result).toMatchSnapshot()
312
-
313
- // Inline snapshots (written into test file by vitest --update)
314
- expect(result).toMatchInlineSnapshot(`{ "id": 1 }`)
315
-
316
- // Custom file path
317
- expect(htmlOutput).toMatchFileSnapshot('./fixtures/expected.html')
318
- ```
319
-
320
- Keep inline snapshots under 10-15 lines. Use file snapshots for complex output. Snapshots catch regressions but don't verify correctness -- combine with explicit assertions on critical values.
321
-
322
- ## In-Source Testing
323
-
324
- ```typescript
325
- // src/utils/math.ts
326
- export function add(...args: number[]) {
327
- return args.reduce((a, b) => a + b, 0)
328
- }
329
-
330
- if (import.meta.vitest) {
331
- const { it, expect } = import.meta.vitest
332
- it('adds numbers', () => {
333
- expect(add(1, 2, 3)).toBe(6)
334
- })
335
- }
336
- ```
337
-
338
- Config:
339
-
340
- ```typescript
341
- export default defineConfig({
342
- test: { includeSource: ['src/**/*.ts'] },
343
- define: { 'import.meta.vitest': 'undefined' }, // tree-shake from production
344
- })
345
- ```
346
-
347
- Best for small utility functions. Use separate test files for components and integration tests.
348
-
349
- ## Browser Mode (Vitest 4+, Stable)
350
-
351
- ```typescript
352
- import { playwright } from '@vitest/browser-playwright'
353
-
354
- export default defineConfig({
355
- test: {
356
- browser: {
357
- enabled: true,
358
- provider: playwright(),
359
- instances: [{ browser: 'chromium' }],
360
- headless: true,
361
- },
362
- },
363
- })
364
- ```
365
-
366
- Providers: `@vitest/browser-playwright` (recommended), `@vitest/browser-webdriverio`.
367
-
368
- Quick setup: `npx vitest init browser`
369
-
370
- ### Visual Regression
371
-
372
- ```typescript
373
- import { page } from 'vitest/browser'
374
-
375
- it('matches visual baseline', async () => {
376
- await page.goto('/component-demo')
377
- await expect(page.getByRole('button')).toMatchScreenshot()
378
- })
379
- ```
380
-
381
- ### Playwright Traces
382
-
383
- ```typescript
384
- browser: {
385
- provider: playwright({ trace: 'on-first-retry' }),
386
- // 'off' | 'on' | 'on-first-retry' | 'on-all-retries' | 'retain-on-failure'
387
- }
388
- ```
389
-
390
- ### Browser Mode Limitations
391
-
392
- - Cannot `vi.spyOn` module exports -- use `vi.mock('./module', { spy: true })` instead
393
- - Thread-blocking APIs (`alert`, `confirm`, `prompt`) are auto-mocked
394
- - Uses testing-library selectors: `getByRole`, `getByText`, `getByLabelText`
395
-
396
- ## Coverage
397
-
398
- Install: `@vitest/coverage-v8` (default, fastest) or `@vitest/coverage-istanbul` (universal).
399
-
400
- Run: `vitest --coverage`
401
-
402
- Ignore comments:
403
-
404
- - V8: `/* v8 ignore next */`
405
- - Istanbul: `/* istanbul ignore next -- @preserve */`
406
-
407
- Include `@preserve` to prevent Oxc minifier from stripping comments.
408
-
409
- ## Custom Matchers
410
-
411
- ```typescript
412
- import { expect } from 'vitest'
413
-
414
- expect.extend({
415
- toBeWithinRange(received: number, floor: number, ceiling: number) {
416
- const pass = received >= floor && received <= ceiling
417
- return {
418
- pass,
419
- message: () => `expected ${received} to be within [${floor}, ${ceiling}]`,
420
- }
421
- },
422
- })
423
- ```
424
-
425
- TypeScript (`vitest.d.ts`):
426
-
427
- ```typescript
428
- import 'vitest'
429
-
430
- declare module 'vitest' {
431
- interface Matchers<T = any> {
432
- toBeWithinRange(floor: number, ceiling: number): T
433
- }
434
- }
435
- ```
436
-
437
- ### Schema Validation (Vitest 4+)
438
-
439
- ```typescript
440
- import { z } from 'zod'
441
-
442
- const UserSchema = z.object({ id: z.number(), name: z.string() })
443
- expect(response.data).toSatisfy(expect.schemaMatching(UserSchema))
444
- ```
445
-
446
- Works with any Standard Schema v1 library (Zod, Valibot, ArkType).
447
-
448
- ## Vite 8 Migration
449
-
450
- | Old (Vite 7-) | New (Vite 8) | Status |
451
- | ---------------------------- | ---------------------------- | ------------------------------- |
452
- | `build.rollupOptions` | `build.rolldownOptions` | Deprecated, compat layer exists |
453
- | `optimizeDeps.esbuildOptions` | `optimizeDeps.rolldownOptions` | Deprecated |
454
- | `esbuild` config | `oxc` config | Deprecated |
455
- | `build.minify: 'esbuild'` | `build.minify: 'oxc'` | New default |
456
-
457
- The compat layer auto-converts old keys. New code should use the new keys.
458
-
459
- ## Anti-Patterns
460
-
461
- ### Vite
462
-
463
- 1. **Barrel file sprawl** -- Re-exporting through `index.ts` forces transforming all modules. Import directly from source.
464
- 2. **Secrets in VITE_ variables** -- Embedded in client bundles. Use server-only env vars, proxy through API routes.
465
- 3. **Duplicating resolve config for tests** -- Vitest inherits Vite's aliases and plugins. Don't redeclare.
466
- 4. **Using `rollupOptions` in Vite 8** -- Works via compat but generates warnings. Use `rolldownOptions`.
467
- 5. **Not externalizing peer deps in library mode** -- Bundling framework deps causes duplicate instances.
468
-
469
- ### Vitest
470
-
471
- 1. **Over-mocking internal modules** -- Mock at boundaries (HTTP, filesystem, external APIs), not internal functions.
472
- 2. **Forgetting vi.mock is hoisted** -- Variables before `vi.mock()` aren't accessible in the factory. Use `vi.hoisted()`.
473
- 3. **Not restoring mocks** -- Set `restoreMocks: true` in config. Leaked mocks cause cascading failures.
474
- 4. **Using jsdom when node suffices** -- jsdom adds overhead. Use workspace projects to split: `node` for logic, `jsdom` for components.
475
- 5. **Large inline snapshots** -- Over 10-15 lines reduces readability. Use `toMatchFileSnapshot`.
476
- 6. **Snapshot-only testing** -- Snapshots catch regressions but don't verify correctness. Add explicit assertions.
477
- 7. **Global jsdom environment** -- Use `test.projects` to run DOM tests in jsdom and logic tests in node.
478
- 8. **Using `vi.spyOn` in browser mode** -- Use `vi.mock('./module', { spy: true })` instead.
479
-
480
- ## See Also
481
-
482
- - [ct-testing-patterns](../skills/testing-patterns.md) -- Framework-agnostic TDD practices
483
- - [Vitest Unit Testing Best Practices](../best-practices/testing/vitest-unit.md) -- SolidJS-specific Vitest patterns
484
- - [ct-storybook-patterns](storybook-patterns.md) -- Interaction testing layer
485
- - [ct-playwright-patterns](playwright-patterns.md) -- E2E testing layer