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 +7 -0
- package/dist/chunk-KOSJII4R.js +62 -0
- package/dist/chunk-KOSJII4R.js.map +1 -0
- package/dist/cli.js +85 -44
- package/dist/cli.js.map +1 -1
- package/dist/{install-4GQ57KCQ.js → install-U6WARER4.js} +46 -20
- package/dist/install-U6WARER4.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-CSLWJEGD.js +0 -25
- package/dist/chunk-CSLWJEGD.js.map +0 -1
- package/dist/install-4GQ57KCQ.js.map +0 -1
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
|
-
|
|
5
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 .
|
|
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
|
|
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(
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
1959
|
-
|
|
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
|
|
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
|
|
1979
|
-
|
|
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
|
|
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
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
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-
|
|
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.
|
|
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" });
|