@claude-code-mastery/starter-kit 1.0.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 (70) hide show
  1. package/.claude/.starter-kit/profiles/clean.md +113 -0
  2. package/.claude/.starter-kit/profiles/go.md +458 -0
  3. package/.claude/.starter-kit/profiles/node.md +429 -0
  4. package/.claude/.starter-kit/profiles/python.md +475 -0
  5. package/.claude/.starter-kit/shared/analytics-rybbit.md +55 -0
  6. package/.claude/.starter-kit/shared/claude-md-base.md +93 -0
  7. package/.claude/.starter-kit/shared/deployment-dokploy.md +158 -0
  8. package/.claude/.starter-kit/shared/feature-manifest.md +43 -0
  9. package/.claude/.starter-kit/shared/mcp-and-pooler.md +38 -0
  10. package/.claude/.starter-kit/shared/mongo-setup.md +20 -0
  11. package/.claude/.starter-kit/shared/profile-config.md +65 -0
  12. package/.claude/.starter-kit/shared/seo.md +113 -0
  13. package/.claude/.starter-kit/shared/sql-setup.md +37 -0
  14. package/.claude/commands/add-feature.md +349 -0
  15. package/.claude/commands/add-project-setup.md +156 -0
  16. package/.claude/commands/architecture.md +27 -0
  17. package/.claude/commands/commit.md +61 -0
  18. package/.claude/commands/convert-project-to-starter-kit.md +508 -0
  19. package/.claude/commands/create-api.md +385 -0
  20. package/.claude/commands/create-e2e.md +230 -0
  21. package/.claude/commands/diagram.md +301 -0
  22. package/.claude/commands/help.md +120 -0
  23. package/.claude/commands/install-global.md +145 -0
  24. package/.claude/commands/new-project.md +244 -0
  25. package/.claude/commands/optimize-docker.md +352 -0
  26. package/.claude/commands/progress.md +61 -0
  27. package/.claude/commands/projects-created.md +79 -0
  28. package/.claude/commands/quickstart.md +105 -0
  29. package/.claude/commands/refactor.md +267 -0
  30. package/.claude/commands/remove-project.md +95 -0
  31. package/.claude/commands/review.md +59 -0
  32. package/.claude/commands/security-check.md +77 -0
  33. package/.claude/commands/set-project-profile-default.md +79 -0
  34. package/.claude/commands/setup.md +337 -0
  35. package/.claude/commands/show-user-guide.md +58 -0
  36. package/.claude/commands/starter-kit.md +90 -0
  37. package/.claude/commands/test-plan.md +118 -0
  38. package/.claude/commands/update-project.md +413 -0
  39. package/.claude/commands/what-is-my-ai-doing.md +42 -0
  40. package/.claude/commands/worktree.md +124 -0
  41. package/.claude/hooks/block-dangerous-bash.py +55 -0
  42. package/.claude/hooks/check-branch.sh +116 -0
  43. package/.claude/hooks/check-e2e.sh +71 -0
  44. package/.claude/hooks/check-env-sync.sh +41 -0
  45. package/.claude/hooks/check-file-length.py +47 -0
  46. package/.claude/hooks/check-ports.sh +59 -0
  47. package/.claude/hooks/check-rulecatch.sh +33 -0
  48. package/.claude/hooks/check-rybbit.sh +63 -0
  49. package/.claude/hooks/lint-on-save.sh +59 -0
  50. package/.claude/hooks/verify-no-secrets.sh +80 -0
  51. package/.claude/settings.json +34 -0
  52. package/.claude/skills/api-conventions/SKILL.md +34 -0
  53. package/.claude/skills/code-review/SKILL.md +87 -0
  54. package/.claude/skills/code-review/references/mongodb-checks.md +25 -0
  55. package/.claude/skills/code-review/references/project-checks.md +38 -0
  56. package/.claude/skills/create-service/SKILL.md +222 -0
  57. package/.claude/skills/debugger/SKILL.md +39 -0
  58. package/.claude/skills/dependency-vetting/SKILL.md +46 -0
  59. package/.claude/skills/design-review/SKILL.md +50 -0
  60. package/.claude/skills/mcp-builder/SKILL.md +57 -0
  61. package/.claude/skills/mongodb-rules/SKILL.md +62 -0
  62. package/.claude/skills/terminal-tui/SKILL.md +106 -0
  63. package/.claude/skills/test-writer/SKILL.md +78 -0
  64. package/LICENSE +21 -0
  65. package/README.md +2152 -0
  66. package/bin/cli.js +205 -0
  67. package/claude-mastery-project.conf +220 -0
  68. package/global-claude-md/CLAUDE.md +212 -0
  69. package/global-claude-md/settings.json +3 -0
  70. package/package.json +81 -0
package/bin/cli.js ADDED
@@ -0,0 +1,205 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import os from 'os';
5
+ import https from 'https';
6
+ import { fileURLToPath } from 'url';
7
+
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = path.dirname(__filename);
10
+ const PKG_ROOT = path.resolve(__dirname, '..');
11
+
12
+ // ── low-level helpers (declared first — no hoisting dependency) ───────────────
13
+
14
+ function paths(homeDir) {
15
+ const claudeDir = path.join(homeDir, '.claude');
16
+ return { claudeDir, starterKitDir: path.join(claudeDir, 'starter-kit') };
17
+ }
18
+
19
+ function ensureDir(dir) {
20
+ fs.mkdirSync(dir, { recursive: true });
21
+ }
22
+
23
+ function symlinkEntry(src, dest, label) {
24
+ if (fs.existsSync(dest)) {
25
+ if (fs.lstatSync(dest).isSymbolicLink()) return; // already linked
26
+ console.log(` ⚠ Skipped ${label} — existing user file at ${dest}`);
27
+ return;
28
+ }
29
+ fs.symlinkSync(src, dest);
30
+ console.log(` Linked ${label}`);
31
+ }
32
+
33
+ function symlinkFiles(srcDir, destDir) {
34
+ if (!fs.existsSync(srcDir)) return;
35
+ ensureDir(destDir);
36
+ for (const name of fs.readdirSync(srcDir)) {
37
+ symlinkEntry(path.join(srcDir, name), path.join(destDir, name), name);
38
+ }
39
+ }
40
+
41
+ function symlinkDirs(srcDir, destDir) {
42
+ if (!fs.existsSync(srcDir)) return;
43
+ ensureDir(destDir);
44
+ for (const name of fs.readdirSync(srcDir)) {
45
+ const src = path.join(srcDir, name);
46
+ if (fs.statSync(src).isDirectory()) {
47
+ symlinkEntry(src, path.join(destDir, name), name);
48
+ }
49
+ }
50
+ }
51
+
52
+ function readInstalledVersion(homeDir) {
53
+ const { starterKitDir } = paths(homeDir);
54
+ const versionFile = path.join(starterKitDir, 'version');
55
+ return fs.existsSync(versionFile) ? fs.readFileSync(versionFile, 'utf8').trim() : null;
56
+ }
57
+
58
+ function fetchLatestVersion() {
59
+ return new Promise((resolve, reject) => {
60
+ https.get(
61
+ 'https://registry.npmjs.org/@claude-code-mastery/starter-kit/latest',
62
+ { headers: { Accept: 'application/json' } },
63
+ res => {
64
+ let body = '';
65
+ res.on('data', chunk => { body += chunk; });
66
+ res.on('end', () => {
67
+ try { resolve(JSON.parse(body).version); } catch { reject(new Error('parse')); }
68
+ });
69
+ },
70
+ ).on('error', reject);
71
+ });
72
+ }
73
+
74
+ // ── exported helpers ──────────────────────────────────────────────────────────
75
+
76
+ export function rewriteHookPath(command, starterKitDir) {
77
+ return command.replace(/(?<=^|\s)\.claude\/hooks\//g, `${starterKitDir}/hooks/`);
78
+ }
79
+
80
+ export function copyPackageFiles(homeDir = os.homedir()) {
81
+ const { starterKitDir } = paths(homeDir);
82
+ ensureDir(starterKitDir);
83
+ fs.cpSync(path.join(PKG_ROOT, '.claude'), starterKitDir, { recursive: true, force: true });
84
+ const pkg = JSON.parse(fs.readFileSync(path.join(PKG_ROOT, 'package.json'), 'utf8'));
85
+ fs.writeFileSync(path.join(starterKitDir, 'version'), pkg.version, 'utf8');
86
+ console.log(` Copied package files → ${starterKitDir}`);
87
+ }
88
+
89
+ export function symlinkAll(homeDir = os.homedir()) {
90
+ const { claudeDir, starterKitDir } = paths(homeDir);
91
+ symlinkFiles(path.join(starterKitDir, 'commands'), path.join(claudeDir, 'commands'));
92
+ symlinkDirs(path.join(starterKitDir, 'skills'), path.join(claudeDir, 'skills'));
93
+ symlinkFiles(path.join(starterKitDir, 'agents'), path.join(claudeDir, 'agents'));
94
+ // Expose scaffolding templates at ~/.claude/.starter-kit/ so command files can
95
+ // reference .claude/.starter-kit/ from any project without a local kit install.
96
+ symlinkEntry(
97
+ path.join(starterKitDir, '.starter-kit'),
98
+ path.join(claudeDir, '.starter-kit'),
99
+ '.starter-kit',
100
+ );
101
+ }
102
+
103
+ export function mergeSettings(homeDir = os.homedir()) {
104
+ const { claudeDir, starterKitDir } = paths(homeDir);
105
+ const kitPath = path.join(starterKitDir, 'settings.json');
106
+ if (!fs.existsSync(kitPath)) return;
107
+
108
+ const kit = JSON.parse(fs.readFileSync(kitPath, 'utf8'));
109
+ const glPath = path.join(claudeDir, 'settings.json');
110
+ const gl = fs.existsSync(glPath) ? JSON.parse(fs.readFileSync(glPath, 'utf8')) : {};
111
+ if (!gl.hooks) gl.hooks = {};
112
+
113
+ for (const [event, groups] of Object.entries(kit.hooks ?? {})) {
114
+ if (!gl.hooks[event]) gl.hooks[event] = [];
115
+
116
+ for (const group of groups) {
117
+ const rewritten = (group.hooks ?? []).map(h => ({
118
+ ...h,
119
+ command: rewriteHookPath(h.command ?? '', starterKitDir),
120
+ }));
121
+
122
+ const registered = new Set(
123
+ gl.hooks[event].flatMap(g => (g.hooks ?? []).map(h => h.command)),
124
+ );
125
+ const fresh = rewritten.filter(h => !registered.has(h.command));
126
+ if (fresh.length === 0) continue;
127
+
128
+ const existing = gl.hooks[event].find(g => g.matcher === group.matcher);
129
+ if (existing) {
130
+ existing.hooks.push(...fresh);
131
+ } else {
132
+ gl.hooks[event].push({ ...group, hooks: fresh });
133
+ }
134
+ for (const h of fresh) console.log(` Registered hook: ${h.command}`);
135
+ }
136
+ }
137
+
138
+ fs.writeFileSync(glPath, JSON.stringify(gl, null, 2), 'utf8');
139
+ }
140
+
141
+ // ── main commands ─────────────────────────────────────────────────────────────
142
+
143
+ export async function init(homeDir = os.homedir()) {
144
+ const { claudeDir, starterKitDir } = paths(homeDir);
145
+ console.log('Installing @claude-code-mastery/starter-kit...\n');
146
+ copyPackageFiles(homeDir);
147
+ symlinkAll(homeDir);
148
+ mergeSettings(homeDir);
149
+ // Copy conf to ~/.claude/ and record source path
150
+ const confSrc = path.join(PKG_ROOT, 'claude-mastery-project.conf');
151
+ if (fs.existsSync(confSrc)) {
152
+ ensureDir(claudeDir);
153
+ fs.copyFileSync(confSrc, path.join(claudeDir, 'claude-mastery-project.conf'));
154
+ console.log(` Copied claude-mastery-project.conf → ${claudeDir}`);
155
+ }
156
+ fs.writeFileSync(path.join(claudeDir, 'starter-kit-source-path'), starterKitDir, 'utf8');
157
+ const version = readInstalledVersion(homeDir);
158
+ console.log(`\n✅ Installed v${version} to ${starterKitDir}`);
159
+ console.log(' Run /starter-kit update inside Claude Code to update in future.\n');
160
+ }
161
+
162
+ export async function update(homeDir = os.homedir()) {
163
+ const { starterKitDir } = paths(homeDir);
164
+ if (!fs.existsSync(starterKitDir)) {
165
+ console.error('Not installed. Run: npx @claude-code-mastery/starter-kit init');
166
+ process.exit(1);
167
+ }
168
+ console.log(`Updating from v${readInstalledVersion(homeDir)}...\n`);
169
+ copyPackageFiles(homeDir);
170
+ symlinkAll(homeDir);
171
+ mergeSettings(homeDir);
172
+ console.log(`\n✅ Updated to v${readInstalledVersion(homeDir)}`);
173
+ }
174
+
175
+ export async function status(homeDir = os.homedir()) {
176
+ const installed = readInstalledVersion(homeDir);
177
+ if (!installed) {
178
+ console.log('Not installed. Run: npx @claude-code-mastery/starter-kit init');
179
+ return;
180
+ }
181
+ console.log(`Installed: v${installed}`);
182
+ try {
183
+ const latest = await fetchLatestVersion();
184
+ console.log(latest === installed
185
+ ? `Latest: v${latest} (up to date ✅)`
186
+ : `Latest: v${latest} (run /starter-kit update to upgrade)`);
187
+ } catch {
188
+ console.log('Latest: (could not reach npm registry)');
189
+ }
190
+ }
191
+
192
+ // ── entry point ───────────────────────────────────────────────────────────────
193
+
194
+ const isMain = process.argv[1] && __filename === fs.realpathSync(process.argv[1]);
195
+ if (isMain) {
196
+ const subcommand = process.argv[2];
197
+ switch (subcommand) {
198
+ case 'init': await init(); break;
199
+ case 'update': await update(); break;
200
+ case 'status': await status(); break;
201
+ default:
202
+ console.log('Usage: npx @claude-code-mastery/starter-kit <init|update|status>');
203
+ process.exit(1);
204
+ }
205
+ }
@@ -0,0 +1,220 @@
1
+ # Claude Mastery Project Configuration
2
+ # =====================================
3
+ # Define reusable profiles for /new-project
4
+ #
5
+ # Usage:
6
+ # /new-project my-app clean → Claude infrastructure only, zero coding opinions
7
+ # /new-project my-app default → creates at ~/projects/my-app with full opinionated stack
8
+ # /new-project my-app api → creates at ~/projects/my-app with API profile
9
+ # /new-project ./custom/path my-app → explicit path overrides root_dir
10
+ # /new-project my-app default vercel → profile + override
11
+ #
12
+ # Global settings:
13
+ # root_dir: Default parent directory for new projects
14
+ # If just a project name is given (no path), it creates at root_dir/<name>
15
+ # Override by passing an explicit path (./foo, ~/bar, /abs/path)
16
+ # default_profile: Profile to use when no profile is specified in /new-project arguments
17
+ # e.g. default_profile = clean → /new-project my-app uses [clean] automatically
18
+ # If not set, /new-project asks the user for all choices
19
+ # auto_branch: Auto-create feature branches when commands detect you're on main (default: true)
20
+ # Set to false if you prefer manual branch management
21
+ # sanitize: Auto-sanitize all database query inputs (default: true, handled by StrictDB)
22
+ # Set to false if you handle sanitization yourself
23
+ # docker_test_before_push:
24
+ # When true, BLOCK any docker push until the image is built, run locally,
25
+ # and verified to start without error (exit code 0, health check passes).
26
+ # Default: false. Enable for production projects to prevent broken deploys.
27
+ #
28
+ # Profile values:
29
+ # type: webapp | api | fullstack | cli
30
+ # language: node | go | python (default: node)
31
+ # framework:
32
+ # Node.js frontend: vite | react | vue | svelte | sveltekit | angular | nuxt | next | astro
33
+ # Node.js backend: fastify | express | hono
34
+ # Go: gin | chi | echo | fiber | stdlib
35
+ # Python: fastapi | django | flask
36
+ # hosting: dokploy | vercel | static
37
+ # package_manager: pnpm | npm | bun | gomod | pip | uv | poetry
38
+ # database: mongo | postgres | mysql | mssql | sqlite | none
39
+ # analytics: rybbit | none
40
+ # options: seo, ssr, tailwind, prisma, docker, ci, multiregion
41
+ # mcp: playwright, context7, rulecatch, classmcp, strictdb
42
+ # npm: additional npm packages (e.g., @rulecatch/ai-pooler, classpresso)
43
+ #
44
+ # Customize these profiles to match YOUR preferred stack.
45
+ # Global fallback: ~/.claude/claude-mastery-project.conf
46
+
47
+ [global]
48
+ root_dir = ~/projects
49
+ auto_branch = true # Auto-create feature branches when on main (set false to disable)
50
+ sanitize = true # Auto-sanitize all database query inputs (handled by StrictDB, set false to disable)
51
+ docker_test_before_push = false # When true, must build + run + health-check locally before pushing to Docker Hub
52
+ ask_task_on_build = false # When true, /mdd Build Mode asks "feature or task?" before Phase 1 questions
53
+
54
+ [clean]
55
+ # All Claude Code infrastructure, zero coding opinions.
56
+ # You get: .claude/ (commands, skills, agents, hooks), project-docs templates,
57
+ # CLAUDE.md (security rules only), .env pattern, .gitignore, tests/ templates.
58
+ # You DON'T get: TypeScript enforcement, port assignments, database wrapper,
59
+ # testing frameworks, quality gates, API versioning, SEO rules.
60
+ # Your project, your rules. Claude just works.
61
+ opinionated = false
62
+
63
+ [default]
64
+ type = fullstack
65
+ framework = next
66
+ hosting = dokploy
67
+ package_manager = pnpm
68
+ database = mongo
69
+ analytics = rybbit
70
+ options = seo, tailwind, docker, ci
71
+ mcp = playwright, context7, rulecatch, classmcp, strictdb
72
+ npm = @rulecatch/ai-pooler, classpresso
73
+
74
+ [api]
75
+ type = api
76
+ framework = fastify
77
+ hosting = dokploy
78
+ package_manager = pnpm
79
+ database = mongo
80
+ analytics = none
81
+ options = docker, ci
82
+ mcp = context7, rulecatch, strictdb
83
+ npm = @rulecatch/ai-pooler
84
+
85
+ [static-site]
86
+ type = webapp
87
+ framework = astro
88
+ hosting = static
89
+ package_manager = pnpm
90
+ database = none
91
+ analytics = rybbit
92
+ options = seo, tailwind
93
+ mcp = context7, classmcp
94
+ npm = classpresso
95
+
96
+ [quick]
97
+ type = webapp
98
+ framework = vite
99
+ hosting = vercel
100
+ package_manager = pnpm
101
+ database = none
102
+ analytics = none
103
+ options = tailwind
104
+ mcp = context7, classmcp
105
+ npm = classpresso
106
+
107
+ [enterprise]
108
+ type = fullstack
109
+ framework = next
110
+ hosting = dokploy
111
+ package_manager = pnpm
112
+ database = mongo
113
+ analytics = rybbit
114
+ options = seo, ssr, tailwind, prisma, docker, ci, multiregion
115
+ mcp = playwright, context7, rulecatch, classmcp, strictdb
116
+ npm = @rulecatch/ai-pooler, classpresso
117
+
118
+ [go]
119
+ language = go
120
+ type = api
121
+ framework = gin
122
+ hosting = dokploy
123
+ package_manager = gomod
124
+ database = mongo
125
+ analytics = none
126
+ options = docker, ci
127
+ mcp = context7, rulecatch, strictdb
128
+
129
+ [vue]
130
+ language = node
131
+ type = webapp
132
+ framework = vue
133
+ hosting = vercel
134
+ package_manager = pnpm
135
+ database = none
136
+ analytics = rybbit
137
+ options = tailwind
138
+ mcp = playwright, context7, classmcp
139
+ npm = classpresso
140
+
141
+ [nuxt]
142
+ language = node
143
+ type = fullstack
144
+ framework = nuxt
145
+ hosting = dokploy
146
+ package_manager = pnpm
147
+ database = mongo
148
+ analytics = rybbit
149
+ options = seo, tailwind, docker, ci
150
+ mcp = playwright, context7, rulecatch, classmcp, strictdb
151
+ npm = classpresso
152
+
153
+ [svelte]
154
+ language = node
155
+ type = webapp
156
+ framework = svelte
157
+ hosting = vercel
158
+ package_manager = pnpm
159
+ database = none
160
+ analytics = rybbit
161
+ options = tailwind
162
+ mcp = playwright, context7, classmcp
163
+ npm = classpresso
164
+
165
+ [sveltekit]
166
+ language = node
167
+ type = fullstack
168
+ framework = sveltekit
169
+ hosting = dokploy
170
+ package_manager = pnpm
171
+ database = mongo
172
+ analytics = rybbit
173
+ options = seo, tailwind, docker, ci
174
+ mcp = playwright, context7, rulecatch, classmcp, strictdb
175
+ npm = classpresso
176
+
177
+ [angular]
178
+ language = node
179
+ type = webapp
180
+ framework = angular
181
+ hosting = vercel
182
+ package_manager = npm
183
+ database = none
184
+ analytics = rybbit
185
+ options = tailwind
186
+ mcp = playwright, context7, classmcp
187
+ npm = classpresso
188
+
189
+ [python-api]
190
+ language = python
191
+ type = api
192
+ framework = fastapi
193
+ hosting = dokploy
194
+ package_manager = pip
195
+ database = postgres
196
+ analytics = none
197
+ options = docker, ci
198
+ mcp = context7, rulecatch, strictdb
199
+
200
+ [django]
201
+ language = python
202
+ type = fullstack
203
+ framework = django
204
+ hosting = dokploy
205
+ package_manager = pip
206
+ database = postgres
207
+ analytics = rybbit
208
+ options = docker, ci
209
+ mcp = context7, rulecatch, classmcp, strictdb
210
+
211
+ [flask]
212
+ language = python
213
+ type = api
214
+ framework = flask
215
+ hosting = dokploy
216
+ package_manager = pip
217
+ database = postgres
218
+ analytics = none
219
+ options = docker, ci
220
+ mcp = context7, strictdb
@@ -0,0 +1,212 @@
1
+ # Global CLAUDE.md — Security Gatekeeper & Standards
2
+
3
+ > Place this at ~/.claude/CLAUDE.md
4
+ > It applies to EVERY project you work on.
5
+ > Based on Claude Code Mastery Guides V1-V5 by TheDecipherist
6
+
7
+ ---
8
+
9
+ ## Identity
10
+
11
+ - GitHub: **YourUsername**
12
+ - SSH: `git@github.com:YourUsername/<repo>.git`
13
+
14
+ ---
15
+
16
+ ## NEVER EVER DO
17
+
18
+ These rules are ABSOLUTE and apply to every project:
19
+
20
+ ### NEVER Publish Sensitive Data
21
+ - NEVER publish passwords, API keys, tokens to git/npm/docker
22
+ - Before ANY commit: verify no secrets included
23
+ - NEVER output secrets in responses, logs, or suggestions
24
+
25
+ ### NEVER Commit .env Files
26
+ - NEVER commit `.env` to git
27
+ - ALWAYS verify `.env` is in `.gitignore`
28
+
29
+ ### NEVER Auto-Deploy
30
+ - ALWAYS ask before deploying to production
31
+ - NEVER assume approval — wait for explicit "yes, deploy"
32
+
33
+ ### NEVER Hardcode Credentials
34
+ - ALWAYS use environment variables for secrets
35
+ - NEVER put API keys, passwords, or tokens directly in source code
36
+
37
+ ### NEVER Publish Dynamic Data in Markdown Files
38
+ - NEVER hardcode repo names, project names, or URLs in `.md` files
39
+ - ALWAYS reference environment variables instead
40
+ - BAD: `docker push myusername/myproject:latest`
41
+ - GOOD: `docker push $DOCKER_HUB_REPO:latest`
42
+ - This applies to: CLAUDE.md, README.md, CONTRIBUTING.md, and all documentation
43
+
44
+ ### NEVER Put Personal Instructions in Public Files
45
+ - NEVER add personal workflows or non-project instructions to a project's main `CLAUDE.md`
46
+ - ALWAYS store personal procedures in `.claude/LOCAL-INSTRUCTIONS.md` (gitignored)
47
+ - Examples of what belongs there: social media workflows, personal tracking, marketing procedures
48
+
49
+ ### NEVER Rename Without a Plan
50
+ - NEVER do project-wide search-and-replace renames without a checklist
51
+ - Renaming causes cascading failures in .md, .env, comments, strings, and paths
52
+
53
+ ### NEVER Push Docker Images Without Local Testing
54
+ - NEVER push a Docker image without testing it locally first
55
+ - ALWAYS run the container and verify it starts correctly before pushing
56
+ - Check for: no crash on startup, no 502 errors, basic pages load
57
+
58
+ #### Docker Pre-Push Checklist
59
+ 1. Build: `docker build -t $IMAGE_NAME .`
60
+ 2. Run: `docker run -d -p 3000:3000 --name test-container $IMAGE_NAME`
61
+ 3. Wait for startup, then verify: `curl -s -o /dev/null -w "%{http_code}" http://localhost:3000` (expect 200)
62
+ 4. Check logs: `docker logs test-container`
63
+ 5. Clean up: `docker stop test-container && docker rm test-container`
64
+ 6. Only then push
65
+
66
+ ---
67
+
68
+ ## If Credentials Are Ever Exposed
69
+
70
+ 1. IMMEDIATELY rotate/change the exposed credentials
71
+ 2. Clean git history: `git filter-repo --replace-text <(echo 'OLD_SECRET==>REDACTED')`
72
+ 3. Force push: `git push --force origin main`
73
+ 4. Verify credentials are removed from ALL commits
74
+ 5. Alert anyone who may have cloned the repo
75
+
76
+ ---
77
+
78
+ ## New Project Setup
79
+
80
+ When creating ANY new project:
81
+
82
+ ### Required Files
83
+ - `.env` - Environment variables (NEVER commit)
84
+ - `.env.example` - Template with placeholders (committed)
85
+ - `.gitignore` - Must include: .env, .env.*, node_modules/, dist/, CLAUDE.local.md
86
+ - `.dockerignore` - Must include: .env, .git/, node_modules/
87
+ - `CLAUDE.md` - Project instructions
88
+ - `tsconfig.json` - TypeScript configuration (strict mode)
89
+
90
+ ### Required Structure
91
+ ```
92
+ project/
93
+ ├── src/
94
+ ├── tests/
95
+ ├── project-docs/
96
+ ├── .claude/
97
+ │ ├── commands/
98
+ │ ├── skills/
99
+ │ └── agents/
100
+ └── scripts/
101
+ ```
102
+
103
+ ### TypeScript - Always
104
+ - All new files MUST be TypeScript
105
+ - Use strict mode
106
+ - Never use `any` unless absolutely necessary
107
+
108
+ ---
109
+
110
+ ## Local Instructions Storage
111
+
112
+ When you have personal procedures that are NOT project code:
113
+
114
+ - **Project `CLAUDE.md`** - code architecture, build/test/deploy commands, technical standards
115
+ - **`.claude/LOCAL-INSTRUCTIONS.md`** - personal workflows, social media posting, marketing procedures, anything that shouldn't be in the public repo
116
+
117
+ Setup:
118
+ 1. Create `.claude/` in the project root if it doesn't exist
119
+ 2. Add `.claude/` to `.gitignore`
120
+ 3. Create `.claude/LOCAL-INSTRUCTIONS.md` for personal procedures
121
+
122
+ ---
123
+
124
+ ## Markdown Writing Rules
125
+
126
+ These apply to any `.md` file:
127
+
128
+ ### No Em Dashes
129
+ - NEVER use em dashes (--)
130
+ - ALWAYS use a regular hyphen (-) instead
131
+
132
+ ### Write Like a Human
133
+ - Avoid AI writing patterns: no "delve into", "leverage", "seamlessly", "robust", "comprehensive", "streamline"
134
+ - Be direct and specific - say what something does, not how impressive it is
135
+ - No filler sentences that add length without adding meaning
136
+
137
+ ### No Repetition
138
+ - NEVER repeat a point already made earlier in the same document
139
+ - If the opening makes an argument, the body must go deeper - not restate it
140
+ - Introductions and conclusions are the worst offenders
141
+
142
+ ---
143
+
144
+ ## Default File Locations
145
+
146
+ ### Documents and Reports
147
+ When asked to create documents (PDF, MD, reports, notes) with no specified location:
148
+ - ALWAYS default to the `/docs` directory in the project root
149
+ - Create `/docs` if it doesn't exist
150
+ - Add `/docs` to `.gitignore` - generated docs don't belong in git
151
+
152
+ ### Tracking Files (CSVs, Logs, Metrics)
153
+ When tracking data in files:
154
+ - ALWAYS create tracking files in `/docs`
155
+ - NEVER commit tracking files to git
156
+ - Before creating any tracking file: verify `/docs` is in `.gitignore`
157
+
158
+ ### Temporary AI Research Files
159
+ When creating research notes, API doc summaries, or analysis during a session:
160
+ - ALWAYS store in `_ai_temp/` directory
161
+ - Add `_ai_temp/` to `.gitignore` if not already there
162
+ - What goes here: research compilations, code analysis notes, temporary drafts, brainstorming
163
+
164
+ ---
165
+
166
+ ## Coding Standards (All Projects)
167
+
168
+ ### Error Handling
169
+ - NEVER swallow errors silently
170
+ - ALWAYS log errors with context before re-throwing
171
+ - Add `process.on('unhandledRejection')` handler to entry points
172
+
173
+ ### Testing
174
+ - ALWAYS define explicit success criteria
175
+ - "Page loads" is NOT a success criterion
176
+ - Every test must assert something meaningful
177
+
178
+ ### Quality Gates
179
+ - No file > 300 lines (split if larger)
180
+ - No function > 50 lines (extract helpers)
181
+ - All tests must pass before committing
182
+ - TypeScript compiles with no errors
183
+ - No linter warnings
184
+
185
+ ### Database
186
+ - ALWAYS use StrictDB for all database access (shared instance pattern)
187
+ - NEVER create database connections in individual files
188
+
189
+ ### Async Performance
190
+ - When multiple `await` calls are independent, ALWAYS use `Promise.all`
191
+ - NEVER await independent operations sequentially - evaluate dependencies first
192
+
193
+ ---
194
+
195
+ ## Image Conversion
196
+
197
+ When converting images to WebP:
198
+ - Try `ffmpeg` first (most commonly available)
199
+ - Fallback: `cwebp` then `convert` (ImageMagick)
200
+
201
+ ```bash
202
+ ffmpeg -i input.png -quality 85 output.webp
203
+ ```
204
+
205
+ ---
206
+
207
+ ## Workflow
208
+
209
+ - One task, one chat
210
+ - Use `/clear` between unrelated tasks
211
+ - Quality over speed - ask if unsure
212
+ - Use Plan Mode for anything bigger than a simple fix
@@ -0,0 +1,3 @@
1
+ {
2
+ "hooks": {}
3
+ }