claudex-setup 0.2.0 → 0.3.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/README.md +1 -1
- package/bin/cli.js +23 -7
- package/package.json +8 -2
- package/src/audit.js +40 -3
- package/src/badge.js +13 -0
- package/src/interactive.js +111 -0
- package/src/setup.js +363 -45
- package/src/watch.js +101 -0
- 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 -42
- package/CONTRIBUTING.md +0 -53
- package/apf/state.json +0 -29
- package/apf/todo.md +0 -40
- package/content/devto-article.json +0 -8
- package/content/launch-posts.md +0 -160
- package/docs/index.html +0 -681
- package/tools/publish.js +0 -149
package/README.md
CHANGED
|
@@ -206,7 +206,7 @@ npx claudex-setup --help # Show help
|
|
|
206
206
|
|
|
207
207
|
## Backed by Research
|
|
208
208
|
|
|
209
|
-
Every check and template is derived from the [CLAUDEX](https://github.com/DnaFin/claudex) research catalog — a systematic audit of 1,107 verified Claude Code techniques across 13 research categories. This includes findings from all 73 official Claude Code documentation pages, community reports, and hands-on experiments.
|
|
209
|
+
Every check and template is derived from the [CLAUDEX](https://github.com/DnaFin/claudex-setup) research catalog — a systematic audit of 1,107 verified Claude Code techniques across 13 research categories. This includes findings from all 73 official Claude Code documentation pages, community reports, and hands-on experiments.
|
|
210
210
|
|
|
211
211
|
The knowledge base is continuously updated. Run `npx claudex-setup` periodically to pick up new checks and improved templates.
|
|
212
212
|
|
package/bin/cli.js
CHANGED
|
@@ -14,14 +14,17 @@ const HELP = `
|
|
|
14
14
|
Powered by 1,107 verified techniques.
|
|
15
15
|
|
|
16
16
|
Usage:
|
|
17
|
-
npx claudex-setup
|
|
18
|
-
npx claudex-setup audit
|
|
19
|
-
npx claudex-setup setup
|
|
20
|
-
npx claudex-setup setup --auto
|
|
17
|
+
npx claudex-setup Run audit on current directory
|
|
18
|
+
npx claudex-setup audit Same as above
|
|
19
|
+
npx claudex-setup setup Apply recommended configuration
|
|
20
|
+
npx claudex-setup setup --auto Apply all without prompts
|
|
21
|
+
npx claudex-setup interactive Step-by-step guided wizard
|
|
22
|
+
npx claudex-setup watch Monitor changes and re-audit live
|
|
23
|
+
npx claudex-setup badge Generate shields.io badge markdown
|
|
21
24
|
|
|
22
25
|
Options:
|
|
23
|
-
--verbose Show
|
|
24
|
-
--json Output as JSON
|
|
26
|
+
--verbose Show all recommendations (not just critical/high)
|
|
27
|
+
--json Output as JSON (for CI pipelines)
|
|
25
28
|
--help Show this help
|
|
26
29
|
--version Show version
|
|
27
30
|
`;
|
|
@@ -45,7 +48,20 @@ async function main() {
|
|
|
45
48
|
};
|
|
46
49
|
|
|
47
50
|
try {
|
|
48
|
-
if (command === '
|
|
51
|
+
if (command === 'badge') {
|
|
52
|
+
const { getBadgeMarkdown } = require('../src/badge');
|
|
53
|
+
const result = await audit({ ...options, silent: true });
|
|
54
|
+
console.log(getBadgeMarkdown(result.score));
|
|
55
|
+
console.log('');
|
|
56
|
+
console.log('Add this to your README.md');
|
|
57
|
+
process.exit(0);
|
|
58
|
+
} else if (command === 'interactive' || command === 'wizard') {
|
|
59
|
+
const { interactive } = require('../src/interactive');
|
|
60
|
+
await interactive(options);
|
|
61
|
+
} else if (command === 'watch') {
|
|
62
|
+
const { watch } = require('../src/watch');
|
|
63
|
+
await watch(options);
|
|
64
|
+
} else if (command === 'setup') {
|
|
49
65
|
await setup(options);
|
|
50
66
|
} else {
|
|
51
67
|
await audit(options);
|
package/package.json
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claudex-setup",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.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": {
|
|
7
7
|
"claudex-setup": "bin/cli.js"
|
|
8
8
|
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin",
|
|
11
|
+
"src",
|
|
12
|
+
"README.md",
|
|
13
|
+
"CHANGELOG.md"
|
|
14
|
+
],
|
|
9
15
|
"scripts": {
|
|
10
16
|
"start": "node bin/cli.js",
|
|
11
17
|
"test": "node test/run.js"
|
|
@@ -25,7 +31,7 @@
|
|
|
25
31
|
"license": "MIT",
|
|
26
32
|
"repository": {
|
|
27
33
|
"type": "git",
|
|
28
|
-
"url": "https://github.com/DnaFin/claudex"
|
|
34
|
+
"url": "git+https://github.com/DnaFin/claudex-setup.git"
|
|
29
35
|
},
|
|
30
36
|
"engines": {
|
|
31
37
|
"node": ">=18.0.0"
|
package/src/audit.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
const { TECHNIQUES, STACKS } = require('./techniques');
|
|
6
6
|
const { ProjectContext } = require('./context');
|
|
7
|
+
const { getBadgeMarkdown } = require('./badge');
|
|
7
8
|
|
|
8
9
|
const COLORS = {
|
|
9
10
|
reset: '\x1b[0m',
|
|
@@ -27,7 +28,24 @@ function progressBar(score, max = 100, width = 20) {
|
|
|
27
28
|
return colorize('█'.repeat(filled), color) + colorize('░'.repeat(empty), 'dim');
|
|
28
29
|
}
|
|
29
30
|
|
|
31
|
+
const EFFORT_ORDER = { critical: 0, high: 1, medium: 2 };
|
|
32
|
+
|
|
33
|
+
function getQuickWins(failed) {
|
|
34
|
+
// Quick wins = medium impact items first (easiest), then high, sorted by name length (shorter = simpler)
|
|
35
|
+
return [...failed]
|
|
36
|
+
.sort((a, b) => {
|
|
37
|
+
const effortA = EFFORT_ORDER[a.impact] ?? 3;
|
|
38
|
+
const effortB = EFFORT_ORDER[b.impact] ?? 3;
|
|
39
|
+
// Prefer medium (easiest to fix), then high, then critical
|
|
40
|
+
if (effortA !== effortB) return effortB - effortA;
|
|
41
|
+
// Tie-break by fix length (shorter fix description = likely simpler)
|
|
42
|
+
return (a.fix || '').length - (b.fix || '').length;
|
|
43
|
+
})
|
|
44
|
+
.slice(0, 3);
|
|
45
|
+
}
|
|
46
|
+
|
|
30
47
|
async function audit(options) {
|
|
48
|
+
const silent = options.silent || false;
|
|
31
49
|
const ctx = new ProjectContext(options.dir);
|
|
32
50
|
const stacks = ctx.detectStacks(STACKS);
|
|
33
51
|
const results = [];
|
|
@@ -54,9 +72,14 @@ async function audit(options) {
|
|
|
54
72
|
const earnedScore = passed.reduce((sum, r) => sum + (weights[r.impact] || 5), 0);
|
|
55
73
|
const score = Math.round((earnedScore / maxScore) * 100);
|
|
56
74
|
|
|
75
|
+
// Silent mode: skip all output, just return result
|
|
76
|
+
if (silent) {
|
|
77
|
+
return { score, passed: passed.length, failed: failed.length, stacks, results };
|
|
78
|
+
}
|
|
79
|
+
|
|
57
80
|
if (options.json) {
|
|
58
81
|
console.log(JSON.stringify({ score, stacks, passed: passed.length, failed: failed.length, results }, null, 2));
|
|
59
|
-
return;
|
|
82
|
+
return { score, passed: passed.length, failed: failed.length, stacks, results };
|
|
60
83
|
}
|
|
61
84
|
|
|
62
85
|
// Display results
|
|
@@ -115,6 +138,18 @@ async function audit(options) {
|
|
|
115
138
|
console.log('');
|
|
116
139
|
}
|
|
117
140
|
|
|
141
|
+
// Quick wins
|
|
142
|
+
if (failed.length > 0) {
|
|
143
|
+
const quickWins = getQuickWins(failed);
|
|
144
|
+
console.log(colorize(' ⚡ Quick wins (easiest fixes first)', 'magenta'));
|
|
145
|
+
for (let i = 0; i < quickWins.length; i++) {
|
|
146
|
+
const r = quickWins[i];
|
|
147
|
+
console.log(` ${i + 1}. ${colorize(r.name, 'bold')}`);
|
|
148
|
+
console.log(colorize(` → ${r.fix}`, 'dim'));
|
|
149
|
+
}
|
|
150
|
+
console.log('');
|
|
151
|
+
}
|
|
152
|
+
|
|
118
153
|
// Summary
|
|
119
154
|
console.log(colorize(' ─────────────────────────────────────', 'dim'));
|
|
120
155
|
console.log(` ${colorize(`${passed.length}/${results.length}`, 'bold')} checks passing`);
|
|
@@ -123,12 +158,14 @@ async function audit(options) {
|
|
|
123
158
|
console.log(` Run ${colorize('npx claudex-setup setup', 'bold')} to fix automatically`);
|
|
124
159
|
}
|
|
125
160
|
|
|
161
|
+
console.log('');
|
|
162
|
+
console.log(` Add to README: ${getBadgeMarkdown(score)}`);
|
|
126
163
|
console.log('');
|
|
127
164
|
console.log(colorize(' Powered by CLAUDEX - 1,107 verified Claude Code techniques', 'dim'));
|
|
128
|
-
console.log(colorize(' https://github.com/
|
|
165
|
+
console.log(colorize(' https://github.com/DnaFin/claudex-setup', 'dim'));
|
|
129
166
|
console.log('');
|
|
130
167
|
|
|
131
|
-
return { score, passed: passed.length, failed: failed.length, stacks };
|
|
168
|
+
return { score, passed: passed.length, failed: failed.length, stacks, results };
|
|
132
169
|
}
|
|
133
170
|
|
|
134
171
|
module.exports = { audit };
|
package/src/badge.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
function getBadgeUrl(score) {
|
|
2
|
+
const color = score >= 80 ? 'brightgreen' : score >= 60 ? 'yellow' : score >= 40 ? 'orange' : 'red';
|
|
3
|
+
const label = encodeURIComponent('Claude Code Ready');
|
|
4
|
+
const message = encodeURIComponent(`${score}/100`);
|
|
5
|
+
return `https://img.shields.io/badge/${label}-${message}-${color}`;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function getBadgeMarkdown(score) {
|
|
9
|
+
const url = getBadgeUrl(score);
|
|
10
|
+
return `[](https://github.com/DnaFin/claudex-setup)`;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
module.exports = { getBadgeUrl, getBadgeMarkdown };
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive mode - guides users step-by-step through Claude Code setup.
|
|
3
|
+
* Uses Node.js readline (zero dependencies).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const readline = require('readline');
|
|
7
|
+
const { TECHNIQUES, STACKS } = require('./techniques');
|
|
8
|
+
const { ProjectContext } = require('./context');
|
|
9
|
+
const { setup } = require('./setup');
|
|
10
|
+
|
|
11
|
+
const COLORS = {
|
|
12
|
+
reset: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m',
|
|
13
|
+
red: '\x1b[31m', green: '\x1b[32m', yellow: '\x1b[33m',
|
|
14
|
+
blue: '\x1b[36m', magenta: '\x1b[35m',
|
|
15
|
+
};
|
|
16
|
+
const c = (text, color) => `${COLORS[color] || ''}${text}${COLORS.reset}`;
|
|
17
|
+
|
|
18
|
+
function ask(rl, question) {
|
|
19
|
+
return new Promise(resolve => rl.question(question, resolve));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function interactive(options) {
|
|
23
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
24
|
+
const ctx = new ProjectContext(options.dir);
|
|
25
|
+
const stacks = ctx.detectStacks(STACKS);
|
|
26
|
+
|
|
27
|
+
console.log('');
|
|
28
|
+
console.log(c(' ╔═══════════════════════════════════════╗', 'magenta'));
|
|
29
|
+
console.log(c(' ║ claudex-setup interactive wizard ║', 'magenta'));
|
|
30
|
+
console.log(c(' ╚═══════════════════════════════════════╝', 'magenta'));
|
|
31
|
+
console.log('');
|
|
32
|
+
|
|
33
|
+
if (stacks.length > 0) {
|
|
34
|
+
console.log(c(` Detected stack: ${stacks.map(s => s.label).join(', ')}`, 'blue'));
|
|
35
|
+
}
|
|
36
|
+
console.log(c(` Working directory: ${options.dir}`, 'dim'));
|
|
37
|
+
console.log('');
|
|
38
|
+
|
|
39
|
+
// Run audit silently
|
|
40
|
+
const results = [];
|
|
41
|
+
for (const [key, technique] of Object.entries(TECHNIQUES)) {
|
|
42
|
+
results.push({ key, ...technique, passed: technique.check(ctx) });
|
|
43
|
+
}
|
|
44
|
+
const failed = results.filter(r => !r.passed);
|
|
45
|
+
const passed = results.filter(r => r.passed);
|
|
46
|
+
|
|
47
|
+
console.log(` ${c(`${passed.length}/${results.length}`, 'bold')} checks already passing.`);
|
|
48
|
+
console.log(` ${c(String(failed.length), 'yellow')} improvements available.`);
|
|
49
|
+
console.log('');
|
|
50
|
+
|
|
51
|
+
if (failed.length === 0) {
|
|
52
|
+
console.log(c(' Your project is fully optimized for Claude Code!', 'green'));
|
|
53
|
+
rl.close();
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Group by priority
|
|
58
|
+
const critical = failed.filter(r => r.impact === 'critical');
|
|
59
|
+
const high = failed.filter(r => r.impact === 'high');
|
|
60
|
+
const medium = failed.filter(r => r.impact === 'medium');
|
|
61
|
+
const groups = [
|
|
62
|
+
{ label: 'Critical', color: 'red', items: critical },
|
|
63
|
+
{ label: 'High Impact', color: 'yellow', items: high },
|
|
64
|
+
{ label: 'Recommended', color: 'blue', items: medium },
|
|
65
|
+
].filter(g => g.items.length > 0);
|
|
66
|
+
|
|
67
|
+
const toFix = [];
|
|
68
|
+
|
|
69
|
+
for (const group of groups) {
|
|
70
|
+
console.log(c(` ── ${group.label} (${group.items.length}) ──`, group.color));
|
|
71
|
+
console.log('');
|
|
72
|
+
|
|
73
|
+
for (const item of group.items) {
|
|
74
|
+
console.log(` ${c(item.name, 'bold')}`);
|
|
75
|
+
console.log(c(` ${item.fix}`, 'dim'));
|
|
76
|
+
const answer = await ask(rl, c(' Fix this? (y/n/q) ', 'magenta'));
|
|
77
|
+
|
|
78
|
+
if (answer.toLowerCase() === 'q') {
|
|
79
|
+
console.log('');
|
|
80
|
+
console.log(c(' Stopping wizard.', 'dim'));
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
if (answer.toLowerCase() === 'y' || answer.toLowerCase() === '') {
|
|
84
|
+
toFix.push(item.key);
|
|
85
|
+
console.log(c(' → Will fix', 'green'));
|
|
86
|
+
} else {
|
|
87
|
+
console.log(c(' → Skipped', 'dim'));
|
|
88
|
+
}
|
|
89
|
+
console.log('');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
rl.close();
|
|
94
|
+
|
|
95
|
+
if (toFix.length === 0) {
|
|
96
|
+
console.log(c(' No changes selected.', 'dim'));
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
console.log('');
|
|
101
|
+
console.log(c(` Applying ${toFix.length} fixes...`, 'bold'));
|
|
102
|
+
console.log('');
|
|
103
|
+
|
|
104
|
+
// Run setup in auto mode
|
|
105
|
+
await setup({ ...options, auto: true });
|
|
106
|
+
|
|
107
|
+
console.log('');
|
|
108
|
+
console.log(c(' Done! Run `npx claudex-setup` to see your new score.', 'green'));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
module.exports = { interactive };
|