claude-launchpad 0.15.2 → 0.16.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 +3 -3
- package/dist/{chunk-4D3EBDNB.js → chunk-24VLPHJU.js} +16 -2
- package/dist/chunk-24VLPHJU.js.map +1 -0
- package/dist/{chunk-AHEX2RG7.js → chunk-5MWCQLNL.js} +2 -2
- package/dist/{chunk-IPVN6SO4.js → chunk-JQDMBE7W.js} +14 -65
- package/dist/chunk-JQDMBE7W.js.map +1 -0
- package/dist/{chunk-KOSJII4R.js → chunk-SBA5KYQU.js} +15 -1
- package/dist/chunk-SBA5KYQU.js.map +1 -0
- package/dist/chunk-TSTTFR4B.js +68 -0
- package/dist/chunk-TSTTFR4B.js.map +1 -0
- package/dist/cli.js +300 -125
- package/dist/cli.js.map +1 -1
- package/dist/commands/memory/server.js +1 -1
- package/dist/{context-XPXKLF5V.js → context-CWJUUTTU.js} +3 -3
- package/dist/{install-UXO5BISS.js → install-MVATZUXZ.js} +49 -6
- package/dist/install-MVATZUXZ.js.map +1 -0
- package/dist/{pull-3O4B6EL2.js → pull-YOESZ3UC.js} +9 -7
- package/dist/{pull-3O4B6EL2.js.map → pull-YOESZ3UC.js.map} +1 -1
- package/dist/{push-BGN3DVV5.js → push-74XC5CUK.js} +18 -8
- package/dist/push-74XC5CUK.js.map +1 -0
- package/dist/{stats-P7S3FTCQ.js → stats-QUBHHPV7.js} +3 -3
- package/dist/{tui-GUCKDWDM.js → tui-XIYOOUP6.js} +113 -46
- package/dist/tui-XIYOOUP6.js.map +1 -0
- package/package.json +3 -2
- package/dist/chunk-4D3EBDNB.js.map +0 -1
- package/dist/chunk-IPVN6SO4.js.map +0 -1
- package/dist/chunk-KOSJII4R.js.map +0 -1
- package/dist/install-UXO5BISS.js.map +0 -1
- package/dist/push-BGN3DVV5.js.map +0 -1
- package/dist/tui-GUCKDWDM.js.map +0 -1
- /package/dist/{chunk-AHEX2RG7.js.map → chunk-5MWCQLNL.js.map} +0 -0
- /package/dist/{context-XPXKLF5V.js.map → context-CWJUUTTU.js.map} +0 -0
- /package/dist/{stats-P7S3FTCQ.js.map → stats-QUBHHPV7.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -5,7 +5,10 @@ import {
|
|
|
5
5
|
readSettingsLocalJson,
|
|
6
6
|
writeSettingsJson,
|
|
7
7
|
writeSettingsLocalJson
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-SBA5KYQU.js";
|
|
9
|
+
import {
|
|
10
|
+
readSyncConfig
|
|
11
|
+
} from "./chunk-JQDMBE7W.js";
|
|
9
12
|
import {
|
|
10
13
|
log,
|
|
11
14
|
printBanner,
|
|
@@ -15,7 +18,7 @@ import {
|
|
|
15
18
|
|
|
16
19
|
// src/cli.ts
|
|
17
20
|
import { Command as Command5 } from "commander";
|
|
18
|
-
import { join as
|
|
21
|
+
import { join as join12 } from "path";
|
|
19
22
|
|
|
20
23
|
// src/commands/init/index.ts
|
|
21
24
|
import { Command } from "commander";
|
|
@@ -945,7 +948,7 @@ async function parseClaudeConfig(projectRoot) {
|
|
|
945
948
|
readSettingsFromFile(claudeDir, SETTINGS_LOCAL_FILE),
|
|
946
949
|
readHooks(claudeDir),
|
|
947
950
|
readRules(claudeDir),
|
|
948
|
-
readMcpServers(claudeDir),
|
|
951
|
+
readMcpServers(claudeDir, root),
|
|
949
952
|
readSkills(claudeDir),
|
|
950
953
|
readFileOrNull(join3(root, ".claudeignore"))
|
|
951
954
|
]);
|
|
@@ -995,7 +998,14 @@ async function readSettingsFromFile(claudeDir, filename) {
|
|
|
995
998
|
}
|
|
996
999
|
}
|
|
997
1000
|
async function readHooks(claudeDir) {
|
|
998
|
-
const
|
|
1001
|
+
const [shared, local] = await Promise.all([
|
|
1002
|
+
readHooksFromFile(join3(claudeDir, SETTINGS_FILE)),
|
|
1003
|
+
readHooksFromFile(join3(claudeDir, SETTINGS_LOCAL_FILE))
|
|
1004
|
+
]);
|
|
1005
|
+
return [...shared, ...local];
|
|
1006
|
+
}
|
|
1007
|
+
async function readHooksFromFile(settingsPath) {
|
|
1008
|
+
const settingsRaw = await readFileOrNull(settingsPath);
|
|
999
1009
|
if (settingsRaw === null) return [];
|
|
1000
1010
|
try {
|
|
1001
1011
|
const settings = JSON.parse(settingsRaw);
|
|
@@ -1039,8 +1049,46 @@ async function readRules(claudeDir) {
|
|
|
1039
1049
|
const rulesDir = join3(claudeDir, RULES_DIR);
|
|
1040
1050
|
return listFilesRecursive(rulesDir, ".md");
|
|
1041
1051
|
}
|
|
1042
|
-
async function readMcpServers(claudeDir) {
|
|
1043
|
-
const
|
|
1052
|
+
async function readMcpServers(claudeDir, projectRoot) {
|
|
1053
|
+
const [fromMcpJson, fromSettings, fromLocalSettings] = await Promise.all([
|
|
1054
|
+
readMcpJsonFile(join3(projectRoot, ".mcp.json")),
|
|
1055
|
+
readMcpServersFromSettings(join3(claudeDir, SETTINGS_FILE)),
|
|
1056
|
+
readMcpServersFromSettings(join3(claudeDir, SETTINGS_LOCAL_FILE))
|
|
1057
|
+
]);
|
|
1058
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1059
|
+
const result = [];
|
|
1060
|
+
for (const server of [...fromMcpJson, ...fromLocalSettings, ...fromSettings]) {
|
|
1061
|
+
if (!seen.has(server.name)) {
|
|
1062
|
+
seen.add(server.name);
|
|
1063
|
+
result.push(server);
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
return result;
|
|
1067
|
+
}
|
|
1068
|
+
async function readMcpJsonFile(mcpJsonPath) {
|
|
1069
|
+
const raw = await readFileOrNull(mcpJsonPath);
|
|
1070
|
+
if (raw === null) return [];
|
|
1071
|
+
try {
|
|
1072
|
+
const parsed = JSON.parse(raw);
|
|
1073
|
+
const servers = parsed.mcpServers;
|
|
1074
|
+
if (!servers || typeof servers !== "object") return [];
|
|
1075
|
+
const result = [];
|
|
1076
|
+
for (const [name, config] of Object.entries(servers)) {
|
|
1077
|
+
const c = config;
|
|
1078
|
+
result.push({
|
|
1079
|
+
name,
|
|
1080
|
+
transport: c.transport ?? "stdio",
|
|
1081
|
+
command: c.command,
|
|
1082
|
+
url: c.url
|
|
1083
|
+
});
|
|
1084
|
+
}
|
|
1085
|
+
return result;
|
|
1086
|
+
} catch {
|
|
1087
|
+
return [];
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
async function readMcpServersFromSettings(settingsPath) {
|
|
1091
|
+
const settingsRaw = await readFileOrNull(settingsPath);
|
|
1044
1092
|
if (settingsRaw === null) return [];
|
|
1045
1093
|
try {
|
|
1046
1094
|
const settings = JSON.parse(settingsRaw);
|
|
@@ -1524,6 +1572,32 @@ async function analyzeMcp(config) {
|
|
|
1524
1572
|
}
|
|
1525
1573
|
}
|
|
1526
1574
|
}
|
|
1575
|
+
if (servers.length > 0) {
|
|
1576
|
+
const settings = config.settings ?? {};
|
|
1577
|
+
const localSettings = config.localSettings ?? {};
|
|
1578
|
+
const hasAllowList = settings.allowedMcpServers || localSettings.allowedMcpServers;
|
|
1579
|
+
if (!hasAllowList) {
|
|
1580
|
+
issues.push({
|
|
1581
|
+
analyzer: "MCP",
|
|
1582
|
+
severity: "medium",
|
|
1583
|
+
message: "MCP servers configured but no allowedMcpServers list \u2014 any added server is auto-trusted",
|
|
1584
|
+
fix: "Add allowedMcpServers to settings.json listing only trusted server names"
|
|
1585
|
+
});
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
if (servers.length > 0) {
|
|
1589
|
+
const sandbox = config.settings?.sandbox ?? config.localSettings?.sandbox;
|
|
1590
|
+
const hasNetwork = sandbox?.network !== void 0;
|
|
1591
|
+
const httpServers = servers.filter((s) => s.transport === "sse" || s.transport === "http");
|
|
1592
|
+
if (sandbox?.enabled === true && httpServers.length > 0 && !hasNetwork) {
|
|
1593
|
+
issues.push({
|
|
1594
|
+
analyzer: "MCP",
|
|
1595
|
+
severity: "low",
|
|
1596
|
+
message: "Sandbox enabled with HTTP MCP servers but no network restrictions configured",
|
|
1597
|
+
fix: "Add sandbox.network.allowedHosts to restrict which hosts MCP servers can reach"
|
|
1598
|
+
});
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1527
1601
|
const score = Math.max(0, 100 - issues.filter((i) => i.severity !== "info").length * 25);
|
|
1528
1602
|
return { name: "MCP Servers", issues, score };
|
|
1529
1603
|
}
|
|
@@ -1539,7 +1613,16 @@ var MEMORY_MCP_TOOLS = [
|
|
|
1539
1613
|
"mcp__agentic-memory__memory_update"
|
|
1540
1614
|
];
|
|
1541
1615
|
function hasMemoryIndicators(config) {
|
|
1542
|
-
|
|
1616
|
+
if (config.mcpServers.some((s) => s.name === "agentic-memory")) return true;
|
|
1617
|
+
const permissions = config.settings?.permissions ?? {};
|
|
1618
|
+
const localPermissions = config.localSettings?.permissions ?? {};
|
|
1619
|
+
const allowList = [
|
|
1620
|
+
...permissions.allow ?? [],
|
|
1621
|
+
...localPermissions.allow ?? []
|
|
1622
|
+
];
|
|
1623
|
+
if (allowList.some((t) => t.startsWith("mcp__agentic-memory__"))) return true;
|
|
1624
|
+
if (config.hooks.some((h) => h.event === "SessionStart" && h.command?.includes("memory context"))) return true;
|
|
1625
|
+
return false;
|
|
1543
1626
|
}
|
|
1544
1627
|
async function analyzeMemory(config) {
|
|
1545
1628
|
if (!hasMemoryIndicators(config)) return null;
|
|
@@ -1599,6 +1682,31 @@ async function analyzeMemory(config) {
|
|
|
1599
1682
|
fix: "Add all agentic-memory tool names to allowedTools in .claude/settings.json"
|
|
1600
1683
|
});
|
|
1601
1684
|
}
|
|
1685
|
+
const syncConfig = readSyncConfig();
|
|
1686
|
+
if (syncConfig) {
|
|
1687
|
+
const hasSessionStartPull = config.hooks.some(
|
|
1688
|
+
(h) => h.event === "SessionStart" && h.command?.includes("memory pull")
|
|
1689
|
+
);
|
|
1690
|
+
if (!hasSessionStartPull) {
|
|
1691
|
+
issues.push({
|
|
1692
|
+
analyzer: "Memory",
|
|
1693
|
+
severity: "medium",
|
|
1694
|
+
message: "Sync configured but no SessionStart hook to auto-pull memories before context injection",
|
|
1695
|
+
fix: "Run `doctor --fix` to add a SessionStart hook that pulls memories automatically"
|
|
1696
|
+
});
|
|
1697
|
+
}
|
|
1698
|
+
const hasSessionEndPush = config.hooks.some(
|
|
1699
|
+
(h) => h.event === "SessionEnd" && h.command?.includes("memory push")
|
|
1700
|
+
);
|
|
1701
|
+
if (!hasSessionEndPush) {
|
|
1702
|
+
issues.push({
|
|
1703
|
+
analyzer: "Memory",
|
|
1704
|
+
severity: "medium",
|
|
1705
|
+
message: "Sync configured but no SessionEnd hook to auto-push memories after each session",
|
|
1706
|
+
fix: "Run `doctor --fix` to add a SessionEnd hook that pushes memories automatically"
|
|
1707
|
+
});
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1602
1710
|
const critical = issues.filter((i) => i.severity === "critical").length;
|
|
1603
1711
|
const high = issues.filter((i) => i.severity === "high").length;
|
|
1604
1712
|
const medium = issues.filter((i) => i.severity === "medium").length;
|
|
@@ -1694,9 +1802,127 @@ async function analyzeQuality(config) {
|
|
|
1694
1802
|
}
|
|
1695
1803
|
|
|
1696
1804
|
// src/commands/doctor/fixer.ts
|
|
1697
|
-
import { readFile as
|
|
1698
|
-
import { join as
|
|
1805
|
+
import { readFile as readFile5, writeFile as writeFile2, mkdir as mkdir2, access as access4 } from "fs/promises";
|
|
1806
|
+
import { join as join6 } from "path";
|
|
1699
1807
|
import { homedir as homedir3 } from "os";
|
|
1808
|
+
|
|
1809
|
+
// src/commands/doctor/fixer-memory.ts
|
|
1810
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
1811
|
+
import { join as join5 } from "path";
|
|
1812
|
+
async function addPlacementHook(root, placement, event, dedupKeyword, entry, prepend, successMsg) {
|
|
1813
|
+
const read = placement === "local" ? readSettingsLocalJson : readSettingsJson;
|
|
1814
|
+
const write = placement === "local" ? writeSettingsLocalJson : writeSettingsJson;
|
|
1815
|
+
const settings = await read(root);
|
|
1816
|
+
const hooks = settings.hooks ?? {};
|
|
1817
|
+
const hookList = hooks[event] ?? [];
|
|
1818
|
+
const alreadyHas = hookList.some((g) => {
|
|
1819
|
+
const nested = g.hooks;
|
|
1820
|
+
return nested?.some((h) => String(h.command ?? "").includes(dedupKeyword));
|
|
1821
|
+
});
|
|
1822
|
+
if (alreadyHas) return false;
|
|
1823
|
+
hooks[event] = prepend ? [entry, ...hookList] : [...hookList, entry];
|
|
1824
|
+
settings.hooks = hooks;
|
|
1825
|
+
await write(root, settings);
|
|
1826
|
+
log.success(successMsg);
|
|
1827
|
+
return true;
|
|
1828
|
+
}
|
|
1829
|
+
async function disableAutoMemory(root, placement) {
|
|
1830
|
+
const read = placement === "local" ? readSettingsLocalJson : readSettingsJson;
|
|
1831
|
+
const write = placement === "local" ? writeSettingsLocalJson : writeSettingsJson;
|
|
1832
|
+
const settings = await read(root);
|
|
1833
|
+
if (settings.autoMemoryEnabled === false) return false;
|
|
1834
|
+
settings.autoMemoryEnabled = false;
|
|
1835
|
+
await write(root, settings);
|
|
1836
|
+
const target = placement === "local" ? "settings.local.json" : "settings.json";
|
|
1837
|
+
log.success(`Set autoMemoryEnabled: false in ${target}`);
|
|
1838
|
+
return true;
|
|
1839
|
+
}
|
|
1840
|
+
async function addMemoryToolPermissions(root, placement) {
|
|
1841
|
+
const read = placement === "local" ? readSettingsLocalJson : readSettingsJson;
|
|
1842
|
+
const write = placement === "local" ? writeSettingsLocalJson : writeSettingsJson;
|
|
1843
|
+
const settings = await read(root);
|
|
1844
|
+
const permissions = settings.permissions ?? {};
|
|
1845
|
+
const allow = permissions.allow ?? [];
|
|
1846
|
+
const tools = [
|
|
1847
|
+
"mcp__agentic-memory__memory_store",
|
|
1848
|
+
"mcp__agentic-memory__memory_search",
|
|
1849
|
+
"mcp__agentic-memory__memory_recent",
|
|
1850
|
+
"mcp__agentic-memory__memory_forget",
|
|
1851
|
+
"mcp__agentic-memory__memory_relate",
|
|
1852
|
+
"mcp__agentic-memory__memory_stats",
|
|
1853
|
+
"mcp__agentic-memory__memory_update"
|
|
1854
|
+
];
|
|
1855
|
+
const missing = tools.filter((t) => !allow.includes(t));
|
|
1856
|
+
if (missing.length === 0) return false;
|
|
1857
|
+
settings.permissions = { ...permissions, allow: [...allow, ...missing] };
|
|
1858
|
+
await write(root, settings);
|
|
1859
|
+
const target = placement === "local" ? "settings.local.json" : "settings.json";
|
|
1860
|
+
log.success(`Added agentic-memory MCP tool permissions to ${target}`);
|
|
1861
|
+
return true;
|
|
1862
|
+
}
|
|
1863
|
+
async function addSessionStartPullHook(root, placement) {
|
|
1864
|
+
const target = placement === "local" ? "settings.local.json" : "settings.json";
|
|
1865
|
+
return addPlacementHook(root, placement, "SessionStart", "memory pull", {
|
|
1866
|
+
matcher: "startup",
|
|
1867
|
+
hooks: [{ type: "command", command: "claude-launchpad memory pull -y 2>/dev/null; exit 0" }]
|
|
1868
|
+
}, true, `Added SessionStart hook for memory sync to ${target}`);
|
|
1869
|
+
}
|
|
1870
|
+
async function addSessionEndPushHook(root, placement) {
|
|
1871
|
+
const target = placement === "local" ? "settings.local.json" : "settings.json";
|
|
1872
|
+
return addPlacementHook(root, placement, "SessionEnd", "memory push", {
|
|
1873
|
+
hooks: [{ type: "command", command: "claude-launchpad memory push -y >/dev/null 2>&1 & exit 0" }]
|
|
1874
|
+
}, false, `Added SessionEnd hook for memory sync to ${target}`);
|
|
1875
|
+
}
|
|
1876
|
+
async function removeStaleStopHook(root) {
|
|
1877
|
+
const settings = await readSettingsJson(root);
|
|
1878
|
+
const hooks = settings.hooks;
|
|
1879
|
+
if (!hooks?.Stop) return false;
|
|
1880
|
+
const stopHooks = hooks.Stop;
|
|
1881
|
+
const filtered = stopHooks.filter((h) => {
|
|
1882
|
+
const innerHooks = h.hooks;
|
|
1883
|
+
return !innerHooks?.some(
|
|
1884
|
+
(ih) => typeof ih.command === "string" && ih.command.includes("memory extract")
|
|
1885
|
+
);
|
|
1886
|
+
});
|
|
1887
|
+
if (filtered.length === stopHooks.length) return false;
|
|
1888
|
+
const updated = filtered.length === 0 ? (({ Stop: _, ...rest }) => rest)(hooks) : { ...hooks, Stop: filtered };
|
|
1889
|
+
settings.hooks = updated;
|
|
1890
|
+
await writeSettingsJson(root, settings);
|
|
1891
|
+
log.success("Removed deprecated Stop hook (memory extract)");
|
|
1892
|
+
return true;
|
|
1893
|
+
}
|
|
1894
|
+
async function addAllowedMcpServers(root, placement) {
|
|
1895
|
+
const read = placement === "local" ? readSettingsLocalJson : readSettingsJson;
|
|
1896
|
+
const write = placement === "local" ? writeSettingsLocalJson : writeSettingsJson;
|
|
1897
|
+
const settings = await read(root);
|
|
1898
|
+
if (settings.allowedMcpServers) return false;
|
|
1899
|
+
const other = placement === "local" ? await readSettingsJson(root) : await readSettingsLocalJson(root);
|
|
1900
|
+
if (other.allowedMcpServers) return false;
|
|
1901
|
+
const serverNames = /* @__PURE__ */ new Set();
|
|
1902
|
+
const settingsServers = settings.mcpServers;
|
|
1903
|
+
if (settingsServers && typeof settingsServers === "object") {
|
|
1904
|
+
for (const name of Object.keys(settingsServers)) serverNames.add(name);
|
|
1905
|
+
}
|
|
1906
|
+
const mcpJsonPath = join5(root, ".mcp.json");
|
|
1907
|
+
try {
|
|
1908
|
+
const mcpJson = JSON.parse(await readFile4(mcpJsonPath, "utf-8"));
|
|
1909
|
+
const mcpServers = mcpJson.mcpServers;
|
|
1910
|
+
if (mcpServers && typeof mcpServers === "object") {
|
|
1911
|
+
for (const name of Object.keys(mcpServers)) serverNames.add(name);
|
|
1912
|
+
}
|
|
1913
|
+
} catch {
|
|
1914
|
+
}
|
|
1915
|
+
if (serverNames.size === 0) return false;
|
|
1916
|
+
settings.allowedMcpServers = [...serverNames].map(
|
|
1917
|
+
(name) => ({ serverName: name })
|
|
1918
|
+
);
|
|
1919
|
+
await write(root, settings);
|
|
1920
|
+
const target = placement === "local" ? "settings.local.json" : "settings.json";
|
|
1921
|
+
log.success(`Added allowedMcpServers from configured servers to ${target}`);
|
|
1922
|
+
return true;
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
// src/commands/doctor/fixer.ts
|
|
1700
1926
|
async function applyFixes(issues, projectRoot) {
|
|
1701
1927
|
const detected = await detectProject(projectRoot);
|
|
1702
1928
|
const hasMemoryIssues = issues.some((i) => i.analyzer === "Memory");
|
|
@@ -1718,7 +1944,8 @@ var FIX_TABLE = [
|
|
|
1718
1944
|
const a = await addEnvProtectionHook(root);
|
|
1719
1945
|
const b = await addAutoFormatHook(root, detected);
|
|
1720
1946
|
const c = await addForcePushProtection(root);
|
|
1721
|
-
|
|
1947
|
+
const d = await addSessionStartHook(root);
|
|
1948
|
+
return a || b || c || d;
|
|
1722
1949
|
} },
|
|
1723
1950
|
{ analyzer: "Hooks", match: ".env file protection", fix: (root) => addEnvProtectionHook(root) },
|
|
1724
1951
|
{ analyzer: "Hooks", match: "auto-format", fix: (root, detected) => addAutoFormatHook(root, detected) },
|
|
@@ -1750,9 +1977,12 @@ var FIX_TABLE = [
|
|
|
1750
1977
|
{ analyzer: "Memory", match: "Deprecated Stop hook", fix: (root) => removeStaleStopHook(root) },
|
|
1751
1978
|
{ analyzer: "Memory", match: "autoMemoryEnabled not disabled", fix: (root, _det, placement) => disableAutoMemory(root, placement) },
|
|
1752
1979
|
{ analyzer: "Memory", match: "MCP tool permission", fix: (root, _det, placement) => addMemoryToolPermissions(root, placement) },
|
|
1980
|
+
{ analyzer: "MCP", match: "no allowedMcpServers", fix: (root, _det, placement) => addAllowedMcpServers(root, placement) },
|
|
1981
|
+
{ analyzer: "Memory", match: "SessionStart hook to auto-pull", fix: (root, _det, placement) => addSessionStartPullHook(root, placement) },
|
|
1982
|
+
{ analyzer: "Memory", match: "SessionEnd hook to auto-push", fix: (root, _det, placement) => addSessionEndPushHook(root, placement) },
|
|
1753
1983
|
{ analyzer: "Memory", match: "CLAUDE.md missing memory guidance", fix: (root, _det, placement) => {
|
|
1754
1984
|
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";
|
|
1755
|
-
const target = placement === "local" ?
|
|
1985
|
+
const target = placement === "local" ? join6(root, ".claude", "CLAUDE.md") : void 0;
|
|
1756
1986
|
return addClaudeMdSection(root, "## Memory", content, target);
|
|
1757
1987
|
} }
|
|
1758
1988
|
];
|
|
@@ -1874,10 +2104,10 @@ async function addSandboxSettings(root) {
|
|
|
1874
2104
|
return true;
|
|
1875
2105
|
}
|
|
1876
2106
|
async function addEnvToClaudeignore(root) {
|
|
1877
|
-
const ignorePath =
|
|
2107
|
+
const ignorePath = join6(root, ".claudeignore");
|
|
1878
2108
|
let content;
|
|
1879
2109
|
try {
|
|
1880
|
-
content = await
|
|
2110
|
+
content = await readFile5(ignorePath, "utf-8");
|
|
1881
2111
|
} catch {
|
|
1882
2112
|
return false;
|
|
1883
2113
|
}
|
|
@@ -1888,13 +2118,13 @@ async function addEnvToClaudeignore(root) {
|
|
|
1888
2118
|
return true;
|
|
1889
2119
|
}
|
|
1890
2120
|
async function addClaudeMdSection(root, heading, content, targetPath) {
|
|
1891
|
-
const claudeMdPath = targetPath ??
|
|
2121
|
+
const claudeMdPath = targetPath ?? join6(root, "CLAUDE.md");
|
|
1892
2122
|
let existing;
|
|
1893
2123
|
try {
|
|
1894
|
-
existing = await
|
|
2124
|
+
existing = await readFile5(claudeMdPath, "utf-8");
|
|
1895
2125
|
} catch {
|
|
1896
2126
|
if (!targetPath) return false;
|
|
1897
|
-
await mkdir2(
|
|
2127
|
+
await mkdir2(join6(root, ".claude"), { recursive: true });
|
|
1898
2128
|
existing = "# Local Claude Config\n";
|
|
1899
2129
|
}
|
|
1900
2130
|
if (existing.includes(heading)) return false;
|
|
@@ -1912,7 +2142,7 @@ ${content}
|
|
|
1912
2142
|
return true;
|
|
1913
2143
|
}
|
|
1914
2144
|
async function createBacklogMd(root) {
|
|
1915
|
-
const backlogPath =
|
|
2145
|
+
const backlogPath = join6(root, "BACKLOG.md");
|
|
1916
2146
|
try {
|
|
1917
2147
|
await access4(backlogPath);
|
|
1918
2148
|
return false;
|
|
@@ -1928,7 +2158,7 @@ async function createBacklogMd(root) {
|
|
|
1928
2158
|
return true;
|
|
1929
2159
|
}
|
|
1930
2160
|
async function createClaudeignore(root, detected) {
|
|
1931
|
-
const ignorePath =
|
|
2161
|
+
const ignorePath = join6(root, ".claudeignore");
|
|
1932
2162
|
try {
|
|
1933
2163
|
await access4(ignorePath);
|
|
1934
2164
|
return false;
|
|
@@ -1940,7 +2170,7 @@ async function createClaudeignore(root, detected) {
|
|
|
1940
2170
|
return true;
|
|
1941
2171
|
}
|
|
1942
2172
|
async function createStarterRules(root) {
|
|
1943
|
-
const rulesDir =
|
|
2173
|
+
const rulesDir = join6(root, ".claude", "rules");
|
|
1944
2174
|
try {
|
|
1945
2175
|
await access4(rulesDir);
|
|
1946
2176
|
return false;
|
|
@@ -1948,7 +2178,7 @@ async function createStarterRules(root) {
|
|
|
1948
2178
|
}
|
|
1949
2179
|
await mkdir2(rulesDir, { recursive: true });
|
|
1950
2180
|
await writeFile2(
|
|
1951
|
-
|
|
2181
|
+
join6(rulesDir, "conventions.md"),
|
|
1952
2182
|
`# Project Conventions
|
|
1953
2183
|
|
|
1954
2184
|
- Use conventional commits (feat:, fix:, docs:, refactor:, test:, chore:)
|
|
@@ -1960,46 +2190,12 @@ async function createStarterRules(root) {
|
|
|
1960
2190
|
log.success("Created .claude/rules/conventions.md with starter rules");
|
|
1961
2191
|
return true;
|
|
1962
2192
|
}
|
|
1963
|
-
async function disableAutoMemory(root, placement) {
|
|
1964
|
-
const read = placement === "local" ? readSettingsLocalJson : readSettingsJson;
|
|
1965
|
-
const write = placement === "local" ? writeSettingsLocalJson : writeSettingsJson;
|
|
1966
|
-
const settings = await read(root);
|
|
1967
|
-
if (settings.autoMemoryEnabled === false) return false;
|
|
1968
|
-
settings.autoMemoryEnabled = false;
|
|
1969
|
-
await write(root, settings);
|
|
1970
|
-
const target = placement === "local" ? "settings.local.json" : "settings.json";
|
|
1971
|
-
log.success(`Set autoMemoryEnabled: false in ${target}`);
|
|
1972
|
-
return true;
|
|
1973
|
-
}
|
|
1974
|
-
async function addMemoryToolPermissions(root, placement) {
|
|
1975
|
-
const read = placement === "local" ? readSettingsLocalJson : readSettingsJson;
|
|
1976
|
-
const write = placement === "local" ? writeSettingsLocalJson : writeSettingsJson;
|
|
1977
|
-
const settings = await read(root);
|
|
1978
|
-
const permissions = settings.permissions ?? {};
|
|
1979
|
-
const allow = permissions.allow ?? [];
|
|
1980
|
-
const tools = [
|
|
1981
|
-
"mcp__agentic-memory__memory_store",
|
|
1982
|
-
"mcp__agentic-memory__memory_search",
|
|
1983
|
-
"mcp__agentic-memory__memory_recent",
|
|
1984
|
-
"mcp__agentic-memory__memory_forget",
|
|
1985
|
-
"mcp__agentic-memory__memory_relate",
|
|
1986
|
-
"mcp__agentic-memory__memory_stats",
|
|
1987
|
-
"mcp__agentic-memory__memory_update"
|
|
1988
|
-
];
|
|
1989
|
-
const missing = tools.filter((t) => !allow.includes(t));
|
|
1990
|
-
if (missing.length === 0) return false;
|
|
1991
|
-
settings.permissions = { ...permissions, allow: [...allow, ...missing] };
|
|
1992
|
-
await write(root, settings);
|
|
1993
|
-
const target = placement === "local" ? "settings.local.json" : "settings.json";
|
|
1994
|
-
log.success(`Added agentic-memory MCP tool permissions to ${target}`);
|
|
1995
|
-
return true;
|
|
1996
|
-
}
|
|
1997
2193
|
async function createEnhanceSkill(root) {
|
|
1998
|
-
const skillDir =
|
|
1999
|
-
const skillPath =
|
|
2000
|
-
const globalPath =
|
|
2001
|
-
const legacyProject =
|
|
2002
|
-
const legacyGlobal =
|
|
2194
|
+
const skillDir = join6(root, ".claude", "skills", "lp-enhance");
|
|
2195
|
+
const skillPath = join6(skillDir, "SKILL.md");
|
|
2196
|
+
const globalPath = join6(homedir3(), ".claude", "skills", "lp-enhance", "SKILL.md");
|
|
2197
|
+
const legacyProject = join6(root, ".claude", "commands", "lp-enhance.md");
|
|
2198
|
+
const legacyGlobal = join6(homedir3(), ".claude", "commands", "lp-enhance.md");
|
|
2003
2199
|
if (await fileExists(skillPath) || await fileExists(globalPath) || await fileExists(legacyProject) || await fileExists(legacyGlobal)) return false;
|
|
2004
2200
|
await mkdir2(skillDir, { recursive: true });
|
|
2005
2201
|
await writeFile2(skillPath, generateEnhanceSkill());
|
|
@@ -2007,39 +2203,18 @@ async function createEnhanceSkill(root) {
|
|
|
2007
2203
|
return true;
|
|
2008
2204
|
}
|
|
2009
2205
|
async function updateEnhanceSkill(root) {
|
|
2010
|
-
const projectPath =
|
|
2011
|
-
const globalPath =
|
|
2206
|
+
const projectPath = join6(root, ".claude", "skills", "lp-enhance", "SKILL.md");
|
|
2207
|
+
const globalPath = join6(homedir3(), ".claude", "skills", "lp-enhance", "SKILL.md");
|
|
2012
2208
|
const targetPath = await fileExists(projectPath) ? projectPath : await fileExists(globalPath) ? globalPath : null;
|
|
2013
2209
|
if (!targetPath) return false;
|
|
2014
2210
|
await writeFile2(targetPath, generateEnhanceSkill());
|
|
2015
2211
|
log.success("Updated /lp-enhance skill to latest version");
|
|
2016
2212
|
return true;
|
|
2017
2213
|
}
|
|
2018
|
-
async function removeStaleStopHook(root) {
|
|
2019
|
-
const settings = await readSettingsJson(root);
|
|
2020
|
-
const hooks = settings.hooks;
|
|
2021
|
-
if (!hooks?.Stop) return false;
|
|
2022
|
-
const stopHooks = hooks.Stop;
|
|
2023
|
-
const filtered = stopHooks.filter((h) => {
|
|
2024
|
-
const innerHooks = h.hooks;
|
|
2025
|
-
return !innerHooks?.some(
|
|
2026
|
-
(ih) => typeof ih.command === "string" && ih.command.includes("memory extract")
|
|
2027
|
-
);
|
|
2028
|
-
});
|
|
2029
|
-
if (filtered.length === stopHooks.length) return false;
|
|
2030
|
-
if (filtered.length === 0) {
|
|
2031
|
-
delete hooks.Stop;
|
|
2032
|
-
} else {
|
|
2033
|
-
hooks.Stop = filtered;
|
|
2034
|
-
}
|
|
2035
|
-
await writeSettingsJson(root, settings);
|
|
2036
|
-
log.success("Removed deprecated Stop hook (memory extract)");
|
|
2037
|
-
return true;
|
|
2038
|
-
}
|
|
2039
2214
|
|
|
2040
2215
|
// src/commands/doctor/watcher.ts
|
|
2041
2216
|
import { readdir as readdir2, stat } from "fs/promises";
|
|
2042
|
-
import { join as
|
|
2217
|
+
import { join as join7 } from "path";
|
|
2043
2218
|
async function watchConfig(projectRoot) {
|
|
2044
2219
|
await runAndDisplay(projectRoot);
|
|
2045
2220
|
log.blank();
|
|
@@ -2062,16 +2237,16 @@ async function watchConfig(projectRoot) {
|
|
|
2062
2237
|
}
|
|
2063
2238
|
async function getFileSnapshot(projectRoot) {
|
|
2064
2239
|
const files = [
|
|
2065
|
-
|
|
2066
|
-
|
|
2240
|
+
join7(projectRoot, "CLAUDE.md"),
|
|
2241
|
+
join7(projectRoot, ".claudeignore")
|
|
2067
2242
|
];
|
|
2068
|
-
const claudeDir =
|
|
2243
|
+
const claudeDir = join7(projectRoot, ".claude");
|
|
2069
2244
|
try {
|
|
2070
2245
|
const entries = await readdir2(claudeDir, { withFileTypes: true, recursive: true });
|
|
2071
2246
|
for (const entry of entries) {
|
|
2072
2247
|
if (entry.isFile()) {
|
|
2073
2248
|
const parentPath = entry.parentPath ?? claudeDir;
|
|
2074
|
-
files.push(
|
|
2249
|
+
files.push(join7(parentPath, entry.name));
|
|
2075
2250
|
}
|
|
2076
2251
|
}
|
|
2077
2252
|
} catch {
|
|
@@ -2216,11 +2391,11 @@ import { select as select2 } from "@inquirer/prompts";
|
|
|
2216
2391
|
import ora from "ora";
|
|
2217
2392
|
import chalk2 from "chalk";
|
|
2218
2393
|
import { mkdir as mkdir4, writeFile as writeFile4 } from "fs/promises";
|
|
2219
|
-
import { join as
|
|
2394
|
+
import { join as join10 } from "path";
|
|
2220
2395
|
|
|
2221
2396
|
// src/commands/eval/loader.ts
|
|
2222
|
-
import { readFile as
|
|
2223
|
-
import { join as
|
|
2397
|
+
import { readFile as readFile6, readdir as readdir3, access as access5 } from "fs/promises";
|
|
2398
|
+
import { join as join8, resolve as resolve2, dirname as dirname2 } from "path";
|
|
2224
2399
|
import { fileURLToPath } from "url";
|
|
2225
2400
|
import { parse as parseYaml } from "yaml";
|
|
2226
2401
|
|
|
@@ -2343,14 +2518,14 @@ async function dirExists(path) {
|
|
|
2343
2518
|
async function loadScenarios(options) {
|
|
2344
2519
|
const { suite, customPath } = options;
|
|
2345
2520
|
const scenarioDir = customPath ? resolve2(customPath) : await findScenariosDir();
|
|
2346
|
-
const dirs = suite ? [
|
|
2521
|
+
const dirs = suite ? [join8(scenarioDir, suite)] : await getSubdirectories(scenarioDir);
|
|
2347
2522
|
const allDirs = [scenarioDir, ...dirs];
|
|
2348
2523
|
const scenarios = [];
|
|
2349
2524
|
for (const dir of allDirs) {
|
|
2350
2525
|
const files = await listYamlFiles(dir);
|
|
2351
2526
|
for (const file of files) {
|
|
2352
2527
|
try {
|
|
2353
|
-
const content = await
|
|
2528
|
+
const content = await readFile6(file, "utf-8");
|
|
2354
2529
|
const raw = parseYaml(content);
|
|
2355
2530
|
const scenario = validateScenario(raw, file);
|
|
2356
2531
|
scenarios.push(scenario);
|
|
@@ -2365,7 +2540,7 @@ async function loadScenarios(options) {
|
|
|
2365
2540
|
async function getSubdirectories(dir) {
|
|
2366
2541
|
try {
|
|
2367
2542
|
const entries = await readdir3(dir, { withFileTypes: true });
|
|
2368
|
-
return entries.filter((e) => e.isDirectory()).map((e) =>
|
|
2543
|
+
return entries.filter((e) => e.isDirectory()).map((e) => join8(dir, e.name));
|
|
2369
2544
|
} catch {
|
|
2370
2545
|
return [];
|
|
2371
2546
|
}
|
|
@@ -2373,22 +2548,22 @@ async function getSubdirectories(dir) {
|
|
|
2373
2548
|
async function listYamlFiles(dir) {
|
|
2374
2549
|
try {
|
|
2375
2550
|
const entries = await readdir3(dir, { withFileTypes: true });
|
|
2376
|
-
return entries.filter((e) => e.isFile() && (e.name.endsWith(".yaml") || e.name.endsWith(".yml"))).map((e) =>
|
|
2551
|
+
return entries.filter((e) => e.isFile() && (e.name.endsWith(".yaml") || e.name.endsWith(".yml"))).map((e) => join8(dir, e.name));
|
|
2377
2552
|
} catch {
|
|
2378
2553
|
return [];
|
|
2379
2554
|
}
|
|
2380
2555
|
}
|
|
2381
2556
|
|
|
2382
2557
|
// src/commands/eval/runner.ts
|
|
2383
|
-
import { mkdir as mkdir3, writeFile as writeFile3, readFile as
|
|
2384
|
-
import { join as
|
|
2558
|
+
import { mkdir as mkdir3, writeFile as writeFile3, readFile as readFile7, readdir as readdir4, rm, cp } from "fs/promises";
|
|
2559
|
+
import { join as join9, dirname as dirname3 } from "path";
|
|
2385
2560
|
import { tmpdir } from "os";
|
|
2386
2561
|
import { randomUUID } from "crypto";
|
|
2387
2562
|
import { execFile } from "child_process";
|
|
2388
2563
|
import { promisify } from "util";
|
|
2389
2564
|
var exec = promisify(execFile);
|
|
2390
2565
|
async function runScenario(scenario, options) {
|
|
2391
|
-
const sandboxDir =
|
|
2566
|
+
const sandboxDir = join9(tmpdir(), `claude-eval-${randomUUID()}`);
|
|
2392
2567
|
try {
|
|
2393
2568
|
await setupSandbox(sandboxDir, scenario, options.projectRoot);
|
|
2394
2569
|
await runClaudeInSandbox(sandboxDir, scenario.prompt, options.timeout, options.model);
|
|
@@ -2414,14 +2589,14 @@ async function runScenarioWithRetries(scenario, options) {
|
|
|
2414
2589
|
async function setupSandbox(sandboxDir, scenario, projectRoot) {
|
|
2415
2590
|
await mkdir3(sandboxDir, { recursive: true });
|
|
2416
2591
|
for (const file of scenario.setup.files) {
|
|
2417
|
-
const filePath =
|
|
2592
|
+
const filePath = join9(sandboxDir, file.path);
|
|
2418
2593
|
await mkdir3(dirname3(filePath), { recursive: true });
|
|
2419
2594
|
await writeFile3(filePath, file.content);
|
|
2420
2595
|
}
|
|
2421
2596
|
await copyProjectConfig(sandboxDir, projectRoot);
|
|
2422
2597
|
if (scenario.setup.instructions) {
|
|
2423
2598
|
await writeFile3(
|
|
2424
|
-
|
|
2599
|
+
join9(sandboxDir, "CLAUDE.md"),
|
|
2425
2600
|
`# Eval Scenario
|
|
2426
2601
|
|
|
2427
2602
|
${scenario.setup.instructions}
|
|
@@ -2442,20 +2617,20 @@ ${scenario.setup.instructions}
|
|
|
2442
2617
|
], { cwd: sandboxDir });
|
|
2443
2618
|
}
|
|
2444
2619
|
async function copyProjectConfig(sandboxDir, projectRoot) {
|
|
2445
|
-
const claudeDir =
|
|
2446
|
-
const sandboxClaudeDir =
|
|
2447
|
-
const settingsPath =
|
|
2620
|
+
const claudeDir = join9(projectRoot, ".claude");
|
|
2621
|
+
const sandboxClaudeDir = join9(sandboxDir, ".claude");
|
|
2622
|
+
const settingsPath = join9(claudeDir, "settings.json");
|
|
2448
2623
|
if (await fileExists(settingsPath)) {
|
|
2449
2624
|
await mkdir3(sandboxClaudeDir, { recursive: true });
|
|
2450
|
-
await cp(settingsPath,
|
|
2625
|
+
await cp(settingsPath, join9(sandboxClaudeDir, "settings.json"));
|
|
2451
2626
|
}
|
|
2452
|
-
const rulesDir =
|
|
2627
|
+
const rulesDir = join9(claudeDir, "rules");
|
|
2453
2628
|
if (await fileExists(rulesDir)) {
|
|
2454
|
-
await cp(rulesDir,
|
|
2629
|
+
await cp(rulesDir, join9(sandboxClaudeDir, "rules"), { recursive: true });
|
|
2455
2630
|
}
|
|
2456
|
-
const ignorePath =
|
|
2631
|
+
const ignorePath = join9(projectRoot, ".claudeignore");
|
|
2457
2632
|
if (await fileExists(ignorePath)) {
|
|
2458
|
-
await cp(ignorePath,
|
|
2633
|
+
await cp(ignorePath, join9(sandboxDir, ".claudeignore"));
|
|
2459
2634
|
}
|
|
2460
2635
|
}
|
|
2461
2636
|
async function runClaudeInSandbox(cwd, prompt, timeout, model) {
|
|
@@ -2549,7 +2724,7 @@ async function evaluateSingleCheck(check, sandboxDir) {
|
|
|
2549
2724
|
async function checkGrep(check, sandboxDir) {
|
|
2550
2725
|
if (!check.pattern) return false;
|
|
2551
2726
|
try {
|
|
2552
|
-
const content = await
|
|
2727
|
+
const content = await readFile7(join9(sandboxDir, check.target), "utf-8");
|
|
2553
2728
|
let found;
|
|
2554
2729
|
try {
|
|
2555
2730
|
found = new RegExp(check.pattern).test(content);
|
|
@@ -2563,7 +2738,7 @@ async function checkGrep(check, sandboxDir) {
|
|
|
2563
2738
|
}
|
|
2564
2739
|
async function checkFilePresence(check, sandboxDir) {
|
|
2565
2740
|
try {
|
|
2566
|
-
await
|
|
2741
|
+
await readFile7(join9(sandboxDir, check.target));
|
|
2567
2742
|
return check.expect === "present";
|
|
2568
2743
|
} catch {
|
|
2569
2744
|
return check.expect === "absent";
|
|
@@ -2572,9 +2747,9 @@ async function checkFilePresence(check, sandboxDir) {
|
|
|
2572
2747
|
async function checkMaxLines(check, sandboxDir) {
|
|
2573
2748
|
const maxLines = parseInt(check.pattern ?? "800", 10);
|
|
2574
2749
|
try {
|
|
2575
|
-
const files = await listAllFiles(
|
|
2750
|
+
const files = await listAllFiles(join9(sandboxDir, check.target));
|
|
2576
2751
|
for (const file of files) {
|
|
2577
|
-
const content = await
|
|
2752
|
+
const content = await readFile7(file, "utf-8");
|
|
2578
2753
|
if (content.split("\n").length > maxLines) {
|
|
2579
2754
|
return check.expect === "absent";
|
|
2580
2755
|
}
|
|
@@ -2589,7 +2764,7 @@ async function listAllFiles(dir) {
|
|
|
2589
2764
|
try {
|
|
2590
2765
|
const entries = await readdir4(dir, { withFileTypes: true });
|
|
2591
2766
|
for (const entry of entries) {
|
|
2592
|
-
const fullPath =
|
|
2767
|
+
const fullPath = join9(dir, entry.name);
|
|
2593
2768
|
if (entry.isDirectory()) {
|
|
2594
2769
|
results.push(...await listAllFiles(fullPath));
|
|
2595
2770
|
} else {
|
|
@@ -2775,10 +2950,10 @@ async function saveEvalReport(results, projectRoot, suite, model) {
|
|
|
2775
2950
|
lines.push("");
|
|
2776
2951
|
}
|
|
2777
2952
|
}
|
|
2778
|
-
const evalDir =
|
|
2953
|
+
const evalDir = join10(projectRoot, ".claude", "eval");
|
|
2779
2954
|
await mkdir4(evalDir, { recursive: true });
|
|
2780
2955
|
const filename = `eval-${suite ?? "all"}-${timestamp}.md`;
|
|
2781
|
-
await writeFile4(
|
|
2956
|
+
await writeFile4(join10(evalDir, filename), lines.join("\n"));
|
|
2782
2957
|
log.success(`Report saved to .claude/eval/${filename}`);
|
|
2783
2958
|
}
|
|
2784
2959
|
async function checkClaudeCli() {
|
|
@@ -2795,12 +2970,12 @@ async function checkClaudeCli() {
|
|
|
2795
2970
|
|
|
2796
2971
|
// src/commands/memory/index.ts
|
|
2797
2972
|
import { readFileSync } from "fs";
|
|
2798
|
-
import { join as
|
|
2973
|
+
import { join as join11 } from "path";
|
|
2799
2974
|
import { Command as Command4 } from "commander";
|
|
2800
2975
|
import { confirm as confirm2 } from "@inquirer/prompts";
|
|
2801
2976
|
function isMemoryInstalled() {
|
|
2802
2977
|
const cwd = process.cwd();
|
|
2803
|
-
return hasMemoryHook(
|
|
2978
|
+
return hasMemoryHook(join11(cwd, ".claude", "settings.json")) || hasMemoryHook(join11(cwd, ".claude", "settings.local.json"));
|
|
2804
2979
|
}
|
|
2805
2980
|
function hasMemoryHook(path) {
|
|
2806
2981
|
try {
|
|
@@ -2825,12 +3000,12 @@ function createMemoryCommand() {
|
|
|
2825
3000
|
}
|
|
2826
3001
|
const { requireMemoryDeps } = await import("./require-deps-NKRCPVAO.js");
|
|
2827
3002
|
await requireMemoryDeps();
|
|
2828
|
-
const { startTui } = await import("./tui-
|
|
3003
|
+
const { startTui } = await import("./tui-XIYOOUP6.js");
|
|
2829
3004
|
await startTui();
|
|
2830
3005
|
return;
|
|
2831
3006
|
}
|
|
2832
3007
|
if (!isMemoryInstalled()) {
|
|
2833
|
-
const { detectExistingSetup } = await import("./install-
|
|
3008
|
+
const { detectExistingSetup } = await import("./install-MVATZUXZ.js");
|
|
2834
3009
|
const existing = detectExistingSetup(process.cwd());
|
|
2835
3010
|
if (existing) {
|
|
2836
3011
|
const location = existing === "local" ? ".claude/CLAUDE.md + settings.local.json" : "CLAUDE.md + settings.json";
|
|
@@ -2856,18 +3031,18 @@ function createMemoryCommand() {
|
|
|
2856
3031
|
log.info("Skipped.");
|
|
2857
3032
|
return;
|
|
2858
3033
|
}
|
|
2859
|
-
const { runInstall } = await import("./install-
|
|
3034
|
+
const { runInstall } = await import("./install-MVATZUXZ.js");
|
|
2860
3035
|
await runInstall({});
|
|
2861
3036
|
} else {
|
|
2862
3037
|
const { requireMemoryDeps } = await import("./require-deps-NKRCPVAO.js");
|
|
2863
3038
|
await requireMemoryDeps();
|
|
2864
|
-
const { runStats } = await import("./stats-
|
|
3039
|
+
const { runStats } = await import("./stats-QUBHHPV7.js");
|
|
2865
3040
|
await runStats({});
|
|
2866
3041
|
}
|
|
2867
3042
|
});
|
|
2868
3043
|
memory.addCommand(
|
|
2869
3044
|
new Command4("context").description("Load session context (hook handler)").option("--json", "JSON output").action(async (opts) => {
|
|
2870
|
-
const { runContext } = await import("./context-
|
|
3045
|
+
const { runContext } = await import("./context-CWJUUTTU.js");
|
|
2871
3046
|
await runContext(opts);
|
|
2872
3047
|
}).helpCommand(false),
|
|
2873
3048
|
{ hidden: true }
|
|
@@ -2881,13 +3056,13 @@ function createMemoryCommand() {
|
|
|
2881
3056
|
);
|
|
2882
3057
|
memory.addCommand(
|
|
2883
3058
|
new Command4("push").description("Push current project's memories to GitHub Gist").option("--all", "Push all projects").option("-y, --yes", "Skip confirmation prompt").action(async (opts) => {
|
|
2884
|
-
const { runPush } = await import("./push-
|
|
3059
|
+
const { runPush } = await import("./push-74XC5CUK.js");
|
|
2885
3060
|
await runPush(opts);
|
|
2886
3061
|
})
|
|
2887
3062
|
);
|
|
2888
3063
|
memory.addCommand(
|
|
2889
3064
|
new Command4("pull").description("Pull current project's memories from GitHub Gist").option("--all", "Pull all projects").action(async (opts) => {
|
|
2890
|
-
const { runPull } = await import("./pull-
|
|
3065
|
+
const { runPull } = await import("./pull-YOESZ3UC.js");
|
|
2891
3066
|
await runPull(opts);
|
|
2892
3067
|
})
|
|
2893
3068
|
);
|
|
@@ -2895,8 +3070,8 @@ function createMemoryCommand() {
|
|
|
2895
3070
|
}
|
|
2896
3071
|
|
|
2897
3072
|
// src/cli.ts
|
|
2898
|
-
var program = new Command5().name("claude-launchpad").description("CLI toolkit that makes Claude Code setups measurably good").version("0.
|
|
2899
|
-
const hasConfig = await fileExists(
|
|
3073
|
+
var program = new Command5().name("claude-launchpad").description("CLI toolkit that makes Claude Code setups measurably good").version("0.16.0", "-v, --version").action(async () => {
|
|
3074
|
+
const hasConfig = await fileExists(join12(process.cwd(), "CLAUDE.md")) || await fileExists(join12(process.cwd(), ".claude", "settings.json"));
|
|
2900
3075
|
if (hasConfig) {
|
|
2901
3076
|
await program.commands.find((c) => c.name() === "doctor")?.parseAsync([], { from: "user" });
|
|
2902
3077
|
} else {
|