claudex-setup 1.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudex-setup",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Audit and optimize any project for Claude Code. Powered by 1107 verified techniques.",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/audit.js CHANGED
@@ -76,6 +76,21 @@ async function audit(options) {
76
76
  const earnedScore = passed.reduce((sum, r) => sum + (weights[r.impact] || 5), 0);
77
77
  const score = maxScore > 0 ? Math.round((earnedScore / maxScore) * 100) : 0;
78
78
 
79
+ // Detect scaffolded vs organic: if CLAUDE.md contains our version stamp, some checks
80
+ // are passing because WE generated them, not the user
81
+ const claudeMd = ctx.fileContent('CLAUDE.md') || '';
82
+ const isScaffolded = claudeMd.includes('Generated by claudex-setup') ||
83
+ claudeMd.includes('claudex-setup');
84
+ // Scaffolded checks: things our setup creates (CLAUDE.md, hooks, commands, agents, rules, skills)
85
+ const scaffoldedKeys = new Set(['claudeMd', 'mermaidArchitecture', 'verificationLoop',
86
+ 'hooks', 'customCommands', 'multipleCommands', 'agents', 'pathRules', 'multipleRules',
87
+ 'skills', 'hooksConfigured', 'preToolUseHook', 'postToolUseHook', 'fewShotExamples',
88
+ 'constraintBlocks', 'xmlTags']);
89
+ const organicPassed = passed.filter(r => !scaffoldedKeys.has(r.key));
90
+ const scaffoldedPassed = passed.filter(r => scaffoldedKeys.has(r.key));
91
+ const organicEarned = organicPassed.reduce((sum, r) => sum + (weights[r.impact] || 5), 0);
92
+ const organicScore = maxScore > 0 ? Math.round((organicEarned / maxScore) * 100) : 0;
93
+
79
94
  // Silent mode: skip all output, just return result
80
95
  if (silent) {
81
96
  return { score, passed: passed.length, failed: failed.length, stacks, results };
@@ -100,6 +115,9 @@ async function audit(options) {
100
115
 
101
116
  // Score
102
117
  console.log(` ${progressBar(score)} ${colorize(`${score}/100`, 'bold')}`);
118
+ if (isScaffolded && scaffoldedPassed.length > 0) {
119
+ console.log(colorize(` Organic: ${organicScore}/100 (without claudex-setup generated files)`, 'dim'));
120
+ }
103
121
  console.log('');
104
122
 
105
123
  // Passed
package/src/setup.js CHANGED
@@ -569,38 +569,109 @@ exit 0
569
569
  `,
570
570
  }),
571
571
 
572
- 'commands': () => ({
573
- 'test.md': `Run the test suite and report results.
572
+ 'commands': (stacks) => {
573
+ const stackKeys = stacks.map(s => s.key);
574
+ const isNext = stackKeys.includes('nextjs');
575
+ const isDjango = stackKeys.includes('django');
576
+ const isFastApi = stackKeys.includes('fastapi');
577
+ const isPython = stackKeys.includes('python') || isDjango || isFastApi;
578
+ const hasDocker = stackKeys.includes('docker');
579
+
580
+ const cmds = {};
581
+
582
+ // Test command - stack-specific
583
+ if (isNext) {
584
+ cmds['test.md'] = `Run the test suite for this Next.js project.
585
+
586
+ ## Steps:
587
+ 1. Run \`npm test\` (or \`npx vitest run\`)
588
+ 2. If tests fail, check for missing mocks or async issues
589
+ 3. For component tests, ensure React Testing Library patterns are used
590
+ 4. For API route tests, check request/response handling
591
+ 5. Report: total, passed, failed, coverage if available
592
+ `;
593
+ } else if (isPython) {
594
+ cmds['test.md'] = `Run the test suite for this Python project.
595
+
596
+ ## Steps:
597
+ 1. Run \`python -m pytest -v\` (or the project's test command)
598
+ 2. Check for fixture issues, missing test database, or import errors
599
+ 3. If using Django: \`python manage.py test\`
600
+ 4. Report: total, passed, failed, and any tracebacks
601
+ `;
602
+ } else {
603
+ cmds['test.md'] = `Run the test suite and report results.
574
604
 
575
605
  ## Steps:
576
606
  1. Run the project's test command
577
607
  2. If tests fail, analyze the failures
578
608
  3. Report: total, passed, failed, and any error details
579
- `,
580
- 'review.md': `Review the current changes for quality and correctness.
609
+ `;
610
+ }
611
+
612
+ // Review - always generic (works well as-is)
613
+ cmds['review.md'] = `Review the current changes for quality and correctness.
581
614
 
582
615
  ## Steps:
583
616
  1. Run \`git diff\` to see all changes
584
617
  2. Check for: bugs, security issues, missing tests, code style
585
618
  3. Provide actionable feedback
586
- `,
587
- 'deploy.md': `Pre-deployment checklist and deployment steps.
619
+ `;
588
620
 
589
- ## Pre-deploy checks:
621
+ // Deploy - stack-specific
622
+ if (isNext) {
623
+ cmds['deploy.md'] = `Pre-deployment checklist for Next.js.
624
+
625
+ ## Pre-deploy:
626
+ 1. Run \`git status\` — working tree must be clean
627
+ 2. Run \`npm run build\` — must succeed with no errors
628
+ 3. Run \`npm test\` — all tests pass
629
+ 4. Run \`npm run lint\` — no lint errors
630
+ 5. Check for \`console.log\` in production code
631
+ 6. Verify environment variables are set in deployment platform
632
+
633
+ ## Deploy:
634
+ 1. If Vercel: \`git push\` triggers auto-deploy
635
+ 2. If self-hosted: \`npm run build && npm start\`
636
+ 3. Verify: check /api/health or main page loads
637
+ 4. Tag: \`git tag -a vX.Y.Z -m "Release vX.Y.Z"\`
638
+ `;
639
+ } else if (hasDocker) {
640
+ cmds['deploy.md'] = `Pre-deployment checklist with Docker.
641
+
642
+ ## Pre-deploy:
643
+ 1. Run \`git status\` — working tree must be clean
644
+ 2. Run full test suite — all tests pass
645
+ 3. Run \`docker build -t app .\` — must succeed
646
+ 4. Run \`docker run app\` locally — smoke test
647
+
648
+ ## Deploy:
649
+ 1. Build: \`docker build -t registry/app:latest .\`
650
+ 2. Push: \`docker push registry/app:latest\`
651
+ 3. Deploy to target environment
652
+ 4. Verify health endpoint responds
653
+ 5. Tag: \`git tag -a vX.Y.Z -m "Release vX.Y.Z"\`
654
+ `;
655
+ } else {
656
+ cmds['deploy.md'] = `Pre-deployment checklist.
657
+
658
+ ## Pre-deploy:
590
659
  1. Run \`git status\` — working tree must be clean
591
660
  2. Run full test suite — all tests must pass
592
- 3. Run linter — no errors allowed
593
- 4. Check for TODO/FIXME/HACK comments in changed files
594
- 5. Verify no secrets in staged changes (\`git diff --cached\`)
595
-
596
- ## Deploy steps:
597
- 1. Confirm target environment (staging vs production)
598
- 2. Review the diff since last deploy tag
599
- 3. Run the deployment command
600
- 4. Verify deployment succeeded (health check / smoke test)
601
- 5. Tag the release: \`git tag -a vX.Y.Z -m "Release vX.Y.Z"\`
602
- `,
603
- 'fix.md': `Fix the issue described: $ARGUMENTS
661
+ 3. Run linter — no errors
662
+ 4. Verify no secrets in staged changes
663
+ 5. Review diff since last deploy
664
+
665
+ ## Deploy:
666
+ 1. Confirm target environment
667
+ 2. Run deployment command
668
+ 3. Verify deployment (health check)
669
+ 4. Tag: \`git tag -a vX.Y.Z -m "Release vX.Y.Z"\`
670
+ `;
671
+ }
672
+
673
+ // Fix - always generic with $ARGUMENTS
674
+ cmds['fix.md'] = `Fix the issue described: $ARGUMENTS
604
675
 
605
676
  ## Steps:
606
677
  1. Understand the issue — read relevant code and error messages
@@ -609,8 +680,32 @@ exit 0
609
680
  4. Write or update tests to cover the fix
610
681
  5. Run the full test suite to verify no regressions
611
682
  6. Summarize what was wrong and how the fix addresses it
612
- `,
613
- }),
683
+ `;
684
+
685
+ // Stack-specific bonus commands
686
+ if (isNext) {
687
+ cmds['check-build.md'] = `Run Next.js build check without deploying.
688
+
689
+ 1. Run \`npx next build\`
690
+ 2. Check for: TypeScript errors, missing pages, broken imports
691
+ 3. Verify no "Dynamic server usage" errors in static pages
692
+ 4. Report build output size and any warnings
693
+ `;
694
+ }
695
+
696
+ if (isPython && (isDjango || isFastApi)) {
697
+ cmds['migrate.md'] = `Run database migrations safely.
698
+
699
+ 1. Check current migration status${isDjango ? ': `python manage.py showmigrations`' : ''}
700
+ 2. Create new migration if schema changed${isDjango ? ': `python manage.py makemigrations`' : ''}
701
+ 3. Review the generated migration file
702
+ 4. Apply: ${isDjango ? '`python manage.py migrate`' : '`alembic upgrade head`'}
703
+ 5. Verify: check that the app starts and queries work
704
+ `;
705
+ }
706
+
707
+ return cmds;
708
+ },
614
709
 
615
710
  'skills': () => ({
616
711
  'fix-issue/SKILL.md': `---
package/src/techniques.js CHANGED
@@ -92,7 +92,7 @@ const TECHNIQUES = {
92
92
  },
93
93
 
94
94
  testCommand: {
95
- id: 93,
95
+ id: 93001,
96
96
  name: 'CLAUDE.md contains a test command',
97
97
  check: (ctx) => {
98
98
  const md = ctx.fileContent('CLAUDE.md') || '';
@@ -106,7 +106,7 @@ const TECHNIQUES = {
106
106
  },
107
107
 
108
108
  lintCommand: {
109
- id: 93,
109
+ id: 93002,
110
110
  name: 'CLAUDE.md contains a lint command',
111
111
  check: (ctx) => {
112
112
  const md = ctx.fileContent('CLAUDE.md') || '';
@@ -120,7 +120,7 @@ const TECHNIQUES = {
120
120
  },
121
121
 
122
122
  buildCommand: {
123
- id: 93,
123
+ id: 93003,
124
124
  name: 'CLAUDE.md contains a build command',
125
125
  check: (ctx) => {
126
126
  const md = ctx.fileContent('CLAUDE.md') || '';
@@ -167,7 +167,7 @@ const TECHNIQUES = {
167
167
  },
168
168
 
169
169
  gitIgnoreNodeModules: {
170
- id: 917,
170
+ id: 91701,
171
171
  name: '.gitignore blocks node_modules',
172
172
  check: (ctx) => {
173
173
  const gitignore = ctx.fileContent('.gitignore') || '';
@@ -210,7 +210,7 @@ const TECHNIQUES = {
210
210
  },
211
211
 
212
212
  multipleCommands: {
213
- id: 20,
213
+ id: 20001,
214
214
  name: '3+ slash commands for rich workflow',
215
215
  check: (ctx) => ctx.hasDir('.claude/commands') && ctx.dirFiles('.claude/commands').length >= 3,
216
216
  impact: 'medium',
@@ -221,7 +221,7 @@ const TECHNIQUES = {
221
221
  },
222
222
 
223
223
  deployCommand: {
224
- id: 20,
224
+ id: 20002,
225
225
  name: 'Has /deploy or /release command',
226
226
  check: (ctx) => {
227
227
  if (!ctx.hasDir('.claude/commands')) return false;
@@ -236,7 +236,7 @@ const TECHNIQUES = {
236
236
  },
237
237
 
238
238
  reviewCommand: {
239
- id: 20,
239
+ id: 20003,
240
240
  name: 'Has /review command',
241
241
  check: (ctx) => {
242
242
  if (!ctx.hasDir('.claude/commands')) return false;
@@ -262,7 +262,7 @@ const TECHNIQUES = {
262
262
  },
263
263
 
264
264
  multipleSkills: {
265
- id: 21,
265
+ id: 2101,
266
266
  name: '2+ skills for specialization',
267
267
  check: (ctx) => ctx.hasDir('.claude/skills') && ctx.dirFiles('.claude/skills').length >= 2,
268
268
  impact: 'medium',
@@ -284,7 +284,7 @@ const TECHNIQUES = {
284
284
  },
285
285
 
286
286
  multipleAgents: {
287
- id: 22,
287
+ id: 2201,
288
288
  name: '2+ agents for delegation',
289
289
  check: (ctx) => ctx.hasDir('.claude/agents') && ctx.dirFiles('.claude/agents').length >= 2,
290
290
  impact: 'medium',
@@ -295,7 +295,7 @@ const TECHNIQUES = {
295
295
  },
296
296
 
297
297
  multipleRules: {
298
- id: 3,
298
+ id: 301,
299
299
  name: '2+ rules files for granular control',
300
300
  check: (ctx) => ctx.hasDir('.claude/rules') && ctx.dirFiles('.claude/rules').length >= 2,
301
301
  impact: 'medium',
@@ -324,7 +324,7 @@ const TECHNIQUES = {
324
324
  },
325
325
 
326
326
  permissionDeny: {
327
- id: 24,
327
+ id: 2401,
328
328
  name: 'Deny rules configured in permissions',
329
329
  check: (ctx) => {
330
330
  const settings = ctx.jsonFile('.claude/settings.local.json') || ctx.jsonFile('.claude/settings.json');
@@ -340,7 +340,7 @@ const TECHNIQUES = {
340
340
  },
341
341
 
342
342
  noBypassPermissions: {
343
- id: 24,
343
+ id: 2402,
344
344
  name: 'Default mode is not bypassPermissions',
345
345
  check: (ctx) => {
346
346
  const settings = ctx.jsonFile('.claude/settings.local.json') || ctx.jsonFile('.claude/settings.json');
@@ -400,7 +400,7 @@ const TECHNIQUES = {
400
400
  },
401
401
 
402
402
  hooksInSettings: {
403
- id: 88,
403
+ id: 8801,
404
404
  name: 'Hooks configured in settings',
405
405
  check: (ctx) => {
406
406
  const settings = ctx.jsonFile('.claude/settings.local.json') || ctx.jsonFile('.claude/settings.json');
@@ -415,7 +415,7 @@ const TECHNIQUES = {
415
415
  },
416
416
 
417
417
  preToolUseHook: {
418
- id: 88,
418
+ id: 8802,
419
419
  name: 'PreToolUse hook configured',
420
420
  check: (ctx) => {
421
421
  const settings = ctx.jsonFile('.claude/settings.local.json') || ctx.jsonFile('.claude/settings.json');
@@ -430,7 +430,7 @@ const TECHNIQUES = {
430
430
  },
431
431
 
432
432
  postToolUseHook: {
433
- id: 88,
433
+ id: 8803,
434
434
  name: 'PostToolUse hook configured',
435
435
  check: (ctx) => {
436
436
  const settings = ctx.jsonFile('.claude/settings.local.json') || ctx.jsonFile('.claude/settings.json');
@@ -445,7 +445,7 @@ const TECHNIQUES = {
445
445
  },
446
446
 
447
447
  sessionStartHook: {
448
- id: 88,
448
+ id: 8804,
449
449
  name: 'SessionStart hook configured',
450
450
  check: (ctx) => {
451
451
  const settings = ctx.jsonFile('.claude/settings.local.json') || ctx.jsonFile('.claude/settings.json');
@@ -478,7 +478,7 @@ const TECHNIQUES = {
478
478
  },
479
479
 
480
480
  tailwindMention: {
481
- id: 1025,
481
+ id: 102501,
482
482
  name: 'Tailwind CSS configured',
483
483
  check: (ctx) => {
484
484
  const pkg = ctx.fileContent('package.json') || '';
@@ -508,7 +508,7 @@ const TECHNIQUES = {
508
508
  },
509
509
 
510
510
  dockerCompose: {
511
- id: 399,
511
+ id: 39901,
512
512
  name: 'Has docker-compose.yml',
513
513
  check: (ctx) => ctx.files.some(f => /^docker-compose\.(yml|yaml)$/i.test(f)),
514
514
  impact: 'medium',
@@ -589,7 +589,7 @@ const TECHNIQUES = {
589
589
  },
590
590
 
591
591
  editorconfig: {
592
- id: 0,
592
+ id: 5001,
593
593
  name: 'Has .editorconfig',
594
594
  check: (ctx) => ctx.files.includes('.editorconfig'),
595
595
  impact: 'low',
@@ -600,7 +600,7 @@ const TECHNIQUES = {
600
600
  },
601
601
 
602
602
  nvmrc: {
603
- id: 0,
603
+ id: 5002,
604
604
  name: 'Node version pinned',
605
605
  check: (ctx) => {
606
606
  if (ctx.files.includes('.nvmrc') || ctx.files.includes('.node-version')) return true;
@@ -665,7 +665,7 @@ const TECHNIQUES = {
665
665
  },
666
666
 
667
667
  multipleMcpServers: {
668
- id: 18,
668
+ id: 1801,
669
669
  name: '2+ MCP servers for rich tooling',
670
670
  check: (ctx) => {
671
671
  const settings = ctx.jsonFile('.claude/settings.local.json') || ctx.jsonFile('.claude/settings.json');
@@ -746,7 +746,7 @@ const TECHNIQUES = {
746
746
  },
747
747
 
748
748
  constraintBlocks: {
749
- id: 96,
749
+ id: 9601,
750
750
  name: 'XML constraint blocks in CLAUDE.md',
751
751
  check: (ctx) => {
752
752
  const md = ctx.fileContent('CLAUDE.md') || '';