claudex-setup 0.1.0 → 0.2.1
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/CHANGELOG.md +24 -0
- package/README.md +181 -52
- package/bin/cli.js +10 -2
- package/package.json +9 -3
- package/src/audit.js +41 -4
- package/src/badge.js +13 -0
- package/src/claudex-sync.json +7 -0
- package/src/setup.js +459 -18
- package/src/techniques.js +667 -50
- package/.claude/agents/security-reviewer.md +0 -11
- package/.claude/commands/review.md +0 -6
- package/.claude/commands/test.md +0 -6
- package/.claude/hooks/on-edit-lint.sh +0 -5
- package/.claude/rules/frontend.md +0 -4
- package/.claude/skills/fix-issue/SKILL.md +0 -11
- package/APF.md +0 -121
- package/CLAUDE.md +0 -22
package/src/techniques.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* CLAUDEX Technique Database
|
|
3
|
-
* Curated from
|
|
3
|
+
* Curated from 1,107 verified techniques, filtered to actionable setup recommendations.
|
|
4
4
|
* Each technique includes: what to check, how to fix, impact level.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
const TECHNIQUES = {
|
|
8
|
-
//
|
|
8
|
+
// ============================================================
|
|
9
|
+
// === MEMORY & CONTEXT (category: 'memory') ==================
|
|
10
|
+
// ============================================================
|
|
11
|
+
|
|
9
12
|
claudeMd: {
|
|
10
13
|
id: 1,
|
|
11
14
|
name: 'CLAUDE.md project instructions',
|
|
@@ -17,17 +20,184 @@ const TECHNIQUES = {
|
|
|
17
20
|
template: 'claude-md'
|
|
18
21
|
},
|
|
19
22
|
|
|
20
|
-
|
|
21
|
-
id:
|
|
22
|
-
name: '
|
|
23
|
-
check: (ctx) =>
|
|
23
|
+
mermaidArchitecture: {
|
|
24
|
+
id: 51,
|
|
25
|
+
name: 'Mermaid architecture diagram',
|
|
26
|
+
check: (ctx) => {
|
|
27
|
+
const md = ctx.fileContent('CLAUDE.md') || '';
|
|
28
|
+
return md.includes('mermaid') || md.includes('graph ') || md.includes('flowchart ');
|
|
29
|
+
},
|
|
24
30
|
impact: 'high',
|
|
31
|
+
rating: 5,
|
|
32
|
+
category: 'memory',
|
|
33
|
+
fix: 'Add a Mermaid diagram to CLAUDE.md showing project architecture. Saves 73% tokens vs prose.',
|
|
34
|
+
template: 'mermaid'
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
pathRules: {
|
|
38
|
+
id: 3,
|
|
39
|
+
name: 'Path-specific rules',
|
|
40
|
+
check: (ctx) => ctx.hasDir('.claude/rules') && ctx.dirFiles('.claude/rules').length > 0,
|
|
41
|
+
impact: 'medium',
|
|
25
42
|
rating: 4,
|
|
26
|
-
category: '
|
|
27
|
-
fix: 'Add
|
|
28
|
-
template: '
|
|
43
|
+
category: 'memory',
|
|
44
|
+
fix: 'Add rules for different file types (frontend vs backend conventions).',
|
|
45
|
+
template: 'rules'
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
importSyntax: {
|
|
49
|
+
id: 763,
|
|
50
|
+
name: 'CLAUDE.md uses @import for modularity',
|
|
51
|
+
check: (ctx) => {
|
|
52
|
+
const md = ctx.fileContent('CLAUDE.md') || '';
|
|
53
|
+
return md.includes('@import');
|
|
54
|
+
},
|
|
55
|
+
impact: 'medium',
|
|
56
|
+
rating: 4,
|
|
57
|
+
category: 'memory',
|
|
58
|
+
fix: 'Use @import in CLAUDE.md to split instructions into focused modules (e.g. @import ./docs/coding-style.md).',
|
|
59
|
+
template: null
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
underlines200: {
|
|
63
|
+
id: 681,
|
|
64
|
+
name: 'CLAUDE.md under 200 lines (concise)',
|
|
65
|
+
check: (ctx) => {
|
|
66
|
+
const md = ctx.fileContent('CLAUDE.md') || '';
|
|
67
|
+
return md.split('\n').length < 200;
|
|
68
|
+
},
|
|
69
|
+
impact: 'medium',
|
|
70
|
+
rating: 4,
|
|
71
|
+
category: 'memory',
|
|
72
|
+
fix: 'Keep CLAUDE.md under 200 lines. Use @import or .claude/rules/ to split large instructions.',
|
|
73
|
+
template: null
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
// ============================================================
|
|
77
|
+
// === QUALITY & TESTING (category: 'quality') ================
|
|
78
|
+
// ============================================================
|
|
79
|
+
|
|
80
|
+
verificationLoop: {
|
|
81
|
+
id: 93,
|
|
82
|
+
name: 'Verification criteria in CLAUDE.md',
|
|
83
|
+
check: (ctx) => {
|
|
84
|
+
const md = ctx.fileContent('CLAUDE.md') || '';
|
|
85
|
+
return md.includes('test') || md.includes('verify') || md.includes('lint') || md.includes('check');
|
|
86
|
+
},
|
|
87
|
+
impact: 'critical',
|
|
88
|
+
rating: 5,
|
|
89
|
+
category: 'quality',
|
|
90
|
+
fix: 'Add test/lint/build commands to CLAUDE.md so Claude can verify its own work.',
|
|
91
|
+
template: null
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
testCommand: {
|
|
95
|
+
id: 93,
|
|
96
|
+
name: 'CLAUDE.md contains a test command',
|
|
97
|
+
check: (ctx) => {
|
|
98
|
+
const md = ctx.fileContent('CLAUDE.md') || '';
|
|
99
|
+
return /npm test|pytest|jest|vitest|cargo test|go test|mix test|rspec/.test(md);
|
|
100
|
+
},
|
|
101
|
+
impact: 'high',
|
|
102
|
+
rating: 5,
|
|
103
|
+
category: 'quality',
|
|
104
|
+
fix: 'Add an explicit test command to CLAUDE.md (e.g. "Run `npm test` before committing").',
|
|
105
|
+
template: null
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
lintCommand: {
|
|
109
|
+
id: 93,
|
|
110
|
+
name: 'CLAUDE.md contains a lint command',
|
|
111
|
+
check: (ctx) => {
|
|
112
|
+
const md = ctx.fileContent('CLAUDE.md') || '';
|
|
113
|
+
return /eslint|prettier|ruff|black|clippy|golangci-lint|rubocop/.test(md);
|
|
114
|
+
},
|
|
115
|
+
impact: 'high',
|
|
116
|
+
rating: 4,
|
|
117
|
+
category: 'quality',
|
|
118
|
+
fix: 'Add a lint command to CLAUDE.md so Claude auto-formats and checks code style.',
|
|
119
|
+
template: null
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
buildCommand: {
|
|
123
|
+
id: 93,
|
|
124
|
+
name: 'CLAUDE.md contains a build command',
|
|
125
|
+
check: (ctx) => {
|
|
126
|
+
const md = ctx.fileContent('CLAUDE.md') || '';
|
|
127
|
+
return /npm run build|cargo build|go build|make|tsc|gradle build|mvn compile/.test(md);
|
|
128
|
+
},
|
|
129
|
+
impact: 'medium',
|
|
130
|
+
rating: 4,
|
|
131
|
+
category: 'quality',
|
|
132
|
+
fix: 'Add a build command to CLAUDE.md so Claude can verify compilation before committing.',
|
|
133
|
+
template: null
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
// ============================================================
|
|
137
|
+
// === GIT SAFETY (category: 'git') ===========================
|
|
138
|
+
// ============================================================
|
|
139
|
+
|
|
140
|
+
gitIgnoreClaudeTracked: {
|
|
141
|
+
id: 976,
|
|
142
|
+
name: '.claude/ tracked in git',
|
|
143
|
+
check: (ctx) => {
|
|
144
|
+
if (!ctx.fileContent('.gitignore')) return true; // no gitignore = ok
|
|
145
|
+
const content = ctx.fileContent('.gitignore');
|
|
146
|
+
return !content.includes('.claude/') || content.includes('!.claude/');
|
|
147
|
+
},
|
|
148
|
+
impact: 'high',
|
|
149
|
+
rating: 4,
|
|
150
|
+
category: 'git',
|
|
151
|
+
fix: 'Remove .claude/ from .gitignore (keep .claude/settings.local.json ignored).',
|
|
152
|
+
template: null
|
|
29
153
|
},
|
|
30
154
|
|
|
155
|
+
gitIgnoreEnv: {
|
|
156
|
+
id: 917,
|
|
157
|
+
name: '.gitignore blocks .env files',
|
|
158
|
+
check: (ctx) => {
|
|
159
|
+
const gitignore = ctx.fileContent('.gitignore') || '';
|
|
160
|
+
return gitignore.includes('.env');
|
|
161
|
+
},
|
|
162
|
+
impact: 'critical',
|
|
163
|
+
rating: 5,
|
|
164
|
+
category: 'git',
|
|
165
|
+
fix: 'Add .env to .gitignore to prevent leaking secrets.',
|
|
166
|
+
template: null
|
|
167
|
+
},
|
|
168
|
+
|
|
169
|
+
gitIgnoreNodeModules: {
|
|
170
|
+
id: 917,
|
|
171
|
+
name: '.gitignore blocks node_modules',
|
|
172
|
+
check: (ctx) => {
|
|
173
|
+
const gitignore = ctx.fileContent('.gitignore') || '';
|
|
174
|
+
return gitignore.includes('node_modules');
|
|
175
|
+
},
|
|
176
|
+
impact: 'high',
|
|
177
|
+
rating: 4,
|
|
178
|
+
category: 'git',
|
|
179
|
+
fix: 'Add node_modules/ to .gitignore.',
|
|
180
|
+
template: null
|
|
181
|
+
},
|
|
182
|
+
|
|
183
|
+
noSecretsInClaude: {
|
|
184
|
+
id: 1039,
|
|
185
|
+
name: 'CLAUDE.md has no embedded API keys',
|
|
186
|
+
check: (ctx) => {
|
|
187
|
+
const md = ctx.fileContent('CLAUDE.md') || '';
|
|
188
|
+
return !/sk-[a-zA-Z0-9]{20,}|xoxb-|AKIA[A-Z0-9]{16}/.test(md);
|
|
189
|
+
},
|
|
190
|
+
impact: 'critical',
|
|
191
|
+
rating: 5,
|
|
192
|
+
category: 'git',
|
|
193
|
+
fix: 'Remove API keys from CLAUDE.md. Use environment variables or .env files instead.',
|
|
194
|
+
template: null
|
|
195
|
+
},
|
|
196
|
+
|
|
197
|
+
// ============================================================
|
|
198
|
+
// === WORKFLOW (category: 'workflow') =========================
|
|
199
|
+
// ============================================================
|
|
200
|
+
|
|
31
201
|
customCommands: {
|
|
32
202
|
id: 20,
|
|
33
203
|
name: 'Custom slash commands',
|
|
@@ -39,6 +209,47 @@ const TECHNIQUES = {
|
|
|
39
209
|
template: 'commands'
|
|
40
210
|
},
|
|
41
211
|
|
|
212
|
+
multipleCommands: {
|
|
213
|
+
id: 20,
|
|
214
|
+
name: '3+ slash commands for rich workflow',
|
|
215
|
+
check: (ctx) => ctx.hasDir('.claude/commands') && ctx.dirFiles('.claude/commands').length >= 3,
|
|
216
|
+
impact: 'medium',
|
|
217
|
+
rating: 4,
|
|
218
|
+
category: 'workflow',
|
|
219
|
+
fix: 'Add at least 3 slash commands to cover your main workflows (test, deploy, review, etc.).',
|
|
220
|
+
template: 'commands'
|
|
221
|
+
},
|
|
222
|
+
|
|
223
|
+
deployCommand: {
|
|
224
|
+
id: 20,
|
|
225
|
+
name: 'Has /deploy or /release command',
|
|
226
|
+
check: (ctx) => {
|
|
227
|
+
if (!ctx.hasDir('.claude/commands')) return false;
|
|
228
|
+
const files = ctx.dirFiles('.claude/commands');
|
|
229
|
+
return files.some(f => /deploy|release/i.test(f));
|
|
230
|
+
},
|
|
231
|
+
impact: 'medium',
|
|
232
|
+
rating: 4,
|
|
233
|
+
category: 'workflow',
|
|
234
|
+
fix: 'Create a /deploy or /release command for one-click deployments.',
|
|
235
|
+
template: null
|
|
236
|
+
},
|
|
237
|
+
|
|
238
|
+
reviewCommand: {
|
|
239
|
+
id: 20,
|
|
240
|
+
name: 'Has /review command',
|
|
241
|
+
check: (ctx) => {
|
|
242
|
+
if (!ctx.hasDir('.claude/commands')) return false;
|
|
243
|
+
const files = ctx.dirFiles('.claude/commands');
|
|
244
|
+
return files.some(f => /review/i.test(f));
|
|
245
|
+
},
|
|
246
|
+
impact: 'medium',
|
|
247
|
+
rating: 4,
|
|
248
|
+
category: 'workflow',
|
|
249
|
+
fix: 'Create a /review command for code review workflows.',
|
|
250
|
+
template: null
|
|
251
|
+
},
|
|
252
|
+
|
|
42
253
|
skills: {
|
|
43
254
|
id: 21,
|
|
44
255
|
name: 'Custom skills',
|
|
@@ -50,71 +261,395 @@ const TECHNIQUES = {
|
|
|
50
261
|
template: 'skills'
|
|
51
262
|
},
|
|
52
263
|
|
|
53
|
-
|
|
264
|
+
multipleSkills: {
|
|
265
|
+
id: 21,
|
|
266
|
+
name: '2+ skills for specialization',
|
|
267
|
+
check: (ctx) => ctx.hasDir('.claude/skills') && ctx.dirFiles('.claude/skills').length >= 2,
|
|
268
|
+
impact: 'medium',
|
|
269
|
+
rating: 4,
|
|
270
|
+
category: 'workflow',
|
|
271
|
+
fix: 'Add at least 2 skills to cover different domain areas.',
|
|
272
|
+
template: 'skills'
|
|
273
|
+
},
|
|
274
|
+
|
|
275
|
+
agents: {
|
|
276
|
+
id: 22,
|
|
277
|
+
name: 'Custom agents',
|
|
278
|
+
check: (ctx) => ctx.hasDir('.claude/agents') && ctx.dirFiles('.claude/agents').length > 0,
|
|
279
|
+
impact: 'medium',
|
|
280
|
+
rating: 4,
|
|
281
|
+
category: 'workflow',
|
|
282
|
+
fix: 'Create specialized agents (security-reviewer, test-writer) in .claude/agents/.',
|
|
283
|
+
template: 'agents'
|
|
284
|
+
},
|
|
285
|
+
|
|
286
|
+
multipleAgents: {
|
|
287
|
+
id: 22,
|
|
288
|
+
name: '2+ agents for delegation',
|
|
289
|
+
check: (ctx) => ctx.hasDir('.claude/agents') && ctx.dirFiles('.claude/agents').length >= 2,
|
|
290
|
+
impact: 'medium',
|
|
291
|
+
rating: 4,
|
|
292
|
+
category: 'workflow',
|
|
293
|
+
fix: 'Add at least 2 agents for specialized tasks (e.g. security-reviewer, test-writer).',
|
|
294
|
+
template: 'agents'
|
|
295
|
+
},
|
|
296
|
+
|
|
297
|
+
multipleRules: {
|
|
54
298
|
id: 3,
|
|
55
|
-
name: '
|
|
56
|
-
check: (ctx) => ctx.hasDir('.claude/rules') && ctx.dirFiles('.claude/rules').length
|
|
299
|
+
name: '2+ rules files for granular control',
|
|
300
|
+
check: (ctx) => ctx.hasDir('.claude/rules') && ctx.dirFiles('.claude/rules').length >= 2,
|
|
57
301
|
impact: 'medium',
|
|
58
302
|
rating: 4,
|
|
59
|
-
category: '
|
|
60
|
-
fix: 'Add rules for different
|
|
303
|
+
category: 'workflow',
|
|
304
|
+
fix: 'Add path-specific rules for different parts of the codebase (frontend, backend, tests).',
|
|
61
305
|
template: 'rules'
|
|
62
306
|
},
|
|
63
307
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
308
|
+
// ============================================================
|
|
309
|
+
// === SECURITY (category: 'security') ========================
|
|
310
|
+
// ============================================================
|
|
311
|
+
|
|
312
|
+
settingsPermissions: {
|
|
313
|
+
id: 24,
|
|
314
|
+
name: 'Permission configuration',
|
|
67
315
|
check: (ctx) => {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
return !content.includes('.claude/') || content.includes('!.claude/');
|
|
316
|
+
const settings = ctx.jsonFile('.claude/settings.local.json') || ctx.jsonFile('.claude/settings.json');
|
|
317
|
+
return settings && settings.permissions;
|
|
71
318
|
},
|
|
72
|
-
impact: '
|
|
319
|
+
impact: 'medium',
|
|
73
320
|
rating: 4,
|
|
74
|
-
category: '
|
|
75
|
-
fix: '
|
|
321
|
+
category: 'security',
|
|
322
|
+
fix: 'Configure allow/deny permission lists for safe tool usage.',
|
|
76
323
|
template: null
|
|
77
324
|
},
|
|
78
325
|
|
|
79
|
-
|
|
80
|
-
id:
|
|
81
|
-
name: '
|
|
326
|
+
permissionDeny: {
|
|
327
|
+
id: 24,
|
|
328
|
+
name: 'Deny rules configured in permissions',
|
|
329
|
+
check: (ctx) => {
|
|
330
|
+
const settings = ctx.jsonFile('.claude/settings.local.json') || ctx.jsonFile('.claude/settings.json');
|
|
331
|
+
if (!settings || !settings.permissions) return false;
|
|
332
|
+
const deny = settings.permissions.deny;
|
|
333
|
+
return Array.isArray(deny) && deny.length > 0;
|
|
334
|
+
},
|
|
335
|
+
impact: 'high',
|
|
336
|
+
rating: 5,
|
|
337
|
+
category: 'security',
|
|
338
|
+
fix: 'Add permissions.deny rules to block dangerous operations (e.g. rm -rf, dropping databases).',
|
|
339
|
+
template: null
|
|
340
|
+
},
|
|
341
|
+
|
|
342
|
+
noBypassPermissions: {
|
|
343
|
+
id: 24,
|
|
344
|
+
name: 'Default mode is not bypassPermissions',
|
|
345
|
+
check: (ctx) => {
|
|
346
|
+
const settings = ctx.jsonFile('.claude/settings.local.json') || ctx.jsonFile('.claude/settings.json');
|
|
347
|
+
if (!settings) return true; // no settings = not bypassed
|
|
348
|
+
return settings.defaultMode !== 'bypassPermissions';
|
|
349
|
+
},
|
|
350
|
+
impact: 'critical',
|
|
351
|
+
rating: 5,
|
|
352
|
+
category: 'security',
|
|
353
|
+
fix: 'Do not set defaultMode to bypassPermissions. Use explicit allow rules instead.',
|
|
354
|
+
template: null
|
|
355
|
+
},
|
|
356
|
+
|
|
357
|
+
secretsProtection: {
|
|
358
|
+
id: 1096,
|
|
359
|
+
name: 'Secrets protection configured',
|
|
360
|
+
check: (ctx) => {
|
|
361
|
+
const settings = ctx.jsonFile('.claude/settings.local.json') || ctx.jsonFile('.claude/settings.json');
|
|
362
|
+
if (!settings || !settings.permissions) return false;
|
|
363
|
+
const deny = JSON.stringify(settings.permissions.deny || []);
|
|
364
|
+
return deny.includes('.env') || deny.includes('secrets');
|
|
365
|
+
},
|
|
366
|
+
impact: 'critical',
|
|
367
|
+
rating: 5,
|
|
368
|
+
category: 'security',
|
|
369
|
+
fix: 'Add permissions.deny rules to block reading .env files and secrets directories.',
|
|
370
|
+
template: null
|
|
371
|
+
},
|
|
372
|
+
|
|
373
|
+
securityReview: {
|
|
374
|
+
id: 1031,
|
|
375
|
+
name: 'Security review command awareness',
|
|
82
376
|
check: (ctx) => {
|
|
83
377
|
const md = ctx.fileContent('CLAUDE.md') || '';
|
|
84
|
-
return md.includes('
|
|
378
|
+
return md.includes('security') || md.includes('/security-review');
|
|
85
379
|
},
|
|
86
380
|
impact: 'high',
|
|
87
381
|
rating: 5,
|
|
88
|
-
category: '
|
|
89
|
-
fix: 'Add
|
|
90
|
-
template:
|
|
382
|
+
category: 'security',
|
|
383
|
+
fix: 'Add /security-review to your workflow. Claude Code has built-in OWASP Top 10 scanning.',
|
|
384
|
+
template: null
|
|
91
385
|
},
|
|
92
386
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
387
|
+
// ============================================================
|
|
388
|
+
// === AUTOMATION (category: 'automation') =====================
|
|
389
|
+
// ============================================================
|
|
390
|
+
|
|
391
|
+
hooks: {
|
|
392
|
+
id: 19,
|
|
393
|
+
name: 'Hooks for automation',
|
|
394
|
+
check: (ctx) => ctx.hasDir('.claude/hooks') && ctx.dirFiles('.claude/hooks').length > 0,
|
|
395
|
+
impact: 'high',
|
|
396
|
+
rating: 4,
|
|
397
|
+
category: 'automation',
|
|
398
|
+
fix: 'Add hooks for auto-lint, auto-test, or file change tracking.',
|
|
399
|
+
template: 'hooks'
|
|
400
|
+
},
|
|
401
|
+
|
|
402
|
+
hooksInSettings: {
|
|
403
|
+
id: 88,
|
|
404
|
+
name: 'Hooks configured in settings',
|
|
405
|
+
check: (ctx) => {
|
|
406
|
+
const settings = ctx.jsonFile('.claude/settings.local.json') || ctx.jsonFile('.claude/settings.json');
|
|
407
|
+
if (!settings || !settings.hooks) return false;
|
|
408
|
+
return Object.keys(settings.hooks).length > 0;
|
|
409
|
+
},
|
|
410
|
+
impact: 'high',
|
|
411
|
+
rating: 4,
|
|
412
|
+
category: 'automation',
|
|
413
|
+
fix: 'Add hooks in .claude/settings.json for automated enforcement (lint-on-save, test-on-commit).',
|
|
414
|
+
template: 'hooks'
|
|
415
|
+
},
|
|
416
|
+
|
|
417
|
+
preToolUseHook: {
|
|
418
|
+
id: 88,
|
|
419
|
+
name: 'PreToolUse hook configured',
|
|
420
|
+
check: (ctx) => {
|
|
421
|
+
const settings = ctx.jsonFile('.claude/settings.local.json') || ctx.jsonFile('.claude/settings.json');
|
|
422
|
+
if (!settings || !settings.hooks) return false;
|
|
423
|
+
return !!settings.hooks.PreToolUse;
|
|
424
|
+
},
|
|
425
|
+
impact: 'high',
|
|
426
|
+
rating: 4,
|
|
427
|
+
category: 'automation',
|
|
428
|
+
fix: 'Add PreToolUse hooks for validation before tool calls (e.g. block writes to protected files).',
|
|
429
|
+
template: null
|
|
430
|
+
},
|
|
431
|
+
|
|
432
|
+
postToolUseHook: {
|
|
433
|
+
id: 88,
|
|
434
|
+
name: 'PostToolUse hook configured',
|
|
435
|
+
check: (ctx) => {
|
|
436
|
+
const settings = ctx.jsonFile('.claude/settings.local.json') || ctx.jsonFile('.claude/settings.json');
|
|
437
|
+
if (!settings || !settings.hooks) return false;
|
|
438
|
+
return !!settings.hooks.PostToolUse;
|
|
439
|
+
},
|
|
440
|
+
impact: 'high',
|
|
441
|
+
rating: 4,
|
|
442
|
+
category: 'automation',
|
|
443
|
+
fix: 'Add PostToolUse hooks for auto-lint or auto-format after file writes.',
|
|
444
|
+
template: null
|
|
445
|
+
},
|
|
446
|
+
|
|
447
|
+
sessionStartHook: {
|
|
448
|
+
id: 88,
|
|
449
|
+
name: 'SessionStart hook configured',
|
|
450
|
+
check: (ctx) => {
|
|
451
|
+
const settings = ctx.jsonFile('.claude/settings.local.json') || ctx.jsonFile('.claude/settings.json');
|
|
452
|
+
if (!settings || !settings.hooks) return false;
|
|
453
|
+
return !!settings.hooks.SessionStart;
|
|
454
|
+
},
|
|
455
|
+
impact: 'medium',
|
|
456
|
+
rating: 4,
|
|
457
|
+
category: 'automation',
|
|
458
|
+
fix: 'Add a SessionStart hook for initialization tasks (log rotation, state loading, etc.).',
|
|
459
|
+
template: null
|
|
460
|
+
},
|
|
461
|
+
|
|
462
|
+
// ============================================================
|
|
463
|
+
// === DESIGN (category: 'design') ============================
|
|
464
|
+
// ============================================================
|
|
465
|
+
|
|
466
|
+
frontendDesignSkill: {
|
|
467
|
+
id: 1025,
|
|
468
|
+
name: 'Frontend design skill for anti-AI-slop',
|
|
96
469
|
check: (ctx) => {
|
|
97
470
|
const md = ctx.fileContent('CLAUDE.md') || '';
|
|
98
|
-
return md.includes('
|
|
471
|
+
return md.includes('frontend_aesthetics') || md.includes('anti-AI-slop') || md.includes('frontend-design');
|
|
99
472
|
},
|
|
100
|
-
impact: '
|
|
473
|
+
impact: 'medium',
|
|
101
474
|
rating: 5,
|
|
102
|
-
category: '
|
|
103
|
-
fix: '
|
|
475
|
+
category: 'design',
|
|
476
|
+
fix: 'Install the official frontend-design skill for better UI output quality.',
|
|
104
477
|
template: null
|
|
105
478
|
},
|
|
106
479
|
|
|
107
|
-
|
|
108
|
-
id:
|
|
109
|
-
name: '
|
|
110
|
-
check: (ctx) =>
|
|
480
|
+
tailwindMention: {
|
|
481
|
+
id: 1025,
|
|
482
|
+
name: 'Tailwind CSS configured',
|
|
483
|
+
check: (ctx) => {
|
|
484
|
+
const pkg = ctx.fileContent('package.json') || '';
|
|
485
|
+
return pkg.includes('tailwind') ||
|
|
486
|
+
ctx.files.some(f => /tailwind\.config/.test(f));
|
|
487
|
+
},
|
|
488
|
+
impact: 'low',
|
|
489
|
+
rating: 3,
|
|
490
|
+
category: 'design',
|
|
491
|
+
fix: 'Consider adding Tailwind CSS for rapid, consistent UI styling with Claude.',
|
|
492
|
+
template: null
|
|
493
|
+
},
|
|
494
|
+
|
|
495
|
+
// ============================================================
|
|
496
|
+
// === DEVOPS (category: 'devops') ============================
|
|
497
|
+
// ============================================================
|
|
498
|
+
|
|
499
|
+
dockerfile: {
|
|
500
|
+
id: 399,
|
|
501
|
+
name: 'Has Dockerfile',
|
|
502
|
+
check: (ctx) => ctx.files.some(f => /^Dockerfile/i.test(f)),
|
|
111
503
|
impact: 'medium',
|
|
504
|
+
rating: 3,
|
|
505
|
+
category: 'devops',
|
|
506
|
+
fix: 'Add a Dockerfile for containerized builds and deployments.',
|
|
507
|
+
template: null
|
|
508
|
+
},
|
|
509
|
+
|
|
510
|
+
dockerCompose: {
|
|
511
|
+
id: 399,
|
|
512
|
+
name: 'Has docker-compose.yml',
|
|
513
|
+
check: (ctx) => ctx.files.some(f => /^docker-compose\.(yml|yaml)$/i.test(f)),
|
|
514
|
+
impact: 'medium',
|
|
515
|
+
rating: 3,
|
|
516
|
+
category: 'devops',
|
|
517
|
+
fix: 'Add docker-compose.yml for multi-service local development.',
|
|
518
|
+
template: null
|
|
519
|
+
},
|
|
520
|
+
|
|
521
|
+
ciPipeline: {
|
|
522
|
+
id: 260,
|
|
523
|
+
name: 'CI pipeline configured',
|
|
524
|
+
check: (ctx) => ctx.hasDir('.github/workflows'),
|
|
525
|
+
impact: 'high',
|
|
112
526
|
rating: 4,
|
|
113
|
-
category: '
|
|
114
|
-
fix: '
|
|
115
|
-
template:
|
|
527
|
+
category: 'devops',
|
|
528
|
+
fix: 'Add .github/workflows/ with CI pipeline for automated testing and deployment.',
|
|
529
|
+
template: null
|
|
530
|
+
},
|
|
531
|
+
|
|
532
|
+
terraformFiles: {
|
|
533
|
+
id: 397,
|
|
534
|
+
name: 'Infrastructure as Code (Terraform)',
|
|
535
|
+
check: (ctx) => ctx.files.some(f => /\.tf$/.test(f)) || ctx.files.includes('main.tf'),
|
|
536
|
+
impact: 'medium',
|
|
537
|
+
rating: 3,
|
|
538
|
+
category: 'devops',
|
|
539
|
+
fix: 'Add Terraform files for infrastructure-as-code management.',
|
|
540
|
+
template: null
|
|
541
|
+
},
|
|
542
|
+
|
|
543
|
+
// ============================================================
|
|
544
|
+
// === PROJECT HYGIENE (category: 'hygiene') ==================
|
|
545
|
+
// ============================================================
|
|
546
|
+
|
|
547
|
+
readme: {
|
|
548
|
+
id: 416,
|
|
549
|
+
name: 'Has README.md',
|
|
550
|
+
check: (ctx) => ctx.files.some(f => /^readme\.md$/i.test(f)),
|
|
551
|
+
impact: 'high',
|
|
552
|
+
rating: 4,
|
|
553
|
+
category: 'hygiene',
|
|
554
|
+
fix: 'Add a README.md with project overview, setup instructions, and usage.',
|
|
555
|
+
template: null
|
|
556
|
+
},
|
|
557
|
+
|
|
558
|
+
changelog: {
|
|
559
|
+
id: 417,
|
|
560
|
+
name: 'Has CHANGELOG.md',
|
|
561
|
+
check: (ctx) => ctx.files.some(f => /^changelog\.md$/i.test(f)),
|
|
562
|
+
impact: 'low',
|
|
563
|
+
rating: 3,
|
|
564
|
+
category: 'hygiene',
|
|
565
|
+
fix: 'Add a CHANGELOG.md to track notable changes across versions.',
|
|
566
|
+
template: null
|
|
567
|
+
},
|
|
568
|
+
|
|
569
|
+
contributing: {
|
|
570
|
+
id: 418,
|
|
571
|
+
name: 'Has CONTRIBUTING.md',
|
|
572
|
+
check: (ctx) => ctx.files.some(f => /^contributing\.md$/i.test(f)),
|
|
573
|
+
impact: 'low',
|
|
574
|
+
rating: 3,
|
|
575
|
+
category: 'hygiene',
|
|
576
|
+
fix: 'Add a CONTRIBUTING.md with contribution guidelines and code standards.',
|
|
577
|
+
template: null
|
|
578
|
+
},
|
|
579
|
+
|
|
580
|
+
license: {
|
|
581
|
+
id: 434,
|
|
582
|
+
name: 'Has LICENSE file',
|
|
583
|
+
check: (ctx) => ctx.files.some(f => /^license/i.test(f)),
|
|
584
|
+
impact: 'low',
|
|
585
|
+
rating: 3,
|
|
586
|
+
category: 'hygiene',
|
|
587
|
+
fix: 'Add a LICENSE file to clarify usage rights.',
|
|
588
|
+
template: null
|
|
589
|
+
},
|
|
590
|
+
|
|
591
|
+
editorconfig: {
|
|
592
|
+
id: 0,
|
|
593
|
+
name: 'Has .editorconfig',
|
|
594
|
+
check: (ctx) => ctx.files.includes('.editorconfig'),
|
|
595
|
+
impact: 'low',
|
|
596
|
+
rating: 3,
|
|
597
|
+
category: 'hygiene',
|
|
598
|
+
fix: 'Add .editorconfig for consistent formatting across editors and Claude.',
|
|
599
|
+
template: null
|
|
600
|
+
},
|
|
601
|
+
|
|
602
|
+
nvmrc: {
|
|
603
|
+
id: 0,
|
|
604
|
+
name: 'Node version pinned',
|
|
605
|
+
check: (ctx) => {
|
|
606
|
+
if (ctx.files.includes('.nvmrc') || ctx.files.includes('.node-version')) return true;
|
|
607
|
+
const pkg = ctx.jsonFile('package.json');
|
|
608
|
+
return pkg && pkg.engines && pkg.engines.node;
|
|
609
|
+
},
|
|
610
|
+
impact: 'low',
|
|
611
|
+
rating: 3,
|
|
612
|
+
category: 'hygiene',
|
|
613
|
+
fix: 'Add .nvmrc, .node-version, or engines.node in package.json to pin Node version.',
|
|
614
|
+
template: null
|
|
116
615
|
},
|
|
117
616
|
|
|
617
|
+
// ============================================================
|
|
618
|
+
// === PERFORMANCE (category: 'performance') ==================
|
|
619
|
+
// ============================================================
|
|
620
|
+
|
|
621
|
+
compactionAwareness: {
|
|
622
|
+
id: 568,
|
|
623
|
+
name: 'CLAUDE.md mentions /compact or compaction',
|
|
624
|
+
check: (ctx) => {
|
|
625
|
+
const md = ctx.fileContent('CLAUDE.md') || '';
|
|
626
|
+
return /\/compact|compaction|context.*(limit|manage|budget)/i.test(md);
|
|
627
|
+
},
|
|
628
|
+
impact: 'medium',
|
|
629
|
+
rating: 4,
|
|
630
|
+
category: 'performance',
|
|
631
|
+
fix: 'Add compaction guidance to CLAUDE.md (e.g. "Run /compact when context is heavy").',
|
|
632
|
+
template: null
|
|
633
|
+
},
|
|
634
|
+
|
|
635
|
+
contextManagement: {
|
|
636
|
+
id: 45,
|
|
637
|
+
name: 'Context management awareness',
|
|
638
|
+
check: (ctx) => {
|
|
639
|
+
const md = ctx.fileContent('CLAUDE.md') || '';
|
|
640
|
+
return /context.*(manage|window|limit|budget|token)/i.test(md);
|
|
641
|
+
},
|
|
642
|
+
impact: 'medium',
|
|
643
|
+
rating: 4,
|
|
644
|
+
category: 'performance',
|
|
645
|
+
fix: 'Add context management tips to CLAUDE.md to help Claude stay within token limits.',
|
|
646
|
+
template: null
|
|
647
|
+
},
|
|
648
|
+
|
|
649
|
+
// ============================================================
|
|
650
|
+
// === MCP / TOOLS (category: 'tools') ========================
|
|
651
|
+
// ============================================================
|
|
652
|
+
|
|
118
653
|
mcpServers: {
|
|
119
654
|
id: 18,
|
|
120
655
|
name: 'MCP servers configured',
|
|
@@ -129,20 +664,39 @@ const TECHNIQUES = {
|
|
|
129
664
|
template: null
|
|
130
665
|
},
|
|
131
666
|
|
|
132
|
-
|
|
133
|
-
id:
|
|
134
|
-
name: '
|
|
667
|
+
multipleMcpServers: {
|
|
668
|
+
id: 18,
|
|
669
|
+
name: '2+ MCP servers for rich tooling',
|
|
135
670
|
check: (ctx) => {
|
|
136
671
|
const settings = ctx.jsonFile('.claude/settings.local.json') || ctx.jsonFile('.claude/settings.json');
|
|
137
|
-
return settings && settings.
|
|
672
|
+
return settings && settings.mcpServers && Object.keys(settings.mcpServers).length >= 2;
|
|
138
673
|
},
|
|
139
674
|
impact: 'medium',
|
|
140
675
|
rating: 4,
|
|
141
|
-
category: '
|
|
142
|
-
fix: '
|
|
676
|
+
category: 'tools',
|
|
677
|
+
fix: 'Add at least 2 MCP servers for broader tool coverage (e.g. database + search).',
|
|
143
678
|
template: null
|
|
144
679
|
},
|
|
145
680
|
|
|
681
|
+
context7Mcp: {
|
|
682
|
+
id: 110,
|
|
683
|
+
name: 'Context7 MCP for real-time docs',
|
|
684
|
+
check: (ctx) => {
|
|
685
|
+
const settings = ctx.jsonFile('.claude/settings.local.json') || ctx.jsonFile('.claude/settings.json');
|
|
686
|
+
if (!settings || !settings.mcpServers) return false;
|
|
687
|
+
return Object.keys(settings.mcpServers).some(k => /context7/i.test(k));
|
|
688
|
+
},
|
|
689
|
+
impact: 'medium',
|
|
690
|
+
rating: 4,
|
|
691
|
+
category: 'tools',
|
|
692
|
+
fix: 'Add Context7 MCP server for real-time documentation lookup (always up-to-date library docs).',
|
|
693
|
+
template: null
|
|
694
|
+
},
|
|
695
|
+
|
|
696
|
+
// ============================================================
|
|
697
|
+
// === PROMPTING (category: 'prompting') ======================
|
|
698
|
+
// ============================================================
|
|
699
|
+
|
|
146
700
|
xmlTags: {
|
|
147
701
|
id: 96,
|
|
148
702
|
name: 'XML tags for structured prompts',
|
|
@@ -159,6 +713,63 @@ const TECHNIQUES = {
|
|
|
159
713
|
fix: 'Use XML tags (<constraints>, <validation>) in CLAUDE.md for unambiguous instructions.',
|
|
160
714
|
template: null
|
|
161
715
|
},
|
|
716
|
+
|
|
717
|
+
fewShotExamples: {
|
|
718
|
+
id: 9,
|
|
719
|
+
name: 'CLAUDE.md contains code examples',
|
|
720
|
+
check: (ctx) => {
|
|
721
|
+
const md = ctx.fileContent('CLAUDE.md') || '';
|
|
722
|
+
return (md.match(/```/g) || []).length >= 2;
|
|
723
|
+
},
|
|
724
|
+
impact: 'high',
|
|
725
|
+
rating: 5,
|
|
726
|
+
category: 'prompting',
|
|
727
|
+
fix: 'Add code examples (few-shot) in CLAUDE.md to show preferred patterns and conventions.',
|
|
728
|
+
template: null
|
|
729
|
+
},
|
|
730
|
+
|
|
731
|
+
roleDefinition: {
|
|
732
|
+
id: 10,
|
|
733
|
+
name: 'CLAUDE.md defines a role or persona',
|
|
734
|
+
check: (ctx) => {
|
|
735
|
+
const md = ctx.fileContent('CLAUDE.md') || '';
|
|
736
|
+
return /you are|your role|act as|persona|behave as/i.test(md);
|
|
737
|
+
},
|
|
738
|
+
impact: 'medium',
|
|
739
|
+
rating: 4,
|
|
740
|
+
category: 'prompting',
|
|
741
|
+
fix: 'Define a role or persona in CLAUDE.md (e.g. "You are a senior backend engineer...").',
|
|
742
|
+
template: null
|
|
743
|
+
},
|
|
744
|
+
|
|
745
|
+
constraintBlocks: {
|
|
746
|
+
id: 96,
|
|
747
|
+
name: 'XML constraint blocks in CLAUDE.md',
|
|
748
|
+
check: (ctx) => {
|
|
749
|
+
const md = ctx.fileContent('CLAUDE.md') || '';
|
|
750
|
+
return /<constraints|<rules|<requirements|<boundaries/i.test(md);
|
|
751
|
+
},
|
|
752
|
+
impact: 'high',
|
|
753
|
+
rating: 5,
|
|
754
|
+
category: 'prompting',
|
|
755
|
+
fix: 'Wrap critical rules in <constraints> XML blocks for 40% better adherence.',
|
|
756
|
+
template: null
|
|
757
|
+
},
|
|
758
|
+
|
|
759
|
+
// ============================================================
|
|
760
|
+
// === FEATURES (category: 'features') ========================
|
|
761
|
+
// ============================================================
|
|
762
|
+
|
|
763
|
+
channelsAwareness: {
|
|
764
|
+
id: 1102,
|
|
765
|
+
name: 'Claude Code Channels awareness',
|
|
766
|
+
check: () => true, // informational
|
|
767
|
+
impact: 'low',
|
|
768
|
+
rating: 4,
|
|
769
|
+
category: 'features',
|
|
770
|
+
fix: 'Claude Code Channels (v2.1.80+) lets you control sessions from Telegram/Discord/iMessage.',
|
|
771
|
+
template: null
|
|
772
|
+
},
|
|
162
773
|
};
|
|
163
774
|
|
|
164
775
|
// Stack detection
|
|
@@ -175,6 +786,12 @@ const STACKS = {
|
|
|
175
786
|
rust: { files: ['Cargo.toml'], content: {}, label: 'Rust' },
|
|
176
787
|
go: { files: ['go.mod'], content: {}, label: 'Go' },
|
|
177
788
|
docker: { files: ['Dockerfile', 'docker-compose.yml', 'docker-compose.yaml'], content: {}, label: 'Docker' },
|
|
789
|
+
svelte: { files: ['svelte.config.js'], content: {}, label: 'Svelte' },
|
|
790
|
+
flutter: { files: ['pubspec.yaml'], content: {}, label: 'Flutter' },
|
|
791
|
+
ruby: { files: ['Gemfile'], content: {}, label: 'Ruby' },
|
|
792
|
+
java: { files: ['pom.xml'], content: {}, label: 'Java' },
|
|
793
|
+
kotlin: { files: ['build.gradle.kts'], content: {}, label: 'Kotlin' },
|
|
794
|
+
swift: { files: ['Package.swift'], content: {}, label: 'Swift' },
|
|
178
795
|
};
|
|
179
796
|
|
|
180
797
|
module.exports = { TECHNIQUES, STACKS };
|