claudex-setup 1.15.1 → 1.16.1
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 +63 -28
- package/bin/cli.js +167 -7
- package/content/launch-posts.md +159 -93
- package/package.json +9 -3
- package/src/activity.js +214 -1
- package/src/analyze.js +23 -6
- package/src/audit.js +59 -14
- package/src/benchmark.js +24 -0
- package/src/context.js +119 -0
- package/src/deep-review.js +95 -68
- package/src/domain-packs.js +13 -4
- package/src/governance.js +9 -0
- package/src/index.js +4 -0
- package/src/interactive.js +8 -1
- package/src/mcp-packs.js +16 -0
- package/src/secret-patterns.js +30 -0
- package/src/techniques.js +22 -2
- package/src/watch.js +170 -42
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 85 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)
|
|
@@ -51,6 +51,12 @@ Tested on 4 real projects — not demos:
|
|
|
51
51
|
|
|
52
52
|
Most common gaps found: missing secrets protection, no deny rules, no mermaid diagram, no hooks in settings.
|
|
53
53
|
|
|
54
|
+
> Scores measured with claudex-setup@1.10.3 on 2026-04-03. Current npm latest: 1.16.0, so exact scores may differ slightly on the newer release.
|
|
55
|
+
>
|
|
56
|
+
> Canonical proof artifacts: [Index](https://github.com/DnaFin/claudex/blob/main/research/proof-artifacts/README.md) | [CLAUDEX trace](https://github.com/DnaFin/claudex/blob/main/research/proof-artifacts/claudex-self-dogfood-proof-trace-2026-04-03.md) | [VTCLE trace](https://github.com/DnaFin/claudex/blob/main/research/proof-artifacts/vtcle-proof-trace-2026-04-03.md) | [Social trace](https://github.com/DnaFin/claudex/blob/main/research/proof-artifacts/social-proof-trace-2026-04-03.md) | [Polymiro trace](https://github.com/DnaFin/claudex/blob/main/research/proof-artifacts/polymiro-proof-trace-2026-04-03.md)
|
|
57
|
+
>
|
|
58
|
+
> Narrative case studies: [VTCLE](https://github.com/DnaFin/claudex/blob/main/research/case-study-vtcle-2026-04-03.md) | [Social](https://github.com/DnaFin/claudex/blob/main/research/case-study-social-2026-04-03.md) | [Polymiro](https://github.com/DnaFin/claudex/blob/main/research/case-study-polymiro-2026-04-03.md)
|
|
59
|
+
|
|
54
60
|
## What You Get
|
|
55
61
|
|
|
56
62
|
```
|
|
@@ -89,7 +95,7 @@ Most common gaps found: missing secrets protection, no deny rules, no mermaid di
|
|
|
89
95
|
design: none (0/2)
|
|
90
96
|
devops: none (0/4)
|
|
91
97
|
|
|
92
|
-
29/
|
|
98
|
+
29/85 checks passing
|
|
93
99
|
Next command: npx claudex-setup setup
|
|
94
100
|
```
|
|
95
101
|
|
|
@@ -105,7 +111,7 @@ That prints a compact top-3 quick scan with one clear next command.
|
|
|
105
111
|
|
|
106
112
|
| Command | What it does |
|
|
107
113
|
|---------|-------------|
|
|
108
|
-
| `npx claudex-setup` | **Discover** - Score 0-100 against
|
|
114
|
+
| `npx claudex-setup` | **Discover** - Score 0-100 against 85 checks |
|
|
109
115
|
| `npx claudex-setup discover` | **Discover** - Alias for audit mode |
|
|
110
116
|
| `npx claudex-setup setup` | **Starter** - Smart CLAUDE.md + hooks + commands + agents |
|
|
111
117
|
| `npx claudex-setup starter` | **Starter** - Alias for setup mode |
|
|
@@ -117,11 +123,14 @@ That prints a compact top-3 quick scan with one clear next command.
|
|
|
117
123
|
| `npx claudex-setup governance` | **Governance** - Permission profiles, hook registry, policy packs, pilot kit |
|
|
118
124
|
| `npx claudex-setup benchmark` | **Benchmark** - Before/after evidence from an isolated temp copy |
|
|
119
125
|
| `npx claudex-setup interactive` | **Wizard** - Step-by-step guided tour |
|
|
120
|
-
| `npx claudex-setup watch` | **Watch** - Live monitoring with score delta |
|
|
126
|
+
| `npx claudex-setup watch` | **Watch** - Live monitoring with score delta and cross-platform directory fallback |
|
|
121
127
|
| `npx claudex-setup badge` | **Badge** - Generate shields.io badge for README |
|
|
122
|
-
| `npx claudex-setup
|
|
128
|
+
| `npx claudex-setup feedback` | **Feedback** - Record local recommendation outcomes or show outcome summary |
|
|
129
|
+
| `npx claudex-setup deep-review` | **Deep Review** - AI-powered config analysis (Claude Code or API key, selected config only) |
|
|
123
130
|
| `npx claudex-setup insights` | **Insights** - View community aggregate stats |
|
|
124
131
|
|
|
132
|
+
> Note: the `feedback` command is currently validated on the main working tree for the next release. If your installed npm build does not expose it yet, use the rest of the trust-first flow and pick it up on the next publish.
|
|
133
|
+
|
|
125
134
|
### Options
|
|
126
135
|
|
|
127
136
|
| Flag | Effect |
|
|
@@ -132,6 +141,10 @@ That prints a compact top-3 quick scan with one clear next command.
|
|
|
132
141
|
| `--only A,B` | Limit plan/apply to selected proposal ids |
|
|
133
142
|
| `--profile NAME` | Choose a permission profile for write-capable flows |
|
|
134
143
|
| `--mcp-pack A,B` | Merge named MCP packs into generated or patched settings |
|
|
144
|
+
| `--key NAME` | Recommendation key for `feedback` logging |
|
|
145
|
+
| `--status VALUE` | Outcome status: `accepted`, `rejected`, or `deferred` |
|
|
146
|
+
| `--effect VALUE` | Outcome effect: `positive`, `neutral`, or `negative` |
|
|
147
|
+
| `--score-delta N` | Optional observed score delta tied to the feedback event |
|
|
135
148
|
| `--snapshot` | Save a normalized artifact under `.claude/claudex-setup/snapshots/` |
|
|
136
149
|
| `--lite` | Show a short top-3 quick scan with one clear next command |
|
|
137
150
|
| `--dry-run` | Preview apply without writing files |
|
|
@@ -244,6 +257,19 @@ npx claudex-setup benchmark --snapshot
|
|
|
244
257
|
|
|
245
258
|
Snapshots are written to `.claude/claudex-setup/snapshots/` with a shared envelope and an `index.json` history file.
|
|
246
259
|
|
|
260
|
+
If you want a local-first recommendation loop, record what actually helped:
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
npx claudex-setup feedback --key permissionDeny --status accepted --effect positive --score-delta 12
|
|
264
|
+
npx claudex-setup feedback
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Feedback stays under `.claude/claudex-setup/outcomes/` and is used only as a local ranking signal. Recommendations with repeated positive outcomes get a measured boost; recommendations with repeated negative or rejected outcomes get pushed down.
|
|
268
|
+
|
|
269
|
+
If your currently installed npm build does not expose `feedback` yet, treat this as next-release behavior rather than current npm-latest behavior.
|
|
270
|
+
|
|
271
|
+
`watch` uses native `fs.watch` with recursive directory watches where the platform supports them, and an expanded directory fallback elsewhere. That keeps nested `.claude/` and `.github/` changes visible on Linux too, while staying zero-dependency. Native filesystem watch semantics can still be noisier on very large repos or network filesystems, so the command is best treated as fast local feedback rather than a CI-grade signal.
|
|
272
|
+
|
|
247
273
|
## Use Inside Claude Code
|
|
248
274
|
|
|
249
275
|
If you want the first Claude-native entry point, copy the shipped skill template into your repo.
|
|
@@ -259,39 +285,39 @@ If you are using `npx` only, copy the same file from the GitHub repo at `content
|
|
|
259
285
|
|
|
260
286
|
The skill runs `npx claudex-setup --json`, summarizes the score, shows the top next actions, and points to the right next command without applying changes.
|
|
261
287
|
|
|
262
|
-
##
|
|
288
|
+
## 85 Checks Across 14 Categories
|
|
263
289
|
|
|
264
290
|
The exact applicable count can be lower on a given repo because stack-specific checks are skipped when they do not apply.
|
|
265
291
|
|
|
266
292
|
| Category | Checks | Key items |
|
|
267
293
|
|----------|-------:|-----------|
|
|
268
|
-
| Memory | 8 | CLAUDE.md, architecture, conventions |
|
|
269
|
-
| Quality |
|
|
270
|
-
| Git Safety |
|
|
271
|
-
| Workflow |
|
|
272
|
-
| Security |
|
|
273
|
-
| Automation |
|
|
274
|
-
| Design |
|
|
275
|
-
| DevOps |
|
|
276
|
-
| Hygiene |
|
|
277
|
-
| Performance | 3 | context management, compaction |
|
|
278
|
-
| MCP |
|
|
279
|
-
| Prompting |
|
|
280
|
-
| Features | 2 |
|
|
281
|
-
| **Quality Deep** | **9** | **freshness, contradictions, deprecated patterns, maxTurns, $ARGUMENTS** |
|
|
294
|
+
| Memory | 8 | CLAUDE.md, architecture, conventions, imports |
|
|
295
|
+
| Quality | 6 | verification loops, test/lint/build, testing strategy |
|
|
296
|
+
| Git Safety | 6 | .gitignore, env protection, attribution, secret detection |
|
|
297
|
+
| Workflow | 12 | commands, skills, rules, agents, snapshots |
|
|
298
|
+
| Security | 7 | permissions, secrets, deny rules, sandbox awareness |
|
|
299
|
+
| Automation | 7 | hook coverage, specificity, session and error hooks |
|
|
300
|
+
| Design | 2 | frontend anti-slop guidance, styling signals |
|
|
301
|
+
| DevOps | 5 | Docker, CI, Terraform, infra signals |
|
|
302
|
+
| Hygiene | 8 | README, changelog, license, env example, version pinning |
|
|
303
|
+
| Performance | 3 | context management, compaction, effort level |
|
|
304
|
+
| MCP & Tools | 4 | servers, Context7, tool companions, env config |
|
|
305
|
+
| Prompting | 6 | constraints, examples, negative rules, style guidance |
|
|
306
|
+
| Features | 2 | channels, worktrees |
|
|
307
|
+
| **Quality Deep** | **9** | **freshness, contradictions, deprecated patterns, maxTurns, $ARGUMENTS, hook specificity** |
|
|
282
308
|
|
|
283
309
|
## Stack Detection
|
|
284
310
|
|
|
285
|
-
Auto-detects and tailors output for
|
|
311
|
+
Auto-detects and tailors output for 30 stacks:
|
|
286
312
|
|
|
287
313
|
| | |
|
|
288
314
|
|--|--|
|
|
289
|
-
| **Frontend** | React, Vue, Angular, Next.js, Svelte |
|
|
290
|
-
| **Backend** | Node.js, Python, Django, FastAPI |
|
|
291
|
-
| **Mobile** | Flutter, Swift, Kotlin |
|
|
292
|
-
| **Systems** | Rust, Go, Java, Ruby, C++, Bazel |
|
|
315
|
+
| **Frontend** | React, Vue, Angular, Next.js, Svelte, Astro |
|
|
316
|
+
| **Backend** | Node.js, Python, Django, FastAPI, Express, NestJS, Spring Boot |
|
|
317
|
+
| **Mobile** | React Native, Expo, Flutter, Swift, Kotlin |
|
|
318
|
+
| **Systems** | Rust, Go, Java, Ruby, C++, Bazel, Deno, Bun |
|
|
293
319
|
| **Language** | TypeScript |
|
|
294
|
-
| **Infra** | Docker, Terraform, Kubernetes |
|
|
320
|
+
| **Infra** | Docker, Terraform, Kubernetes, Wrangler |
|
|
295
321
|
|
|
296
322
|
## GitHub Action
|
|
297
323
|
|
|
@@ -305,7 +331,7 @@ jobs:
|
|
|
305
331
|
runs-on: ubuntu-latest
|
|
306
332
|
steps:
|
|
307
333
|
- uses: actions/checkout@v4
|
|
308
|
-
- uses: DnaFin/claudex-setup@v1.
|
|
334
|
+
- uses: DnaFin/claudex-setup@v1.16.0
|
|
309
335
|
with:
|
|
310
336
|
threshold: 50
|
|
311
337
|
```
|
|
@@ -331,6 +357,14 @@ npx claudex-setup deep-review
|
|
|
331
357
|
|
|
332
358
|
Claude reads your actual config and gives specific feedback: what's strong, what has issues, what's missing for your stack. This is an AI-assisted review, not a local heuristic audit. Your config goes to the Anthropic API only when you run this command; we do not receive it.
|
|
333
359
|
|
|
360
|
+
Deep-review trust boundary:
|
|
361
|
+
|
|
362
|
+
- sends only selected Claude-facing config surfaces: `CLAUDE.md`, settings, commands, agents, rules, hooks, and package scripts
|
|
363
|
+
- truncates large files before sending
|
|
364
|
+
- redacts embedded secrets before sending
|
|
365
|
+
- treats embedded repo text as untrusted review data, not as instructions to follow
|
|
366
|
+
- keeps all non-`deep-review` flows local
|
|
367
|
+
|
|
334
368
|
### Quality-Deep Checks
|
|
335
369
|
|
|
336
370
|
The v0.4.0 quality-deep checks catch what basic audits miss:
|
|
@@ -353,7 +387,8 @@ These checks evaluate **quality**, not just existence. A well-configured project
|
|
|
353
387
|
|
|
354
388
|
- **Zero dependencies** - nothing extra to audit
|
|
355
389
|
- **Core flows run locally** - audit, setup, augment, plan, apply, governance, and benchmark run on your machine
|
|
356
|
-
- **Deep review is opt-in** - only `deep-review` sends selected config to Anthropic for analysis
|
|
390
|
+
- **Deep review is opt-in** - only `deep-review` sends selected config to Anthropic or your local Claude Code session for analysis
|
|
391
|
+
- **Deep review sanitizes before send** - selected snippets are truncated, secret-redacted, and wrapped as untrusted review data
|
|
357
392
|
- **Benchmark uses an isolated temp copy** - your live repo is not touched
|
|
358
393
|
- **Anonymous insights** - opt-in, no PII, no file contents (enable with `--insights`)
|
|
359
394
|
- **MIT Licensed** - use anywhere
|
package/bin/cli.js
CHANGED
|
@@ -6,7 +6,7 @@ const { analyzeProject, printAnalysis, exportMarkdown } = require('../src/analyz
|
|
|
6
6
|
const { buildProposalBundle, printProposalBundle, writePlanFile, applyProposalBundle, printApplyResult } = require('../src/plans');
|
|
7
7
|
const { getGovernanceSummary, printGovernanceSummary, ensureWritableProfile, renderGovernanceMarkdown } = require('../src/governance');
|
|
8
8
|
const { runBenchmark, printBenchmark, writeBenchmarkReport } = require('../src/benchmark');
|
|
9
|
-
const { writeSnapshotArtifact } = require('../src/activity');
|
|
9
|
+
const { writeSnapshotArtifact, recordRecommendationOutcome, formatRecommendationOutcomeSummary, getRecommendationOutcomeSummary } = require('../src/activity');
|
|
10
10
|
const { version } = require('../package.json');
|
|
11
11
|
|
|
12
12
|
const args = process.argv.slice(2);
|
|
@@ -18,8 +18,9 @@ const COMMAND_ALIASES = {
|
|
|
18
18
|
starter: 'setup',
|
|
19
19
|
suggest: 'suggest-only',
|
|
20
20
|
gov: 'governance',
|
|
21
|
+
outcome: 'feedback',
|
|
21
22
|
};
|
|
22
|
-
const KNOWN_COMMANDS = ['audit', 'setup', 'augment', 'suggest-only', 'plan', 'apply', 'governance', 'benchmark', 'deep-review', 'interactive', 'watch', 'badge', 'insights', 'history', 'compare', 'trend', 'help', 'version'];
|
|
23
|
+
const KNOWN_COMMANDS = ['audit', 'setup', 'augment', 'suggest-only', 'plan', 'apply', 'governance', 'benchmark', 'deep-review', 'interactive', 'watch', 'badge', 'insights', 'history', 'compare', 'trend', 'scan', 'feedback', 'help', 'version'];
|
|
23
24
|
|
|
24
25
|
function levenshtein(a, b) {
|
|
25
26
|
const matrix = Array.from({ length: a.length + 1 }, () => Array(b.length + 1).fill(0));
|
|
@@ -62,12 +63,19 @@ function parseArgs(rawArgs) {
|
|
|
62
63
|
let profile = 'safe-write';
|
|
63
64
|
let mcpPacks = [];
|
|
64
65
|
let requireChecks = [];
|
|
66
|
+
let feedbackKey = null;
|
|
67
|
+
let feedbackStatus = null;
|
|
68
|
+
let feedbackEffect = null;
|
|
69
|
+
let feedbackNotes = null;
|
|
70
|
+
let feedbackSource = null;
|
|
71
|
+
let feedbackScoreDelta = null;
|
|
65
72
|
let commandSet = false;
|
|
73
|
+
let extraArgs = [];
|
|
66
74
|
|
|
67
75
|
for (let i = 0; i < rawArgs.length; i++) {
|
|
68
76
|
const arg = rawArgs[i];
|
|
69
77
|
|
|
70
|
-
if (arg === '--threshold' || arg === '--out' || arg === '--plan' || arg === '--only' || arg === '--profile' || arg === '--mcp-pack' || arg === '--require') {
|
|
78
|
+
if (arg === '--threshold' || arg === '--out' || arg === '--plan' || arg === '--only' || arg === '--profile' || arg === '--mcp-pack' || arg === '--require' || arg === '--key' || arg === '--status' || arg === '--effect' || arg === '--notes' || arg === '--source' || arg === '--score-delta') {
|
|
71
79
|
const value = rawArgs[i + 1];
|
|
72
80
|
if (!value || value.startsWith('--')) {
|
|
73
81
|
throw new Error(`${arg} requires a value`);
|
|
@@ -79,6 +87,12 @@ function parseArgs(rawArgs) {
|
|
|
79
87
|
if (arg === '--profile') profile = value.trim();
|
|
80
88
|
if (arg === '--mcp-pack') mcpPacks = value.split(',').map(item => item.trim()).filter(Boolean);
|
|
81
89
|
if (arg === '--require') requireChecks = value.split(',').map(item => item.trim()).filter(Boolean);
|
|
90
|
+
if (arg === '--key') feedbackKey = value.trim();
|
|
91
|
+
if (arg === '--status') feedbackStatus = value.trim();
|
|
92
|
+
if (arg === '--effect') feedbackEffect = value.trim();
|
|
93
|
+
if (arg === '--notes') feedbackNotes = value;
|
|
94
|
+
if (arg === '--source') feedbackSource = value.trim();
|
|
95
|
+
if (arg === '--score-delta') feedbackScoreDelta = value.trim();
|
|
82
96
|
i++;
|
|
83
97
|
continue;
|
|
84
98
|
}
|
|
@@ -118,6 +132,36 @@ function parseArgs(rawArgs) {
|
|
|
118
132
|
continue;
|
|
119
133
|
}
|
|
120
134
|
|
|
135
|
+
if (arg.startsWith('--key=')) {
|
|
136
|
+
feedbackKey = arg.split('=').slice(1).join('=').trim();
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (arg.startsWith('--status=')) {
|
|
141
|
+
feedbackStatus = arg.split('=').slice(1).join('=').trim();
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (arg.startsWith('--effect=')) {
|
|
146
|
+
feedbackEffect = arg.split('=').slice(1).join('=').trim();
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (arg.startsWith('--notes=')) {
|
|
151
|
+
feedbackNotes = arg.split('=').slice(1).join('=');
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (arg.startsWith('--source=')) {
|
|
156
|
+
feedbackSource = arg.split('=').slice(1).join('=').trim();
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (arg.startsWith('--score-delta=')) {
|
|
161
|
+
feedbackScoreDelta = arg.split('=').slice(1).join('=').trim();
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
|
|
121
165
|
if (arg.startsWith('--')) {
|
|
122
166
|
flags.push(arg);
|
|
123
167
|
continue;
|
|
@@ -126,12 +170,14 @@ function parseArgs(rawArgs) {
|
|
|
126
170
|
if (!commandSet) {
|
|
127
171
|
command = arg;
|
|
128
172
|
commandSet = true;
|
|
173
|
+
} else {
|
|
174
|
+
extraArgs.push(arg);
|
|
129
175
|
}
|
|
130
176
|
}
|
|
131
177
|
|
|
132
178
|
const normalizedCommand = COMMAND_ALIASES[command] || command;
|
|
133
179
|
|
|
134
|
-
return { flags, command, normalizedCommand, threshold, out, planFile, only, profile, mcpPacks, requireChecks };
|
|
180
|
+
return { flags, command, normalizedCommand, threshold, out, planFile, only, profile, mcpPacks, requireChecks, feedbackKey, feedbackStatus, feedbackEffect, feedbackNotes, feedbackSource, feedbackScoreDelta, extraArgs };
|
|
135
181
|
}
|
|
136
182
|
|
|
137
183
|
const HELP = `
|
|
@@ -155,13 +201,17 @@ const HELP = `
|
|
|
155
201
|
npx claudex-setup compare Compare latest vs previous snapshot
|
|
156
202
|
npx claudex-setup trend --out r.md Export trend report as markdown
|
|
157
203
|
|
|
204
|
+
Multi-repo:
|
|
205
|
+
npx claudex-setup scan dir1 dir2 Compare multiple repos side-by-side
|
|
206
|
+
|
|
158
207
|
Advanced:
|
|
159
208
|
npx claudex-setup governance Permission profiles, hooks, policy packs
|
|
160
209
|
npx claudex-setup benchmark Before/after in isolated temp copy
|
|
161
210
|
npx claudex-setup deep-review AI-powered config review (opt-in, uses API)
|
|
162
211
|
npx claudex-setup interactive Step-by-step guided wizard
|
|
163
|
-
npx claudex-setup watch Live monitoring on config changes
|
|
212
|
+
npx claudex-setup watch Live monitoring on config changes with cross-platform watch fallback
|
|
164
213
|
npx claudex-setup badge Generate shields.io badge markdown
|
|
214
|
+
npx claudex-setup feedback Record recommendation outcomes or show local outcome summary
|
|
165
215
|
|
|
166
216
|
Options:
|
|
167
217
|
--threshold N Exit with code 1 if score is below N (useful for CI)
|
|
@@ -171,6 +221,12 @@ const HELP = `
|
|
|
171
221
|
--only A,B Limit plan/apply to selected proposal ids or technique keys
|
|
172
222
|
--profile NAME Choose permission profile (read-only, suggest-only, safe-write, power-user, internal-research)
|
|
173
223
|
--mcp-pack A,B Merge named MCP packs into generated settings (e.g. context7-docs,next-devtools)
|
|
224
|
+
--key NAME Recommendation key for feedback logging (e.g. permissionDeny)
|
|
225
|
+
--status VALUE Feedback status: accepted, rejected, deferred
|
|
226
|
+
--effect VALUE Feedback effect: positive, neutral, negative
|
|
227
|
+
--notes TEXT Short notes to store with a feedback event
|
|
228
|
+
--source NAME Source label for feedback event (default: manual-cli)
|
|
229
|
+
--score-delta N Optional observed score delta tied to the outcome
|
|
174
230
|
--snapshot Save a normalized snapshot artifact under .claude/claudex-setup/snapshots/
|
|
175
231
|
--lite Show a short top-3 quick scan with one clear next command
|
|
176
232
|
--dry-run Preview apply without writing files
|
|
@@ -197,6 +253,8 @@ const HELP = `
|
|
|
197
253
|
npx claudex-setup apply --profile power-user --only claude-md,hooks
|
|
198
254
|
npx claudex-setup governance --json
|
|
199
255
|
npx claudex-setup benchmark --out benchmark.md
|
|
256
|
+
npx claudex-setup feedback
|
|
257
|
+
npx claudex-setup feedback --key permissionDeny --status accepted --effect positive --score-delta 12
|
|
200
258
|
npx claudex-setup --json --threshold 60
|
|
201
259
|
npx claudex-setup setup --auto
|
|
202
260
|
npx claudex-setup interactive
|
|
@@ -249,7 +307,7 @@ async function main() {
|
|
|
249
307
|
process.exit(1);
|
|
250
308
|
}
|
|
251
309
|
|
|
252
|
-
if (options.require && normalizedCommand !== 'audit' && !['audit', 'discover'].includes(command)) {
|
|
310
|
+
if (options.require && options.require.length > 0 && normalizedCommand !== 'audit' && !['audit', 'discover'].includes(command)) {
|
|
253
311
|
console.error(`\n Warning: --require is only supported with the audit command. Ignoring for '${normalizedCommand}'.\n`);
|
|
254
312
|
}
|
|
255
313
|
|
|
@@ -279,7 +337,74 @@ async function main() {
|
|
|
279
337
|
}
|
|
280
338
|
|
|
281
339
|
try {
|
|
282
|
-
if (normalizedCommand === '
|
|
340
|
+
if (normalizedCommand === 'scan') {
|
|
341
|
+
const scanDirs = parsed.extraArgs;
|
|
342
|
+
if (scanDirs.length === 0) {
|
|
343
|
+
console.error('\n Error: scan requires at least one directory argument.');
|
|
344
|
+
console.error(' Usage: npx claudex-setup scan dir1 dir2 dir3\n');
|
|
345
|
+
process.exit(1);
|
|
346
|
+
}
|
|
347
|
+
const fs = require('fs');
|
|
348
|
+
const pathMod = require('path');
|
|
349
|
+
const rows = [];
|
|
350
|
+
for (const rawDir of scanDirs) {
|
|
351
|
+
const dir = pathMod.resolve(rawDir);
|
|
352
|
+
if (!fs.existsSync(dir)) {
|
|
353
|
+
rows.push({ name: pathMod.basename(rawDir), dir: rawDir, score: null, passed: '-', failed: '-', suggested: '-', error: 'directory not found' });
|
|
354
|
+
continue;
|
|
355
|
+
}
|
|
356
|
+
try {
|
|
357
|
+
const result = await audit({ dir, silent: true });
|
|
358
|
+
rows.push({
|
|
359
|
+
name: pathMod.basename(dir),
|
|
360
|
+
dir: rawDir,
|
|
361
|
+
score: result.score,
|
|
362
|
+
passed: result.passed,
|
|
363
|
+
failed: result.failed,
|
|
364
|
+
suggested: result.suggestedNextCommand || '-',
|
|
365
|
+
error: null,
|
|
366
|
+
});
|
|
367
|
+
} catch (err) {
|
|
368
|
+
rows.push({ name: pathMod.basename(dir), dir: rawDir, score: null, passed: '-', failed: '-', suggested: '-', error: err.message });
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
if (options.json) {
|
|
373
|
+
console.log(JSON.stringify(rows, null, 2));
|
|
374
|
+
} else {
|
|
375
|
+
// Find weakest
|
|
376
|
+
const validRows = rows.filter(r => r.score !== null);
|
|
377
|
+
const minScore = validRows.length > 0 ? Math.min(...validRows.map(r => r.score)) : null;
|
|
378
|
+
const weakest = validRows.length > 1 && validRows.filter(r => r.score > minScore).length > 0
|
|
379
|
+
? validRows.find(r => r.score === minScore)
|
|
380
|
+
: null;
|
|
381
|
+
|
|
382
|
+
console.log('');
|
|
383
|
+
console.log('\x1b[1m claudex-setup multi-repo scan\x1b[0m');
|
|
384
|
+
console.log('\x1b[2m ═══════════════════════════════════════\x1b[0m');
|
|
385
|
+
console.log('');
|
|
386
|
+
|
|
387
|
+
// Table header
|
|
388
|
+
const nameW = Math.max(8, ...rows.map(r => r.name.length)) + 2;
|
|
389
|
+
const header = ` ${'Project'.padEnd(nameW)} ${'Score'.padStart(5)} ${'Pass'.padStart(4)} ${'Fail'.padStart(4)} Suggested Command`;
|
|
390
|
+
console.log('\x1b[1m' + header + '\x1b[0m');
|
|
391
|
+
console.log(' ' + '─'.repeat(header.trim().length));
|
|
392
|
+
|
|
393
|
+
for (const row of rows) {
|
|
394
|
+
if (row.error) {
|
|
395
|
+
console.log(` ${row.name.padEnd(nameW)} \x1b[31m${('ERR').padStart(5)}\x1b[0m ${String(row.passed).padStart(4)} ${String(row.failed).padStart(4)} ${row.error}`);
|
|
396
|
+
continue;
|
|
397
|
+
}
|
|
398
|
+
const isWeak = weakest && row.name === weakest.name && row.dir === weakest.dir;
|
|
399
|
+
const scoreColor = row.score >= 70 ? '\x1b[32m' : row.score >= 40 ? '\x1b[33m' : '\x1b[31m';
|
|
400
|
+
const prefix = isWeak ? '\x1b[31m⚠ ' : ' ';
|
|
401
|
+
const suffix = isWeak ? ' ← weakest\x1b[0m' : '';
|
|
402
|
+
console.log(`${prefix}${row.name.padEnd(nameW)} ${scoreColor}${String(row.score).padStart(5)}\x1b[0m ${String(row.passed).padStart(4)} ${String(row.failed).padStart(4)} ${row.suggested}${suffix}`);
|
|
403
|
+
}
|
|
404
|
+
console.log('');
|
|
405
|
+
}
|
|
406
|
+
process.exit(0);
|
|
407
|
+
} else if (normalizedCommand === 'history') {
|
|
283
408
|
const { formatHistory } = require('../src/activity');
|
|
284
409
|
console.log('');
|
|
285
410
|
console.log(formatHistory(options.dir));
|
|
@@ -366,6 +491,41 @@ async function main() {
|
|
|
366
491
|
console.log(' Insights request timed out. Run locally: npx claudex-setup');
|
|
367
492
|
});
|
|
368
493
|
return; // keep process alive for http
|
|
494
|
+
} else if (normalizedCommand === 'feedback') {
|
|
495
|
+
if (parsed.feedbackKey) {
|
|
496
|
+
if (!parsed.feedbackStatus) {
|
|
497
|
+
console.error('\n Error: feedback logging requires --status when --key is provided.\n');
|
|
498
|
+
process.exit(1);
|
|
499
|
+
}
|
|
500
|
+
const artifact = recordRecommendationOutcome(options.dir, {
|
|
501
|
+
key: parsed.feedbackKey,
|
|
502
|
+
status: parsed.feedbackStatus,
|
|
503
|
+
effect: parsed.feedbackEffect || 'neutral',
|
|
504
|
+
notes: parsed.feedbackNotes || '',
|
|
505
|
+
source: parsed.feedbackSource || 'manual-cli',
|
|
506
|
+
scoreDelta: parsed.feedbackScoreDelta !== null ? Number(parsed.feedbackScoreDelta) : null,
|
|
507
|
+
});
|
|
508
|
+
const summary = getRecommendationOutcomeSummary(options.dir);
|
|
509
|
+
if (options.json) {
|
|
510
|
+
console.log(JSON.stringify({ artifact, summary }, null, 2));
|
|
511
|
+
} else {
|
|
512
|
+
console.log('');
|
|
513
|
+
console.log(` Feedback recorded for ${parsed.feedbackKey}`);
|
|
514
|
+
console.log(` Artifact: ${artifact.relativePath}`);
|
|
515
|
+
console.log('');
|
|
516
|
+
console.log(formatRecommendationOutcomeSummary(options.dir));
|
|
517
|
+
console.log('');
|
|
518
|
+
}
|
|
519
|
+
} else {
|
|
520
|
+
if (options.json) {
|
|
521
|
+
console.log(JSON.stringify(getRecommendationOutcomeSummary(options.dir), null, 2));
|
|
522
|
+
} else {
|
|
523
|
+
console.log('');
|
|
524
|
+
console.log(formatRecommendationOutcomeSummary(options.dir));
|
|
525
|
+
console.log('');
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
process.exit(0);
|
|
369
529
|
} else if (normalizedCommand === 'augment' || normalizedCommand === 'suggest-only') {
|
|
370
530
|
const report = await analyzeProject({ ...options, mode: normalizedCommand });
|
|
371
531
|
const snapshot = options.snapshot ? writeSnapshotArtifact(options.dir, normalizedCommand, report, {
|