claudex-setup 1.7.0 → 1.9.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/CHANGELOG.md +35 -0
- package/LICENSE +21 -0
- package/README.md +34 -12
- package/bin/cli.js +42 -5
- package/package.json +3 -2
- package/src/analyze.js +156 -4
- package/src/audit.js +2 -2
- package/src/benchmark.js +81 -7
- package/src/claudex-sync.json +6 -2
- package/src/context.js +3 -2
- package/src/domain-packs.js +223 -0
- package/src/governance.js +207 -2
- package/src/index.js +8 -0
- package/src/mcp-packs.js +139 -0
- package/src/plans.js +329 -59
- package/src/setup.js +60 -36
- package/src/techniques.js +30 -10
package/src/setup.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Setup engine - applies recommended Claude Code configuration to a project.
|
|
3
|
-
* v1.
|
|
3
|
+
* v1.8.0 - Starter-safe setup engine with reusable planning primitives.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const fs = require('fs');
|
|
@@ -8,6 +8,7 @@ const path = require('path');
|
|
|
8
8
|
const { TECHNIQUES, STACKS } = require('./techniques');
|
|
9
9
|
const { ProjectContext } = require('./context');
|
|
10
10
|
const { audit } = require('./audit');
|
|
11
|
+
const { buildSettingsForProfile } = require('./governance');
|
|
11
12
|
|
|
12
13
|
// ============================================================
|
|
13
14
|
// Helper: detect project scripts from package.json
|
|
@@ -826,6 +827,19 @@ mkdir -p "$LOG_DIR"
|
|
|
826
827
|
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
|
|
827
828
|
echo "[$TIMESTAMP] $TOOL_NAME: $FILE_PATH" >> "$LOG_FILE"
|
|
828
829
|
|
|
830
|
+
exit 0
|
|
831
|
+
`,
|
|
832
|
+
'session-start.sh': `#!/bin/bash
|
|
833
|
+
# SessionStart hook - prepares logs and records session entry
|
|
834
|
+
|
|
835
|
+
LOG_DIR=".claude/logs"
|
|
836
|
+
LOG_FILE="$LOG_DIR/sessions.log"
|
|
837
|
+
|
|
838
|
+
mkdir -p "$LOG_DIR"
|
|
839
|
+
|
|
840
|
+
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
|
|
841
|
+
echo "[$TIMESTAMP] session started" >> "$LOG_FILE"
|
|
842
|
+
|
|
829
843
|
exit 0
|
|
830
844
|
`,
|
|
831
845
|
}),
|
|
@@ -877,6 +891,15 @@ exit 0
|
|
|
877
891
|
1. Run \`git diff\` to see all changes
|
|
878
892
|
2. Check for: bugs, security issues, missing tests, code style
|
|
879
893
|
3. Provide actionable feedback
|
|
894
|
+
`;
|
|
895
|
+
|
|
896
|
+
cmds['security-review.md'] = `Run a focused security review using Claude Code's built-in security workflow.
|
|
897
|
+
|
|
898
|
+
## Steps:
|
|
899
|
+
1. Review auth, permissions, secrets handling, and data access paths
|
|
900
|
+
2. Run \`/security-review\` for OWASP-focused analysis
|
|
901
|
+
3. Check for unsafe shell commands, token leakage, and risky file access
|
|
902
|
+
4. Report findings ordered by severity with concrete fixes
|
|
880
903
|
`;
|
|
881
904
|
|
|
882
905
|
// Deploy - stack-specific
|
|
@@ -980,6 +1003,17 @@ Fix the GitHub issue: $ARGUMENTS
|
|
|
980
1003
|
3. Implement the fix
|
|
981
1004
|
4. Write tests
|
|
982
1005
|
5. Create a descriptive commit
|
|
1006
|
+
`,
|
|
1007
|
+
'release-check/SKILL.md': `---
|
|
1008
|
+
name: release-check
|
|
1009
|
+
description: Prepare a release candidate and verify publish readiness
|
|
1010
|
+
---
|
|
1011
|
+
Prepare a release candidate for: $ARGUMENTS
|
|
1012
|
+
|
|
1013
|
+
1. Read CHANGELOG.md and package.json version
|
|
1014
|
+
2. Run the test suite and packaging checks
|
|
1015
|
+
3. Verify docs, tags, and release notes are aligned
|
|
1016
|
+
4. Flag anything that would make the release unsafe or misleading
|
|
983
1017
|
`,
|
|
984
1018
|
}),
|
|
985
1019
|
|
|
@@ -1027,6 +1061,12 @@ Fix the GitHub issue: $ARGUMENTS
|
|
|
1027
1061
|
- Never skip or disable tests without a tracking issue
|
|
1028
1062
|
- Mock external dependencies, not internal logic
|
|
1029
1063
|
- Include both happy path and edge case tests
|
|
1064
|
+
`;
|
|
1065
|
+
rules['repository.md'] = `When changing release, packaging, or workflow files:
|
|
1066
|
+
- Keep package.json, CHANGELOG.md, README.md, and docs in sync
|
|
1067
|
+
- Prefer tagged release references over floating branch references in public docs
|
|
1068
|
+
- Preserve backward compatibility in CLI flags where practical
|
|
1069
|
+
- Any automation that writes files must document rollback expectations
|
|
1030
1070
|
`;
|
|
1031
1071
|
return rules;
|
|
1032
1072
|
},
|
|
@@ -1037,12 +1077,26 @@ name: security-reviewer
|
|
|
1037
1077
|
description: Reviews code for security vulnerabilities
|
|
1038
1078
|
tools: [Read, Grep, Glob]
|
|
1039
1079
|
model: sonnet
|
|
1080
|
+
maxTurns: 50
|
|
1040
1081
|
---
|
|
1041
1082
|
Review code for security issues:
|
|
1042
1083
|
- Injection vulnerabilities (SQL, XSS, command injection)
|
|
1043
1084
|
- Authentication and authorization flaws
|
|
1044
1085
|
- Secrets or credentials in code
|
|
1045
1086
|
- Insecure data handling
|
|
1087
|
+
`,
|
|
1088
|
+
'release-manager.md': `---
|
|
1089
|
+
name: release-manager
|
|
1090
|
+
description: Checks release readiness and packaging consistency
|
|
1091
|
+
tools: [Read, Grep, Glob]
|
|
1092
|
+
model: sonnet
|
|
1093
|
+
maxTurns: 50
|
|
1094
|
+
---
|
|
1095
|
+
Review release readiness:
|
|
1096
|
+
- version alignment across package.json, changelog, and docs
|
|
1097
|
+
- publish safety and packaging scope
|
|
1098
|
+
- missing rollback or migration notes
|
|
1099
|
+
- documentation drift that would confuse adopters
|
|
1046
1100
|
`,
|
|
1047
1101
|
}),
|
|
1048
1102
|
|
|
@@ -1164,41 +1218,11 @@ async function setup(options) {
|
|
|
1164
1218
|
if (fs.existsSync(hooksDir) && !fs.existsSync(settingsPath)) {
|
|
1165
1219
|
const hookFiles = fs.readdirSync(hooksDir).filter(f => f.endsWith('.sh'));
|
|
1166
1220
|
if (hookFiles.length > 0) {
|
|
1167
|
-
const settings = {
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
"Read(./secrets/**)",
|
|
1173
|
-
"Bash(rm -rf *)",
|
|
1174
|
-
"Bash(git reset --hard *)",
|
|
1175
|
-
"Bash(git checkout -- *)",
|
|
1176
|
-
"Bash(git clean *)",
|
|
1177
|
-
"Bash(git push --force *)"
|
|
1178
|
-
]
|
|
1179
|
-
},
|
|
1180
|
-
hooks: {
|
|
1181
|
-
PostToolUse: [{
|
|
1182
|
-
matcher: "Write|Edit",
|
|
1183
|
-
hooks: hookFiles.filter(f => f !== 'protect-secrets.sh').map(f => ({
|
|
1184
|
-
type: "command",
|
|
1185
|
-
command: `bash .claude/hooks/${f}`,
|
|
1186
|
-
timeout: 10
|
|
1187
|
-
}))
|
|
1188
|
-
}]
|
|
1189
|
-
}
|
|
1190
|
-
};
|
|
1191
|
-
// Add protect-secrets as PreToolUse if it exists
|
|
1192
|
-
if (hookFiles.includes('protect-secrets.sh')) {
|
|
1193
|
-
settings.hooks.PreToolUse = [{
|
|
1194
|
-
matcher: "Read|Write|Edit",
|
|
1195
|
-
hooks: [{
|
|
1196
|
-
type: "command",
|
|
1197
|
-
command: "bash .claude/hooks/protect-secrets.sh",
|
|
1198
|
-
timeout: 5
|
|
1199
|
-
}]
|
|
1200
|
-
}];
|
|
1201
|
-
}
|
|
1221
|
+
const settings = buildSettingsForProfile({
|
|
1222
|
+
profileKey: options.profile || 'safe-write',
|
|
1223
|
+
hookFiles,
|
|
1224
|
+
mcpPackKeys: options.mcpPacks || [],
|
|
1225
|
+
});
|
|
1202
1226
|
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf8');
|
|
1203
1227
|
writtenFiles.push('.claude/settings.json');
|
|
1204
1228
|
log(` \x1b[32m✅\x1b[0m Created .claude/settings.json (hooks registered)`);
|
package/src/techniques.js
CHANGED
|
@@ -4,6 +4,12 @@
|
|
|
4
4
|
* Each technique includes: what to check, how to fix, impact level.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
function hasFrontendSignals(ctx) {
|
|
8
|
+
const pkg = ctx.fileContent('package.json') || '';
|
|
9
|
+
return /react|vue|angular|next|svelte|tailwind|vite|astro/i.test(pkg) ||
|
|
10
|
+
ctx.files.some(f => /tailwind\.config|vite\.config|next\.config|svelte\.config|nuxt\.config|pages\/|components\/|app\//i.test(f));
|
|
11
|
+
}
|
|
12
|
+
|
|
7
13
|
const TECHNIQUES = {
|
|
8
14
|
// ============================================================
|
|
9
15
|
// === MEMORY & CONTEXT (category: 'memory') ==================
|
|
@@ -142,8 +148,13 @@ const TECHNIQUES = {
|
|
|
142
148
|
name: '.claude/ tracked in git',
|
|
143
149
|
check: (ctx) => {
|
|
144
150
|
if (!ctx.fileContent('.gitignore')) return true; // no gitignore = ok
|
|
145
|
-
const
|
|
146
|
-
|
|
151
|
+
const lines = ctx.fileContent('.gitignore')
|
|
152
|
+
.split(/\r?\n/)
|
|
153
|
+
.map(line => line.trim())
|
|
154
|
+
.filter(line => line && !line.startsWith('#'));
|
|
155
|
+
const ignoresClaudeDir = lines.some(line => /^(\/|\*\*\/)?\.claude\/?$/.test(line));
|
|
156
|
+
const unignoresClaudeDir = lines.some(line => /^!(\/)?\.claude(\/|\*\*)?$/.test(line));
|
|
157
|
+
return !ignoresClaudeDir || unignoresClaudeDir;
|
|
147
158
|
},
|
|
148
159
|
impact: 'high',
|
|
149
160
|
rating: 4,
|
|
@@ -318,7 +329,7 @@ const TECHNIQUES = {
|
|
|
318
329
|
name: 'Permission configuration',
|
|
319
330
|
check: (ctx) => {
|
|
320
331
|
const settings = ctx.jsonFile('.claude/settings.local.json') || ctx.jsonFile('.claude/settings.json');
|
|
321
|
-
return settings && settings.permissions;
|
|
332
|
+
return !!(settings && settings.permissions);
|
|
322
333
|
},
|
|
323
334
|
impact: 'medium',
|
|
324
335
|
rating: 4,
|
|
@@ -347,9 +358,15 @@ const TECHNIQUES = {
|
|
|
347
358
|
id: 2402,
|
|
348
359
|
name: 'Default mode is not bypassPermissions',
|
|
349
360
|
check: (ctx) => {
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
361
|
+
// Check shared settings first (committed to git) — if the shared baseline
|
|
362
|
+
// is safe, a personal settings.local.json override should not fail the audit.
|
|
363
|
+
const shared = ctx.jsonFile('.claude/settings.json');
|
|
364
|
+
if (shared && shared.permissions) {
|
|
365
|
+
return shared.permissions.defaultMode !== 'bypassPermissions';
|
|
366
|
+
}
|
|
367
|
+
const local = ctx.jsonFile('.claude/settings.local.json');
|
|
368
|
+
if (!local || !local.permissions) return null;
|
|
369
|
+
return local.permissions.defaultMode !== 'bypassPermissions';
|
|
353
370
|
},
|
|
354
371
|
impact: 'critical',
|
|
355
372
|
rating: 5,
|
|
@@ -362,7 +379,8 @@ const TECHNIQUES = {
|
|
|
362
379
|
id: 1096,
|
|
363
380
|
name: 'Secrets protection configured',
|
|
364
381
|
check: (ctx) => {
|
|
365
|
-
|
|
382
|
+
// Prefer shared settings.json (committed) over local override
|
|
383
|
+
const settings = ctx.jsonFile('.claude/settings.json') || ctx.jsonFile('.claude/settings.local.json');
|
|
366
384
|
if (!settings || !settings.permissions) return false;
|
|
367
385
|
const deny = JSON.stringify(settings.permissions.deny || []);
|
|
368
386
|
return deny.includes('.env') || deny.includes('secrets');
|
|
@@ -471,6 +489,7 @@ const TECHNIQUES = {
|
|
|
471
489
|
id: 1025,
|
|
472
490
|
name: 'Frontend design skill for anti-AI-slop',
|
|
473
491
|
check: (ctx) => {
|
|
492
|
+
if (!hasFrontendSignals(ctx)) return null;
|
|
474
493
|
const md = ctx.fileContent('CLAUDE.md') || '';
|
|
475
494
|
return md.includes('frontend_aesthetics') || md.includes('anti-AI-slop') || md.includes('frontend-design');
|
|
476
495
|
},
|
|
@@ -485,6 +504,7 @@ const TECHNIQUES = {
|
|
|
485
504
|
id: 102501,
|
|
486
505
|
name: 'Tailwind CSS configured',
|
|
487
506
|
check: (ctx) => {
|
|
507
|
+
if (!hasFrontendSignals(ctx)) return null;
|
|
488
508
|
const pkg = ctx.fileContent('package.json') || '';
|
|
489
509
|
return pkg.includes('tailwind') ||
|
|
490
510
|
ctx.files.some(f => /tailwind\.config/.test(f));
|
|
@@ -613,7 +633,7 @@ const TECHNIQUES = {
|
|
|
613
633
|
if (!hasNodeSignals) return null;
|
|
614
634
|
if (ctx.files.includes('.nvmrc') || ctx.files.includes('.node-version')) return true;
|
|
615
635
|
const pkg = ctx.jsonFile('package.json');
|
|
616
|
-
return pkg && pkg.engines && pkg.engines.node;
|
|
636
|
+
return !!(pkg && pkg.engines && pkg.engines.node);
|
|
617
637
|
},
|
|
618
638
|
impact: 'low',
|
|
619
639
|
rating: 3,
|
|
@@ -663,7 +683,7 @@ const TECHNIQUES = {
|
|
|
663
683
|
name: 'MCP servers configured',
|
|
664
684
|
check: (ctx) => {
|
|
665
685
|
const settings = ctx.jsonFile('.claude/settings.local.json') || ctx.jsonFile('.claude/settings.json');
|
|
666
|
-
return settings && settings.mcpServers && Object.keys(settings.mcpServers).length > 0;
|
|
686
|
+
return !!(settings && settings.mcpServers && Object.keys(settings.mcpServers).length > 0);
|
|
667
687
|
},
|
|
668
688
|
impact: 'medium',
|
|
669
689
|
rating: 3,
|
|
@@ -677,7 +697,7 @@ const TECHNIQUES = {
|
|
|
677
697
|
name: '2+ MCP servers for rich tooling',
|
|
678
698
|
check: (ctx) => {
|
|
679
699
|
const settings = ctx.jsonFile('.claude/settings.local.json') || ctx.jsonFile('.claude/settings.json');
|
|
680
|
-
return settings && settings.mcpServers && Object.keys(settings.mcpServers).length >= 2;
|
|
700
|
+
return !!(settings && settings.mcpServers && Object.keys(settings.mcpServers).length >= 2);
|
|
681
701
|
},
|
|
682
702
|
impact: 'medium',
|
|
683
703
|
rating: 4,
|