claude-launchpad 0.5.0 → 0.5.2
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 +22 -47
- package/dist/cli.js +102 -6
- package/dist/cli.js.map +1 -1
- package/package.json +4 -2
- package/scenarios/workflow/deferred-tracking.yaml +58 -0
- package/scenarios/workflow/memory-persistence.yaml +49 -0
package/README.md
CHANGED
|
@@ -5,19 +5,16 @@
|
|
|
5
5
|
[](https://github.com/mboss37/claude-launchpad)
|
|
6
6
|
[](https://github.com/mboss37/claude-launchpad/blob/master/LICENSE)
|
|
7
7
|
|
|
8
|
-
**
|
|
8
|
+
**Score your Claude Code setup. Fix what's broken. Prove it works.**
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
- **Launch new projects** with production-ready Claude Code config from day one
|
|
13
|
-
- **Check existing projects** — score your config, find issues, auto-fix them
|
|
14
|
-
- **Prove it works** — run Claude against test scenarios and see if your rules are actually followed
|
|
10
|
+
CLAUDE.md is advisory — Claude follows your rules ~80% of the time. Hooks are deterministic — 100% compliance. But most developers have zero hooks and too many instructions. This tool gives you a number, fixes the gaps, and lets you prove Claude actually follows your config.
|
|
15
11
|
|
|
16
12
|
```bash
|
|
17
|
-
|
|
18
|
-
cd your-project
|
|
13
|
+
npx claude-launchpad
|
|
19
14
|
```
|
|
20
15
|
|
|
16
|
+
That's it. Run it in any project with Claude Code. You'll see a score out of 100 and a list of exactly what's wrong. Run `--fix` to auto-repair.
|
|
17
|
+
|
|
21
18
|
## Two Paths, One Tool
|
|
22
19
|
|
|
23
20
|
### Starting a new project?
|
|
@@ -26,9 +23,9 @@ cd your-project
|
|
|
26
23
|
claude-launchpad init
|
|
27
24
|
```
|
|
28
25
|
|
|
29
|
-
Detects your stack, generates `CLAUDE.md` with your commands
|
|
26
|
+
Detects your stack, generates `CLAUDE.md` with your commands and conventions, creates `TASKS.md` for tracking work across sessions, sets up hooks that auto-format code and block dangerous operations, and adds a `.claudeignore` so Claude skips `node_modules` and build artifacts.
|
|
30
27
|
|
|
31
|
-
Then run `enhance` to have Claude read your codebase and fill in the architecture
|
|
28
|
+
Then run `enhance` to have Claude read your actual codebase and fill in the architecture and guardrails — not boilerplate, real project-specific content. Requires Claude Code CLI.
|
|
32
29
|
|
|
33
30
|
### Already have a project?
|
|
34
31
|
|
|
@@ -40,35 +37,24 @@ Scans your Claude Code config, gives you a score out of 100, and tells you exact
|
|
|
40
37
|
|
|
41
38
|
## All Commands
|
|
42
39
|
|
|
43
|
-
| Command | What it does |
|
|
44
|
-
|
|
45
|
-
| `claude-launchpad init` |
|
|
46
|
-
| `claude-launchpad` |
|
|
47
|
-
| `claude-launchpad doctor --fix` | Auto-fix issues:
|
|
48
|
-
| `claude-launchpad doctor --watch` | Live score that updates when you save config files |
|
|
49
|
-
| `claude-launchpad enhance` | Claude reads your code and completes CLAUDE.md
|
|
50
|
-
| `claude-launchpad eval
|
|
40
|
+
| Command | What it does | Runs |
|
|
41
|
+
|---|---|---|
|
|
42
|
+
| `claude-launchpad init` | Detect stack, generate config, hooks, permissions | Locally |
|
|
43
|
+
| `claude-launchpad` | Score your config 0-100, list issues | Locally |
|
|
44
|
+
| `claude-launchpad doctor --fix` | Auto-fix issues: hooks, rules, sections, .claudeignore | Locally |
|
|
45
|
+
| `claude-launchpad doctor --watch` | Live score that updates when you save config files | Locally |
|
|
46
|
+
| `claude-launchpad enhance` | Claude reads your code and completes CLAUDE.md | Via Claude CLI |
|
|
47
|
+
| `claude-launchpad eval` | Run Claude against test scenarios, prove config works | Via Claude CLI |
|
|
51
48
|
|
|
52
49
|
## Quick Start
|
|
53
50
|
|
|
54
51
|
```bash
|
|
55
|
-
# Install
|
|
56
|
-
npm i -g claude-launchpad
|
|
57
|
-
|
|
58
|
-
# Go to any project with Claude Code
|
|
59
52
|
cd your-project
|
|
60
|
-
|
|
61
|
-
#
|
|
62
|
-
claude-launchpad
|
|
63
|
-
|
|
64
|
-
# Fix everything it found
|
|
65
|
-
claude-launchpad doctor --fix
|
|
66
|
-
|
|
67
|
-
# See your new score
|
|
68
|
-
claude-launchpad
|
|
53
|
+
npx claude-launchpad # see your score
|
|
54
|
+
npx claude-launchpad doctor --fix # fix everything
|
|
69
55
|
```
|
|
70
56
|
|
|
71
|
-
|
|
57
|
+
A typical unconfigured project scores ~42%. After `--fix`, it jumps to ~86%. Run `init` on a fresh project and you start at ~93%.
|
|
72
58
|
|
|
73
59
|
## The Doctor
|
|
74
60
|
|
|
@@ -105,6 +91,7 @@ Output looks like this:
|
|
|
105
91
|
| Flag | What it does |
|
|
106
92
|
|---|---|
|
|
107
93
|
| `--fix` | Auto-fixes issues: adds hooks, CLAUDE.md sections, rules, .claudeignore |
|
|
94
|
+
| `--fix --dry-run` | Preview what --fix would change without applying |
|
|
108
95
|
| `--watch` | Re-runs every second, updates when you save a config file |
|
|
109
96
|
| `--json` | Pure JSON output, no colors, no banner — for scripts and CI |
|
|
110
97
|
| `--min-score <n>` | Exit code 1 if score is below threshold — use in CI to block bad configs |
|
|
@@ -182,7 +169,7 @@ Results are saved to `.claude/eval/` as structured markdown — you can feed the
|
|
|
182
169
|
|---|---|---|
|
|
183
170
|
| `security` | 6 | SQL injection, .env protection, secret exposure, input validation, credential read, sandbox escape |
|
|
184
171
|
| `conventions` | 5 | Error handling, immutability, file size, naming, no hardcoded values |
|
|
185
|
-
| `workflow` |
|
|
172
|
+
| `workflow` | 4 | Git conventions, session continuity, memory persistence, deferred tracking |
|
|
186
173
|
|
|
187
174
|
**All eval flags:**
|
|
188
175
|
|
|
@@ -217,14 +204,6 @@ jobs:
|
|
|
217
204
|
|
|
218
205
|
Score below threshold = exit code 1 = PR blocked.
|
|
219
206
|
|
|
220
|
-
## Plugin (pending marketplace review)
|
|
221
|
-
|
|
222
|
-
```bash
|
|
223
|
-
claude plugin install claude-launchpad
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
Then use `/launchpad:doctor`, `/launchpad:init`, `/launchpad:enhance`, `/launchpad:eval` inside Claude Code. The plugin nudges you to re-check your score when you edit config files.
|
|
227
|
-
|
|
228
207
|
## How It Works
|
|
229
208
|
|
|
230
209
|
**Doctor** reads your files and runs static analysis. No API calls. No network. No cost.
|
|
@@ -237,12 +216,7 @@ Then use `/launchpad:doctor`, `/launchpad:init`, `/launchpad:enhance`, `/launchp
|
|
|
237
216
|
|
|
238
217
|
## Why This Exists
|
|
239
218
|
|
|
240
|
-
|
|
241
|
-
- **Hooks are deterministic.** 100% compliance. But most people have zero hooks.
|
|
242
|
-
- **Instruction budget is real.** Past ~150, compliance drops. Most people don't know they're over.
|
|
243
|
-
- **Nobody measures.** You can't improve what you can't measure.
|
|
244
|
-
|
|
245
|
-
This tool gives you a number. Fix the issues, re-run, watch the number go up.
|
|
219
|
+
Nobody measures their Claude Code config quality. You write CLAUDE.md, hope Claude follows it, and never verify. This tool gives you a number. Fix the issues, re-run, watch it go up.
|
|
246
220
|
|
|
247
221
|
## Glossary
|
|
248
222
|
|
|
@@ -254,6 +228,7 @@ New to Claude Code? Here's what the terms mean:
|
|
|
254
228
|
| **Hooks** | Shell commands that run automatically when Claude does something. For example: auto-format a file after Claude edits it, or block Claude from reading your `.env` file. They live in `.claude/settings.json`. |
|
|
255
229
|
| **Instruction budget** | CLAUDE.md has a soft limit of ~150 actionable lines. Past that, Claude starts ignoring rules at the bottom. Doctor counts your lines and warns you. |
|
|
256
230
|
| **Rules** | Extra markdown files in `.claude/rules/` that Claude reads alongside CLAUDE.md. Use them to offload detailed conventions so CLAUDE.md stays under budget. |
|
|
231
|
+
| **Compaction** | When a Claude Code conversation gets too long, it compresses older messages to free up space. This can lose context — a PostCompact hook re-injects critical files (like TASKS.md) after compaction. |
|
|
257
232
|
| **MCP Servers** | External tools Claude can connect to (databases, APIs, docs). Configured in `.claude/settings.json`. Most projects don't need them. |
|
|
258
233
|
| **.claudeignore** | Like `.gitignore` but for Claude. Tells Claude which files to skip (node_modules, dist, lockfiles) so it doesn't waste time reading noise. |
|
|
259
234
|
|
package/dist/cli.js
CHANGED
|
@@ -404,6 +404,13 @@ function generateSettings(detected) {
|
|
|
404
404
|
if (formatHook) {
|
|
405
405
|
postToolUse.push(formatHook);
|
|
406
406
|
}
|
|
407
|
+
const sessionStart = [{
|
|
408
|
+
matcher: "startup|resume",
|
|
409
|
+
hooks: [{
|
|
410
|
+
type: "command",
|
|
411
|
+
command: "cat TASKS.md 2>/dev/null; exit 0"
|
|
412
|
+
}]
|
|
413
|
+
}];
|
|
407
414
|
const postCompact = [{
|
|
408
415
|
matcher: "",
|
|
409
416
|
hooks: [{
|
|
@@ -412,6 +419,7 @@ function generateSettings(detected) {
|
|
|
412
419
|
}]
|
|
413
420
|
}];
|
|
414
421
|
const hooks = {};
|
|
422
|
+
hooks.SessionStart = sessionStart;
|
|
415
423
|
if (preToolUse.length > 0) hooks.PreToolUse = preToolUse;
|
|
416
424
|
if (postToolUse.length > 0) hooks.PostToolUse = postToolUse;
|
|
417
425
|
hooks.PostCompact = postCompact;
|
|
@@ -810,7 +818,8 @@ async function readHooks(claudeDir) {
|
|
|
810
818
|
event,
|
|
811
819
|
type: h.type ?? "command",
|
|
812
820
|
matcher,
|
|
813
|
-
command: h.command
|
|
821
|
+
command: h.command,
|
|
822
|
+
timeout: h.timeout
|
|
814
823
|
});
|
|
815
824
|
}
|
|
816
825
|
} else {
|
|
@@ -818,7 +827,8 @@ async function readHooks(claudeDir) {
|
|
|
818
827
|
event,
|
|
819
828
|
type: g.type ?? "command",
|
|
820
829
|
matcher,
|
|
821
|
-
command: g.command
|
|
830
|
+
command: g.command,
|
|
831
|
+
timeout: g.timeout
|
|
822
832
|
});
|
|
823
833
|
}
|
|
824
834
|
}
|
|
@@ -981,6 +991,44 @@ async function analyzeSettings(config) {
|
|
|
981
991
|
fix: "Add PreToolUse hooks for security or remove allowedTools to use interactive prompting"
|
|
982
992
|
});
|
|
983
993
|
}
|
|
994
|
+
if (config.settings.includeCoAuthoredBy !== void 0) {
|
|
995
|
+
issues.push({
|
|
996
|
+
analyzer: "Settings",
|
|
997
|
+
severity: "low",
|
|
998
|
+
message: 'Deprecated includeCoAuthoredBy \u2014 use attribution: { commit: "", pr: "" } instead',
|
|
999
|
+
fix: "Replace includeCoAuthoredBy with the attribution object in settings.json"
|
|
1000
|
+
});
|
|
1001
|
+
}
|
|
1002
|
+
if (!config.settings.claudeMdExcludes) {
|
|
1003
|
+
issues.push({
|
|
1004
|
+
analyzer: "Settings",
|
|
1005
|
+
severity: "info",
|
|
1006
|
+
message: "No claudeMdExcludes configured \u2014 consider adding this if you have a monorepo"
|
|
1007
|
+
});
|
|
1008
|
+
}
|
|
1009
|
+
const broadMatchers = ["Bash", "Write", "Edit", "Read"];
|
|
1010
|
+
const hooksWithoutTimeout = config.hooks.filter(
|
|
1011
|
+
(h) => !h.timeout && broadMatchers.some((m) => h.matcher?.includes(m))
|
|
1012
|
+
);
|
|
1013
|
+
if (hooksWithoutTimeout.length > 0) {
|
|
1014
|
+
issues.push({
|
|
1015
|
+
analyzer: "Settings",
|
|
1016
|
+
severity: "low",
|
|
1017
|
+
message: `${hooksWithoutTimeout.length} hook(s) on broad matchers without timeout \u2014 defaults to 60s per invocation`,
|
|
1018
|
+
fix: "Add timeout (in seconds) to hooks on Bash, Write, Edit, or Read matchers"
|
|
1019
|
+
});
|
|
1020
|
+
}
|
|
1021
|
+
if (config.settings.autoMemoryEnabled === false) {
|
|
1022
|
+
const hasMemorySection = config.claudeMdContent?.includes("## Memory") ?? false;
|
|
1023
|
+
if (!hasMemorySection) {
|
|
1024
|
+
issues.push({
|
|
1025
|
+
analyzer: "Settings",
|
|
1026
|
+
severity: "medium",
|
|
1027
|
+
message: "Auto-memory is disabled with no manual memory strategy in CLAUDE.md",
|
|
1028
|
+
fix: "Re-enable autoMemoryEnabled or add a ## Memory section to CLAUDE.md"
|
|
1029
|
+
});
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
984
1032
|
const actionableCount = issues.filter((i) => i.severity !== "info").length;
|
|
985
1033
|
const score = Math.max(0, 100 - actionableCount * 20);
|
|
986
1034
|
return { name: "Settings", issues, score };
|
|
@@ -1040,7 +1088,16 @@ async function analyzeHooks(config) {
|
|
|
1040
1088
|
fix: "Add a PostCompact hook that re-injects TASKS.md after compaction"
|
|
1041
1089
|
});
|
|
1042
1090
|
}
|
|
1043
|
-
const
|
|
1091
|
+
const hasSessionStart = hooks.some((h) => h.event === "SessionStart");
|
|
1092
|
+
if (!hasSessionStart) {
|
|
1093
|
+
issues.push({
|
|
1094
|
+
analyzer: "Hooks",
|
|
1095
|
+
severity: "low",
|
|
1096
|
+
message: "No SessionStart hook \u2014 session starts without project context loaded",
|
|
1097
|
+
fix: "Add a SessionStart hook that injects TASKS.md at startup"
|
|
1098
|
+
});
|
|
1099
|
+
}
|
|
1100
|
+
const score = Math.max(0, 100 - issues.length * 15);
|
|
1044
1101
|
return { name: "Hooks", issues, score };
|
|
1045
1102
|
}
|
|
1046
1103
|
|
|
@@ -1373,7 +1430,8 @@ var FIX_TABLE = [
|
|
|
1373
1430
|
{ analyzer: "Permissions", match: "Credential files not blocked", fix: (root) => addCredentialDenyRules(root) },
|
|
1374
1431
|
{ analyzer: "Permissions", match: "Bypass permissions mode", fix: (root) => addBypassDisable(root) },
|
|
1375
1432
|
{ analyzer: "Permissions", match: "Sandbox not enabled", fix: (root) => addSandboxSettings(root) },
|
|
1376
|
-
{ analyzer: "Permissions", match: ".env is protected by hooks but not in .claudeignore", fix: (root) => addEnvToClaudeignore(root) }
|
|
1433
|
+
{ analyzer: "Permissions", match: ".env is protected by hooks but not in .claudeignore", fix: (root) => addEnvToClaudeignore(root) },
|
|
1434
|
+
{ analyzer: "Settings", match: "Deprecated includeCoAuthoredBy", fix: (root) => migrateAttribution(root) }
|
|
1377
1435
|
];
|
|
1378
1436
|
async function tryFix(issue, root, detected) {
|
|
1379
1437
|
const entry = FIX_TABLE.find(
|
|
@@ -1475,6 +1533,15 @@ async function addPostCompactHook(root) {
|
|
|
1475
1533
|
log.success("Added PostCompact hook (re-injects TASKS.md after compaction)");
|
|
1476
1534
|
return true;
|
|
1477
1535
|
}
|
|
1536
|
+
async function migrateAttribution(root) {
|
|
1537
|
+
const settings = await readSettingsJson(root);
|
|
1538
|
+
if (settings.includeCoAuthoredBy === void 0) return false;
|
|
1539
|
+
const { includeCoAuthoredBy: _, ...rest } = settings;
|
|
1540
|
+
const updated = { ...rest, attribution: { commit: "", pr: "" } };
|
|
1541
|
+
await writeSettingsJson(root, updated);
|
|
1542
|
+
log.success("Migrated includeCoAuthoredBy \u2192 attribution object");
|
|
1543
|
+
return true;
|
|
1544
|
+
}
|
|
1478
1545
|
async function addCredentialDenyRules(root) {
|
|
1479
1546
|
const settings = await readSettingsJson(root);
|
|
1480
1547
|
const permissions = settings.permissions ?? {};
|
|
@@ -1660,7 +1727,7 @@ async function runAndDisplay(projectRoot) {
|
|
|
1660
1727
|
|
|
1661
1728
|
// src/commands/doctor/index.ts
|
|
1662
1729
|
function createDoctorCommand() {
|
|
1663
|
-
return new Command2("doctor").description("Diagnose your Claude Code configuration and report issues").option("-p, --path <path>", "Project root path", process.cwd()).option("--json", "Output as JSON").option("--min-score <n>", "Exit non-zero if overall score is below this threshold (for CI)").option("--fix", "Auto-apply deterministic fixes for detected issues").option("--watch", "Watch for config changes and re-run automatically").action(async (opts) => {
|
|
1730
|
+
return new Command2("doctor").description("Diagnose your Claude Code configuration and report issues").option("-p, --path <path>", "Project root path", process.cwd()).option("--json", "Output as JSON").option("--min-score <n>", "Exit non-zero if overall score is below this threshold (for CI)").option("--fix", "Auto-apply deterministic fixes for detected issues").option("--dry-run", "Preview what --fix would change without applying").option("--watch", "Watch for config changes and re-run automatically").action(async (opts) => {
|
|
1664
1731
|
if (opts.watch) {
|
|
1665
1732
|
await watchConfig(opts.path);
|
|
1666
1733
|
return;
|
|
@@ -1697,13 +1764,36 @@ function createDoctorCommand() {
|
|
|
1697
1764
|
const allIssues = results.flatMap((r) => r.issues);
|
|
1698
1765
|
const fixable = allIssues.filter((i) => i.severity !== "info");
|
|
1699
1766
|
if (fixable.length > 0) {
|
|
1767
|
+
if (opts.dryRun) {
|
|
1768
|
+
log.blank();
|
|
1769
|
+
log.step("Dry run \u2014 would apply these fixes:");
|
|
1770
|
+
log.blank();
|
|
1771
|
+
for (const issue of fixable) {
|
|
1772
|
+
log.info(` Would fix: ${issue.message}`);
|
|
1773
|
+
}
|
|
1774
|
+
log.blank();
|
|
1775
|
+
log.success(`${fixable.length} fix(es) available. Run --fix without --dry-run to apply.`);
|
|
1776
|
+
return;
|
|
1777
|
+
}
|
|
1700
1778
|
log.blank();
|
|
1701
1779
|
log.step("Applying fixes...");
|
|
1702
1780
|
log.blank();
|
|
1703
1781
|
const { fixed, skipped } = await applyFixes(fixable, opts.path);
|
|
1704
1782
|
log.blank();
|
|
1705
1783
|
if (fixed > 0) {
|
|
1706
|
-
log.success(`Applied ${fixed} fix(es).
|
|
1784
|
+
log.success(`Applied ${fixed} fix(es). Re-scanning...`);
|
|
1785
|
+
log.blank();
|
|
1786
|
+
const updatedConfig = await parseClaudeConfig(opts.path);
|
|
1787
|
+
const updatedResults = await Promise.all([
|
|
1788
|
+
analyzeBudget(updatedConfig),
|
|
1789
|
+
analyzeQuality(updatedConfig),
|
|
1790
|
+
analyzeSettings(updatedConfig),
|
|
1791
|
+
analyzeHooks(updatedConfig),
|
|
1792
|
+
analyzeRules(updatedConfig),
|
|
1793
|
+
analyzePermissions(updatedConfig),
|
|
1794
|
+
analyzeMcp(updatedConfig)
|
|
1795
|
+
]);
|
|
1796
|
+
renderDoctorReport(updatedResults);
|
|
1707
1797
|
}
|
|
1708
1798
|
if (skipped > 0) {
|
|
1709
1799
|
log.info(`${skipped} issue(s) require manual intervention.`);
|
|
@@ -2346,9 +2436,15 @@ Also review .claude/settings.json hooks:
|
|
|
2346
2436
|
- Read the existing hooks in .claude/settings.json
|
|
2347
2437
|
- If you see project-specific patterns that deserve hooks (e.g., protected directories, test file patterns, migration files), suggest adding them
|
|
2348
2438
|
- If no PostCompact hook exists, suggest adding one that re-injects TASKS.md after context compaction (critical for session continuity)
|
|
2439
|
+
- If no SessionStart hook exists, suggest adding one that injects TASKS.md at session startup
|
|
2349
2440
|
- DO NOT overwrite existing hooks \u2014 only add new ones that are specific to this project
|
|
2350
2441
|
- Print hook suggestions at the end with the exact JSON to add, don't modify settings.json directly
|
|
2351
2442
|
|
|
2443
|
+
Also check for advanced configuration opportunities:
|
|
2444
|
+
- If the project has both app code and tests, suggest creating path-scoped .claude/rules/ files with paths: frontmatter (e.g., test conventions only load when editing test files)
|
|
2445
|
+
- If the project uses external APIs (Stripe, GitHub, AWS SDKs, etc.), suggest sandbox.network.allowedDomains to restrict outbound traffic
|
|
2446
|
+
- If you detect a monorepo (Turborepo, Lerna, pnpm workspaces, multiple package.json), suggest claudeMdExcludes in settings.json
|
|
2447
|
+
|
|
2352
2448
|
Rules:
|
|
2353
2449
|
- Don't remove existing content \u2014 only add or improve
|
|
2354
2450
|
- Be specific to THIS project, not generic advice
|