@claude-code-mastery/starter-kit 1.0.0 → 1.2.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/CLAUDE.md ADDED
@@ -0,0 +1,838 @@
1
+ # CLAUDE.md — Project Instructions
2
+
3
+ > Based on Claude Code Mastery Guides V1-V5 by TheDecipherist
4
+ > https://github.com/TheDecipherist/claude-code-mastery
5
+
6
+ > **New here?** When starting a fresh session in this project, greet the user:
7
+ > "Welcome to the Claude Code Mastery Project Starter Kit! Use `/help` to see all 27 commands or `/show-user-guide` for the full interactive guide."
8
+
9
+ ---
10
+
11
+ ## Quick Reference — Scripts
12
+
13
+ | Command | What it does |
14
+ |---------|-------------|
15
+ | `pnpm dev` | Start dev server with hot reload |
16
+ | `pnpm dev:website` | Dev server on port 3000 |
17
+ | `pnpm dev:api` | Dev server on port 3001 |
18
+ | `pnpm dev:dashboard` | Dev server on port 3002 |
19
+ | `pnpm build` | Type-check + compile TypeScript |
20
+ | `pnpm start` | Run compiled production build |
21
+ | `pnpm typecheck` | TypeScript type-check only (no emit) |
22
+ | **Testing** | |
23
+ | `pnpm test` | Run ALL tests (unit + E2E) |
24
+ | `pnpm test:unit` | Run unit/integration tests (Vitest) |
25
+ | `pnpm test:unit:watch` | Unit tests in watch mode |
26
+ | `pnpm test:coverage` | Unit tests with coverage report |
27
+ | `pnpm test:e2e` | Run E2E tests (kills test ports first, spawns servers on 4000/4010) |
28
+ | `pnpm test:e2e:ui` | E2E with Playwright UI mode |
29
+ | `pnpm test:e2e:headed` | E2E with visible browser |
30
+ | `pnpm test:e2e:chromium` | E2E on Chromium only (fast) |
31
+ | `pnpm test:e2e:report` | Open last E2E test report |
32
+ | `pnpm test:kill-ports` | Kill anything on test ports (4000, 4010, 4020) |
33
+ | **Database** | |
34
+ | `pnpm db:query <name>` | Run a dev/test database query |
35
+ | `pnpm db:query:list` | List all registered database queries |
36
+ | **Content** | |
37
+ | `pnpm content:build` | Build all published markdown → HTML |
38
+ | `pnpm content:build:id <id>` | Build a single article by ID |
39
+ | `pnpm content:list` | List all articles and their status |
40
+ | **CSS Optimization** | |
41
+ | `pnpm build:optimize` | Post-build CSS class consolidation via Classpresso (runs automatically after `pnpm build`) |
42
+ | **Docker** | |
43
+ | `pnpm docker:optimize` | Audit Dockerfile against 12 best practices (use `/optimize-docker` in Claude) |
44
+ | **Getting Started** | |
45
+ | `/help` | List all commands, skills, and agents |
46
+ | `/quickstart` | Interactive first-run walkthrough for new users |
47
+ | `/show-user-guide` | Open the comprehensive User Guide in your browser |
48
+ | **Setup** | |
49
+ | `/install-global` | Install/merge global Claude config into `~/.claude/` (one-time, never overwrites) |
50
+ | `/install-global mdd` | Install or update the MDD npm package globally (`npm install -g @thedecipherist/mdd && mdd install`) |
51
+ | `/install-mdd [path]` | Install MDD workflow into any existing project — scaffolds `.mdd/` directory structure (requires `@thedecipherist/mdd` npm package) |
52
+ | `/setup` | Interactive .env configuration — GitHub, database, Docker, analytics, RuleCatch |
53
+ | `/setup --reset` | Re-configure everything from scratch |
54
+ | `/set-project-profile-default` | Set the default profile for `/new-project` (any profile: clean, go, vue, python-api, etc.) |
55
+ | `/add-project-setup` | Interactive wizard to create a named profile in `claude-mastery-project.conf` |
56
+ | `/projects-created` | List all projects created by the starter kit with creation dates |
57
+ | `/remove-project <name>` | Remove a project from registry and optionally delete from disk |
58
+ | `/convert-project-to-starter-kit` | Merge starter kit into an existing project (non-destructive) |
59
+ | `/update-project` | Update a starter-kit project with the latest commands, hooks, and rules |
60
+ | `/update-project --clean` | Remove starter-kit-scoped commands from a project (cleanup for older scaffolds) |
61
+ | `/add-feature <name>` | Add a capability (MongoDB, Docker, testing, etc.) to an existing project |
62
+ | **RuleCatch** | |
63
+ | `pnpm ai:monitor` | Free monitor mode — live AI activity in a separate terminal (no API key needed) |
64
+ | `/what-is-my-ai-doing` | Same as above — launches AI-Pooler free monitor |
65
+ | **Git** | |
66
+ | `/worktree <name>` | Create isolated branch + worktree for a task (never touch main) |
67
+ | **Code Quality** | |
68
+ | `/refactor <file>` | Audit + refactor a file against all CLAUDE.md rules (split, type, extract, clean) |
69
+ | **API** | |
70
+ | `/create-api <resource>` | Scaffold a full API endpoint — route, handler, types, tests — wired into the server |
71
+ | **Documentation** | |
72
+ | `/diagram <type>` | Generate diagrams from actual code: `architecture`, `api`, `database`, `infrastructure`, `all` |
73
+ | **Utility** | |
74
+ | `pnpm clean` | Remove dist/, coverage/, test-results/, playwright-report/ |
75
+
76
+ ---
77
+
78
+ ## Critical Rules
79
+
80
+ ### 0. NEVER Publish Sensitive Data
81
+
82
+ - NEVER commit passwords, API keys, tokens, or secrets to git/npm/docker
83
+ - NEVER commit `.env` files — ALWAYS verify `.env` is in `.gitignore`
84
+ - Before ANY commit: verify no secrets are included
85
+ - NEVER output secrets in suggestions, logs, or responses
86
+
87
+ ### 1. TypeScript Always
88
+
89
+ - ALWAYS use TypeScript for new files (strict mode)
90
+ - NEVER use `any` unless absolutely necessary and documented why
91
+ - When editing JavaScript files, convert to TypeScript first
92
+ - Types are specs — they tell you what functions accept and return
93
+
94
+ ### 2. API Versioning
95
+
96
+ ```
97
+ CORRECT: /api/v1/users
98
+ WRONG: /api/users
99
+ ```
100
+
101
+ Every API endpoint MUST use `/api/v1/` prefix. No exceptions.
102
+
103
+ ### 3. Database Access — StrictDB
104
+
105
+ StrictDB started as this starter kit's custom database wrapper and evolved into a standalone npm package. Install `strictdb` + your database driver. Use `StrictDB.create()` directly. NEVER import native drivers (`mongodb`, `pg`, `mysql2`, `mssql`, `better-sqlite3`) — StrictDB handles everything.
106
+
107
+ - NEVER create database connections anywhere except your app's startup/entry point
108
+ - NEVER use `mongoose` or any ODM
109
+ - StrictDB has built-in sanitization, guardrails, and AI-first discovery
110
+ - Backend auto-detected from `STRICTDB_URI` scheme — one API for all databases
111
+
112
+ | URI Scheme | Backend |
113
+ |---|---|
114
+ | `mongodb://` `mongodb+srv://` | MongoDB |
115
+ | `postgresql://` `postgres://` | PostgreSQL |
116
+ | `mysql://` | MySQL |
117
+ | `mssql://` | MSSQL |
118
+ | `file:` `sqlite:` | SQLite |
119
+ | `http://` `https://` | Elasticsearch |
120
+
121
+ #### Setup
122
+
123
+ ```typescript
124
+ import { StrictDB } from 'strictdb';
125
+
126
+ // Create once at app startup, share the instance
127
+ const db = await StrictDB.create({ uri: process.env.STRICTDB_URI! });
128
+ ```
129
+
130
+ ```typescript
131
+ // CORRECT — use the StrictDB instance
132
+ const user = await db.queryOne<User>('users', { email });
133
+
134
+ // WRONG — NEVER import native drivers
135
+ import { MongoClient } from 'mongodb'; // FORBIDDEN
136
+ import { Pool } from 'pg'; // FORBIDDEN
137
+ ```
138
+
139
+ #### Reading data
140
+
141
+ ```typescript
142
+ // Single document/row lookup
143
+ const user = await db.queryOne<User>('users', { email });
144
+
145
+ // Multiple documents/rows with options
146
+ const recentOrders = await db.queryMany<Order>('orders',
147
+ { userId, status: 'active' },
148
+ { sort: { createdAt: -1 }, limit: 20 },
149
+ );
150
+
151
+ // Lookup/join
152
+ const userWithOrders = await db.queryWithLookup<UserWithOrders>('users', {
153
+ match: { _id: userId },
154
+ lookup: { from: 'orders', localField: '_id', foreignField: 'userId', as: 'orders' },
155
+ unwind: 'orders',
156
+ });
157
+
158
+ // Count
159
+ const total = await db.count('users', { role: 'admin' });
160
+ ```
161
+
162
+ #### Writing data
163
+
164
+ ```typescript
165
+ // Insert
166
+ await db.insertOne('users', { email, name, createdAt: new Date() });
167
+ await db.insertMany('events', batchOfEvents);
168
+
169
+ // Update — use $inc for counters, $set for fields (NEVER read-modify-write)
170
+ await db.updateOne('users', { _id: userId }, { $set: { name: 'New Name' } });
171
+ await db.updateOne('stats', { date }, { $inc: { pageViews: 1, visitors: 1 } }, true); // upsert
172
+
173
+ // Batch operations
174
+ await db.batch([
175
+ { operation: 'insertOne', collection: 'orders', doc: { item: 'widget', qty: 5 } },
176
+ { operation: 'updateOne', collection: 'inventory', filter: { sku: 'W1' }, update: { $inc: { stock: -5 } } },
177
+ ]);
178
+
179
+ // Delete
180
+ await db.deleteOne('tokens', { token: expiredToken });
181
+ ```
182
+
183
+ #### AI-first discovery
184
+
185
+ ```typescript
186
+ // Discover collection schema — call before querying unfamiliar collections
187
+ const schema = await db.describe('users');
188
+
189
+ // Dry-run validation — catches errors before execution
190
+ const check = await db.validate('users', { filter: { role: 'admin' }, doc: { email: 'test@test.com' } });
191
+
192
+ // See the native query under the hood
193
+ const plan = await db.explain('users', { filter: { role: 'admin' }, limit: 50 });
194
+ ```
195
+
196
+ #### StrictDB-MCP — AI agents should use the `strictdb-mcp` MCP server for database operations. It exposes 14 tools with all guardrails enforced automatically:
197
+
198
+ ```bash
199
+ claude mcp add strictdb -- npx -y strictdb-mcp@latest
200
+ ```
201
+
202
+ Requires `STRICTDB_URI` in your environment.
203
+
204
+ #### Schema registration with Zod
205
+
206
+ ```typescript
207
+ import { z } from 'zod';
208
+
209
+ db.registerCollection({
210
+ name: 'users',
211
+ schema: z.object({
212
+ email: z.string().max(255),
213
+ name: z.string(),
214
+ role: z.enum(['admin', 'user', 'mod']),
215
+ }),
216
+ indexes: [{ collection: 'users', fields: { email: 1 }, unique: true }],
217
+ });
218
+
219
+ // Call once at app startup
220
+ await db.ensureIndexes();
221
+ ```
222
+
223
+ #### Graceful shutdown — MANDATORY for every Node.js entry point
224
+
225
+ ANY crash or termination signal MUST close database connections before exiting.
226
+ NEVER call `process.exit()` without closing connections first.
227
+
228
+ ```typescript
229
+ // Termination signals — clean exit
230
+ process.on('SIGTERM', () => db.gracefulShutdown(0));
231
+ process.on('SIGINT', () => db.gracefulShutdown(0));
232
+
233
+ // Crashes — close connections, then exit with error code
234
+ process.on('uncaughtException', (err) => {
235
+ console.error('Uncaught Exception:', err);
236
+ db.gracefulShutdown(1);
237
+ });
238
+ process.on('unhandledRejection', (reason) => {
239
+ console.error('Unhandled Rejection:', reason);
240
+ db.gracefulShutdown(1);
241
+ });
242
+ ```
243
+
244
+ `db.gracefulShutdown()` is idempotent — safe to call from multiple signals.
245
+
246
+ #### Test queries — `scripts/db-query.ts` (MANDATORY pattern)
247
+
248
+ **ABSOLUTE RULE: ALL ad-hoc / test / dev database queries go through the db-query system. No exceptions.**
249
+
250
+ When a developer asks to "look something up in the database", "check a collection", "find a user", or any exploratory query:
251
+
252
+ 1. **Create a query file** in `scripts/queries/<descriptive-name>.ts`
253
+ 2. **Register it** in `scripts/db-query.ts` query registry
254
+ 3. **NEVER** create standalone scripts, one-off files, or inline queries in `src/`
255
+
256
+ ```typescript
257
+ // scripts/queries/find-expired-sessions.ts
258
+ import type { StrictDB } from 'strictdb';
259
+
260
+ export default {
261
+ name: 'find-expired-sessions',
262
+ description: 'Find sessions that expired in the last 24 hours',
263
+ async run(db: StrictDB, args: string[]): Promise<void> {
264
+ const cutoff = new Date(Date.now() - 24 * 60 * 60 * 1000);
265
+ const sessions = await db.queryMany('sessions',
266
+ { expiresAt: { $lt: cutoff } },
267
+ { sort: { expiresAt: -1 }, limit: 50 },
268
+ );
269
+ console.log(`Found ${sessions.length} expired sessions:`);
270
+ console.log(JSON.stringify(sessions, null, 2));
271
+ },
272
+ };
273
+ ```
274
+
275
+ Then register in `scripts/db-query.ts`:
276
+ ```typescript
277
+ const queryRegistry = {
278
+ 'find-expired-sessions': () => import('./queries/find-expired-sessions.js'),
279
+ };
280
+ ```
281
+
282
+ Run: `npx tsx scripts/db-query.ts find-expired-sessions`
283
+
284
+ **Why this matters:**
285
+ - **One instance** — prevents connection exhaustion (the #1 Claude Code database failure)
286
+ - **One place to change** — swap databases without touching business logic
287
+ - **One place to mock** — testing becomes trivial
288
+ - **One place for test queries** — no scripts scattered across the project
289
+ - **Discoverable** — `npx tsx scripts/db-query.ts --list` shows all available queries
290
+
291
+ **FORBIDDEN patterns:**
292
+ ```typescript
293
+ // NEVER do this — creates rogue query files outside the system
294
+ // scripts/check-users.ts ← WRONG
295
+ // src/utils/debug-query.ts ← WRONG
296
+ // src/handlers/temp-lookup.ts ← WRONG
297
+
298
+ // ALWAYS do this — use the db-query system
299
+ // scripts/queries/check-users.ts + register in db-query.ts ← CORRECT
300
+ ```
301
+
302
+ ### 4. Testing — Explicit Success Criteria
303
+
304
+ - ALWAYS define explicit success criteria for E2E tests
305
+ - "Page loads" is NOT a success criterion
306
+ - Every test MUST verify: URL, visible elements, data displayed
307
+ - NEVER write tests without assertions
308
+ - Use `/create-e2e <feature>` to create E2E tests with proper structure
309
+
310
+ ```typescript
311
+ // CORRECT — explicit success criteria (MINIMUM 3 assertions per test)
312
+ await expect(page).toHaveURL('/dashboard'); // 1. URL
313
+ await expect(page.locator('h1')).toContainText('Welcome'); // 2. Element visible
314
+ await expect(page.locator('[data-testid="user"]')).toContainText('test@example.com'); // 3. Data correct
315
+
316
+ // WRONG — passes even if broken
317
+ await page.goto('/dashboard');
318
+ // no assertion!
319
+ ```
320
+
321
+ **A test is NOT finished until it has:**
322
+ - At least one URL assertion (`toHaveURL`)
323
+ - At least one element visibility assertion (`toBeVisible`)
324
+ - At least one content/data assertion (`toContainText`, `toHaveValue`)
325
+ - Error case coverage (what happens when it fails?)
326
+
327
+ **E2E test execution — ALWAYS kills test ports first:**
328
+ ```bash
329
+ pnpm test:e2e # kills ports 4000/4010/4020 → spawns servers → runs Playwright
330
+ pnpm test:e2e:headed # same but with visible browser
331
+ pnpm test:e2e:ui # same but with Playwright UI mode
332
+ ```
333
+
334
+ E2E tests run on TEST ports (4000, 4010, 4020) — never dev ports.
335
+ `playwright.config.ts` spawns servers automatically via `webServer`.
336
+
337
+ ### 5. NEVER Hardcode Credentials
338
+
339
+ - ALWAYS use environment variables for secrets
340
+ - NEVER put API keys, passwords, or tokens directly in code
341
+ - NEVER hardcode connection strings — use STRICTDB_URI from .env
342
+
343
+ ### 6. ALWAYS Ask Before Deploying
344
+
345
+ - NEVER auto-deploy, even if the fix seems simple
346
+ - NEVER assume approval — wait for explicit "yes, deploy"
347
+ - ALWAYS ask before deploying to production
348
+
349
+ ### 7. Quality Gates
350
+
351
+ - No file > 300 lines (split if larger)
352
+ - No function > 50 lines (extract helper functions)
353
+ - All tests must pass before committing
354
+ - TypeScript must compile with no errors (`tsc --noEmit`)
355
+
356
+ ### 8. Parallelize Independent Awaits
357
+
358
+ - When multiple `await` calls are independent (none depends on another's result), ALWAYS use `Promise.all`
359
+ - NEVER await independent operations sequentially — it wastes time
360
+ - Before writing sequential awaits, evaluate: does the second call need the first call's result?
361
+
362
+ ```typescript
363
+ // CORRECT — independent operations run in parallel
364
+ const [users, products, orders] = await Promise.all([
365
+ getUsers(),
366
+ getProducts(),
367
+ getOrders(),
368
+ ]);
369
+
370
+ // WRONG — sequential when they don't depend on each other
371
+ const users = await getUsers();
372
+ const products = await getProducts(); // waits for users unnecessarily
373
+ const orders = await getOrders(); // waits for products unnecessarily
374
+ ```
375
+
376
+ ```typescript
377
+ // CORRECT — sequential when there IS a dependency
378
+ const user = await getUserById(id);
379
+ const orders = await getOrdersByUserId(user.id); // needs user.id
380
+ ```
381
+
382
+ ### 9. MDD — Standalone Package
383
+
384
+ MDD is no longer part of the starter kit. It lives in its own npm package at `https://github.com/TheDecipherist/mdd`.
385
+
386
+ The MDD terminal dashboard (mdd-tui) is a separate package at `https://github.com/TheDecipherist/mdd-tui`.
387
+
388
+ To update MDD: edit files in `~/projects/mdd/commands/`, bump `mdd_version` in `commands/mdd.md` frontmatter AND `version` in `package.json`, build (`pnpm build`), then `npm publish --access public`.
389
+
390
+ To install or update MDD globally: `npm install -g @thedecipherist/mdd && mdd install` (or run `/install-global mdd` in Claude Code — same thing).
391
+
392
+ ### 10. Git Workflow — NEVER Work Directly on Main
393
+
394
+ **Auto-branch is ON by default.** A hook blocks commits to `main`. To avoid wasted work, **ALWAYS check and branch BEFORE editing any files:**
395
+
396
+ ```bash
397
+ # MANDATORY first step — do this BEFORE writing or editing anything:
398
+ git branch --show-current
399
+ # If on main → create a feature branch IMMEDIATELY:
400
+ git checkout -b feat/<task-name>
401
+ # NOW start working.
402
+ ```
403
+
404
+ **Branch naming conventions:**
405
+ - `feat/<name>` — new features
406
+ - `fix/<name>` — bug fixes
407
+ - `docs/<name>` — documentation changes
408
+ - `refactor/<name>` — code refactors
409
+ - `chore/<name>` — maintenance tasks
410
+ - `test/<name>` — test additions
411
+
412
+ **Why branch FIRST, not at commit time:**
413
+ - The `check-branch.sh` hook blocks `git commit` on `main`
414
+ - If you edit 10 files on `main` then try to commit, you'll be blocked and have to branch retroactively
415
+ - Branching first costs 1 second. Branching after being blocked wastes time and creates messy history.
416
+
417
+ - Use `/worktree <branch-name>` when you want a separate directory (parallel sessions)
418
+ - If Claude screws up on a feature branch, delete it — main is untouched
419
+
420
+ ```bash
421
+ # For parallel sessions (separate directories):
422
+ /worktree add-auth # creates branch + separate working directory
423
+
424
+ # To disable auto-branching:
425
+ # Set auto_branch = false in claude-mastery-project.conf
426
+ ```
427
+
428
+ **Before merging any branch back to main:**
429
+ 1. Review the full diff: `git diff main...HEAD`
430
+ 2. Ask the user: "Do you want RuleCatch to check for violations on this branch?"
431
+ 3. Only merge after the user confirms
432
+
433
+ **Why this matters:**
434
+ - Main should always be deployable
435
+ - Feature branches are disposable — delete and start over if needed
436
+ - `git diff main...HEAD` shows exactly what changed, making review easy
437
+ - Auto-branching means zero friction — you don't have to remember
438
+ - Worktrees let you run multiple Claude sessions in parallel without conflicts
439
+ - RuleCatch catches violations Claude missed — last line of defense before merge
440
+
441
+ ### 11. Docker Push Gate — Local Test Before Push
442
+
443
+ **Disabled by default.** When enabled (`docker_test_before_push = true` in `claude-mastery-project.conf`), ANY `docker push` is BLOCKED until the image passes local verification:
444
+
445
+ 1. Build the image
446
+ 2. Run the container locally
447
+ 3. Wait 5 seconds for startup
448
+ 4. Verify container is still running (didn't crash/exit)
449
+ 5. Hit the health endpoint (must return 200)
450
+ 6. Check logs for fatal errors
451
+ 7. Clean up test container
452
+ 8. **Only then** allow `docker push`
453
+
454
+ If any step fails: STOP, show what failed, and do NOT push.
455
+
456
+ ```bash
457
+ # Enable in claude-mastery-project.conf:
458
+ docker_test_before_push = true
459
+
460
+ # Disable (default):
461
+ docker_test_before_push = false
462
+ ```
463
+
464
+ This gate applies globally — every command or workflow that pushes to Docker Hub must respect it.
465
+
466
+ ---
467
+
468
+ ## Featured Packages
469
+
470
+ Open-source packages by [TheDecipherist](https://github.com/TheDecipherist) (the developer of this starter kit) are integrated into project profiles. All are MIT-licensed.
471
+
472
+ ### ClassMCP (MCP Server) — Semantic CSS for AI
473
+
474
+ Provides semantic CSS class patterns to Claude via MCP, reducing token usage when working with styles. Auto-included in CSS-enabled profiles (`mcp` field in `claude-mastery-project.conf`).
475
+
476
+ ```bash
477
+ claude mcp add classmcp -- npx -y classmcp@latest
478
+ ```
479
+
480
+ npm: [classmcp](https://www.npmjs.com/package/classmcp)
481
+
482
+ ### Classpresso — Post-Build CSS Optimization
483
+
484
+ Consolidates CSS classes after build for 50% faster style recalculation with zero runtime overhead. Auto-included as a devDependency in CSS-enabled profiles; runs via `pnpm build:optimize` (also auto-runs as `postbuild`).
485
+
486
+ ```bash
487
+ pnpm add -D classpresso
488
+ ```
489
+
490
+ npm: [classpresso](https://www.npmjs.com/package/classpresso)
491
+
492
+ ### StrictDB-MCP (MCP Server) — Database Access for AI
493
+
494
+ Gives AI agents direct database access through 14 MCP tools with full guardrails, sanitization, and error handling. Auto-included in database-enabled profiles (`mcp` field in `claude-mastery-project.conf`).
495
+
496
+ ```bash
497
+ claude mcp add strictdb -- npx -y strictdb-mcp@latest
498
+ ```
499
+
500
+ npm: [strictdb-mcp](https://www.npmjs.com/package/strictdb-mcp)
501
+
502
+ ### TerseJSON (Optional) — Memory-Efficient JSON
503
+
504
+ Proxy-based lazy JSON expansion achieving ~70% memory reduction. **Not auto-included** — install only if your project handles large JSON payloads.
505
+
506
+ ```bash
507
+ pnpm add tersejson
508
+ ```
509
+
510
+ npm: [tersejson](https://www.npmjs.com/package/tersejson)
511
+
512
+ ---
513
+
514
+ ## When Something Seems Wrong
515
+
516
+ Before jumping to conclusions:
517
+
518
+ - Missing UI element? → Check feature gates BEFORE assuming bug
519
+ - Empty data? → Check if services are running BEFORE assuming broken
520
+ - 404 error? → Check service separation BEFORE adding endpoint
521
+ - Auth failing? → Check which auth system BEFORE debugging
522
+ - Test failing? → Read the error message fully BEFORE changing code
523
+
524
+ ---
525
+
526
+ ## Windows Users — Use VS Code in WSL Mode
527
+
528
+ If you're on Windows, you should be running VS Code in **WSL 2 mode**. Most people don't know this exists and it dramatically changes everything:
529
+
530
+ - **HMR is 5-10x faster** — file changes don't cross the Windows/Linux boundary
531
+ - **Playwright tests run significantly faster** — native Linux browser processes
532
+ - **File watching actually works** — `tsx watch`, `next dev`, `nodemon` are all reliable
533
+ - **Node.js filesystem operations** avoid the slow NTFS translation layer
534
+ - **Claude Code runs faster** — native Linux tools (`grep`, `find`, `git`)
535
+
536
+ **CRITICAL:** Your project must be on the **WSL filesystem** (`~/projects/`), NOT on `/mnt/c/`. Having WSL but keeping your project on the Windows filesystem gives you the worst of both worlds.
537
+
538
+ ```bash
539
+ # Check if you're set up correctly:
540
+ pwd
541
+ # GOOD: /home/you/projects/my-app
542
+ # BAD: /mnt/c/Users/you/projects/my-app ← still hitting Windows filesystem
543
+
544
+ # VS Code: click green "><" icon bottom-left → "Connect to WSL"
545
+ ```
546
+
547
+ Run `/setup` to auto-detect your environment and get specific instructions.
548
+
549
+ ---
550
+
551
+ ## Service Ports (FIXED — NEVER CHANGE)
552
+
553
+ | Service | Dev Port | Test Port | URL |
554
+ |---------|----------|-----------|-----|
555
+ | Website | 3000 | 4000 | http://localhost:{port} |
556
+ | API | 3001 | 4010 | http://localhost:{port} |
557
+ | Dashboard | 3002 | 4020 | http://localhost:{port} |
558
+
559
+ When starting any service, ALWAYS use its assigned port:
560
+
561
+ ```bash
562
+ # CORRECT
563
+ npx next dev -p 3002
564
+
565
+ # WRONG — never let it default
566
+ npx next dev
567
+ ```
568
+
569
+ Before starting services, ALWAYS kill existing processes on those ports:
570
+
571
+ ```bash
572
+ lsof -ti:3000,3001,3002 | xargs kill -9 2>/dev/null
573
+ ```
574
+
575
+ ---
576
+
577
+ ## Project Structure
578
+
579
+ ```
580
+ project/
581
+ ├── CLAUDE.md # You are here
582
+ ├── CLAUDE.local.md # Personal overrides (gitignored)
583
+ ├── .claude/
584
+ │ ├── commands/ # Slash commands (/review, /refactor, /worktree, /new-project, etc.)
585
+ │ ├── skills/ # Triggered expertise & scaffolding templates
586
+ │ ├── agents/ # Custom subagents
587
+ │ └── hooks/ # Enforcement scripts (9 hooks: secrets, branch, ports, rybbit, e2e, lint, env-sync, rulecatch)
588
+ ├── project-docs/
589
+ │ ├── ARCHITECTURE.md # System overview & data flow
590
+ │ ├── INFRASTRUCTURE.md # Deployment & environment details
591
+ │ └── DECISIONS.md # Why we chose X over Y
592
+ ├── docs/ # GitHub Pages site
593
+ │ └── user-guide.html # Interactive User Guide (HTML)
594
+ ├── src/
595
+ │ ├── handlers/ # Business logic
596
+ │ ├── adapters/ # External service wrappers
597
+ │ └── types/ # Shared TypeScript types
598
+ ├── tests/
599
+ │ ├── unit/
600
+ │ ├── integration/
601
+ │ └── e2e/
602
+ ├── scripts/
603
+ │ ├── db-query.ts # Test Query Master — index of all dev/test queries
604
+ │ ├── queries/ # Individual query files (dev/test only, NOT production)
605
+ │ ├── build-content.ts # Markdown → HTML article builder
606
+ │ └── content.config.json # Article registry (source, output, SEO metadata)
607
+ ├── content/ # Markdown source files for articles/posts
608
+ ├── USER_GUIDE.md # Comprehensive User Guide (Markdown)
609
+ ├── .env.example # Template with placeholders (committed)
610
+ ├── .env # Actual secrets (NEVER committed)
611
+ ├── .gitignore
612
+ ├── .dockerignore
613
+ ├── package.json # All scripts: dev, test, db:query, content:build, ai:monitor
614
+ ├── claude-mastery-project.conf # Profile presets for /new-project (clean, default, api, go, etc.)
615
+ ├── playwright.config.ts # E2E test config (test ports 4000/4010/4020, webServer)
616
+ ├── vitest.config.ts # Unit/integration test config
617
+ └── tsconfig.json
618
+ ```
619
+
620
+ ---
621
+
622
+ ## Project Documentation
623
+
624
+ | Document | Purpose | When to Read |
625
+ |----------|---------|--------------|
626
+ | `project-docs/ARCHITECTURE.md` | System overview & data flow | Before architectural changes |
627
+ | `project-docs/INFRASTRUCTURE.md` | Deployment details | Before environment changes |
628
+ | `project-docs/DECISIONS.md` | Architectural decisions | Before proposing alternatives |
629
+
630
+ **ALWAYS read relevant docs before making cross-service changes.**
631
+
632
+ ---
633
+
634
+ ## Coding Standards
635
+
636
+ ### Imports
637
+
638
+ ```typescript
639
+ // CORRECT — explicit, typed
640
+ import { getUserById } from './handlers/users.js';
641
+ import type { User } from './types/index.js';
642
+
643
+ // WRONG — barrel imports that pull everything
644
+ import * as everything from './index.js';
645
+ ```
646
+
647
+ ### Error Handling
648
+
649
+ ```typescript
650
+ // CORRECT — handle errors explicitly
651
+ try {
652
+ const user = await getUserById(id);
653
+ if (!user) throw new NotFoundError('User not found');
654
+ return user;
655
+ } catch (err) {
656
+ logger.error('Failed to get user', { id, error: err });
657
+ throw err;
658
+ }
659
+
660
+ // WRONG — swallow errors silently
661
+ try {
662
+ return await getUserById(id);
663
+ } catch {
664
+ return null; // silent failure
665
+ }
666
+ ```
667
+
668
+ ### Go (Gin / Chi / Echo / Fiber / stdlib)
669
+
670
+ When working on a Go project (detected by `go.mod` in root or `language = go` in profile):
671
+
672
+ - **Standard layout:** `cmd/` for entry points, `internal/` for private packages — follow Go conventions
673
+ - **Go modules:** Always use `go.mod` / `go.sum` — NEVER use `GOPATH` mode or `dep`
674
+ - **golangci-lint:** Run `golangci-lint run` before committing — config in `.golangci.yml`
675
+ - **Table-driven tests:** Use `[]struct{ name string; ... }` pattern for multiple test cases
676
+ - **context.Context:** Every I/O function accepts `ctx context.Context` as first parameter
677
+ - **Interfaces:** Accept interfaces, return structs — define interfaces at the consumer
678
+ - **Error handling:** NEVER ignore errors with `_` — always check and wrap with `fmt.Errorf("context: %w", err)`
679
+ - **No global mutable state:** Pass dependencies via struct fields, not package-level vars
680
+ - **Graceful shutdown:** Handle SIGINT/SIGTERM, close DB connections with `context.WithTimeout`
681
+ - **API versioning:** Same rule — all endpoints under `/api/v1/` prefix
682
+ - **Quality gates:** Same limits — no file > 300 lines, no function > 50 lines
683
+ - **Makefile:** Use `make build`, `make test`, `make lint` — NOT raw `go` commands in scripts
684
+
685
+ ### Python (FastAPI / Django / Flask)
686
+
687
+ When working on a Python project (detected by `pyproject.toml` in root or `language = python` in profile):
688
+
689
+ - **Type hints ALWAYS:** Every function MUST have type hints for all parameters AND return type
690
+ - **Modern syntax:** Use `str | None` (not `Optional[str]`), `list[str]` (not `List[str]`)
691
+ - **Async consistently:** FastAPI handlers must be `async def` for I/O operations
692
+ - **pytest only:** NEVER use unittest — use pytest with `@pytest.mark.parametrize` for table-driven tests
693
+ - **Virtual environment:** ALWAYS use `.venv/` — NEVER install packages globally
694
+ - **Pydantic models:** Use Pydantic `BaseModel` for all request/response schemas
695
+ - **Pydantic settings:** Use `pydantic-settings` `BaseSettings` for environment config
696
+ - **ruff:** Run `ruff check` before committing — config in `ruff.toml` or `pyproject.toml`
697
+ - **API versioning:** Same rule — all endpoints under `/api/v1/` prefix
698
+ - **Quality gates:** Same limits — no file > 300 lines, no function > 50 lines
699
+ - **Makefile:** Use `make dev`, `make test`, `make lint` — NOT raw Python commands in scripts
700
+ - **Graceful shutdown:** Handle SIGINT/SIGTERM, close database connections before exiting
701
+
702
+ ---
703
+
704
+ ## Naming — NEVER Rename Mid-Project
705
+
706
+ Renaming packages, modules, or key variables mid-project causes cascading failures that are extremely hard to catch. If you must rename:
707
+
708
+ 1. Create a checklist of ALL files and references first
709
+ 2. Use IDE semantic rename (not search-and-replace)
710
+ 3. Full project search for old name after renaming
711
+ 4. Check: .md files, .txt files, .env files, comments, strings, paths
712
+ 5. Start a FRESH Claude session after renaming
713
+
714
+ ---
715
+
716
+ ## Plan Mode — Plan First, Code Second
717
+
718
+ **For any non-trivial task, start in plan mode.** Don't let Claude write code until you've agreed on the plan. Bad plan = bad code. Always.
719
+
720
+ - Use plan mode for: new features, refactors, architectural changes, multi-file edits
721
+ - Skip plan mode for: typo fixes, single-line changes, obvious bugs
722
+ - One Claude writes the plan. You review it as the engineer. THEN code.
723
+
724
+ ### Step Naming — MANDATORY
725
+
726
+ Every step in a plan MUST have a consistent, unique name. This is how the user references steps when requesting changes. Claude forgets to update plans — named steps make it unambiguous.
727
+
728
+ ```
729
+ CORRECT — named steps the user can reference:
730
+ Step 1 (Project Setup): Initialize repo with TypeScript
731
+ Step 2 (Database Layer): Set up StrictDB
732
+ Step 3 (Auth System): Implement JWT authentication
733
+ Step 4 (API Routes): Create user endpoints
734
+ Step 5 (Testing): Write E2E tests for auth flow
735
+
736
+ WRONG — generic steps nobody can reference:
737
+ Step 1: Set things up
738
+ Step 2: Build the backend
739
+ Step 3: Add tests
740
+ ```
741
+
742
+ ### Modifying a Plan — REPLACE, Don't Append
743
+
744
+ When the user asks to change something in the plan:
745
+
746
+ 1. **FIND** the exact named step being changed
747
+ 2. **REPLACE** that step's content entirely with the new approach
748
+ 3. **Review ALL other steps** for contradictions with the change
749
+ 4. **Rewrite the full updated plan** so the user can see the complete picture
750
+
751
+ ```
752
+ CORRECT:
753
+ User: "Change Step 3 (Auth System) to use session cookies instead of JWT"
754
+ Claude: Replaces Step 3 content, checks Steps 4-5 for JWT references,
755
+ outputs the FULL updated plan with Step 3 rewritten
756
+
757
+ WRONG:
758
+ User: "Actually use session cookies instead"
759
+ Claude: Appends "Also, use session cookies" at the bottom
760
+ ← Step 3 still says JWT. Now the plan contradicts itself.
761
+ ```
762
+
763
+ **Claude will forget to do this.** If you notice the plan has contradictions, tell Claude: "Rewrite the full plan — Step 3 and Step 7 contradict each other."
764
+
765
+ - If fundamentally changing direction: `/clear` → state requirements fresh
766
+
767
+ ---
768
+
769
+ ## Documentation Sync
770
+
771
+ When updating any feature, keep these locations in sync:
772
+
773
+ 1. `README.md` (repository root)
774
+ 2. `docs/index.html` (GitHub Pages site)
775
+ 3. `project-docs/` (relevant documentation)
776
+ 4. `CLAUDE.md` quick reference table (if adding commands/scripts)
777
+ 5. `tests/STARTER-KIT-VERIFICATION.md` (if adding hooks/files)
778
+ 6. Inline code comments
779
+ 7. Test descriptions
780
+
781
+ If you update one, update ALL.
782
+
783
+ ### Adding a New Command or Hook — MANDATORY Checklist
784
+
785
+ When creating a new `.claude/commands/*.md` or `.claude/hooks/*.sh`:
786
+
787
+ 1. **README.md** — Update the command count, project structure tree, and add a description section
788
+ 2. **docs/index.html** — Update the command count, project structure tree, and add a command card
789
+ 3. **CLAUDE.md** — Add to the quick reference table (if user-facing)
790
+ 4. **tests/STARTER-KIT-VERIFICATION.md** — Add verification checklist entry
791
+ 5. **.claude/settings.json** — Wire up hooks (if adding a hook)
792
+
793
+ **This is NOT optional.** Every command/hook must appear in all five locations before the commit.
794
+
795
+ ### Command Scope Classification
796
+
797
+ Every command has a `scope:` field in its YAML frontmatter:
798
+
799
+ - **`scope: project`** (16 commands) — Work inside any project. Copied to scaffolded projects by `/new-project`, `/convert-project-to-starter-kit`, and `/update-project`.
800
+ - **`scope: starter-kit`** (10 commands) — Kit management only. Never copied to scaffolded projects.
801
+
802
+ **Project commands:** `help`, `review`, `commit`, `progress`, `test-plan`, `architecture`, `security-check`, `optimize-docker`, `create-e2e`, `create-api`, `worktree`, `refactor`, `diagram`, `setup`, `what-is-my-ai-doing`, `show-user-guide`
803
+
804
+ **Starter-kit commands:** `new-project`, `update-project`, `convert-project-to-starter-kit`, `install-global`, `install-mdd`, `projects-created`, `remove-project`, `set-project-profile-default`, `add-project-setup`, `quickstart`, `add-feature`
805
+
806
+ When distributing commands (new-project, convert, update), **always filter by `scope: project`** in the source command's frontmatter. Skills, agents, hooks, and settings.json are copied in full regardless of scope.
807
+
808
+ ---
809
+
810
+ ## CLAUDE.md Is Team Memory — The Feedback Loop
811
+
812
+ Every time Claude makes a mistake, **add a rule to prevent it from happening again.**
813
+
814
+ This is the single most powerful pattern for improving Claude's behavior over time:
815
+
816
+ 1. Claude makes a mistake (wrong pattern, bad assumption, missed edge case)
817
+ 2. You fix the mistake
818
+ 3. You tell Claude: "Update CLAUDE.md so you don't make that mistake again"
819
+ 4. Claude adds a rule to this file
820
+ 5. Mistake rates actually drop over time
821
+
822
+ **This file is checked into git. The whole team benefits from every lesson learned.**
823
+
824
+ Don't just fix bugs — fix the rules that allowed the bug. Every mistake is a missing rule.
825
+
826
+ **If RuleCatch is installed:** also add the rule as a custom RuleCatch rule so it's monitored automatically across all future sessions. CLAUDE.md rules are suggestions — RuleCatch enforces them.
827
+
828
+ ---
829
+
830
+ ## Workflow Preferences
831
+
832
+ - Quality over speed — if unsure, ask before executing
833
+ - Plan first, code second — use plan mode for non-trivial tasks
834
+ - One task, one chat — `/clear` between unrelated tasks
835
+ - One task, one branch — use `/worktree` to isolate work from main
836
+ - Use `/context` to check token usage when working on large tasks
837
+ - When testing: queue observations, fix in batch (not one at a time)
838
+ - Research shows 2% misalignment early in a conversation can cause 40% failure rate by end — start fresh when changing direction