claudex-setup 0.2.1 → 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 +15 -7
- package/package.json +2 -2
- package/src/audit.js +1 -1
- package/src/badge.js +1 -1
- package/src/interactive.js +111 -0
- package/src/watch.js +101 -0
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,15 +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
|
|
21
|
-
npx claudex-setup
|
|
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
|
|
22
24
|
|
|
23
25
|
Options:
|
|
24
|
-
--verbose Show
|
|
25
|
-
--json Output as JSON
|
|
26
|
+
--verbose Show all recommendations (not just critical/high)
|
|
27
|
+
--json Output as JSON (for CI pipelines)
|
|
26
28
|
--help Show this help
|
|
27
29
|
--version Show version
|
|
28
30
|
`;
|
|
@@ -53,6 +55,12 @@ async function main() {
|
|
|
53
55
|
console.log('');
|
|
54
56
|
console.log('Add this to your README.md');
|
|
55
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);
|
|
56
64
|
} else if (command === 'setup') {
|
|
57
65
|
await setup(options);
|
|
58
66
|
} else {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
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": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"repository": {
|
|
33
33
|
"type": "git",
|
|
34
|
-
"url": "git+https://github.com/DnaFin/claudex.git"
|
|
34
|
+
"url": "git+https://github.com/DnaFin/claudex-setup.git"
|
|
35
35
|
},
|
|
36
36
|
"engines": {
|
|
37
37
|
"node": ">=18.0.0"
|
package/src/audit.js
CHANGED
|
@@ -162,7 +162,7 @@ async function audit(options) {
|
|
|
162
162
|
console.log(` Add to README: ${getBadgeMarkdown(score)}`);
|
|
163
163
|
console.log('');
|
|
164
164
|
console.log(colorize(' Powered by CLAUDEX - 1,107 verified Claude Code techniques', 'dim'));
|
|
165
|
-
console.log(colorize(' https://github.com/DnaFin/claudex', 'dim'));
|
|
165
|
+
console.log(colorize(' https://github.com/DnaFin/claudex-setup', 'dim'));
|
|
166
166
|
console.log('');
|
|
167
167
|
|
|
168
168
|
return { score, passed: passed.length, failed: failed.length, stacks, results };
|
package/src/badge.js
CHANGED
|
@@ -7,7 +7,7 @@ function getBadgeUrl(score) {
|
|
|
7
7
|
|
|
8
8
|
function getBadgeMarkdown(score) {
|
|
9
9
|
const url = getBadgeUrl(score);
|
|
10
|
-
return `[](https://github.com/DnaFin/claudex)`;
|
|
10
|
+
return `[](https://github.com/DnaFin/claudex-setup)`;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
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 };
|
package/src/watch.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Watch mode - monitors project for Claude Code config changes and re-audits.
|
|
3
|
+
* Uses Node.js fs.watch (zero dependencies).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const { audit } = require('./audit');
|
|
9
|
+
|
|
10
|
+
const COLORS = {
|
|
11
|
+
reset: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m',
|
|
12
|
+
green: '\x1b[32m', yellow: '\x1b[33m', blue: '\x1b[36m',
|
|
13
|
+
};
|
|
14
|
+
const c = (text, color) => `${COLORS[color] || ''}${text}${COLORS.reset}`;
|
|
15
|
+
|
|
16
|
+
const WATCH_PATHS = [
|
|
17
|
+
'CLAUDE.md',
|
|
18
|
+
'.claude',
|
|
19
|
+
'.gitignore',
|
|
20
|
+
'package.json',
|
|
21
|
+
'tsconfig.json',
|
|
22
|
+
'.github',
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
async function watch(options) {
|
|
26
|
+
console.log('');
|
|
27
|
+
console.log(c(' claudex-setup watch mode', 'bold'));
|
|
28
|
+
console.log(c(' ═══════════════════════════════════════', 'dim'));
|
|
29
|
+
console.log(c(` Watching: ${options.dir}`, 'dim'));
|
|
30
|
+
console.log(c(' Press Ctrl+C to stop', 'dim'));
|
|
31
|
+
console.log('');
|
|
32
|
+
|
|
33
|
+
// Initial audit
|
|
34
|
+
let lastScore = null;
|
|
35
|
+
try {
|
|
36
|
+
const result = await audit({ ...options, silent: true });
|
|
37
|
+
lastScore = result.score;
|
|
38
|
+
console.log(` ${c('Initial score:', 'bold')} ${scoreColor(result.score)}`);
|
|
39
|
+
console.log(` ${result.passed} / ${result.passed + result.failed} checks passing`);
|
|
40
|
+
console.log('');
|
|
41
|
+
} catch (e) {
|
|
42
|
+
console.log(c(` Initial audit failed: ${e.message}`, 'dim'));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Watch relevant paths
|
|
46
|
+
const watchers = [];
|
|
47
|
+
let debounceTimer = null;
|
|
48
|
+
|
|
49
|
+
for (const watchPath of WATCH_PATHS) {
|
|
50
|
+
const fullPath = path.join(options.dir, watchPath);
|
|
51
|
+
try {
|
|
52
|
+
const watcher = fs.watch(fullPath, { recursive: true }, (eventType, filename) => {
|
|
53
|
+
// Debounce: wait 500ms after last change
|
|
54
|
+
clearTimeout(debounceTimer);
|
|
55
|
+
debounceTimer = setTimeout(async () => {
|
|
56
|
+
const timestamp = new Date().toLocaleTimeString();
|
|
57
|
+
console.log(c(` [${timestamp}] Change detected: ${filename || watchPath}`, 'dim'));
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
const result = await audit({ ...options, silent: true });
|
|
61
|
+
const delta = lastScore !== null ? result.score - lastScore : 0;
|
|
62
|
+
const arrow = delta > 0 ? c(`+${delta}`, 'green') : delta < 0 ? c(String(delta), 'yellow') : '';
|
|
63
|
+
|
|
64
|
+
console.log(` Score: ${scoreColor(result.score)} ${arrow} (${result.passed}/${result.passed + result.failed} passing)`);
|
|
65
|
+
|
|
66
|
+
if (result.score > lastScore) {
|
|
67
|
+
console.log(c(' Nice improvement!', 'green'));
|
|
68
|
+
} else if (result.score < lastScore) {
|
|
69
|
+
console.log(c(' Score dropped - check what changed.', 'yellow'));
|
|
70
|
+
}
|
|
71
|
+
lastScore = result.score;
|
|
72
|
+
console.log('');
|
|
73
|
+
} catch (e) {
|
|
74
|
+
// Ignore transient errors during file saves
|
|
75
|
+
}
|
|
76
|
+
}, 500);
|
|
77
|
+
});
|
|
78
|
+
watchers.push(watcher);
|
|
79
|
+
} catch (e) {
|
|
80
|
+
// Path doesn't exist yet - that's fine
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (watchers.length === 0) {
|
|
85
|
+
console.log(c(' No watchable paths found. Create CLAUDE.md or .claude/ to start.', 'yellow'));
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
console.log(c(` Watching ${watchers.length} paths for changes...`, 'dim'));
|
|
90
|
+
console.log('');
|
|
91
|
+
|
|
92
|
+
// Keep alive
|
|
93
|
+
await new Promise(() => {});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function scoreColor(score) {
|
|
97
|
+
const color = score >= 70 ? 'green' : score >= 40 ? 'yellow' : 'dim';
|
|
98
|
+
return c(`${score}/100`, color);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
module.exports = { watch };
|