start-vibing-stacks 2.2.0 → 2.4.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.
@@ -1,80 +1,198 @@
1
- # PHP Security Scan
1
+ # Laravel Security Scan
2
2
 
3
- ## OWASP Top 10 for PHP
3
+ ## OWASP Top 10 for Laravel
4
4
 
5
5
  ### A01 - Broken Access Control
6
6
 
7
7
  ```php
8
- // NEVER trust user input for authorization
9
- $userId = $_GET['user_id'];
8
+ // WRONG: Trust user input for authorization
9
+ $userId = $request->input('user_id');
10
10
  $user = User::find($userId);
11
11
 
12
- // Use authenticated session
13
- $user = Auth::user();
12
+ // CORRECT: Use authenticated session
13
+ $user = $request->user();
14
+
15
+ // CORRECT: Scope queries by authenticated user
16
+ $query = Resource::query();
17
+ if (!$request->user()->isAdmin()) {
18
+ $query->where('user_id', $request->user()->id);
19
+ }
14
20
  ```
15
21
 
22
+ **Rules:**
23
+ - NEVER return unscoped queries — always filter by authenticated user
24
+ - Use Policies for authorization logic
25
+ - Use Form Requests with `authorize()` method
26
+ - Use Route Model Binding with scoping
27
+
16
28
  ### A02 - Cryptographic Failures
17
29
 
18
30
  ```php
19
- // ❌ NEVER
31
+ // WRONG
20
32
  md5($password);
21
33
  sha1($password);
22
34
 
23
- // ALWAYS
24
- password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);
25
- password_verify($input, $hash);
35
+ // CORRECT (Laravel handles this via Hash facade)
36
+ Hash::make($password);
37
+ Hash::check($input, $hashedPassword);
38
+
39
+ // For API tokens: use Laravel Sanctum
40
+ // Table: users_access_tokens (UUIDs + Soft Deletes)
41
+ // All token actions logged via Loggable trait
26
42
  ```
27
43
 
28
44
  ### A03 - Injection
29
45
 
30
46
  ```php
31
- // SQL Injection
32
- $db->query("SELECT * FROM users WHERE id = {$_GET['id']}");
47
+ // WRONG: SQL Injection via DB::raw
48
+ $users = DB::select("SELECT * FROM users WHERE id = {$id}");
49
+ DB::raw("WHERE name = '{$name}'");
33
50
 
34
- // Prepared statements (PDO)
35
- $stmt = $db->prepare("SELECT * FROM users WHERE id = :id");
36
- $stmt->execute([':id' => $id]);
51
+ // CORRECT: Eloquent (preferred)
52
+ $user = User::findOrFail($id);
37
53
 
38
- // Prepared statements (MySQLi)
39
- $stmt = $db->prepare("SELECT * FROM users WHERE id = ?");
40
- $stmt->bind_param('i', $id);
41
- $stmt->execute();
54
+ // CORRECT: Query Builder with bindings
55
+ $users = DB::table('users')->where('name', $name)->get();
56
+
57
+ // CORRECT: Raw with parameter binding (last resort)
58
+ $results = DB::select('SELECT * FROM users WHERE id = ?', [$id]);
42
59
  ```
43
60
 
44
61
  ### A07 - XSS Prevention
45
62
 
46
63
  ```php
47
- // Raw output
48
- echo $userInput;
64
+ // WRONG: Unescaped output in Blade
65
+ {!! $userInput !!}
49
66
 
50
- // Always escape
51
- echo htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8');
67
+ // CORRECT: Auto-escaped (Blade default)
68
+ {{ $userInput }}
52
69
 
53
- // In templates (Blade)
54
- {{ $userInput }} // Auto-escaped
55
- {!! $trustedHtml !!} // Only for trusted content
70
+ // Only use {!! !!} for TRUSTED, pre-sanitized HTML
71
+ {!! $trustedHtmlFromCMS !!}
56
72
  ```
57
73
 
58
- ## Security Checklist
74
+ ### A08 - Insecure Deserialization
75
+
76
+ ```php
77
+ // WRONG: Unserialize user data
78
+ $data = unserialize($request->input('data'));
79
+
80
+ // CORRECT: Use JSON with Model casts
81
+ protected $casts = [
82
+ 'metadata' => 'array',
83
+ 'settings' => 'array',
84
+ ];
85
+
86
+ // CORRECT: Defensive JSON handling
87
+ $data = is_string($model->data)
88
+ ? json_decode($model->data, true)
89
+ : $model->data;
90
+ ```
91
+
92
+ ## Laravel-Specific Security
93
+
94
+ ### Mass Assignment Protection
95
+
96
+ ```php
97
+ // WRONG: No protection
98
+ $user = User::create($request->all());
99
+
100
+ // CORRECT: Define $fillable
101
+ class User extends Model {
102
+ protected $fillable = ['name', 'email'];
103
+ }
104
+
105
+ // CORRECT: Use Form Request validated data
106
+ $user = User::create($request->validated());
107
+ ```
108
+
109
+ ### Environment Variables
110
+
111
+ ```php
112
+ // WRONG: env() outside config files (null when cached)
113
+ $apiKey = env('API_KEY');
59
114
 
60
- - [ ] All SQL uses prepared statements
61
- - [ ] All output is escaped (htmlspecialchars)
62
- - [ ] CSRF tokens on all forms
63
- - [ ] Passwords use password_hash/verify
64
- - [ ] File uploads validated (type, size, extension)
65
- - [ ] Sessions use httpOnly + secure cookies
66
- - [ ] Input validated before processing
67
- - [ ] No `eval()`, `exec()` with user input
68
- - [ ] No `extract()` on user data
69
- - [ ] Headers: X-Content-Type-Options, X-Frame-Options, CSP
115
+ // CORRECT: Use config files
116
+ // config/services.php
117
+ 'stripe' => ['key' => env('STRIPE_KEY')],
118
+
119
+ // In code:
120
+ $apiKey = config('services.stripe.key');
121
+ ```
122
+
123
+ ### CSRF & Authentication
124
+
125
+ ```php
126
+ // Blade forms — CSRF automatic
127
+ <form method="POST">
128
+ @csrf
129
+ ...
130
+ </form>
131
+
132
+ // API routes — use Sanctum middleware
133
+ Route::middleware('auth:sanctum')->group(function () {
134
+ Route::apiResource('users', UserController::class);
135
+ });
136
+ ```
137
+
138
+ ### File Upload Validation
139
+
140
+ ```php
141
+ public function rules(): array
142
+ {
143
+ return [
144
+ 'avatar' => [
145
+ 'required',
146
+ 'image',
147
+ 'mimes:jpg,jpeg,png,webp',
148
+ 'max:2048', // 2MB
149
+ 'dimensions:max_width=2000,max_height=2000',
150
+ ],
151
+ ];
152
+ }
153
+ ```
154
+
155
+ ## Octane Security Considerations
156
+
157
+ ```php
158
+ // WRONG: Static state leaks user data between requests
159
+ class AuthService {
160
+ private static ?User $currentUser = null; // LEAKS!
161
+ }
162
+
163
+ // WRONG: Superglobals are stale in Octane
164
+ $token = $_SERVER['HTTP_AUTHORIZATION'];
165
+
166
+ // CORRECT: Use Request object
167
+ $token = $request->bearerToken();
168
+ $user = $request->user();
169
+ ```
170
+
171
+ ## Security Checklist
70
172
 
71
- ## Sensitive Data Patterns (FORBIDDEN)
173
+ - [ ] All queries use Eloquent or Query Builder (no raw SQL with user input)
174
+ - [ ] All Blade output uses `{{ }}` (auto-escaped)
175
+ - [ ] CSRF protection on all forms (`@csrf`)
176
+ - [ ] Passwords use `Hash::make()` / `Hash::check()`
177
+ - [ ] File uploads validated (type, size, dimensions)
178
+ - [ ] API routes protected with Sanctum middleware
179
+ - [ ] Models define `$fillable` (no `$guarded = []`)
180
+ - [ ] Queries scoped by authenticated user (unless admin)
181
+ - [ ] No `env()` calls outside config files
182
+ - [ ] No static state in services (Octane-safe)
183
+ - [ ] No superglobals (`$_GET`, `$_POST`, `$_SESSION`)
184
+ - [ ] Sensitive headers set (X-Content-Type-Options, X-Frame-Options, CSP)
185
+ - [ ] Rate limiting on authentication endpoints
186
+
187
+ ## Sensitive Patterns (FORBIDDEN)
72
188
 
73
189
  | Pattern | Risk |
74
190
  |---------|------|
75
- | `$_GET` used directly in SQL | SQL Injection |
76
- | `echo $_POST[...]` | XSS |
191
+ | `DB::raw()` with user input | SQL Injection |
192
+ | `{!! $userInput !!}` | XSS |
77
193
  | `md5()` / `sha1()` for passwords | Weak hashing |
78
- | `eval($userInput)` | RCE |
79
- | `include $_GET['page']` | LFI/RFI |
80
- | `serialize()` user data | Object injection |
194
+ | Dynamic code execution | RCE |
195
+ | `unserialize()` on user data | Object injection |
196
+ | `$request->all()` without `$fillable` | Mass assignment |
197
+ | `env()` in runtime code | Null after config cache |
198
+ | Static user state in services | Data leaks in Octane |
@@ -27,13 +27,20 @@
27
27
  "name": "Laravel 12 + Octane (RoadRunner) + Inertia.js",
28
28
  "icon": "🚀",
29
29
  "detectFiles": ["artisan", "rr.yaml"],
30
- "default": true
30
+ "default": true,
31
+ "skills": [
32
+ "laravel-patterns",
33
+ "laravel-octane"
34
+ ]
31
35
  },
32
36
  {
33
37
  "id": "laravel",
34
38
  "name": "Laravel 12 (standard)",
35
39
  "icon": "🏗️",
36
- "detectFiles": ["artisan", "bootstrap/app.php"]
40
+ "detectFiles": ["artisan", "bootstrap/app.php"],
41
+ "skills": [
42
+ "laravel-patterns"
43
+ ]
37
44
  }
38
45
  ],
39
46
  "databases": [
@@ -46,12 +53,20 @@
46
53
  "id": "react-inertia",
47
54
  "name": "ReactJS 19 + Inertia.js + TailwindCSS 4",
48
55
  "icon": "⚛️",
49
- "default": true
56
+ "default": true,
57
+ "frameworks": ["laravel", "laravel-octane"]
50
58
  },
51
59
  {
52
60
  "id": "blade",
53
61
  "name": "Blade + TailwindCSS 4",
54
- "icon": "🖼️"
62
+ "icon": "🖼️",
63
+ "frameworks": ["laravel", "laravel-octane"]
64
+ },
65
+ {
66
+ "id": "livewire",
67
+ "name": "Livewire + Alpine.js",
68
+ "icon": "⚡",
69
+ "frameworks": ["laravel", "laravel-octane"]
55
70
  },
56
71
  {
57
72
  "id": "none",
@@ -68,8 +83,6 @@
68
83
  "phpstan-analysis",
69
84
  "composer-workflow",
70
85
  "security-scan-php",
71
- "laravel-patterns",
72
- "laravel-octane",
73
86
  "api-design"
74
87
  ],
75
88
  "requirements": [
@@ -0,0 +1,323 @@
1
+ # {{PROJECT_NAME}}
2
+
3
+ > **CHARACTER LIMIT**: Max 40,000 chars. Validate with `wc -m CLAUDE.md` before commit.
4
+
5
+ ## Last Change
6
+
7
+ **Branch:** main
8
+ **Date:** {{DATE}}
9
+ **Summary:** Initial project setup with start-vibing-stacks (Node.js)
10
+
11
+ ## 30 Seconds Overview
12
+
13
+ {{PROJECT_NAME}} is a TypeScript project using {{FRAMEWORK}}.
14
+
15
+ ## Stack
16
+
17
+ | Component | Technology |
18
+ |-----------|------------|
19
+ | Runtime | Bun / Node.js 20+ |
20
+ | Language | TypeScript **strict mode** |
21
+ | Framework | {{FRAMEWORK}} |
22
+ | Database | {{DATABASE}} |
23
+ | Validation | Zod |
24
+ | Testing | Vitest + Playwright |
25
+ | UI | React + Tailwind + shadcn |
26
+ | Data | TanStack Query + Sonner |
27
+ | Forms | react-hook-form + Zod |
28
+
29
+ ## Architecture
30
+
31
+ ```
32
+ project/
33
+ ├── CLAUDE.md # This file (40k char max)
34
+ ├── .claude/
35
+ │ ├── agents/ # 6 active subagents
36
+ │ ├── skills/ # Skill systems (auto-injected)
37
+ │ ├── hooks/ # Validation hooks
38
+ │ ├── config/ # Project configuration
39
+ │ └── commands/ # Slash commands (/feature, /fix, /research, /validate)
40
+ ├── src/
41
+ │ ├── app/ # Next.js App Router pages
42
+ │ │ ├── (marketing)/ # Route group — public pages
43
+ │ │ ├── (app)/ # Route group — authenticated
44
+ │ │ │ └── dashboard/
45
+ │ │ │ ├── page.tsx
46
+ │ │ │ └── _components/ # Page-specific components
47
+ │ │ ├── api/ # Route handlers (API endpoints)
48
+ │ │ ├── layout.tsx # Root layout with providers
49
+ │ │ └── loading.tsx # Global loading skeleton
50
+ │ ├── components/
51
+ │ │ ├── ui/ # shadcn primitives (Button, Input)
52
+ │ │ ├── layout/ # Header, Sidebar, Footer
53
+ │ │ ├── shared/ # Cross-feature components
54
+ │ │ └── providers.tsx # Context providers (client)
55
+ │ ├── lib/
56
+ │ │ ├── utils.ts # cn utility (clsx + tailwind-merge)
57
+ │ │ ├── api/ # API client instances
58
+ │ │ └── validations/ # Zod schemas
59
+ │ ├── hooks/ # Custom React hooks
60
+ │ └── styles/ # Global styles, theme tokens
61
+ ├── types/ # ALL TypeScript interfaces (MANDATORY)
62
+ ├── tests/
63
+ │ ├── unit/ # Vitest unit tests
64
+ │ └── e2e/ # Playwright E2E tests
65
+ ├── public/ # Static assets
66
+ ├── tsconfig.json # TypeScript config (strict: true)
67
+ ├── next.config.ts # Framework config
68
+ ├── tailwind.config.ts # TailwindCSS config
69
+ ├── vitest.config.ts # Test config
70
+ └── package.json # Dependencies
71
+ ```
72
+
73
+ ## Workflow
74
+
75
+ ```
76
+ 0. TODO LIST → Create detailed todo list from prompt
77
+ 1. BRANCH → Create feature/ | fix/ | refactor/ | test/
78
+ 2. RESEARCH → Run research-web agent for NEW features
79
+ 3. IMPLEMENT → Follow project rules + strict types
80
+ 4. TEST → Run tester agent (Vitest / Playwright)
81
+ 5. DOCUMENT → Run documenter agent for modified files
82
+ 6. UPDATE → Update THIS FILE (CLAUDE.md) with changes
83
+ 7. QUALITY → bun run typecheck && lint && test
84
+ 8. COMMIT → Conventional commits, merge to main
85
+ ```
86
+
87
+ ## CLAUDE.md Update Rules
88
+
89
+ > After ANY implementation, update this file to reflect the current state.
90
+
91
+ | Change Type | Sections to Update |
92
+ |-------------|-------------------|
93
+ | Any file change | Last Change (branch, date, summary) |
94
+ | API/routes | Critical Rules, Architecture |
95
+ | UI components | Architecture, Component Organization |
96
+ | New feature | 30s Overview, Architecture |
97
+ | New gotcha | FORBIDDEN or NRY |
98
+ | New dependency | Stack |
99
+ | Workflow change | Workflow section |
100
+
101
+ 1. **Last Change** documents WHAT was done
102
+ 2. **Other sections** document HOW things work NOW
103
+ 3. **Both must be current** — updating only Last Change is insufficient
104
+ 4. Keep only the LATEST Last Change entry (no stacking)
105
+
106
+ ## Agent System
107
+
108
+ ### Subagents (6)
109
+
110
+ | Agent | Purpose |
111
+ |-------|---------|
112
+ | **research-web** | Researches best practices before new features |
113
+ | **documenter** | Maps files to domains, creates/updates domain docs |
114
+ | **domain-updater** | Records problems, solutions, learnings |
115
+ | **commit-manager** | Manages git commits, conventional format |
116
+ | **claude-md-compactor** | Compacts CLAUDE.md when > 40k chars |
117
+ | **tester** | Creates tests with Vitest/Playwright |
118
+
119
+ ### Skills
120
+
121
+ | Category | Skills |
122
+ |----------|--------|
123
+ | **Development** | typescript-strict, react-patterns, nextjs-app-router, zod-validation, shadcn-ui, tailwind-patterns |
124
+ | **Quality** | quality-gate, security-scan, test-coverage, final-check |
125
+ | **Infrastructure** | docker-patterns, git-workflow, performance-patterns, debugging-patterns |
126
+ | **Documentation** | codebase-knowledge, docs-tracker, research-cache, ui-ux-audit |
127
+
128
+ ## Critical Rules
129
+
130
+ - **TypeScript strict mode** — `strict: true` in tsconfig.json
131
+ - **Bracket notation** for env vars: `process.env['VARIABLE']`
132
+ - **Zod validation** for ALL external input (forms, API, env)
133
+ - **Server Components by default** — push `'use client'` to leaf components
134
+ - **Parallel data fetching** — `Promise.all()` over waterfall
135
+ - **Type everything** — no `any`, use `unknown` for truly unknown data
136
+ - **Loading states** — every data page must have `loading.tsx`
137
+ - **Error boundaries** — every route should handle errors gracefully
138
+ - **Conventional commits** — `feat:`, `fix:`, `refactor:`, `docs:`, `chore:`
139
+
140
+ ### Environment Variables Security (MANDATORY)
141
+
142
+ > **NEVER expose secrets to the browser.** `NEXT_PUBLIC_*` vars are embedded in the JS bundle and visible to anyone.
143
+
144
+ | Prefix | Where it runs | Safe for |
145
+ |--------|--------------|----------|
146
+ | `NEXT_PUBLIC_*` | Browser + Server | Public URLs, analytics IDs, Stripe **publishable** key (`pk_`) |
147
+ | No prefix | Server ONLY | API keys, secrets, tokens, database URLs, private keys |
148
+
149
+ ```typescript
150
+ // .env.local
151
+ OPENAI_KEY=sk-abc123 // Server only — SAFE
152
+ STRIPE_SECRET_KEY=sk_live_abc // Server only — SAFE
153
+ NEXT_PUBLIC_APP_URL=https://myapp.com // Public — OK (no secret)
154
+ NEXT_PUBLIC_STRIPE_KEY=pk_live_abc // Public — OK (publishable key)
155
+
156
+ // NEXT_PUBLIC_OPENAI_KEY=sk-abc123 // FORBIDDEN — exposed in browser bundle!
157
+ ```
158
+
159
+ ### API Proxy Pattern (MANDATORY for external APIs)
160
+
161
+ > **ALL calls to external APIs with secrets MUST go through server-side Route Handlers or Server Actions. NEVER call external APIs directly from client components.**
162
+
163
+ ```typescript
164
+ // app/api/chat/route.ts — Server-side proxy (token NEVER leaves server)
165
+ import { NextRequest, NextResponse } from 'next/server';
166
+
167
+ export async function POST(req: NextRequest) {
168
+ const { message } = await req.json();
169
+ const response = await fetch('https://api.openai.com/v1/chat/completions', {
170
+ headers: { Authorization: `Bearer ${process.env['OPENAI_KEY']}` },
171
+ method: 'POST',
172
+ body: JSON.stringify({ model: 'gpt-4', messages: [{ role: 'user', content: message }] }),
173
+ });
174
+ return NextResponse.json(await response.json());
175
+ }
176
+
177
+ // components/chat.tsx — Client calls YOUR API, not the external one
178
+ 'use client';
179
+ const response = await fetch('/api/chat', {
180
+ method: 'POST',
181
+ body: JSON.stringify({ message }),
182
+ });
183
+ ```
184
+
185
+ ### Types Location
186
+
187
+ - **ALL** interfaces/types MUST be in `types/` folder
188
+ - **NEVER** define types in `src/` files
189
+ - **EXCEPTION:** Zod inferred types (`z.infer<typeof Schema>`)
190
+
191
+ ### TypeScript Strict
192
+
193
+ ```typescript
194
+ process.env['VARIABLE']; // CORRECT (bracket notation)
195
+ source: 'listed' as const; // CORRECT (literal type)
196
+ ```
197
+
198
+ ### Component Organization
199
+
200
+ | Question | Location |
201
+ |----------|----------|
202
+ | Used in ONE page only? | `app/[page]/_components/` |
203
+ | Used across 2+ features? | `components/shared/` |
204
+ | UI primitive (Button, Input)? | `components/ui/` |
205
+ | Layout element (Header)? | `components/layout/` |
206
+
207
+ | Lines | Action |
208
+ |-------|--------|
209
+ | < 200 | Keep in single file |
210
+ | 200-400 | Consider splitting |
211
+ | > 400 | **MUST split** into smaller components |
212
+
213
+ ## FORBIDDEN
214
+
215
+ ### Security (CRITICAL)
216
+
217
+ | Action | Reason |
218
+ |--------|--------|
219
+ | `NEXT_PUBLIC_` with API keys/secrets/tokens | Exposes credentials in browser JS bundle — use server-side proxy |
220
+ | Call external APIs from client components | Leaks tokens — route through `app/api/` Route Handlers |
221
+ | `process.env['SECRET']` in `'use client'` files | Only `NEXT_PUBLIC_*` vars reach the browser — use Server Actions |
222
+ | Hardcode API keys in source code | Use `.env.local` + server-side access only |
223
+ | Commit `.env.local` / `.env` to git | Add to `.gitignore` — use `.env.example` with empty values |
224
+
225
+ ### Code Quality
226
+
227
+ | Action | Reason |
228
+ |--------|--------|
229
+ | `any` type | Defeats strict mode — use `unknown` |
230
+ | Skip typecheck | TypeScript errors become runtime bugs |
231
+ | Relative imports (shared) | Breaks when files move — use `@/` alias |
232
+ | Define types in `src/` | Must be in `types/` folder |
233
+ | `'use client'` at top-level layouts | Breaks server rendering, push to leaves |
234
+ | Waterfall data fetching | Use `Promise.all()` for parallel |
235
+ | Skip `loading.tsx` on data pages | Flash of empty content |
236
+ | Files > 400 lines | MUST split into smaller components |
237
+ | Wildcard icon imports | Use named: `import { X } from 'lucide-react'` |
238
+ | `var` keyword | Use `const` or `let` |
239
+ | Raw `console.log` in production | Use structured logging |
240
+
241
+ ### Workflow
242
+
243
+ | Action | Reason |
244
+ |--------|--------|
245
+ | Commit directly to main | Create feature/fix branches |
246
+ | Skip research for new features | Leads to outdated patterns |
247
+ | Skip todo list creation | Loses track of tasks |
248
+ | Skip documenter agent | Documentation is mandatory |
249
+ | Skip domain documentation | MUST update domains/*.md |
250
+ | Stack Last Change entries | Keep only the LATEST |
251
+ | Use MUI/Chakra | Use shadcn/ui + Radix |
252
+ | Skip CLAUDE.md update | MUST update after implementations |
253
+
254
+ ## UI Architecture
255
+
256
+ > Web apps MUST have **separate UIs** for each platform, NOT just "responsive design".
257
+
258
+ | Platform | Layout |
259
+ |----------|--------|
260
+ | Mobile (375px) | Full-screen modals, bottom nav, touch-first |
261
+ | Tablet (768px) | Condensed dropdowns, hybrid nav |
262
+ | Desktop (1280px+) | Sidebar left, top navbar with search |
263
+
264
+ ## Quality Gates
265
+
266
+ ```bash
267
+ bun run typecheck # MUST pass
268
+ bun run lint # MUST pass
269
+ bun run test # MUST pass
270
+ bun run build # MUST pass
271
+ ```
272
+
273
+ ## Domain Documentation
274
+
275
+ > Domain docs prevent Claude from re-exploring the codebase every session.
276
+
277
+ ```
278
+ .claude/skills/codebase-knowledge/domains/
279
+ ├── authentication.md
280
+ ├── api.md
281
+ ├── database.md
282
+ ├── ui-components.md
283
+ └── [domain-name].md
284
+ ```
285
+
286
+ Each domain file tracks: Files, Connections, Recent Commits, Attention Points, Problems & Solutions.
287
+
288
+ ## Commit Format
289
+
290
+ ```
291
+ [type]: [description]
292
+
293
+ - Detail 1
294
+ - Detail 2
295
+
296
+ Generated with Claude Code
297
+ Co-Authored-By: Claude <noreply@anthropic.com>
298
+ ```
299
+
300
+ Types: `feat`, `fix`, `refactor`, `docs`, `chore`
301
+
302
+ ## NRY (Never Repeat Yourself)
303
+
304
+ - Multi-line bash with `\` continuations (breaks permissions)
305
+ - Relative paths in permission patterns
306
+ - Using bash for file operations (use Read/Write/Edit tools)
307
+ - Ignoring context size (use `/compact`)
308
+
309
+ ## Configuration
310
+
311
+ Project settings in `.claude/config/`:
312
+
313
+ - `active-project.json` — Stack, framework, database, skills
314
+ - `domain-mapping.json` — File-to-domain mapping
315
+ - `quality-gates.json` — Quality check commands
316
+ - `testing-config.json` — Test framework config
317
+ - `security-rules.json` — Security audit rules
318
+ - `standards-review.json` — Imported project standards
319
+
320
+ ## Setup by start-vibing-stacks
321
+
322
+ This project was set up with `npx start-vibing-stacks`.
323
+ For updates: `npx start-vibing-stacks --force`