claudex-setup 1.10.2 → 1.11.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 +36 -0
- package/README.md +83 -5
- package/bin/cli.js +146 -23
- package/content/case-study-template.md +91 -0
- package/content/claims-governance.md +37 -0
- package/content/claude-code/audit-repo/SKILL.md +20 -0
- package/content/claude-native-integration.md +64 -0
- package/content/devto-article.json +9 -0
- package/content/launch-posts.md +160 -0
- package/content/pilot-rollout-kit.md +30 -0
- package/content/release-checklist.md +31 -0
- package/package.json +3 -2
- package/src/activity.js +242 -1
- package/src/analyze.js +18 -3
- package/src/audit.js +157 -10
- package/src/claudex-sync.json +2 -6
- package/src/governance.js +69 -0
- package/src/insights.js +3 -2
- package/src/techniques.js +16 -13
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Using claudex-setup from inside Claude Code
|
|
2
|
+
|
|
3
|
+
## Skill: Audit Repo
|
|
4
|
+
|
|
5
|
+
Add this to `.claude/skills/audit-repo.md` in any project:
|
|
6
|
+
|
|
7
|
+
```markdown
|
|
8
|
+
---
|
|
9
|
+
name: audit-repo
|
|
10
|
+
description: Run claudex-setup audit on the current project and show score + top gaps
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
Run `npx claudex-setup --json` on the current project directory.
|
|
14
|
+
Parse the JSON output and present:
|
|
15
|
+
1. Score X/100
|
|
16
|
+
2. Top 3 critical/high gaps with fix descriptions
|
|
17
|
+
3. Suggest next command based on score
|
|
18
|
+
|
|
19
|
+
$ARGUMENTS — optional: --lite for quick scan
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Hook: Auto-audit on SessionStart
|
|
23
|
+
|
|
24
|
+
Add to `.claude/settings.json`:
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"hooks": {
|
|
29
|
+
"SessionStart": [
|
|
30
|
+
{
|
|
31
|
+
"hooks": [
|
|
32
|
+
{
|
|
33
|
+
"type": "command",
|
|
34
|
+
"command": "node -e \"try{const r=require('child_process').execSync('npx claudex-setup --json 2>/dev/null',{timeout:15000}).toString();const d=JSON.parse(r);if(d.score<50)console.log(JSON.stringify({systemMessage:'⚠️ Claude Code setup score: '+d.score+'/100. Consider running: npx claudex-setup --lite'}))}catch(e){console.log('{}')}\"",
|
|
35
|
+
"timeout": 20,
|
|
36
|
+
"statusMessage": "Checking Claude Code setup..."
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Agent: Setup Advisor
|
|
46
|
+
|
|
47
|
+
Add to `.claude/agents/setup-advisor.md`:
|
|
48
|
+
|
|
49
|
+
```markdown
|
|
50
|
+
---
|
|
51
|
+
name: setup-advisor
|
|
52
|
+
description: Analyzes Claude Code setup and recommends improvements
|
|
53
|
+
tools: [Bash, Read, Glob, Grep]
|
|
54
|
+
model: haiku
|
|
55
|
+
maxTurns: 10
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
You are a Claude Code setup advisor.
|
|
59
|
+
|
|
60
|
+
1. Run `npx claudex-setup augment --json` on the current project
|
|
61
|
+
2. Analyze gaps and strengths
|
|
62
|
+
3. Recommend top 5 improvements with rationale
|
|
63
|
+
4. If user approves, guide them through applying changes
|
|
64
|
+
```
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"article": {
|
|
3
|
+
"title": "Your Claude Code project scores 10/100. Here's how to fix it in 60 seconds.",
|
|
4
|
+
"published": false,
|
|
5
|
+
"tags": ["claude", "ai", "productivity", "devtools"],
|
|
6
|
+
"series": "Claude Code Optimization",
|
|
7
|
+
"body_markdown": "After cataloging **1,107 Claude Code entries** and verifying **948 with real evidence**, I found that most projects use barely 10% of what's available.\n\nI built a CLI that scores your project:\n\n```bash\nnpx claudex-setup\n```\n\nMost projects score **10-20 out of 100**. After running setup, they jump to **70+**.\n\n## The Top 10 Things You're Missing\n\n### 1. CLAUDE.md (Critical)\n\nClaude reads this file at the start of every session. Without it, Claude doesn't know your build commands, code style, or project rules.\n\nOur tool generates a smart CLAUDE.md that detects your framework, TypeScript config, and creates a Mermaid architecture diagram automatically.\n\n### 2. Mermaid Architecture Diagrams (73% Token Savings)\n\nA Mermaid diagram in CLAUDE.md gives Claude your project structure in a fraction of the tokens that prose requires.\n\n### 3. Hooks > CLAUDE.md Rules (100% vs 80%)\n\nCLAUDE.md instructions are advisory (~80% compliance). Hooks are deterministic (100%). Auto-lint after every edit. Every time.\n\n### 4. Custom Commands\n\nStop typing the same prompts. Create `/test`, `/deploy`, `/review` in `.claude/commands/`.\n\n### 5. Verification Loops (The #1 Best Practice)\n\n> *This is the single highest-leverage thing you can do.* — Anthropic Best Practices\n\nClaude performs dramatically better when it can verify its own work.\n\n### 6. XML Tags (30% Quality Boost)\n\nUse `<constraints>`, `<validation>` in CLAUDE.md for unambiguous instructions.\n\n### 7. Secrets Protection\n\nClaude Code loads `.env` automatically. Add deny rules to prevent reading sensitive files.\n\n### 8. /security-review\n\nBuilt-in OWASP Top 10 scanning. Most people don't know this command exists.\n\n### 9. Custom Agents\n\nSpecialized subagents: security-reviewer, test-writer in `.claude/agents/`.\n\n### 10. Skills (On-Demand Knowledge)\n\nReusable skills package expertise that Claude can load on demand.\n\n## Try It Now\n\n```bash\nnpx claudex-setup --lite # Quick scan\nnpx claudex-setup # Full audit\nnpx claudex-setup --snapshot # Save evidence artifact\nnpx claudex-setup governance --out governance.md\n```\n\nFree, open source, zero dependencies.\n\n**GitHub:** [github.com/DnaFin/claudex-setup](https://github.com/DnaFin/claudex-setup)\n**npm:** [npmjs.com/package/claudex-setup](https://www.npmjs.com/package/claudex-setup)\n\n---\n\n*Built from a research catalog of 1,107 Claude Code entries, 948 verified with evidence.*"
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# Launch Posts — Ready to Publish
|
|
2
|
+
|
|
3
|
+
## Post 1: Reddit r/ClaudeAI
|
|
4
|
+
|
|
5
|
+
**Title:** I built a tool that audits your project for Claude Code optimization — scores you 0-100
|
|
6
|
+
|
|
7
|
+
**Body:**
|
|
8
|
+
After cataloging 1,107 Claude Code entries and verifying 948 of them with evidence, I built a CLI that checks if your project is actually set up to get the most out of Claude Code.
|
|
9
|
+
|
|
10
|
+
Most projects score around 10-20/100. After running setup, they jump to 70+.
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
npx claudex-setup
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
It checks for: CLAUDE.md, hooks, custom commands, skills, agents, Mermaid diagrams, XML tags, path rules, MCP config, permissions, and more.
|
|
17
|
+
|
|
18
|
+
Then `npx claudex-setup setup` auto-creates everything that's missing, tailored to your stack (React, Python, TypeScript, etc).
|
|
19
|
+
|
|
20
|
+
Zero dependencies. No API keys. Runs entirely local.
|
|
21
|
+
|
|
22
|
+
GitHub: https://github.com/DnaFin/claudex-setup
|
|
23
|
+
|
|
24
|
+
Would love feedback!
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Post 2: Reddit r/ChatGPTCoding
|
|
29
|
+
|
|
30
|
+
**Title:** Your Claude Code project is probably running at 10% efficiency. Here's how to check.
|
|
31
|
+
|
|
32
|
+
**Body:**
|
|
33
|
+
I spent weeks cataloging every Claude Code feature, technique, and best practice — 1,107 total, 948 verified with real evidence.
|
|
34
|
+
|
|
35
|
+
Turns out most projects are missing basic stuff that makes a huge difference:
|
|
36
|
+
- No CLAUDE.md (Claude doesn't know your project conventions)
|
|
37
|
+
- No hooks (no auto-lint, no auto-test)
|
|
38
|
+
- No custom commands (repeating the same prompts manually)
|
|
39
|
+
- No Mermaid diagrams (wasting 73% more tokens on prose descriptions)
|
|
40
|
+
|
|
41
|
+
Built a quick checker:
|
|
42
|
+
```
|
|
43
|
+
npx claudex-setup
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Scores your project 0-100, tells you exactly what to fix, and can auto-apply everything.
|
|
47
|
+
|
|
48
|
+
Free, open source, zero dependencies: https://github.com/DnaFin/claudex-setup
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Post 3: Dev.to Article
|
|
53
|
+
|
|
54
|
+
**Title:** 1,107 Claude Code Entries: What I Learned Building the Most Comprehensive Catalog
|
|
55
|
+
|
|
56
|
+
**Body (excerpt):**
|
|
57
|
+
I set out to catalog every single Claude Code capability, technique, and best practice. After repeated research cycles, I have 1,107 entries — 948 verified with real evidence.
|
|
58
|
+
|
|
59
|
+
Here are the top 10 things most developers are missing:
|
|
60
|
+
|
|
61
|
+
1. **CLAUDE.md** — Claude reads this at the start of every session. Without it, Claude doesn't know your build commands, code style, or project rules.
|
|
62
|
+
|
|
63
|
+
2. **Mermaid diagrams** — A Mermaid architecture diagram saves 73% tokens compared to describing your project in prose.
|
|
64
|
+
|
|
65
|
+
3. **Hooks** — Auto-lint after every edit. Auto-test before every commit. Hooks fire 100% of the time, CLAUDE.md rules fire ~80%.
|
|
66
|
+
|
|
67
|
+
4. **Custom commands** — `/test`, `/deploy`, `/review` — package your repeated workflows.
|
|
68
|
+
|
|
69
|
+
5. **Verification loops** — Tell Claude how to verify its own work. Include test commands in CLAUDE.md.
|
|
70
|
+
|
|
71
|
+
6. **Path-specific rules** — Different conventions for frontend vs backend files.
|
|
72
|
+
|
|
73
|
+
7. **XML tags** — `<constraints>`, `<validation>` in CLAUDE.md = unambiguous instructions.
|
|
74
|
+
|
|
75
|
+
8. **Custom agents** — Security reviewer, test writer — specialized subagents for focused tasks.
|
|
76
|
+
|
|
77
|
+
9. **Skills** — Domain-specific workflows that load on demand, not every session.
|
|
78
|
+
|
|
79
|
+
10. **MCP servers** — Connect Claude to your database, ticket system, Slack.
|
|
80
|
+
|
|
81
|
+
I packaged this into a CLI that checks your project:
|
|
82
|
+
```
|
|
83
|
+
npx claudex-setup
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Full catalog: https://github.com/DnaFin/claudex-setup
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Post 4: Twitter/X Thread
|
|
91
|
+
|
|
92
|
+
**Tweet 1:**
|
|
93
|
+
I cataloged 1,107 Claude Code entries and verified 948 of them with evidence.
|
|
94
|
+
|
|
95
|
+
Most projects use less than 5% of what Claude Code can do.
|
|
96
|
+
|
|
97
|
+
Here's a free tool that checks your project and tells you exactly what's missing:
|
|
98
|
+
|
|
99
|
+
npx claudex-setup
|
|
100
|
+
|
|
101
|
+
Thread 🧵👇
|
|
102
|
+
|
|
103
|
+
**Tweet 2:**
|
|
104
|
+
The #1 thing you're probably missing: CLAUDE.md
|
|
105
|
+
|
|
106
|
+
It's a file Claude reads at the start of every session. Without it, Claude doesn't know your:
|
|
107
|
+
- Build commands
|
|
108
|
+
- Code style
|
|
109
|
+
- Testing framework
|
|
110
|
+
- Project architecture
|
|
111
|
+
|
|
112
|
+
Takes 2 minutes to create. Impact: massive.
|
|
113
|
+
|
|
114
|
+
**Tweet 3:**
|
|
115
|
+
#2: Mermaid diagrams in CLAUDE.md
|
|
116
|
+
|
|
117
|
+
A few hundred tokens of Mermaid syntax conveys what takes thousands of tokens in prose.
|
|
118
|
+
|
|
119
|
+
73% token savings = faster responses, lower cost, better context.
|
|
120
|
+
|
|
121
|
+
**Tweet 4:**
|
|
122
|
+
#3: Hooks > CLAUDE.md rules
|
|
123
|
+
|
|
124
|
+
CLAUDE.md instructions = ~80% compliance
|
|
125
|
+
Hooks = 100% enforcement
|
|
126
|
+
|
|
127
|
+
Auto-lint after edits. Block commits without tests. Prevent force-push.
|
|
128
|
+
|
|
129
|
+
Hooks are deterministic. Instructions are advisory.
|
|
130
|
+
|
|
131
|
+
**Tweet 5:**
|
|
132
|
+
Want to check your project in 10 seconds?
|
|
133
|
+
|
|
134
|
+
npx claudex-setup
|
|
135
|
+
|
|
136
|
+
Scores 0-100. Shows what's missing. Auto-fixes with `setup`.
|
|
137
|
+
|
|
138
|
+
Free. Open source. Zero dependencies.
|
|
139
|
+
|
|
140
|
+
https://github.com/DnaFin/claudex-setup
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Post 5: Hacker News (Show HN)
|
|
145
|
+
|
|
146
|
+
**Title:** Show HN: claudex-setup – Audit any project for Claude Code optimization (1,107 entries)
|
|
147
|
+
|
|
148
|
+
**Body:**
|
|
149
|
+
I built a CLI tool that scores your project against Claude Code best practices.
|
|
150
|
+
|
|
151
|
+
After researching 1,107 entries (948 verified with evidence), most projects score 10-20 out of 100 because they're missing basic optimizations like CLAUDE.md files, hooks, custom commands, and architecture diagrams.
|
|
152
|
+
|
|
153
|
+
npx claudex-setup → audit (0-100 score)
|
|
154
|
+
npx claudex-setup setup → auto-fix
|
|
155
|
+
|
|
156
|
+
Detects your stack (React, Python, TS, Rust, Go, etc) and tailors recommendations.
|
|
157
|
+
|
|
158
|
+
Zero dependencies, no API keys, runs locally.
|
|
159
|
+
|
|
160
|
+
https://github.com/DnaFin/claudex-setup
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Pilot Rollout Kit
|
|
2
|
+
|
|
3
|
+
## Suggested pilot shape
|
|
4
|
+
|
|
5
|
+
1. Choose 1-2 repos with active owners and low blast radius.
|
|
6
|
+
2. Run `discover`, `suggest-only`, and `governance` before any write flow.
|
|
7
|
+
3. Pick one permission profile and document why it fits the pilot.
|
|
8
|
+
4. Run `benchmark` to capture a baseline and expected value.
|
|
9
|
+
5. Use `plan` and selective `apply` for the first write batch.
|
|
10
|
+
|
|
11
|
+
## Approval checklist
|
|
12
|
+
|
|
13
|
+
- Engineering owner approves scope.
|
|
14
|
+
- Security owner approves permission profile and hooks.
|
|
15
|
+
- Pilot owner records success metrics.
|
|
16
|
+
- Rollback expectations are documented before apply.
|
|
17
|
+
|
|
18
|
+
## Success metrics
|
|
19
|
+
|
|
20
|
+
- readiness score delta
|
|
21
|
+
- organic score delta
|
|
22
|
+
- number of proposal bundles accepted
|
|
23
|
+
- rollback-free apply rate
|
|
24
|
+
- time to first useful Claude workflow
|
|
25
|
+
|
|
26
|
+
## Rollback expectations
|
|
27
|
+
|
|
28
|
+
- every apply run must produce a rollback artifact
|
|
29
|
+
- rejected starter artifacts are deleted using the rollback manifest
|
|
30
|
+
- rollback decisions are logged in the activity trail
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# claudex-setup Release Checklist
|
|
2
|
+
|
|
3
|
+
Use this before tagging or publishing a release.
|
|
4
|
+
|
|
5
|
+
## Code And Packaging
|
|
6
|
+
|
|
7
|
+
- bump `package.json` version intentionally
|
|
8
|
+
- update `CHANGELOG.md` with the shipped changes
|
|
9
|
+
- run `npm test`
|
|
10
|
+
- run `npm pack --dry-run`
|
|
11
|
+
|
|
12
|
+
## Product Surface Consistency
|
|
13
|
+
|
|
14
|
+
- verify `README.md` reflects the current CLI surface
|
|
15
|
+
- verify `docs/index.html` reflects the current CLI surface
|
|
16
|
+
- verify new flags and commands appear in `--help`
|
|
17
|
+
- verify proof numbers and public claims match the current state
|
|
18
|
+
|
|
19
|
+
## Trust And Governance
|
|
20
|
+
|
|
21
|
+
- run `npx claudex-setup --snapshot` on the repo itself
|
|
22
|
+
- run `npx claudex-setup governance --out governance.md`
|
|
23
|
+
- verify MCP package names and env preflight behavior for changed packs
|
|
24
|
+
- verify no recommendation regressions on known scenarios
|
|
25
|
+
|
|
26
|
+
## Release Readiness
|
|
27
|
+
|
|
28
|
+
- confirm npm publish target and account are correct
|
|
29
|
+
- confirm git branch / commit matches the intended release
|
|
30
|
+
- confirm any new templates or content files are included in the package
|
|
31
|
+
- capture one final note about what changed and what still remains intentionally deferred
|
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claudex-setup",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.11.0",
|
|
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": {
|
|
7
7
|
"claudex-setup": "bin/cli.js"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"bin",
|
|
11
|
+
"content",
|
|
11
12
|
"src",
|
|
12
13
|
"README.md",
|
|
13
14
|
"CHANGELOG.md"
|
package/src/activity.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
+
const { version } = require('../package.json');
|
|
3
4
|
|
|
4
5
|
function timestampId() {
|
|
5
6
|
return new Date().toISOString().replace(/[:.]/g, '-');
|
|
@@ -9,9 +10,11 @@ function ensureArtifactDirs(dir) {
|
|
|
9
10
|
const root = path.join(dir, '.claude', 'claudex-setup');
|
|
10
11
|
const activityDir = path.join(root, 'activity');
|
|
11
12
|
const rollbackDir = path.join(root, 'rollbacks');
|
|
13
|
+
const snapshotDir = path.join(root, 'snapshots');
|
|
12
14
|
fs.mkdirSync(activityDir, { recursive: true });
|
|
13
15
|
fs.mkdirSync(rollbackDir, { recursive: true });
|
|
14
|
-
|
|
16
|
+
fs.mkdirSync(snapshotDir, { recursive: true });
|
|
17
|
+
return { root, activityDir, rollbackDir, snapshotDir };
|
|
15
18
|
}
|
|
16
19
|
|
|
17
20
|
function writeJson(filePath, payload) {
|
|
@@ -53,8 +56,246 @@ function writeRollbackArtifact(dir, payload) {
|
|
|
53
56
|
};
|
|
54
57
|
}
|
|
55
58
|
|
|
59
|
+
function summarizeSnapshot(snapshotKind, payload) {
|
|
60
|
+
if (snapshotKind === 'audit') {
|
|
61
|
+
return {
|
|
62
|
+
score: payload.score,
|
|
63
|
+
organicScore: payload.organicScore,
|
|
64
|
+
passed: payload.passed,
|
|
65
|
+
failed: payload.failed,
|
|
66
|
+
checkCount: payload.checkCount,
|
|
67
|
+
suggestedNextCommand: payload.suggestedNextCommand,
|
|
68
|
+
topActionKeys: Array.isArray(payload.topNextActions)
|
|
69
|
+
? payload.topNextActions.slice(0, 3).map(item => item.key)
|
|
70
|
+
: [],
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (snapshotKind === 'augment' || snapshotKind === 'suggest-only') {
|
|
75
|
+
return {
|
|
76
|
+
score: payload.projectSummary?.score,
|
|
77
|
+
organicScore: payload.projectSummary?.organicScore,
|
|
78
|
+
maturity: payload.projectSummary?.maturity,
|
|
79
|
+
domains: payload.projectSummary?.domains || [],
|
|
80
|
+
topActionKeys: Array.isArray(payload.topNextActions)
|
|
81
|
+
? payload.topNextActions.slice(0, 3).map(item => item.key)
|
|
82
|
+
: [],
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (snapshotKind === 'benchmark') {
|
|
87
|
+
return {
|
|
88
|
+
beforeScore: payload.before?.score,
|
|
89
|
+
afterScore: payload.after?.score,
|
|
90
|
+
scoreDelta: payload.delta?.score,
|
|
91
|
+
organicDelta: payload.delta?.organicScore,
|
|
92
|
+
decisionGuidance: payload.executiveSummary?.decisionGuidance || null,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (snapshotKind === 'governance') {
|
|
97
|
+
return {
|
|
98
|
+
permissionProfiles: Array.isArray(payload.permissionProfiles) ? payload.permissionProfiles.length : 0,
|
|
99
|
+
hooks: Array.isArray(payload.hookRegistry) ? payload.hookRegistry.length : 0,
|
|
100
|
+
policyPacks: Array.isArray(payload.policyPacks) ? payload.policyPacks.length : 0,
|
|
101
|
+
domainPacks: Array.isArray(payload.domainPacks) ? payload.domainPacks.length : 0,
|
|
102
|
+
mcpPacks: Array.isArray(payload.mcpPacks) ? payload.mcpPacks.length : 0,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return {};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function updateSnapshotIndex(snapshotDir, record) {
|
|
110
|
+
const indexPath = path.join(snapshotDir, 'index.json');
|
|
111
|
+
let entries = [];
|
|
112
|
+
|
|
113
|
+
if (fs.existsSync(indexPath)) {
|
|
114
|
+
try {
|
|
115
|
+
entries = JSON.parse(fs.readFileSync(indexPath, 'utf8'));
|
|
116
|
+
if (!Array.isArray(entries)) {
|
|
117
|
+
entries = [];
|
|
118
|
+
}
|
|
119
|
+
} catch {
|
|
120
|
+
entries = [];
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
entries.push(record);
|
|
125
|
+
fs.writeFileSync(indexPath, JSON.stringify(entries, null, 2), 'utf8');
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function writeSnapshotArtifact(dir, snapshotKind, payload, meta = {}) {
|
|
129
|
+
const id = timestampId();
|
|
130
|
+
const { snapshotDir } = ensureArtifactDirs(dir);
|
|
131
|
+
const filePath = path.join(snapshotDir, `${id}-${snapshotKind}.json`);
|
|
132
|
+
const summary = summarizeSnapshot(snapshotKind, payload);
|
|
133
|
+
const envelope = {
|
|
134
|
+
schemaVersion: 1,
|
|
135
|
+
artifactType: 'snapshot',
|
|
136
|
+
snapshotKind,
|
|
137
|
+
id,
|
|
138
|
+
createdAt: new Date().toISOString(),
|
|
139
|
+
generatedBy: `claudex-setup@${version}`,
|
|
140
|
+
directory: dir,
|
|
141
|
+
summary,
|
|
142
|
+
...meta,
|
|
143
|
+
payload,
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
writeJson(filePath, envelope);
|
|
147
|
+
|
|
148
|
+
const record = {
|
|
149
|
+
id,
|
|
150
|
+
snapshotKind,
|
|
151
|
+
createdAt: envelope.createdAt,
|
|
152
|
+
relativePath: path.relative(dir, filePath),
|
|
153
|
+
summary,
|
|
154
|
+
};
|
|
155
|
+
updateSnapshotIndex(snapshotDir, record);
|
|
156
|
+
|
|
157
|
+
return {
|
|
158
|
+
id,
|
|
159
|
+
filePath,
|
|
160
|
+
relativePath: path.relative(dir, filePath),
|
|
161
|
+
indexPath: path.relative(dir, path.join(snapshotDir, 'index.json')),
|
|
162
|
+
summary,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function readSnapshotIndex(dir) {
|
|
167
|
+
const indexPath = path.join(dir, '.claude', 'claudex-setup', 'snapshots', 'index.json');
|
|
168
|
+
if (!fs.existsSync(indexPath)) return [];
|
|
169
|
+
try {
|
|
170
|
+
const entries = JSON.parse(fs.readFileSync(indexPath, 'utf8'));
|
|
171
|
+
return Array.isArray(entries) ? entries : [];
|
|
172
|
+
} catch {
|
|
173
|
+
return [];
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function getHistory(dir, limit = 20) {
|
|
178
|
+
const entries = readSnapshotIndex(dir);
|
|
179
|
+
return entries
|
|
180
|
+
.filter(e => e.snapshotKind === 'audit')
|
|
181
|
+
.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt))
|
|
182
|
+
.slice(0, limit);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function compareLatest(dir) {
|
|
186
|
+
const audits = getHistory(dir, 2);
|
|
187
|
+
if (audits.length < 2) return null;
|
|
188
|
+
|
|
189
|
+
const current = audits[0];
|
|
190
|
+
const previous = audits[1];
|
|
191
|
+
|
|
192
|
+
const delta = {
|
|
193
|
+
score: (current.summary?.score || 0) - (previous.summary?.score || 0),
|
|
194
|
+
organic: (current.summary?.organicScore || 0) - (previous.summary?.organicScore || 0),
|
|
195
|
+
passed: (current.summary?.passed || 0) - (previous.summary?.passed || 0),
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
const regressions = [];
|
|
199
|
+
const improvements = [];
|
|
200
|
+
|
|
201
|
+
const prevKeys = new Set(previous.summary?.topActionKeys || []);
|
|
202
|
+
const currKeys = new Set(current.summary?.topActionKeys || []);
|
|
203
|
+
|
|
204
|
+
for (const key of currKeys) {
|
|
205
|
+
if (!prevKeys.has(key)) regressions.push(key);
|
|
206
|
+
}
|
|
207
|
+
for (const key of prevKeys) {
|
|
208
|
+
if (!currKeys.has(key)) improvements.push(key);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return {
|
|
212
|
+
current: { date: current.createdAt, score: current.summary?.score, passed: current.summary?.passed },
|
|
213
|
+
previous: { date: previous.createdAt, score: previous.summary?.score, passed: previous.summary?.passed },
|
|
214
|
+
delta,
|
|
215
|
+
regressions,
|
|
216
|
+
improvements,
|
|
217
|
+
trend: delta.score > 0 ? 'improving' : delta.score < 0 ? 'regressing' : 'stable',
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function formatHistory(dir) {
|
|
222
|
+
const history = getHistory(dir, 10);
|
|
223
|
+
if (history.length === 0) return 'No snapshots found. Run `npx claudex-setup --snapshot` to save one.';
|
|
224
|
+
|
|
225
|
+
const lines = ['Score history (most recent first):', ''];
|
|
226
|
+
for (const entry of history) {
|
|
227
|
+
const date = entry.createdAt?.split('T')[0] || 'unknown';
|
|
228
|
+
const score = entry.summary?.score ?? '?';
|
|
229
|
+
const passed = entry.summary?.passed ?? '?';
|
|
230
|
+
const total = entry.summary?.checkCount ?? '?';
|
|
231
|
+
lines.push(` ${date} ${score}/100 (${passed}/${total} passing)`);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const comparison = compareLatest(dir);
|
|
235
|
+
if (comparison) {
|
|
236
|
+
lines.push('');
|
|
237
|
+
const sign = comparison.delta.score >= 0 ? '+' : '';
|
|
238
|
+
lines.push(` Trend: ${comparison.trend} (${sign}${comparison.delta.score} since previous)`);
|
|
239
|
+
if (comparison.improvements.length > 0) {
|
|
240
|
+
lines.push(` Fixed: ${comparison.improvements.join(', ')}`);
|
|
241
|
+
}
|
|
242
|
+
if (comparison.regressions.length > 0) {
|
|
243
|
+
lines.push(` New gaps: ${comparison.regressions.join(', ')}`);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return lines.join('\n');
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function exportTrendReport(dir) {
|
|
251
|
+
const history = getHistory(dir, 50);
|
|
252
|
+
if (history.length === 0) return null;
|
|
253
|
+
|
|
254
|
+
const comparison = compareLatest(dir);
|
|
255
|
+
const lines = [
|
|
256
|
+
'# Claude Code Setup Trend Report',
|
|
257
|
+
'',
|
|
258
|
+
`**Project:** ${path.basename(dir)}`,
|
|
259
|
+
`**Generated:** ${new Date().toISOString().split('T')[0]}`,
|
|
260
|
+
`**Snapshots:** ${history.length}`,
|
|
261
|
+
'',
|
|
262
|
+
'## Score History',
|
|
263
|
+
'',
|
|
264
|
+
'| Date | Score | Passed | Checks |',
|
|
265
|
+
'|------|-------|--------|--------|',
|
|
266
|
+
];
|
|
267
|
+
|
|
268
|
+
for (const entry of history) {
|
|
269
|
+
const date = entry.createdAt?.split('T')[0] || '?';
|
|
270
|
+
lines.push(`| ${date} | ${entry.summary?.score ?? '?'}/100 | ${entry.summary?.passed ?? '?'} | ${entry.summary?.checkCount ?? '?'} |`);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (comparison) {
|
|
274
|
+
lines.push('');
|
|
275
|
+
lines.push('## Latest Comparison');
|
|
276
|
+
lines.push('');
|
|
277
|
+
lines.push(`- **Previous:** ${comparison.previous.score}/100 (${comparison.previous.date?.split('T')[0]})`);
|
|
278
|
+
lines.push(`- **Current:** ${comparison.current.score}/100 (${comparison.current.date?.split('T')[0]})`);
|
|
279
|
+
lines.push(`- **Delta:** ${comparison.delta.score >= 0 ? '+' : ''}${comparison.delta.score} points`);
|
|
280
|
+
lines.push(`- **Trend:** ${comparison.trend}`);
|
|
281
|
+
if (comparison.improvements.length > 0) lines.push(`- **Fixed:** ${comparison.improvements.join(', ')}`);
|
|
282
|
+
if (comparison.regressions.length > 0) lines.push(`- **New gaps:** ${comparison.regressions.join(', ')}`);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
lines.push('');
|
|
286
|
+
lines.push(`---`);
|
|
287
|
+
lines.push(`*Generated by claudex-setup v${version}*`);
|
|
288
|
+
return lines.join('\n');
|
|
289
|
+
}
|
|
290
|
+
|
|
56
291
|
module.exports = {
|
|
57
292
|
ensureArtifactDirs,
|
|
58
293
|
writeActivityArtifact,
|
|
59
294
|
writeRollbackArtifact,
|
|
295
|
+
writeSnapshotArtifact,
|
|
296
|
+
readSnapshotIndex,
|
|
297
|
+
getHistory,
|
|
298
|
+
compareLatest,
|
|
299
|
+
formatHistory,
|
|
300
|
+
exportTrendReport,
|
|
60
301
|
};
|
package/src/analyze.js
CHANGED
|
@@ -351,7 +351,7 @@ async function analyzeProject(options) {
|
|
|
351
351
|
},
|
|
352
352
|
strengthsPreserved: toStrengths(auditResult.results),
|
|
353
353
|
gapsIdentified: toGaps(auditResult.results),
|
|
354
|
-
topNextActions: auditResult.quickWins,
|
|
354
|
+
topNextActions: auditResult.topNextActions || auditResult.quickWins,
|
|
355
355
|
recommendedImprovements: toRecommendations(auditResult),
|
|
356
356
|
recommendedDomainPacks,
|
|
357
357
|
recommendedMcpPacks,
|
|
@@ -417,7 +417,14 @@ function printAnalysis(report, options = {}) {
|
|
|
417
417
|
console.log(c(' Top 5 Next Actions', 'magenta'));
|
|
418
418
|
report.topNextActions.slice(0, 5).forEach((item, index) => {
|
|
419
419
|
console.log(` ${index + 1}. ${item.name}`);
|
|
420
|
-
console.log(c(` ${item.fix}`, 'dim'));
|
|
420
|
+
console.log(c(` Why: ${item.why || item.fix}`, 'dim'));
|
|
421
|
+
if (Array.isArray(item.signals) && item.signals.length > 0) {
|
|
422
|
+
console.log(c(` Trace: ${item.signals.join(' | ')}`, 'dim'));
|
|
423
|
+
}
|
|
424
|
+
if (item.risk || item.confidence) {
|
|
425
|
+
console.log(c(` Risk: ${item.risk || 'low'} | Confidence: ${item.confidence || 'medium'}`, 'dim'));
|
|
426
|
+
}
|
|
427
|
+
console.log(c(` Fix: ${item.fix}`, 'dim'));
|
|
421
428
|
});
|
|
422
429
|
console.log('');
|
|
423
430
|
}
|
|
@@ -500,7 +507,15 @@ function exportMarkdown(report) {
|
|
|
500
507
|
lines.push('## Top Next Actions');
|
|
501
508
|
lines.push('');
|
|
502
509
|
report.topNextActions.slice(0, 5).forEach((item, index) => {
|
|
503
|
-
lines.push(`${index + 1}. **${item.name}
|
|
510
|
+
lines.push(`${index + 1}. **${item.name}**`);
|
|
511
|
+
lines.push(` - Why: ${item.why || item.fix}`);
|
|
512
|
+
if (Array.isArray(item.signals) && item.signals.length > 0) {
|
|
513
|
+
lines.push(` - Trace: ${item.signals.join(' | ')}`);
|
|
514
|
+
}
|
|
515
|
+
if (item.risk || item.confidence) {
|
|
516
|
+
lines.push(` - Risk / Confidence: ${item.risk || 'low'} / ${item.confidence || 'medium'}`);
|
|
517
|
+
}
|
|
518
|
+
lines.push(` - Fix: ${item.fix}`);
|
|
504
519
|
});
|
|
505
520
|
lines.push('');
|
|
506
521
|
}
|