@bennys001/claude-code-memory 0.9.12 → 0.11.1
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/dist/index.js +210 -69
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
var package_default = {
|
|
5
5
|
name: "@bennys001/claude-code-memory",
|
|
6
6
|
publishConfig: { access: "public" },
|
|
7
|
-
version: "0.
|
|
7
|
+
version: "0.11.1",
|
|
8
8
|
description: "MCP server that gives Claude Code persistent memory via an Obsidian knowledge vault",
|
|
9
9
|
module: "dist/index.js",
|
|
10
10
|
main: "dist/index.js",
|
|
@@ -866,6 +866,107 @@ function registerResearchTool(server, entries, vaultPath) {
|
|
|
866
866
|
});
|
|
867
867
|
}
|
|
868
868
|
|
|
869
|
+
// src/cli/claude-code.ts
|
|
870
|
+
import { spawn } from "child_process";
|
|
871
|
+
var SERVER_CMD = ["ccm", "--stdio"];
|
|
872
|
+
function installGlobal() {
|
|
873
|
+
return new Promise((resolve4) => {
|
|
874
|
+
let stderr = "";
|
|
875
|
+
const proc = spawn("bun", ["install", "-g", "@bennys001/claude-code-memory"], { stdio: ["ignore", "ignore", "pipe"] });
|
|
876
|
+
proc.stderr.on("data", (data) => {
|
|
877
|
+
stderr += data.toString();
|
|
878
|
+
});
|
|
879
|
+
proc.on("error", (err) => {
|
|
880
|
+
resolve4({ success: false, error: err.message });
|
|
881
|
+
});
|
|
882
|
+
proc.on("close", (code) => {
|
|
883
|
+
if (code === 0) {
|
|
884
|
+
resolve4({ success: true });
|
|
885
|
+
} else {
|
|
886
|
+
resolve4({ success: false, error: stderr.trim() || `bun install exited with code ${code}` });
|
|
887
|
+
}
|
|
888
|
+
});
|
|
889
|
+
});
|
|
890
|
+
}
|
|
891
|
+
function uninstallGlobal() {
|
|
892
|
+
return new Promise((resolve4) => {
|
|
893
|
+
let stderr = "";
|
|
894
|
+
const proc = spawn("bun", ["remove", "-g", "@bennys001/claude-code-memory"], { stdio: ["ignore", "ignore", "pipe"] });
|
|
895
|
+
proc.stderr.on("data", (data) => {
|
|
896
|
+
stderr += data.toString();
|
|
897
|
+
});
|
|
898
|
+
proc.on("error", (err) => {
|
|
899
|
+
resolve4({ success: false, error: err.message });
|
|
900
|
+
});
|
|
901
|
+
proc.on("close", (code) => {
|
|
902
|
+
if (code === 0) {
|
|
903
|
+
resolve4({ success: true });
|
|
904
|
+
} else {
|
|
905
|
+
resolve4({ success: false, error: stderr.trim() || `bun remove exited with code ${code}` });
|
|
906
|
+
}
|
|
907
|
+
});
|
|
908
|
+
});
|
|
909
|
+
}
|
|
910
|
+
var REGISTER_ARGS = [
|
|
911
|
+
"mcp",
|
|
912
|
+
"add",
|
|
913
|
+
"--transport",
|
|
914
|
+
"stdio",
|
|
915
|
+
"--scope",
|
|
916
|
+
"user",
|
|
917
|
+
"ccm",
|
|
918
|
+
"--",
|
|
919
|
+
...SERVER_CMD
|
|
920
|
+
];
|
|
921
|
+
var MANUAL_COMMAND = `claude mcp add --transport stdio --scope user ccm -- ${SERVER_CMD.join(" ")}`;
|
|
922
|
+
function removeMcpServer() {
|
|
923
|
+
return new Promise((resolve4) => {
|
|
924
|
+
const proc = spawn("claude", ["mcp", "remove", "ccm"], { stdio: "ignore" });
|
|
925
|
+
proc.on("error", () => resolve4());
|
|
926
|
+
proc.on("close", () => resolve4());
|
|
927
|
+
});
|
|
928
|
+
}
|
|
929
|
+
async function registerMcpServer() {
|
|
930
|
+
await removeMcpServer();
|
|
931
|
+
return new Promise((resolve4) => {
|
|
932
|
+
let stdout = "";
|
|
933
|
+
let stderr = "";
|
|
934
|
+
const proc = spawn("claude", REGISTER_ARGS, { stdio: "pipe" });
|
|
935
|
+
proc.stdout.on("data", (data) => {
|
|
936
|
+
stdout += data.toString();
|
|
937
|
+
});
|
|
938
|
+
proc.stderr.on("data", (data) => {
|
|
939
|
+
stderr += data.toString();
|
|
940
|
+
});
|
|
941
|
+
proc.on("error", (err) => {
|
|
942
|
+
if (err.code === "ENOENT") {
|
|
943
|
+
resolve4({
|
|
944
|
+
success: false,
|
|
945
|
+
error: "Claude CLI not found in PATH",
|
|
946
|
+
manualCommand: MANUAL_COMMAND
|
|
947
|
+
});
|
|
948
|
+
} else {
|
|
949
|
+
resolve4({
|
|
950
|
+
success: false,
|
|
951
|
+
error: err.message,
|
|
952
|
+
manualCommand: MANUAL_COMMAND
|
|
953
|
+
});
|
|
954
|
+
}
|
|
955
|
+
});
|
|
956
|
+
proc.on("close", (code) => {
|
|
957
|
+
if (code === 0) {
|
|
958
|
+
resolve4({ success: true, output: (stdout || stderr).trim() });
|
|
959
|
+
} else {
|
|
960
|
+
resolve4({
|
|
961
|
+
success: false,
|
|
962
|
+
error: (stderr || stdout).trim() || `Process exited with code ${code}`,
|
|
963
|
+
manualCommand: MANUAL_COMMAND
|
|
964
|
+
});
|
|
965
|
+
}
|
|
966
|
+
});
|
|
967
|
+
});
|
|
968
|
+
}
|
|
969
|
+
|
|
869
970
|
// src/cli/init.ts
|
|
870
971
|
import { mkdir as mkdir2 } from "fs/promises";
|
|
871
972
|
import { join as join6 } from "path";
|
|
@@ -1027,72 +1128,17 @@ async function registerVaultWithObsidian(vaultPath, configPath = DEFAULT_CONFIG_
|
|
|
1027
1128
|
await writeFile2(configPath, JSON.stringify(config, null, 2));
|
|
1028
1129
|
return { registered: true, vaultId };
|
|
1029
1130
|
}
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
return
|
|
1041
|
-
"mcp",
|
|
1042
|
-
"add",
|
|
1043
|
-
"--transport",
|
|
1044
|
-
"stdio",
|
|
1045
|
-
"--scope",
|
|
1046
|
-
"user",
|
|
1047
|
-
"ccm",
|
|
1048
|
-
"--",
|
|
1049
|
-
...serverCmd
|
|
1050
|
-
];
|
|
1051
|
-
}
|
|
1052
|
-
function formatManualCommand(serverCmd) {
|
|
1053
|
-
return `claude mcp add --transport stdio --scope user ccm -- ${serverCmd.join(" ")}`;
|
|
1054
|
-
}
|
|
1055
|
-
function registerMcpServer() {
|
|
1056
|
-
const serverCmd = buildServerCommand();
|
|
1057
|
-
const registerArgs = buildRegisterArgs(serverCmd);
|
|
1058
|
-
const manualCommand = formatManualCommand(serverCmd);
|
|
1059
|
-
return new Promise((resolve4) => {
|
|
1060
|
-
let stdout = "";
|
|
1061
|
-
let stderr = "";
|
|
1062
|
-
const proc = spawn("claude", registerArgs, { stdio: "pipe" });
|
|
1063
|
-
proc.stdout.on("data", (data) => {
|
|
1064
|
-
stdout += data.toString();
|
|
1065
|
-
});
|
|
1066
|
-
proc.stderr.on("data", (data) => {
|
|
1067
|
-
stderr += data.toString();
|
|
1068
|
-
});
|
|
1069
|
-
proc.on("error", (err) => {
|
|
1070
|
-
if (err.code === "ENOENT") {
|
|
1071
|
-
resolve4({
|
|
1072
|
-
success: false,
|
|
1073
|
-
error: "Claude CLI not found in PATH",
|
|
1074
|
-
manualCommand
|
|
1075
|
-
});
|
|
1076
|
-
} else {
|
|
1077
|
-
resolve4({
|
|
1078
|
-
success: false,
|
|
1079
|
-
error: err.message,
|
|
1080
|
-
manualCommand
|
|
1081
|
-
});
|
|
1082
|
-
}
|
|
1083
|
-
});
|
|
1084
|
-
proc.on("close", (code) => {
|
|
1085
|
-
if (code === 0) {
|
|
1086
|
-
resolve4({ success: true, output: (stdout || stderr).trim() });
|
|
1087
|
-
} else {
|
|
1088
|
-
resolve4({
|
|
1089
|
-
success: false,
|
|
1090
|
-
error: (stderr || stdout).trim() || `Process exited with code ${code}`,
|
|
1091
|
-
manualCommand
|
|
1092
|
-
});
|
|
1093
|
-
}
|
|
1094
|
-
});
|
|
1095
|
-
});
|
|
1131
|
+
async function unregisterVaultFromObsidian(vaultPath, configPath = DEFAULT_CONFIG_PATH) {
|
|
1132
|
+
const config = await loadObsidianConfig(configPath);
|
|
1133
|
+
if (!config)
|
|
1134
|
+
return false;
|
|
1135
|
+
const vaultId = findVaultByPath(config, vaultPath);
|
|
1136
|
+
if (!vaultId)
|
|
1137
|
+
return false;
|
|
1138
|
+
await copyFile(configPath, `${configPath}.backup`);
|
|
1139
|
+
delete config.vaults[vaultId];
|
|
1140
|
+
await writeFile2(configPath, JSON.stringify(config, null, 2));
|
|
1141
|
+
return true;
|
|
1096
1142
|
}
|
|
1097
1143
|
|
|
1098
1144
|
// src/cli/init.ts
|
|
@@ -1135,6 +1181,12 @@ async function executeInit() {
|
|
|
1135
1181
|
detail: obsidianResult.reason
|
|
1136
1182
|
});
|
|
1137
1183
|
}
|
|
1184
|
+
const installResult = await installGlobal();
|
|
1185
|
+
if (installResult.success) {
|
|
1186
|
+
steps.push({ name: "global install", status: "created", detail: "ccm binary installed" });
|
|
1187
|
+
} else {
|
|
1188
|
+
steps.push({ name: "global install", status: "failed", detail: installResult.error });
|
|
1189
|
+
}
|
|
1138
1190
|
const mcpResult = await registerMcpServer();
|
|
1139
1191
|
if (mcpResult.success) {
|
|
1140
1192
|
steps.push({ name: "Claude Code MCP", status: "created", detail: mcpResult.output });
|
|
@@ -1178,24 +1230,100 @@ function formatInitSummary(result) {
|
|
|
1178
1230
|
}
|
|
1179
1231
|
|
|
1180
1232
|
// src/index.ts
|
|
1233
|
+
import { rm } from "fs/promises";
|
|
1234
|
+
import { createInterface } from "readline";
|
|
1181
1235
|
var VAULT_PATH2 = join7(homedir4(), ".ccm", "knowledge-base");
|
|
1182
1236
|
function parseCliArgs() {
|
|
1183
1237
|
const args = process.argv.slice(2);
|
|
1238
|
+
if (args.includes("--version") || args.includes("-v"))
|
|
1239
|
+
return "version";
|
|
1240
|
+
if (args.includes("--update"))
|
|
1241
|
+
return "update";
|
|
1242
|
+
if (args.includes("--uninstall"))
|
|
1243
|
+
return "uninstall";
|
|
1184
1244
|
if (args.includes("--init"))
|
|
1185
1245
|
return "init";
|
|
1186
1246
|
if (args.includes("--stdio"))
|
|
1187
1247
|
return "serve";
|
|
1248
|
+
if (!process.stdin.isTTY)
|
|
1249
|
+
return "serve";
|
|
1188
1250
|
return "help";
|
|
1189
1251
|
}
|
|
1190
1252
|
function printHelp() {
|
|
1191
1253
|
console.log(`${C.bold}claude-code-memory${C.reset} ${C.dim}(ccm)${C.reset} \u2014 Persistent memory for Claude Code
|
|
1192
1254
|
|
|
1193
1255
|
${C.bold}Usage:${C.reset}
|
|
1194
|
-
${C.cyan}
|
|
1256
|
+
${C.cyan}ccm --init${C.reset} Set up vault and register MCP server
|
|
1257
|
+
${C.cyan}ccm --update${C.reset} Update to the latest version
|
|
1258
|
+
${C.cyan}ccm --uninstall${C.reset} Remove ccm, MCP server, and optionally the vault
|
|
1259
|
+
${C.cyan}ccm --version${C.reset} Show installed version
|
|
1260
|
+
|
|
1261
|
+
${C.bold}First-time install:${C.reset}
|
|
1262
|
+
${C.cyan}bun install -g @bennys001/claude-code-memory && ccm --init${C.reset}
|
|
1195
1263
|
|
|
1196
1264
|
${C.dim}Vault:${C.reset} ~/.ccm/knowledge-base/
|
|
1197
1265
|
${C.dim}Docs:${C.reset} https://github.com/bennys001/claude-code-memory`);
|
|
1198
1266
|
}
|
|
1267
|
+
async function fetchLatestVersion() {
|
|
1268
|
+
const res = await fetch("https://registry.npmjs.org/@bennys001/claude-code-memory/latest");
|
|
1269
|
+
if (!res.ok)
|
|
1270
|
+
throw new Error(`npm registry returned ${res.status}`);
|
|
1271
|
+
const data = await res.json();
|
|
1272
|
+
return data.version;
|
|
1273
|
+
}
|
|
1274
|
+
async function runUpdate() {
|
|
1275
|
+
console.log(`${C.dim}Checking for updates...${C.reset}`);
|
|
1276
|
+
const latest = await fetchLatestVersion();
|
|
1277
|
+
if (latest === package_default.version) {
|
|
1278
|
+
console.log(`Already on the latest version: ${C.green}v${package_default.version}${C.reset}`);
|
|
1279
|
+
return;
|
|
1280
|
+
}
|
|
1281
|
+
console.log(`${C.dim}v${package_default.version}${C.reset} \u2192 ${C.green}v${latest}${C.reset}
|
|
1282
|
+
`);
|
|
1283
|
+
const installResult = await installGlobal();
|
|
1284
|
+
if (!installResult.success) {
|
|
1285
|
+
throw new Error(`Global install failed: ${installResult.error}`);
|
|
1286
|
+
}
|
|
1287
|
+
const mcpResult = await registerMcpServer();
|
|
1288
|
+
if (!mcpResult.success) {
|
|
1289
|
+
throw new Error(`MCP registration failed: ${mcpResult.error}`);
|
|
1290
|
+
}
|
|
1291
|
+
console.log(`
|
|
1292
|
+
${C.green}Updated to v${latest}${C.reset}`);
|
|
1293
|
+
}
|
|
1294
|
+
function promptConfirm(question) {
|
|
1295
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
1296
|
+
return new Promise((resolve4) => {
|
|
1297
|
+
rl.question(question, (answer) => {
|
|
1298
|
+
rl.close();
|
|
1299
|
+
resolve4(answer.toLowerCase() === "y");
|
|
1300
|
+
});
|
|
1301
|
+
});
|
|
1302
|
+
}
|
|
1303
|
+
async function runUninstall() {
|
|
1304
|
+
console.log(`${C.bold}ccm uninstall${C.reset}
|
|
1305
|
+
`);
|
|
1306
|
+
await removeMcpServer();
|
|
1307
|
+
console.log(` ${C.green}+${C.reset} Removed MCP server`);
|
|
1308
|
+
await unregisterVaultFromObsidian(VAULT_PATH);
|
|
1309
|
+
console.log(` ${C.green}+${C.reset} Unregistered Obsidian vault`);
|
|
1310
|
+
const ccmDir = join7(homedir4(), ".ccm");
|
|
1311
|
+
const deleteVault = await promptConfirm(` Delete vault at ${C.dim}${VAULT_PATH}${C.reset}? ${C.dim}(y/N)${C.reset} `);
|
|
1312
|
+
if (deleteVault) {
|
|
1313
|
+
await rm(ccmDir, { recursive: true, force: true });
|
|
1314
|
+
console.log(` ${C.green}+${C.reset} Deleted vault`);
|
|
1315
|
+
} else {
|
|
1316
|
+
console.log(` ${C.yellow}-${C.reset} Kept vault`);
|
|
1317
|
+
}
|
|
1318
|
+
const uninstallResult = await uninstallGlobal();
|
|
1319
|
+
if (uninstallResult.success) {
|
|
1320
|
+
console.log(` ${C.green}+${C.reset} Uninstalled ccm binary`);
|
|
1321
|
+
} else {
|
|
1322
|
+
console.log(` ${C.red}!${C.reset} Failed to uninstall: ${uninstallResult.error}`);
|
|
1323
|
+
}
|
|
1324
|
+
console.log(`
|
|
1325
|
+
${C.green}Done${C.reset}`);
|
|
1326
|
+
}
|
|
1199
1327
|
async function runInit() {
|
|
1200
1328
|
const result = await executeInit();
|
|
1201
1329
|
console.log(formatInitSummary(result));
|
|
@@ -1226,9 +1354,22 @@ async function runServer() {
|
|
|
1226
1354
|
process.on("SIGTERM", shutdown);
|
|
1227
1355
|
}
|
|
1228
1356
|
var cli = parseCliArgs();
|
|
1229
|
-
if (cli === "
|
|
1357
|
+
if (cli === "version") {
|
|
1358
|
+
console.log(package_default.version);
|
|
1359
|
+
process.exit(0);
|
|
1360
|
+
} else if (cli === "help") {
|
|
1230
1361
|
printHelp();
|
|
1231
1362
|
process.exit(0);
|
|
1363
|
+
} else if (cli === "update") {
|
|
1364
|
+
runUpdate().catch((err) => {
|
|
1365
|
+
console.error("Fatal:", err);
|
|
1366
|
+
process.exit(1);
|
|
1367
|
+
});
|
|
1368
|
+
} else if (cli === "uninstall") {
|
|
1369
|
+
runUninstall().catch((err) => {
|
|
1370
|
+
console.error("Fatal:", err);
|
|
1371
|
+
process.exit(1);
|
|
1372
|
+
});
|
|
1232
1373
|
} else if (cli === "init") {
|
|
1233
1374
|
runInit().catch((err) => {
|
|
1234
1375
|
console.error("Fatal:", err);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bennys001/claude-code-memory",
|
|
3
3
|
"publishConfig": { "access": "public" },
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.11.1",
|
|
5
5
|
"description": "MCP server that gives Claude Code persistent memory via an Obsidian knowledge vault",
|
|
6
6
|
"module": "dist/index.js",
|
|
7
7
|
"main": "dist/index.js",
|