claude-launchpad 0.14.2 → 0.15.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
@@ -201,6 +201,13 @@ 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
+ During setup, you choose where memory config lives:
205
+
206
+ - **Shared** (default) — config goes to `CLAUDE.md` + `settings.json` (committed, team sees it)
207
+ - **Local** — config goes to `.claude/CLAUDE.md` + `settings.local.json` (gitignored, only you)
208
+
209
+ Use "local" when co-devs have different memory setups (e.g. you use agentic-memory, they use built-in). Your choice is persisted so `doctor --fix` won't re-ask.
210
+
204
211
  Every session, Claude loads what it needs to know and stores new knowledge as it works. 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
212
 
206
213
  Browse everything with `--dashboard` -- a terminal UI with vim navigation, filtering, and search.
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/lib/settings.ts
4
+ import { readFile, writeFile, mkdir } from "fs/promises";
5
+ import { join } from "path";
6
+ async function readSettingsJson(root) {
7
+ const path = join(root, ".claude", "settings.json");
8
+ try {
9
+ const content = await readFile(path, "utf-8");
10
+ return JSON.parse(content);
11
+ } catch {
12
+ return {};
13
+ }
14
+ }
15
+ async function writeSettingsJson(root, settings) {
16
+ const dir = join(root, ".claude");
17
+ await mkdir(dir, { recursive: true });
18
+ await writeFile(join(dir, "settings.json"), JSON.stringify(settings, null, 2) + "\n");
19
+ }
20
+ async function readSettingsLocalJson(root) {
21
+ const path = join(root, ".claude", "settings.local.json");
22
+ try {
23
+ const content = await readFile(path, "utf-8");
24
+ return JSON.parse(content);
25
+ } catch {
26
+ return {};
27
+ }
28
+ }
29
+ async function writeSettingsLocalJson(root, settings) {
30
+ const dir = join(root, ".claude");
31
+ await mkdir(dir, { recursive: true });
32
+ await writeFile(join(dir, "settings.local.json"), JSON.stringify(settings, null, 2) + "\n");
33
+ }
34
+
35
+ // src/lib/memory-placement.ts
36
+ import { select } from "@inquirer/prompts";
37
+ async function getMemoryPlacement(root, skipPrompt = false) {
38
+ const local = await readSettingsLocalJson(root);
39
+ const persisted = local.memoryPlacement;
40
+ if (persisted === "shared" || persisted === "local") {
41
+ return persisted;
42
+ }
43
+ if (skipPrompt) return "shared";
44
+ const choice = await select({
45
+ message: "Where should memory config go?",
46
+ choices: [
47
+ { value: "shared", name: "Shared (team sees it) \u2014 CLAUDE.md + settings.json" },
48
+ { value: "local", name: "Local (only you) \u2014 .claude/CLAUDE.md + settings.local.json" }
49
+ ]
50
+ });
51
+ await writeSettingsLocalJson(root, { ...local, memoryPlacement: choice });
52
+ return choice;
53
+ }
54
+
55
+ export {
56
+ readSettingsJson,
57
+ writeSettingsJson,
58
+ readSettingsLocalJson,
59
+ writeSettingsLocalJson,
60
+ getMemoryPlacement
61
+ };
62
+ //# sourceMappingURL=chunk-KOSJII4R.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/settings.ts","../src/lib/memory-placement.ts"],"sourcesContent":["import { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport async function readSettingsJson(root: string): Promise<Record<string, unknown>> {\n const path = join(root, \".claude\", \"settings.json\");\n try {\n const content = await readFile(path, \"utf-8\");\n return JSON.parse(content) as Record<string, unknown>;\n } catch {\n return {};\n }\n}\n\nexport async function writeSettingsJson(root: string, settings: Record<string, unknown>): Promise<void> {\n const dir = join(root, \".claude\");\n await mkdir(dir, { recursive: true });\n await writeFile(join(dir, \"settings.json\"), JSON.stringify(settings, null, 2) + \"\\n\");\n}\n\nexport async function readSettingsLocalJson(root: string): Promise<Record<string, unknown>> {\n const path = join(root, \".claude\", \"settings.local.json\");\n try {\n const content = await readFile(path, \"utf-8\");\n return JSON.parse(content) as Record<string, unknown>;\n } catch {\n return {};\n }\n}\n\nexport async function writeSettingsLocalJson(root: string, settings: Record<string, unknown>): Promise<void> {\n const dir = join(root, \".claude\");\n await mkdir(dir, { recursive: true });\n await writeFile(join(dir, \"settings.local.json\"), JSON.stringify(settings, null, 2) + \"\\n\");\n}\n","import { select } from \"@inquirer/prompts\";\nimport { readSettingsLocalJson, writeSettingsLocalJson } from \"./settings.js\";\nimport type { MemoryPlacement } from \"../types/index.js\";\n\nexport async function getMemoryPlacement(root: string, skipPrompt = false): Promise<MemoryPlacement> {\n const local = await readSettingsLocalJson(root);\n const persisted = local.memoryPlacement;\n if (persisted === \"shared\" || persisted === \"local\") {\n return persisted;\n }\n\n if (skipPrompt) return \"shared\";\n\n const choice = await select<MemoryPlacement>({\n message: \"Where should memory config go?\",\n choices: [\n { value: \"shared\", name: \"Shared (team sees it) — CLAUDE.md + settings.json\" },\n { value: \"local\", name: \"Local (only you) — .claude/CLAUDE.md + settings.local.json\" },\n ],\n });\n\n await writeSettingsLocalJson(root, { ...local, memoryPlacement: choice });\n return choice;\n}\n"],"mappings":";;;AAAA,SAAS,UAAU,WAAW,aAAa;AAC3C,SAAS,YAAY;AAErB,eAAsB,iBAAiB,MAAgD;AACrF,QAAM,OAAO,KAAK,MAAM,WAAW,eAAe;AAClD,MAAI;AACF,UAAM,UAAU,MAAM,SAAS,MAAM,OAAO;AAC5C,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEA,eAAsB,kBAAkB,MAAc,UAAkD;AACtG,QAAM,MAAM,KAAK,MAAM,SAAS;AAChC,QAAM,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AACpC,QAAM,UAAU,KAAK,KAAK,eAAe,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,IAAI,IAAI;AACtF;AAEA,eAAsB,sBAAsB,MAAgD;AAC1F,QAAM,OAAO,KAAK,MAAM,WAAW,qBAAqB;AACxD,MAAI;AACF,UAAM,UAAU,MAAM,SAAS,MAAM,OAAO;AAC5C,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEA,eAAsB,uBAAuB,MAAc,UAAkD;AAC3G,QAAM,MAAM,KAAK,MAAM,SAAS;AAChC,QAAM,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AACpC,QAAM,UAAU,KAAK,KAAK,qBAAqB,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,IAAI,IAAI;AAC5F;;;ACjCA,SAAS,cAAc;AAIvB,eAAsB,mBAAmB,MAAc,aAAa,OAAiC;AACnG,QAAM,QAAQ,MAAM,sBAAsB,IAAI;AAC9C,QAAM,YAAY,MAAM;AACxB,MAAI,cAAc,YAAY,cAAc,SAAS;AACnD,WAAO;AAAA,EACT;AAEA,MAAI,WAAY,QAAO;AAEvB,QAAM,SAAS,MAAM,OAAwB;AAAA,IAC3C,SAAS;AAAA,IACT,SAAS;AAAA,MACP,EAAE,OAAO,UAAU,MAAM,yDAAoD;AAAA,MAC7E,EAAE,OAAO,SAAS,MAAM,kEAA6D;AAAA,IACvF;AAAA,EACF,CAAC;AAED,QAAM,uBAAuB,MAAM,EAAE,GAAG,OAAO,iBAAiB,OAAO,CAAC;AACxE,SAAO;AACT;","names":[]}
package/dist/cli.js CHANGED
@@ -1,8 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ getMemoryPlacement,
3
4
  readSettingsJson,
4
- writeSettingsJson
5
- } from "./chunk-CSLWJEGD.js";
5
+ readSettingsLocalJson,
6
+ writeSettingsJson,
7
+ writeSettingsLocalJson
8
+ } from "./chunk-KOSJII4R.js";
6
9
  import {
7
10
  log,
8
11
  printBanner,
@@ -824,6 +827,7 @@ async function scaffold(root, options, detected, skipPrompts) {
824
827
  if (!hasClaudeGitignore) {
825
828
  writes.push(writeFile(claudeGitignorePath, [
826
829
  "# Local-only Claude Code files (never commit these)",
830
+ "CLAUDE.md",
827
831
  "settings.local.json",
828
832
  "plans/",
829
833
  "memory/",
@@ -942,13 +946,16 @@ import { join as join3, resolve } from "path";
942
946
  var CLAUDE_MD = "CLAUDE.md";
943
947
  var CLAUDE_DIR = ".claude";
944
948
  var SETTINGS_FILE = "settings.json";
949
+ var SETTINGS_LOCAL_FILE = "settings.local.json";
945
950
  var RULES_DIR = "rules";
946
951
  async function parseClaudeConfig(projectRoot) {
947
952
  const root = resolve(projectRoot);
948
953
  const claudeDir = join3(root, CLAUDE_DIR);
949
- const [claudeMd, settings, hooks, rules, mcpServers, skills, claudeignore] = await Promise.all([
954
+ const [claudeMd, localClaudeMd, settings, localSettings, hooks, rules, mcpServers, skills, claudeignore] = await Promise.all([
950
955
  readClaudeMd(root),
956
+ readFileOrNull(join3(claudeDir, CLAUDE_MD)),
951
957
  readSettings(claudeDir),
958
+ readSettingsFromFile(claudeDir, SETTINGS_LOCAL_FILE),
952
959
  readHooks(claudeDir),
953
960
  readRules(claudeDir),
954
961
  readMcpServers(claudeDir),
@@ -962,6 +969,8 @@ async function parseClaudeConfig(projectRoot) {
962
969
  claudeMdInstructionCount: instructionCount,
963
970
  settingsPath: settings !== null ? join3(claudeDir, SETTINGS_FILE) : null,
964
971
  settings,
972
+ localClaudeMdContent: localClaudeMd,
973
+ localSettings,
965
974
  hooks,
966
975
  rules,
967
976
  mcpServers,
@@ -987,7 +996,10 @@ function countInstructions(content) {
987
996
  return count;
988
997
  }
989
998
  async function readSettings(claudeDir) {
990
- const raw = await readFileOrNull(join3(claudeDir, SETTINGS_FILE));
999
+ return readSettingsFromFile(claudeDir, SETTINGS_FILE);
1000
+ }
1001
+ async function readSettingsFromFile(claudeDir, filename) {
1002
+ const raw = await readFileOrNull(join3(claudeDir, filename));
991
1003
  if (raw === null) return null;
992
1004
  try {
993
1005
  return JSON.parse(raw);
@@ -1540,11 +1552,7 @@ var MEMORY_MCP_TOOLS = [
1540
1552
  "mcp__agentic-memory__memory_update"
1541
1553
  ];
1542
1554
  function hasMemoryIndicators(config) {
1543
- const hasMcpServer = config.mcpServers.some((s) => s.name === "agentic-memory");
1544
- const hasHookRef = config.hooks.some(
1545
- (h) => h.command?.includes("memory context")
1546
- );
1547
- return hasMcpServer || hasHookRef;
1555
+ return config.mcpServers.some((s) => s.name === "agentic-memory");
1548
1556
  }
1549
1557
  async function analyzeMemory(config) {
1550
1558
  if (!hasMemoryIndicators(config)) return null;
@@ -1571,16 +1579,16 @@ async function analyzeMemory(config) {
1571
1579
  fix: "Run `doctor --fix` to remove the stale Stop hook"
1572
1580
  });
1573
1581
  }
1574
- const autoMemoryDisabled = config.settings?.autoMemoryEnabled === false;
1582
+ const autoMemoryDisabled = config.settings?.autoMemoryEnabled === false || config.localSettings?.autoMemoryEnabled === false;
1575
1583
  if (!autoMemoryDisabled) {
1576
1584
  issues.push({
1577
1585
  analyzer: "Memory",
1578
1586
  severity: "medium",
1579
1587
  message: "autoMemoryEnabled not disabled \u2014 built-in memory may conflict with agentic-memory",
1580
- fix: "Set autoMemoryEnabled: false in .claude/settings.json"
1588
+ fix: "Set autoMemoryEnabled: false in settings.json or settings.local.json"
1581
1589
  });
1582
1590
  }
1583
- const hasMemoryGuidance = config.claudeMdContent?.includes("agentic-memory") || config.claudeMdContent?.includes("## Memory");
1591
+ const hasMemoryGuidance = config.claudeMdContent?.includes("agentic-memory") || config.claudeMdContent?.includes("## Memory") || config.localClaudeMdContent?.includes("agentic-memory") || config.localClaudeMdContent?.includes("## Memory");
1584
1592
  if (!hasMemoryGuidance) {
1585
1593
  issues.push({
1586
1594
  analyzer: "Memory",
@@ -1590,7 +1598,11 @@ async function analyzeMemory(config) {
1590
1598
  });
1591
1599
  }
1592
1600
  const permissions = config.settings?.permissions ?? {};
1593
- const allowList = permissions.allow ?? [];
1601
+ const localPermissions = config.localSettings?.permissions ?? {};
1602
+ const allowList = [
1603
+ ...permissions.allow ?? [],
1604
+ ...localPermissions.allow ?? []
1605
+ ];
1594
1606
  const missingTools = MEMORY_MCP_TOOLS.filter((t) => !allowList.includes(t));
1595
1607
  if (missingTools.length > 0) {
1596
1608
  issues.push({
@@ -1643,9 +1655,10 @@ async function analyzeQuality(config) {
1643
1655
  return { name: "CLAUDE.md Quality", issues, score: 0 };
1644
1656
  }
1645
1657
  const sections = hasMemoryIndicators(config) ? [...BASE_SECTIONS, MEMORY_SECTION] : [...BASE_SECTIONS];
1658
+ const combinedContent = [content, config.localClaudeMdContent].filter(Boolean).join("\n");
1646
1659
  let sectionsFound = 0;
1647
1660
  for (const section of sections) {
1648
- if (section.pattern.test(content)) {
1661
+ if (section.pattern.test(combinedContent)) {
1649
1662
  sectionsFound++;
1650
1663
  } else {
1651
1664
  issues.push({
@@ -1699,10 +1712,12 @@ import { join as join5 } from "path";
1699
1712
  import { homedir as homedir3 } from "os";
1700
1713
  async function applyFixes(issues, projectRoot) {
1701
1714
  const detected = await detectProject(projectRoot);
1715
+ const hasMemoryIssues = issues.some((i) => i.analyzer === "Memory");
1716
+ const placement = hasMemoryIssues ? await getMemoryPlacement(projectRoot) : "shared";
1702
1717
  let fixed = 0;
1703
1718
  let skipped = 0;
1704
1719
  for (const issue of issues) {
1705
- const applied = await tryFix(issue, projectRoot, detected);
1720
+ const applied = await tryFix(issue, projectRoot, detected, placement);
1706
1721
  if (applied) {
1707
1722
  fixed++;
1708
1723
  } else {
@@ -1746,15 +1761,19 @@ var FIX_TABLE = [
1746
1761
  { analyzer: "Settings", match: "Deprecated includeCoAuthoredBy", fix: (root) => migrateAttribution(root) },
1747
1762
  { analyzer: "Hooks", match: "SessionStart", fix: (root) => addSessionStartHook(root) },
1748
1763
  { analyzer: "Memory", match: "Deprecated Stop hook", fix: (root) => removeStaleStopHook(root) },
1749
- { analyzer: "Memory", match: "autoMemoryEnabled not disabled", fix: (root) => disableAutoMemory(root) },
1750
- { analyzer: "Memory", match: "MCP tool permission", fix: (root) => addMemoryToolPermissions(root) },
1751
- { analyzer: "Memory", match: "CLAUDE.md missing memory guidance", fix: (root) => addClaudeMdSection(root, "## Memory", "Use agentic-memory to persist knowledge across sessions:\n- Memories are automatically injected at session start\n- STORE IMMEDIATELY when: a dependency strategy changes, an architecture decision is made, a convention is established, a bug pattern is discovered, or a feature is killed/added\n- Use memory_search before memory_store to check for duplicates\n- NEVER store credentials, API keys, tokens, or secrets in memories") }
1764
+ { analyzer: "Memory", match: "autoMemoryEnabled not disabled", fix: (root, _det, placement) => disableAutoMemory(root, placement) },
1765
+ { analyzer: "Memory", match: "MCP tool permission", fix: (root, _det, placement) => addMemoryToolPermissions(root, placement) },
1766
+ { analyzer: "Memory", match: "CLAUDE.md missing memory guidance", fix: (root, _det, placement) => {
1767
+ const content = "Use agentic-memory to persist knowledge across sessions:\n- Memories are automatically injected at session start\n- STORE IMMEDIATELY when: a dependency strategy changes, an architecture decision is made, a convention is established, a bug pattern is discovered, or a feature is killed/added\n- Use memory_search before memory_store to check for duplicates\n- NEVER store credentials, API keys, tokens, or secrets in memories";
1768
+ const target = placement === "local" ? join5(root, ".claude", "CLAUDE.md") : void 0;
1769
+ return addClaudeMdSection(root, "## Memory", content, target);
1770
+ } }
1752
1771
  ];
1753
- async function tryFix(issue, root, detected) {
1772
+ async function tryFix(issue, root, detected, placement) {
1754
1773
  const entry = FIX_TABLE.find(
1755
1774
  (e) => e.analyzer === issue.analyzer && issue.message.includes(e.match)
1756
1775
  );
1757
- return entry ? entry.fix(root, detected) : false;
1776
+ return entry ? entry.fix(root, detected, placement) : false;
1758
1777
  }
1759
1778
  async function addHook(root, event, dedupKeyword, entry, successMsg) {
1760
1779
  const settings = await readSettingsJson(root);
@@ -1881,13 +1900,15 @@ async function addEnvToClaudeignore(root) {
1881
1900
  log.success("Added .env to .claudeignore");
1882
1901
  return true;
1883
1902
  }
1884
- async function addClaudeMdSection(root, heading, content) {
1885
- const claudeMdPath = join5(root, "CLAUDE.md");
1903
+ async function addClaudeMdSection(root, heading, content, targetPath) {
1904
+ const claudeMdPath = targetPath ?? join5(root, "CLAUDE.md");
1886
1905
  let existing;
1887
1906
  try {
1888
1907
  existing = await readFile4(claudeMdPath, "utf-8");
1889
1908
  } catch {
1890
- return false;
1909
+ if (!targetPath) return false;
1910
+ await mkdir2(join5(root, ".claude"), { recursive: true });
1911
+ existing = "# Local Claude Config\n";
1891
1912
  }
1892
1913
  if (existing.includes(heading)) return false;
1893
1914
  const keyDecisionsIdx = existing.indexOf("## Key Decisions");
@@ -1899,7 +1920,8 @@ ${content}
1899
1920
  `;
1900
1921
  const updated = existing.slice(0, insertAt) + section + existing.slice(insertAt);
1901
1922
  await writeFile2(claudeMdPath, updated);
1902
- log.success(`Added "${heading}" section to CLAUDE.md`);
1923
+ const label = targetPath ? ".claude/CLAUDE.md" : "CLAUDE.md";
1924
+ log.success(`Added "${heading}" section to ${label}`);
1903
1925
  return true;
1904
1926
  }
1905
1927
  async function createBacklogMd(root) {
@@ -1951,16 +1973,21 @@ async function createStarterRules(root) {
1951
1973
  log.success("Created .claude/rules/conventions.md with starter rules");
1952
1974
  return true;
1953
1975
  }
1954
- async function disableAutoMemory(root) {
1955
- const settings = await readSettingsJson(root);
1976
+ async function disableAutoMemory(root, placement) {
1977
+ const read = placement === "local" ? readSettingsLocalJson : readSettingsJson;
1978
+ const write = placement === "local" ? writeSettingsLocalJson : writeSettingsJson;
1979
+ const settings = await read(root);
1956
1980
  if (settings.autoMemoryEnabled === false) return false;
1957
1981
  settings.autoMemoryEnabled = false;
1958
- await writeSettingsJson(root, settings);
1959
- log.success("Set autoMemoryEnabled: false (prevents conflict with agentic-memory)");
1982
+ await write(root, settings);
1983
+ const target = placement === "local" ? "settings.local.json" : "settings.json";
1984
+ log.success(`Set autoMemoryEnabled: false in ${target}`);
1960
1985
  return true;
1961
1986
  }
1962
- async function addMemoryToolPermissions(root) {
1963
- const settings = await readSettingsJson(root);
1987
+ async function addMemoryToolPermissions(root, placement) {
1988
+ const read = placement === "local" ? readSettingsLocalJson : readSettingsJson;
1989
+ const write = placement === "local" ? writeSettingsLocalJson : writeSettingsJson;
1990
+ const settings = await read(root);
1964
1991
  const permissions = settings.permissions ?? {};
1965
1992
  const allow = permissions.allow ?? [];
1966
1993
  const tools = [
@@ -1975,8 +2002,9 @@ async function addMemoryToolPermissions(root) {
1975
2002
  const missing = tools.filter((t) => !allow.includes(t));
1976
2003
  if (missing.length === 0) return false;
1977
2004
  settings.permissions = { ...permissions, allow: [...allow, ...missing] };
1978
- await writeSettingsJson(root, settings);
1979
- log.success("Added agentic-memory MCP tool permissions to allowedTools");
2005
+ await write(root, settings);
2006
+ const target = placement === "local" ? "settings.local.json" : "settings.json";
2007
+ log.success(`Added agentic-memory MCP tool permissions to ${target}`);
1980
2008
  return true;
1981
2009
  }
1982
2010
  async function createEnhanceSkill(root) {
@@ -2784,9 +2812,12 @@ import { join as join10 } from "path";
2784
2812
  import { Command as Command4 } from "commander";
2785
2813
  import { confirm as confirm2 } from "@inquirer/prompts";
2786
2814
  function isMemoryInstalled() {
2815
+ const cwd = process.cwd();
2816
+ return hasMemoryHook(join10(cwd, ".claude", "settings.json")) || hasMemoryHook(join10(cwd, ".claude", "settings.local.json"));
2817
+ }
2818
+ function hasMemoryHook(path) {
2787
2819
  try {
2788
- const settingsPath = join10(process.cwd(), ".claude", "settings.json");
2789
- const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
2820
+ const settings = JSON.parse(readFileSync(path, "utf-8"));
2790
2821
  const hooks = settings.hooks;
2791
2822
  if (!hooks) return false;
2792
2823
  const sessionStart = hooks.SessionStart;
@@ -2812,14 +2843,24 @@ function createMemoryCommand() {
2812
2843
  return;
2813
2844
  }
2814
2845
  if (!isMemoryInstalled()) {
2815
- log.blank();
2816
- log.step("Claude doesn't have a knowledge base for this project yet.");
2817
- log.blank();
2818
- log.info("After setup, Claude will:");
2819
- log.info(" - Remember decisions, gotchas, and learnings across sessions");
2820
- log.info(" - Automatically recall relevant context when you start a session");
2821
- log.info(" - Save important facts as you work, so nothing gets lost");
2822
- log.blank();
2846
+ const { detectExistingSetup } = await import("./install-U6WARER4.js");
2847
+ const existing = detectExistingSetup(process.cwd());
2848
+ if (existing) {
2849
+ const location = existing === "local" ? ".claude/CLAUDE.md + settings.local.json" : "CLAUDE.md + settings.json";
2850
+ log.blank();
2851
+ log.success(`Memory config found (${location}) but database not set up.`);
2852
+ log.info("Run the install to complete setup.");
2853
+ log.blank();
2854
+ } else {
2855
+ log.blank();
2856
+ log.step("Claude doesn't have a knowledge base for this project yet.");
2857
+ log.blank();
2858
+ log.info("After setup, Claude will:");
2859
+ log.info(" - Remember decisions, gotchas, and learnings across sessions");
2860
+ log.info(" - Automatically recall relevant context when you start a session");
2861
+ log.info(" - Save important facts as you work, so nothing gets lost");
2862
+ log.blank();
2863
+ }
2823
2864
  const proceed = await confirm2({
2824
2865
  message: "Set up knowledge base?",
2825
2866
  default: true
@@ -2828,7 +2869,7 @@ function createMemoryCommand() {
2828
2869
  log.info("Skipped.");
2829
2870
  return;
2830
2871
  }
2831
- const { runInstall } = await import("./install-4GQ57KCQ.js");
2872
+ const { runInstall } = await import("./install-U6WARER4.js");
2832
2873
  await runInstall({});
2833
2874
  } else {
2834
2875
  const { requireMemoryDeps } = await import("./require-deps-NKRCPVAO.js");
@@ -2867,7 +2908,7 @@ function createMemoryCommand() {
2867
2908
  }
2868
2909
 
2869
2910
  // src/cli.ts
2870
- var program = new Command5().name("claude-launchpad").description("CLI toolkit that makes Claude Code setups measurably good").version("0.14.2", "-v, --version").action(async () => {
2911
+ var program = new Command5().name("claude-launchpad").description("CLI toolkit that makes Claude Code setups measurably good").version("0.15.0", "-v, --version").action(async () => {
2871
2912
  const hasConfig = await fileExists(join11(process.cwd(), "CLAUDE.md")) || await fileExists(join11(process.cwd(), ".claude", "settings.json"));
2872
2913
  if (hasConfig) {
2873
2914
  await program.commands.find((c) => c.name() === "doctor")?.parseAsync([], { from: "user" });