claude-launchpad 0.13.0 → 0.14.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/README.md CHANGED
@@ -72,7 +72,7 @@ Init generates all three. Doctor checks for them. `--fix` creates any that are m
72
72
  | `claude-launchpad init` | Detect stack, generate config + hooks + permissions | Locally, free |
73
73
  | `claude-launchpad doctor --fix` | Auto-fix issues found by doctor | Locally, free |
74
74
  | `claude-launchpad eval` | Run Claude against test scenarios, score results | Via Claude CLI |
75
- | `claude-launchpad memory` | Optional persistent memory system | Locally |
75
+ | `claude-launchpad memory` | Optional knowledge base that persists across sessions | Locally |
76
76
  | `/lp-enhance` (skill) | Claude reads your code and completes CLAUDE.md | Inside Claude Code |
77
77
 
78
78
  ## Doctor
@@ -193,7 +193,7 @@ Results save to `.claude/eval/` as structured markdown. Feed them back to Claude
193
193
 
194
194
  ## Memory
195
195
 
196
- Optional persistent memory that replaces Claude Code's built-in flat-file system. Memories decay naturally, so stale knowledge fades and relevant context stays.
196
+ Claude maintains a personal knowledge base about your project. It learns what matters, forgets what doesn't, and gets smarter every session.
197
197
 
198
198
  ```bash
199
199
  claude-launchpad memory
@@ -201,14 +201,9 @@ claude-launchpad memory
201
201
 
202
202
  If memory is not installed, it runs interactive setup. If installed, it shows stats. Requires native deps first: `npm install better-sqlite3 sqlite-vec`.
203
203
 
204
- **What it does:**
205
- - **Smart session injection** loads the most relevant memories at session start
206
- - **Stop hook** extracts facts from the conversation when you finish
207
- - **Decay model** fades memories naturally (episodic: 30 days, semantic: 18 months, procedural: 2 years)
208
- - **Self-tuning retrieval** promotes memories Claude searches for, demotes ones injected but never used
209
- - **Project-scoped** with no cross-contamination between projects
210
- - **TUI dashboard** (`--dashboard`) with vim navigation, filtering, and search
211
- - **Cross-device sync** pushes and pulls memories between machines via private GitHub Gist
204
+ Every session, Claude loads what it needs to know and extracts new knowledge when you finish. Stale facts fade on their own. Knowledge Claude actually uses gets reinforced. Each project has its own isolated memory, and you can sync it across machines via private GitHub Gist.
205
+
206
+ Browse everything with `--dashboard` -- a terminal UI with vim navigation, filtering, and search.
212
207
 
213
208
  Data stays in `~/.agentic-memory/memory.db`. Sync requires the [GitHub CLI](https://cli.github.com/) (`gh`).
214
209
 
package/dist/cli.js CHANGED
@@ -534,8 +534,10 @@ DerivedData/
534
534
  }
535
535
 
536
536
  // src/commands/init/generators/skill-enhance.ts
537
+ var ENHANCE_SKILL_VERSION = 4;
537
538
  function generateEnhanceSkill() {
538
539
  return [
540
+ `<!-- lp-enhance-version: ${ENHANCE_SKILL_VERSION} -->`,
539
541
  "---",
540
542
  "name: lp-enhance",
541
543
  "description: |",
@@ -555,9 +557,11 @@ function generateEnhanceSkill() {
555
557
  "1. Read CLAUDE.md (if it exists)",
556
558
  "2. Read .claude/settings.json (hooks, permissions, MCP)",
557
559
  "3. Read .claude/rules/*.md (existing rules)",
558
- "4. Scan src/ directory structure (top-level dirs, key files)",
559
- "5. Read package.json / go.mod / pyproject.toml for stack detection",
560
- "6. Check for monorepo indicators (workspaces, nx.json, lerna.json)",
560
+ "4. Read .claudeignore (if it exists)",
561
+ "5. Scan src/ directory structure (top-level dirs, key files)",
562
+ "6. Read package.json / go.mod / pyproject.toml for stack detection",
563
+ "7. Check for monorepo indicators (workspaces, nx.json, lerna.json)",
564
+ "8. Check scenarios/ directory for existing eval scenarios",
561
565
  "",
562
566
  "**Done when:** you have a mental model of the stack, architecture, and existing config.",
563
567
  "",
@@ -584,7 +588,9 @@ function generateEnhanceSkill() {
584
588
  "",
585
589
  "1. Create or update .claude/rules/ files for overflow content",
586
590
  "2. Generate path-scoped rules if the project has distinct areas (see below)",
587
- "3. Verify line count is under 200",
591
+ "3. Review .claudeignore and print suggestions (see below)",
592
+ "4. Generate 2-3 custom eval scenarios in scenarios/custom/ (see below)",
593
+ "5. Verify line count is under 200",
588
594
  "",
589
595
  "**Rules:**",
590
596
  "- Don't remove existing content, only add or improve",
@@ -596,8 +602,9 @@ function generateEnhanceSkill() {
596
602
  "1. Run `claude-launchpad doctor` to check the score improved",
597
603
  "2. Print suggested hooks (exact JSON) for .claude/settings.json but don't modify it",
598
604
  "3. Print suggested MCP servers if external services detected (Postgres, Redis, Stripe, etc.)",
605
+ '4. If eval scenarios were generated, print: "Run this in your terminal (not inside Claude Code): `claude-launchpad eval --scenarios scenarios/`"',
599
606
  "",
600
- "**Done when:** doctor score is equal or higher, suggestions printed.",
607
+ "**Done when:** doctor score is equal or higher, suggestions printed, eval scenarios created if applicable.",
601
608
  "",
602
609
  "## Path-scoped rules generation",
603
610
  "",
@@ -657,6 +664,72 @@ function generateEnhanceSkill() {
657
664
  "- If no SessionStart hook exists, suggest one that injects TASKS.md",
658
665
  "- DO NOT modify settings.json directly. Print exact JSON to add.",
659
666
  "",
667
+ "## .claudeignore review",
668
+ "",
669
+ "Read .claudeignore and check if the patterns make sense for the detected stack:",
670
+ "",
671
+ "**Always flag:**",
672
+ "- Missing node_modules/ (JS/TS projects)",
673
+ "- Missing __pycache__/ or .venv/ (Python projects)",
674
+ "- Missing target/ (Rust/Java projects)",
675
+ "- Missing .env / .env.* patterns",
676
+ "- Missing lock files (pnpm-lock.yaml, package-lock.json, yarn.lock, etc.)",
677
+ "- Missing coverage/ directory",
678
+ "- Large generated files that waste context (*.min.js, *.map, migrations/)",
679
+ "",
680
+ "**Never flag:**",
681
+ "- Patterns the user clearly added intentionally",
682
+ "- Test fixtures or seed data (might be needed for context)",
683
+ "",
684
+ "If .claudeignore is missing entirely, create one with sensible defaults for the detected stack.",
685
+ "If it exists but has gaps, print suggested additions. Do NOT modify it directly.",
686
+ "",
687
+ "## Eval scenario generation",
688
+ "",
689
+ "After improving CLAUDE.md, generate 2-3 custom eval scenarios that test whether Claude follows the project's specific rules. Write them as YAML files in scenarios/ at the project root.",
690
+ "",
691
+ "**Scenario YAML format:**",
692
+ "```yaml",
693
+ "name: custom/scenario-name",
694
+ "description: What this scenario tests",
695
+ "setup:",
696
+ " files:",
697
+ " - path: src/example.ts",
698
+ " content: |",
699
+ " // Starter file that tempts Claude to break a rule",
700
+ " instructions: |",
701
+ " The specific rule from CLAUDE.md being tested.",
702
+ 'prompt: "A task that would tempt Claude to break the rule"',
703
+ "checks:",
704
+ " - type: grep",
705
+ ' pattern: "expected_pattern"',
706
+ " target: src/example.ts",
707
+ " expect: present",
708
+ " points: 5",
709
+ " label: What this check verifies",
710
+ " - type: file-exists",
711
+ " target: path/to/expected/file",
712
+ " expect: present",
713
+ " points: 5",
714
+ " label: What this check verifies",
715
+ "passingScore: 7",
716
+ "runs: 3",
717
+ "```",
718
+ "",
719
+ "**How to choose scenarios:**",
720
+ "1. Pick the 2-3 most important rules from ## Off-Limits and ## Conventions",
721
+ "2. Design a task that naturally tempts Claude to break each rule",
722
+ "3. Write checks that verify compliance (grep for patterns, file-exists for structure)",
723
+ "",
724
+ "**Check types available:** `grep` (pattern in file), `file-exists` (present/absent), `max-lines` (file length)",
725
+ "",
726
+ "**Examples of good custom scenarios:**",
727
+ '- Off-limits says "never use any" \u2192 task asks to build types, check for no `any` keyword',
728
+ '- Convention says "max 400 lines per file" \u2192 task asks to generate a large module, check line count',
729
+ '- Off-limits says "no raw SQL" \u2192 task asks to add a query, check for ORM usage',
730
+ "",
731
+ "**Skip if:** scenarios/ already has 3+ YAML files, or CLAUDE.md has no project-specific rules worth testing.",
732
+ "",
660
733
  "## Other advanced configuration",
661
734
  "",
662
735
  "- If the project uses external APIs, suggest sandbox.network.allowedDomains",
@@ -1241,6 +1314,16 @@ async function analyzeRules(config) {
1241
1314
  message: "No /lp-enhance skill found \u2014 use it inside Claude Code to AI-complete your CLAUDE.md",
1242
1315
  fix: "Run `claude-launchpad init` or `doctor --fix` to generate the skill"
1243
1316
  });
1317
+ } else {
1318
+ const installedVersion = await getSkillVersion(projectRoot);
1319
+ if (installedVersion !== null && installedVersion < ENHANCE_SKILL_VERSION) {
1320
+ issues.push({
1321
+ analyzer: "Rules",
1322
+ severity: "low",
1323
+ message: `/lp-enhance skill is outdated (v${installedVersion}, latest v${ENHANCE_SKILL_VERSION})`,
1324
+ fix: "Run `doctor --fix` to update the skill"
1325
+ });
1326
+ }
1244
1327
  }
1245
1328
  if (config.rules.length === 0) {
1246
1329
  issues.push({
@@ -1280,6 +1363,23 @@ async function analyzeRules(config) {
1280
1363
  const score = Math.max(0, 100 - issues.length * 10);
1281
1364
  return { name: "Rules", issues, score };
1282
1365
  }
1366
+ async function getSkillVersion(projectRoot) {
1367
+ const paths = [
1368
+ join4(projectRoot, ".claude", "skills", "lp-enhance", "SKILL.md"),
1369
+ join4(homedir2(), ".claude", "skills", "lp-enhance", "SKILL.md")
1370
+ ];
1371
+ for (const p of paths) {
1372
+ try {
1373
+ const content = await readFile3(p, "utf-8");
1374
+ const match = content.match(/<!-- lp-enhance-version: (\d+) -->/);
1375
+ if (match) return parseInt(match[1], 10);
1376
+ return 0;
1377
+ } catch {
1378
+ continue;
1379
+ }
1380
+ }
1381
+ return null;
1382
+ }
1283
1383
 
1284
1384
  // src/commands/doctor/analyzers/permissions.ts
1285
1385
  async function analyzePermissions(config) {
@@ -1641,6 +1741,7 @@ var FIX_TABLE = [
1641
1741
  { analyzer: "Permissions", match: "Sandbox not enabled", fix: (root) => addSandboxSettings(root) },
1642
1742
  { analyzer: "Permissions", match: ".env is protected by hooks but not in .claudeignore", fix: (root) => addEnvToClaudeignore(root) },
1643
1743
  { analyzer: "Rules", match: "No /lp-enhance skill", fix: (root) => createEnhanceSkill(root) },
1744
+ { analyzer: "Rules", match: "lp-enhance skill is outdated", fix: (root) => updateEnhanceSkill(root) },
1644
1745
  { analyzer: "Settings", match: "Deprecated includeCoAuthoredBy", fix: (root) => migrateAttribution(root) },
1645
1746
  { analyzer: "Hooks", match: "SessionStart", fix: (root) => addSessionStartHook(root) },
1646
1747
  { analyzer: "Memory", match: "autoMemoryEnabled not disabled", fix: (root) => disableAutoMemory(root) },
@@ -1888,6 +1989,15 @@ async function createEnhanceSkill(root) {
1888
1989
  log.success("Generated /lp-enhance skill (.claude/skills/lp-enhance/)");
1889
1990
  return true;
1890
1991
  }
1992
+ async function updateEnhanceSkill(root) {
1993
+ const projectPath = join5(root, ".claude", "skills", "lp-enhance", "SKILL.md");
1994
+ const globalPath = join5(homedir3(), ".claude", "skills", "lp-enhance", "SKILL.md");
1995
+ const targetPath = await fileExists(projectPath) ? projectPath : await fileExists(globalPath) ? globalPath : null;
1996
+ if (!targetPath) return false;
1997
+ await writeFile2(targetPath, generateEnhanceSkill());
1998
+ log.success("Updated /lp-enhance skill to latest version");
1999
+ return true;
2000
+ }
1891
2001
 
1892
2002
  // src/commands/doctor/watcher.ts
1893
2003
  import { readdir as readdir2, stat } from "fs/promises";
@@ -2666,10 +2776,10 @@ function isMemoryInstalled() {
2666
2776
  }
2667
2777
  }
2668
2778
  function createMemoryCommand() {
2669
- const memory = new Command4("memory").description("Persistent memory system for Claude Code sessions").option("--dashboard", "Open the memory dashboard").action(async (opts) => {
2779
+ const memory = new Command4("memory").description("Knowledge base that Claude maintains across sessions").option("--dashboard", "Open the memory dashboard").action(async (opts) => {
2670
2780
  if (opts.dashboard) {
2671
2781
  if (!isMemoryInstalled()) {
2672
- log.error("Memory system is not installed. Run `claude-launchpad memory` first.");
2782
+ log.error("Knowledge base not set up yet. Run `claude-launchpad memory` first.");
2673
2783
  return;
2674
2784
  }
2675
2785
  const { requireMemoryDeps } = await import("./require-deps-NKRCPVAO.js");
@@ -2680,23 +2790,22 @@ function createMemoryCommand() {
2680
2790
  }
2681
2791
  if (!isMemoryInstalled()) {
2682
2792
  log.blank();
2683
- log.step("Agentic memory is not set up for this project.");
2793
+ log.step("Claude doesn't have a knowledge base for this project yet.");
2684
2794
  log.blank();
2685
- log.info("This will (skipping what's already in place):");
2686
- log.info(" - Set up SQLite database at ~/.agentic-memory/");
2687
- log.info(" - Add SessionStart + Stop hooks to .claude/settings.json");
2688
- log.info(" - Register the MCP server with Claude Code (global)");
2689
- log.info(" - Add memory guidance to CLAUDE.md");
2795
+ log.info("After setup, Claude will:");
2796
+ log.info(" - Remember decisions, gotchas, and learnings across sessions");
2797
+ log.info(" - Automatically recall relevant context when you start a session");
2798
+ log.info(" - Save important facts as you work, so nothing gets lost");
2690
2799
  log.blank();
2691
2800
  const proceed = await confirm2({
2692
- message: "Install agentic-memory?",
2801
+ message: "Set up knowledge base?",
2693
2802
  default: true
2694
2803
  });
2695
2804
  if (!proceed) {
2696
2805
  log.info("Skipped.");
2697
2806
  return;
2698
2807
  }
2699
- const { runInstall } = await import("./install-C5XDWATE.js");
2808
+ const { runInstall } = await import("./install-H6GW4P6K.js");
2700
2809
  await runInstall({});
2701
2810
  } else {
2702
2811
  const { requireMemoryDeps } = await import("./require-deps-NKRCPVAO.js");
@@ -2742,7 +2851,7 @@ function createMemoryCommand() {
2742
2851
  }
2743
2852
 
2744
2853
  // src/cli.ts
2745
- var program = new Command5().name("claude-launchpad").description("CLI toolkit that makes Claude Code setups measurably good").version("0.13.0", "-v, --version").action(async () => {
2854
+ var program = new Command5().name("claude-launchpad").description("CLI toolkit that makes Claude Code setups measurably good").version("0.14.0", "-v, --version").action(async () => {
2746
2855
  const hasConfig = await fileExists(join11(process.cwd(), "CLAUDE.md")) || await fileExists(join11(process.cwd(), ".claude", "settings.json"));
2747
2856
  if (hasConfig) {
2748
2857
  await program.commands.find((c) => c.name() === "doctor")?.parseAsync([], { from: "user" });