claudex-setup 1.11.0 → 1.13.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 +18 -0
- package/README.md +4 -4
- package/package.json +1 -1
- package/src/domain-packs.js +8 -2
- package/src/techniques.js +312 -0
package/CHANGELOG.md
CHANGED
|
@@ -15,6 +15,24 @@
|
|
|
15
15
|
- README and docs now reflect snapshot artifacts, governance export, and the Claude-native skill path
|
|
16
16
|
- packaged content and public-facing counts are now aligned with the current CLAUDEX state
|
|
17
17
|
|
|
18
|
+
## [1.13.0] - 2026-04-03
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
- 10 new checks (74→84): project description, directory structure, multiple hook types, stop-failure hook, skill paths, MCP env config, gitignore local settings, .env.example, package scripts, type checking
|
|
22
|
+
- 15 new tests (58→73): history/compare/trend, new checks structure, CLI commands, deny depth, negative instructions, --require flag
|
|
23
|
+
- All references updated to 74→84 checks
|
|
24
|
+
|
|
25
|
+
## [1.12.0] - 2026-04-03
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
- 12 new checks (62→74): test coverage, agent tool restrictions, auto-memory, sandbox, deny rule depth, git attribution, effort level, snapshot history, worktree, negative instructions, output style, CI variants
|
|
29
|
+
- 8 new stacks (22→30): Deno, Bun, Elixir, Astro, Remix, NestJS, Laravel, .NET
|
|
30
|
+
- Deeper domain detection: llamaindex, crewai, autogen, ollama for AI/ML; paypal, square, adyen, medusa for ecommerce; chromatic, style-dictionary for design; capacitor, ionic for mobile
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
- `githubActionsOrCI` check used non-existent `ctx.hasFile()` — now uses `ctx.fileContent()`
|
|
34
|
+
- `.NET` stack detection no longer uses glob patterns
|
|
35
|
+
|
|
18
36
|
## [1.11.0] - 2026-04-03
|
|
19
37
|
|
|
20
38
|
### Added
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# claudex-setup
|
|
2
2
|
|
|
3
|
-
> Score your repo's Claude Code setup against
|
|
3
|
+
> Score your repo's Claude Code setup against 84 checks. See what's missing, apply only what you approve with rollback, and benchmark the impact — without breaking existing config.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/claudex-setup)
|
|
6
6
|
[](https://www.npmjs.com/package/claudex-setup)
|
|
@@ -89,7 +89,7 @@ Most common gaps found: missing secrets protection, no deny rules, no mermaid di
|
|
|
89
89
|
design: none (0/2)
|
|
90
90
|
devops: none (0/4)
|
|
91
91
|
|
|
92
|
-
29/
|
|
92
|
+
29/84 checks passing
|
|
93
93
|
Next command: npx claudex-setup setup
|
|
94
94
|
```
|
|
95
95
|
|
|
@@ -105,7 +105,7 @@ That prints a compact top-3 quick scan with one clear next command.
|
|
|
105
105
|
|
|
106
106
|
| Command | What it does |
|
|
107
107
|
|---------|-------------|
|
|
108
|
-
| `npx claudex-setup` | **Discover** - Score 0-100 against
|
|
108
|
+
| `npx claudex-setup` | **Discover** - Score 0-100 against 84 checks |
|
|
109
109
|
| `npx claudex-setup discover` | **Discover** - Alias for audit mode |
|
|
110
110
|
| `npx claudex-setup setup` | **Starter** - Smart CLAUDE.md + hooks + commands + agents |
|
|
111
111
|
| `npx claudex-setup starter` | **Starter** - Alias for setup mode |
|
|
@@ -305,7 +305,7 @@ jobs:
|
|
|
305
305
|
runs-on: ubuntu-latest
|
|
306
306
|
steps:
|
|
307
307
|
- uses: actions/checkout@v4
|
|
308
|
-
- uses: DnaFin/claudex-setup@v1.
|
|
308
|
+
- uses: DnaFin/claudex-setup@v1.13.0
|
|
309
309
|
with:
|
|
310
310
|
threshold: 50
|
|
311
311
|
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claudex-setup",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.0",
|
|
4
4
|
"description": "Score your repo's Claude Code setup against 62 checks. See gaps, apply fixes selectively with rollback, govern hooks and permissions, and benchmark impact — without breaking existing config.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
package/src/domain-packs.js
CHANGED
|
@@ -231,6 +231,7 @@ function detectDomainPacks(ctx, stacks, assets = null) {
|
|
|
231
231
|
|
|
232
232
|
// Mobile detection
|
|
233
233
|
const isMobile = deps['react-native'] || deps.expo || deps.flutter ||
|
|
234
|
+
deps['@capacitor/core'] || deps['@ionic/angular'] || deps['@ionic/react'] ||
|
|
234
235
|
ctx.files.includes('Podfile') || ctx.files.includes('build.gradle') ||
|
|
235
236
|
ctx.files.includes('build.gradle.kts') || ctx.hasDir('ios') || ctx.hasDir('android');
|
|
236
237
|
if (isMobile) {
|
|
@@ -257,7 +258,9 @@ function detectDomainPacks(ctx, stacks, assets = null) {
|
|
|
257
258
|
|
|
258
259
|
// E-commerce detection
|
|
259
260
|
const isEcommerce = deps.stripe || deps['@stripe/stripe-js'] || deps.shopify || deps['@shopify/shopify-api'] ||
|
|
260
|
-
deps.woocommerce ||
|
|
261
|
+
deps.woocommerce || deps.paypal || deps['@paypal/react-paypal-js'] || deps.square || deps['@adyen/adyen-web'] ||
|
|
262
|
+
deps.medusa || deps.saleor ||
|
|
263
|
+
ctx.hasDir('products') || ctx.hasDir('checkout') || ctx.hasDir('cart');
|
|
261
264
|
if (isEcommerce) {
|
|
262
265
|
addMatch('ecommerce', [
|
|
263
266
|
'Detected e-commerce dependencies or storefront structure.',
|
|
@@ -269,6 +272,8 @@ function detectDomainPacks(ctx, stacks, assets = null) {
|
|
|
269
272
|
// AI/ML detection
|
|
270
273
|
const isAiMl = deps.langchain || deps['@langchain/core'] || deps.openai || deps.anthropic ||
|
|
271
274
|
deps['@anthropic-ai/sdk'] || deps.transformers || deps.torch || deps.tensorflow ||
|
|
275
|
+
deps.llamaindex || deps['llama-index'] || deps.crewai || deps.autogen ||
|
|
276
|
+
deps['@ai-sdk/core'] || deps.ollama ||
|
|
272
277
|
ctx.hasDir('chains') || ctx.hasDir('agents') || ctx.hasDir('models') || ctx.hasDir('prompts');
|
|
273
278
|
if (isAiMl && !hasData) {
|
|
274
279
|
addMatch('ai-ml', [
|
|
@@ -292,8 +297,9 @@ function detectDomainPacks(ctx, stacks, assets = null) {
|
|
|
292
297
|
|
|
293
298
|
// Design system detection
|
|
294
299
|
const isDesignSystem = deps.storybook || deps['@storybook/react'] || deps['@storybook/vue3'] ||
|
|
300
|
+
deps.chromatic || deps['style-dictionary'] || deps['@tokens-studio/sd-transforms'] ||
|
|
295
301
|
ctx.hasDir('tokens') || ctx.hasDir('design-tokens') ||
|
|
296
|
-
(ctx.hasDir('components') && ctx.hasDir('.storybook'));
|
|
302
|
+
ctx.hasDir('.storybook') || (ctx.hasDir('components') && ctx.hasDir('.storybook'));
|
|
297
303
|
if (isDesignSystem) {
|
|
298
304
|
addMatch('design-system', [
|
|
299
305
|
'Detected design system or component library signals.',
|
package/src/techniques.js
CHANGED
|
@@ -946,6 +946,310 @@ const TECHNIQUES = {
|
|
|
946
946
|
template: null
|
|
947
947
|
},
|
|
948
948
|
|
|
949
|
+
// --- New checks: testing depth ---
|
|
950
|
+
testCoverage: {
|
|
951
|
+
id: 2010,
|
|
952
|
+
name: 'Test coverage or strategy mentioned',
|
|
953
|
+
check: (ctx) => {
|
|
954
|
+
const md = ctx.fileContent('CLAUDE.md') || '';
|
|
955
|
+
return /coverage|test.*strateg|e2e|integration test|unit test/i.test(md);
|
|
956
|
+
},
|
|
957
|
+
impact: 'medium', rating: 3, category: 'quality',
|
|
958
|
+
fix: 'Mention your testing strategy in CLAUDE.md (unit, integration, E2E, coverage targets).',
|
|
959
|
+
template: null
|
|
960
|
+
},
|
|
961
|
+
|
|
962
|
+
// --- New checks: agent depth ---
|
|
963
|
+
agentHasAllowedTools: {
|
|
964
|
+
id: 2011,
|
|
965
|
+
name: 'At least one agent restricts tools',
|
|
966
|
+
check: (ctx) => {
|
|
967
|
+
if (!ctx.hasDir('.claude/agents')) return null;
|
|
968
|
+
const files = ctx.dirFiles('.claude/agents');
|
|
969
|
+
if (files.length === 0) return null;
|
|
970
|
+
for (const f of files) {
|
|
971
|
+
const content = ctx.fileContent(`.claude/agents/${f}`) || '';
|
|
972
|
+
if (/tools:\s*\[/.test(content)) return true;
|
|
973
|
+
}
|
|
974
|
+
return false;
|
|
975
|
+
},
|
|
976
|
+
impact: 'medium', rating: 3, category: 'workflow',
|
|
977
|
+
fix: 'Add a tools restriction to agent frontmatter (e.g. tools: [Read, Grep]) for safer delegation.',
|
|
978
|
+
template: null
|
|
979
|
+
},
|
|
980
|
+
|
|
981
|
+
// --- New checks: memory / auto-memory ---
|
|
982
|
+
autoMemoryAwareness: {
|
|
983
|
+
id: 2012,
|
|
984
|
+
name: 'Auto-memory or memory management mentioned',
|
|
985
|
+
check: (ctx) => {
|
|
986
|
+
const md = ctx.fileContent('CLAUDE.md') || '';
|
|
987
|
+
return /auto.?memory|memory.*manage|remember|persistent.*context/i.test(md);
|
|
988
|
+
},
|
|
989
|
+
impact: 'low', rating: 3, category: 'memory',
|
|
990
|
+
fix: 'Claude Code supports auto-memory for cross-session learning. Mention your memory strategy if relevant.',
|
|
991
|
+
template: null
|
|
992
|
+
},
|
|
993
|
+
|
|
994
|
+
// --- New checks: sandbox / security depth ---
|
|
995
|
+
sandboxAwareness: {
|
|
996
|
+
id: 2013,
|
|
997
|
+
name: 'Sandbox or isolation mentioned',
|
|
998
|
+
check: (ctx) => {
|
|
999
|
+
const md = ctx.fileContent('CLAUDE.md') || '';
|
|
1000
|
+
const settings = ctx.jsonFile('.claude/settings.json') || {};
|
|
1001
|
+
return /sandbox|isolat/i.test(md) || !!settings.sandbox;
|
|
1002
|
+
},
|
|
1003
|
+
impact: 'medium', rating: 3, category: 'security',
|
|
1004
|
+
fix: 'Claude Code supports sandboxed command execution. Consider enabling it for untrusted operations.',
|
|
1005
|
+
template: null
|
|
1006
|
+
},
|
|
1007
|
+
|
|
1008
|
+
denyRulesDepth: {
|
|
1009
|
+
id: 2014,
|
|
1010
|
+
name: 'Deny rules cover 3+ patterns',
|
|
1011
|
+
check: (ctx) => {
|
|
1012
|
+
const shared = ctx.jsonFile('.claude/settings.json');
|
|
1013
|
+
const local = ctx.jsonFile('.claude/settings.local.json');
|
|
1014
|
+
const deny = (shared?.permissions?.deny || []).concat(local?.permissions?.deny || []);
|
|
1015
|
+
return deny.length >= 3;
|
|
1016
|
+
},
|
|
1017
|
+
impact: 'high', rating: 4, category: 'security',
|
|
1018
|
+
fix: 'Add at least 3 deny rules: rm -rf, force-push, and .env reads. More patterns = safer Claude.',
|
|
1019
|
+
template: null
|
|
1020
|
+
},
|
|
1021
|
+
|
|
1022
|
+
// --- New checks: git depth ---
|
|
1023
|
+
gitAttributionDecision: {
|
|
1024
|
+
id: 2015,
|
|
1025
|
+
name: 'Git attribution configured',
|
|
1026
|
+
check: (ctx) => {
|
|
1027
|
+
const shared = ctx.jsonFile('.claude/settings.json') || {};
|
|
1028
|
+
const local = ctx.jsonFile('.claude/settings.local.json') || {};
|
|
1029
|
+
return shared.attribution !== undefined || local.attribution !== undefined ||
|
|
1030
|
+
shared.includeCoAuthoredBy !== undefined || local.includeCoAuthoredBy !== undefined;
|
|
1031
|
+
},
|
|
1032
|
+
impact: 'low', rating: 3, category: 'git',
|
|
1033
|
+
fix: 'Decide on git attribution: set attribution.commit or includeCoAuthoredBy in settings.',
|
|
1034
|
+
template: null
|
|
1035
|
+
},
|
|
1036
|
+
|
|
1037
|
+
// --- New checks: performance ---
|
|
1038
|
+
effortLevelConfigured: {
|
|
1039
|
+
id: 2016,
|
|
1040
|
+
name: 'Effort level or thinking configuration',
|
|
1041
|
+
check: (ctx) => {
|
|
1042
|
+
const md = ctx.fileContent('CLAUDE.md') || '';
|
|
1043
|
+
const shared = ctx.jsonFile('.claude/settings.json') || {};
|
|
1044
|
+
const local = ctx.jsonFile('.claude/settings.local.json') || {};
|
|
1045
|
+
return /effort|thinking/i.test(md) || shared.effortLevel || local.effortLevel ||
|
|
1046
|
+
shared.alwaysThinkingEnabled !== undefined || local.alwaysThinkingEnabled !== undefined;
|
|
1047
|
+
},
|
|
1048
|
+
impact: 'low', rating: 3, category: 'performance',
|
|
1049
|
+
fix: 'Configure effortLevel or mention thinking strategy in CLAUDE.md for task-appropriate reasoning depth.',
|
|
1050
|
+
template: null
|
|
1051
|
+
},
|
|
1052
|
+
|
|
1053
|
+
// --- New checks: workflow depth ---
|
|
1054
|
+
hasSnapshotHistory: {
|
|
1055
|
+
id: 2017,
|
|
1056
|
+
name: 'Audit snapshot history exists',
|
|
1057
|
+
check: (ctx) => {
|
|
1058
|
+
return !!ctx.fileContent('.claude/claudex-setup/snapshots/index.json');
|
|
1059
|
+
},
|
|
1060
|
+
impact: 'low', rating: 3, category: 'workflow',
|
|
1061
|
+
fix: 'Run `npx claudex-setup --snapshot` to start tracking your setup score over time.',
|
|
1062
|
+
template: null
|
|
1063
|
+
},
|
|
1064
|
+
|
|
1065
|
+
worktreeAwareness: {
|
|
1066
|
+
id: 2018,
|
|
1067
|
+
name: 'Worktree or parallel sessions mentioned',
|
|
1068
|
+
check: (ctx) => {
|
|
1069
|
+
const md = ctx.fileContent('CLAUDE.md') || '';
|
|
1070
|
+
const shared = ctx.jsonFile('.claude/settings.json') || {};
|
|
1071
|
+
return /worktree|parallel.*session/i.test(md) || !!shared.worktree;
|
|
1072
|
+
},
|
|
1073
|
+
impact: 'low', rating: 3, category: 'features',
|
|
1074
|
+
fix: 'Claude Code supports git worktrees for parallel isolated sessions. Mention if relevant.',
|
|
1075
|
+
template: null
|
|
1076
|
+
},
|
|
1077
|
+
|
|
1078
|
+
// --- New checks: prompting depth ---
|
|
1079
|
+
negativeInstructions: {
|
|
1080
|
+
id: 2019,
|
|
1081
|
+
name: 'CLAUDE.md includes "do not" instructions',
|
|
1082
|
+
check: (ctx) => {
|
|
1083
|
+
const md = ctx.fileContent('CLAUDE.md') || '';
|
|
1084
|
+
return /do not|don't|never|avoid|must not/i.test(md);
|
|
1085
|
+
},
|
|
1086
|
+
impact: 'medium', rating: 4, category: 'prompting',
|
|
1087
|
+
fix: 'Add explicit "do not" rules to CLAUDE.md. Negative constraints reduce common mistakes.',
|
|
1088
|
+
template: null
|
|
1089
|
+
},
|
|
1090
|
+
|
|
1091
|
+
outputStyleGuidance: {
|
|
1092
|
+
id: 2020,
|
|
1093
|
+
name: 'CLAUDE.md includes output or style guidance',
|
|
1094
|
+
check: (ctx) => {
|
|
1095
|
+
const md = ctx.fileContent('CLAUDE.md') || '';
|
|
1096
|
+
return /style|format|convention|naming|pattern|prefer/i.test(md);
|
|
1097
|
+
},
|
|
1098
|
+
impact: 'medium', rating: 3, category: 'prompting',
|
|
1099
|
+
fix: 'Add coding style and naming conventions to CLAUDE.md so Claude matches your project patterns.',
|
|
1100
|
+
template: null
|
|
1101
|
+
},
|
|
1102
|
+
|
|
1103
|
+
// --- New checks: devops depth ---
|
|
1104
|
+
githubActionsOrCI: {
|
|
1105
|
+
id: 2021,
|
|
1106
|
+
name: 'GitHub Actions or CI configured',
|
|
1107
|
+
check: (ctx) => {
|
|
1108
|
+
return ctx.hasDir('.github/workflows') || !!ctx.fileContent('.circleci/config.yml') ||
|
|
1109
|
+
!!ctx.fileContent('.gitlab-ci.yml') || !!ctx.fileContent('Jenkinsfile') ||
|
|
1110
|
+
!!ctx.fileContent('.travis.yml') || !!ctx.fileContent('bitbucket-pipelines.yml');
|
|
1111
|
+
},
|
|
1112
|
+
impact: 'medium', rating: 3, category: 'devops',
|
|
1113
|
+
fix: 'Add CI pipeline for automated testing. Claude Code has a GitHub Action for audit gates.',
|
|
1114
|
+
template: null
|
|
1115
|
+
},
|
|
1116
|
+
|
|
1117
|
+
// --- New checks: depth round 2 ---
|
|
1118
|
+
projectDescriptionInClaudeMd: {
|
|
1119
|
+
id: 2022,
|
|
1120
|
+
name: 'CLAUDE.md describes what the project does',
|
|
1121
|
+
check: (ctx) => {
|
|
1122
|
+
const md = ctx.fileContent('CLAUDE.md') || '';
|
|
1123
|
+
return /what.*does|overview|purpose|about|description|project.*is/i.test(md) && md.length > 100;
|
|
1124
|
+
},
|
|
1125
|
+
impact: 'high', rating: 4, category: 'memory',
|
|
1126
|
+
fix: 'Start CLAUDE.md with a clear project description. Claude needs to know what your project does.',
|
|
1127
|
+
template: null
|
|
1128
|
+
},
|
|
1129
|
+
|
|
1130
|
+
directoryStructureInClaudeMd: {
|
|
1131
|
+
id: 2023,
|
|
1132
|
+
name: 'CLAUDE.md documents directory structure',
|
|
1133
|
+
check: (ctx) => {
|
|
1134
|
+
const md = ctx.fileContent('CLAUDE.md') || '';
|
|
1135
|
+
return /src\/|app\/|lib\/|structure|director|folder/i.test(md);
|
|
1136
|
+
},
|
|
1137
|
+
impact: 'medium', rating: 4, category: 'memory',
|
|
1138
|
+
fix: 'Document your directory structure in CLAUDE.md so Claude navigates your codebase efficiently.',
|
|
1139
|
+
template: null
|
|
1140
|
+
},
|
|
1141
|
+
|
|
1142
|
+
multipleHookTypes: {
|
|
1143
|
+
id: 2024,
|
|
1144
|
+
name: '2+ hook event types configured',
|
|
1145
|
+
check: (ctx) => {
|
|
1146
|
+
const shared = ctx.jsonFile('.claude/settings.json') || {};
|
|
1147
|
+
const local = ctx.jsonFile('.claude/settings.local.json') || {};
|
|
1148
|
+
const hooks = { ...(shared.hooks || {}), ...(local.hooks || {}) };
|
|
1149
|
+
return Object.keys(hooks).length >= 2;
|
|
1150
|
+
},
|
|
1151
|
+
impact: 'medium', rating: 3, category: 'automation',
|
|
1152
|
+
fix: 'Add at least 2 hook types (e.g. PostToolUse for linting + SessionStart for initialization).',
|
|
1153
|
+
template: null
|
|
1154
|
+
},
|
|
1155
|
+
|
|
1156
|
+
stopFailureHook: {
|
|
1157
|
+
id: 2025,
|
|
1158
|
+
name: 'StopFailure or error handling hook',
|
|
1159
|
+
check: (ctx) => {
|
|
1160
|
+
const shared = ctx.jsonFile('.claude/settings.json') || {};
|
|
1161
|
+
const local = ctx.jsonFile('.claude/settings.local.json') || {};
|
|
1162
|
+
return !!(shared.hooks?.StopFailure || shared.hooks?.Stop || local.hooks?.StopFailure || local.hooks?.Stop);
|
|
1163
|
+
},
|
|
1164
|
+
impact: 'low', rating: 3, category: 'automation',
|
|
1165
|
+
fix: 'Add a StopFailure hook to log errors for debugging. Helps track why Claude stops unexpectedly.',
|
|
1166
|
+
template: null
|
|
1167
|
+
},
|
|
1168
|
+
|
|
1169
|
+
skillUsesPaths: {
|
|
1170
|
+
id: 2026,
|
|
1171
|
+
name: 'At least one skill uses paths for scoping',
|
|
1172
|
+
check: (ctx) => {
|
|
1173
|
+
if (!ctx.hasDir('.claude/skills')) return null;
|
|
1174
|
+
const files = ctx.dirFiles('.claude/skills');
|
|
1175
|
+
if (files.length === 0) return null;
|
|
1176
|
+
for (const f of files) {
|
|
1177
|
+
const content = ctx.fileContent(`.claude/skills/${f}`) || '';
|
|
1178
|
+
if (/paths:/i.test(content)) return true;
|
|
1179
|
+
}
|
|
1180
|
+
return false;
|
|
1181
|
+
},
|
|
1182
|
+
impact: 'low', rating: 3, category: 'workflow',
|
|
1183
|
+
fix: 'Add paths to skill frontmatter to scope when skills activate (e.g. paths: ["src/**/*.ts"]).',
|
|
1184
|
+
template: null
|
|
1185
|
+
},
|
|
1186
|
+
|
|
1187
|
+
mcpHasEnvConfig: {
|
|
1188
|
+
id: 2027,
|
|
1189
|
+
name: 'MCP servers have environment configuration',
|
|
1190
|
+
check: (ctx) => {
|
|
1191
|
+
const shared = ctx.jsonFile('.claude/settings.json') || {};
|
|
1192
|
+
const local = ctx.jsonFile('.claude/settings.local.json') || {};
|
|
1193
|
+
const mcp = ctx.jsonFile('.mcp.json') || {};
|
|
1194
|
+
const allServers = { ...(shared.mcpServers || {}), ...(local.mcpServers || {}), ...(mcp.mcpServers || {}) };
|
|
1195
|
+
if (Object.keys(allServers).length === 0) return null;
|
|
1196
|
+
return Object.values(allServers).some(s => s.env && Object.keys(s.env).length > 0);
|
|
1197
|
+
},
|
|
1198
|
+
impact: 'low', rating: 3, category: 'tools',
|
|
1199
|
+
fix: 'Configure environment variables for MCP servers that need authentication (e.g. GITHUB_TOKEN).',
|
|
1200
|
+
template: null
|
|
1201
|
+
},
|
|
1202
|
+
|
|
1203
|
+
gitIgnoreClaudeLocal: {
|
|
1204
|
+
id: 2028,
|
|
1205
|
+
name: '.gitignore excludes settings.local.json',
|
|
1206
|
+
check: (ctx) => {
|
|
1207
|
+
const gitignore = ctx.fileContent('.gitignore') || '';
|
|
1208
|
+
return /settings\.local\.json|settings\.local/i.test(gitignore);
|
|
1209
|
+
},
|
|
1210
|
+
impact: 'medium', rating: 4, category: 'git',
|
|
1211
|
+
fix: 'Add .claude/settings.local.json to .gitignore. Personal overrides should not be committed.',
|
|
1212
|
+
template: null
|
|
1213
|
+
},
|
|
1214
|
+
|
|
1215
|
+
envExampleExists: {
|
|
1216
|
+
id: 2029,
|
|
1217
|
+
name: '.env.example or .env.template exists',
|
|
1218
|
+
check: (ctx) => {
|
|
1219
|
+
return !!(ctx.fileContent('.env.example') || ctx.fileContent('.env.template') || ctx.fileContent('.env.sample'));
|
|
1220
|
+
},
|
|
1221
|
+
impact: 'low', rating: 3, category: 'hygiene',
|
|
1222
|
+
fix: 'Add .env.example so new developers know which environment variables are needed.',
|
|
1223
|
+
template: null
|
|
1224
|
+
},
|
|
1225
|
+
|
|
1226
|
+
packageJsonHasScripts: {
|
|
1227
|
+
id: 2030,
|
|
1228
|
+
name: 'package.json has dev/test/build scripts',
|
|
1229
|
+
check: (ctx) => {
|
|
1230
|
+
const pkg = ctx.jsonFile('package.json');
|
|
1231
|
+
if (!pkg) return null;
|
|
1232
|
+
const scripts = pkg.scripts || {};
|
|
1233
|
+
const has = (k) => !!scripts[k];
|
|
1234
|
+
return has('test') || has('dev') || has('build') || has('start');
|
|
1235
|
+
},
|
|
1236
|
+
impact: 'medium', rating: 3, category: 'hygiene',
|
|
1237
|
+
fix: 'Add scripts to package.json (test, dev, build). Claude uses these for verification.',
|
|
1238
|
+
template: null
|
|
1239
|
+
},
|
|
1240
|
+
|
|
1241
|
+
typeCheckingConfigured: {
|
|
1242
|
+
id: 2031,
|
|
1243
|
+
name: 'Type checking configured (TypeScript or similar)',
|
|
1244
|
+
check: (ctx) => {
|
|
1245
|
+
return !!(ctx.fileContent('tsconfig.json') || ctx.fileContent('jsconfig.json') ||
|
|
1246
|
+
ctx.fileContent('pyrightconfig.json') || ctx.fileContent('mypy.ini'));
|
|
1247
|
+
},
|
|
1248
|
+
impact: 'medium', rating: 3, category: 'quality',
|
|
1249
|
+
fix: 'Add type checking configuration. Type-safe code produces fewer Claude errors.',
|
|
1250
|
+
template: null
|
|
1251
|
+
},
|
|
1252
|
+
|
|
949
1253
|
noDeprecatedPatterns: {
|
|
950
1254
|
id: 2009,
|
|
951
1255
|
name: 'No deprecated patterns detected',
|
|
@@ -992,6 +1296,14 @@ const STACKS = {
|
|
|
992
1296
|
kubernetes: { files: ['k8s', 'kubernetes', 'helm'], content: {}, label: 'Kubernetes' },
|
|
993
1297
|
cpp: { files: ['CMakeLists.txt', 'Makefile', '.clang-format'], content: {}, label: 'C++' },
|
|
994
1298
|
bazel: { files: ['BUILD', 'WORKSPACE', 'BUILD.bazel', 'WORKSPACE.bazel'], content: {}, label: 'Bazel' },
|
|
1299
|
+
deno: { files: ['deno.json', 'deno.jsonc', 'deno.lock'], content: {}, label: 'Deno' },
|
|
1300
|
+
bun: { files: ['bun.lockb', 'bunfig.toml'], content: {}, label: 'Bun' },
|
|
1301
|
+
elixir: { files: ['mix.exs'], content: {}, label: 'Elixir' },
|
|
1302
|
+
astro: { files: ['astro.config.mjs', 'astro.config.ts'], content: {}, label: 'Astro' },
|
|
1303
|
+
remix: { files: ['remix.config.js', 'remix.config.ts'], content: {}, label: 'Remix' },
|
|
1304
|
+
nestjs: { files: ['nest-cli.json'], content: {}, label: 'NestJS' },
|
|
1305
|
+
laravel: { files: ['artisan'], content: {}, label: 'Laravel' },
|
|
1306
|
+
dotnet: { files: ['global.json', 'Directory.Build.props'], content: {}, label: '.NET' },
|
|
995
1307
|
};
|
|
996
1308
|
|
|
997
1309
|
module.exports = { TECHNIQUES, STACKS };
|