@bennys001/claude-code-memory 0.10.0 → 0.11.2
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 +18 -4
- package/dist/index.js +126 -24
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,17 +7,31 @@ MCP server that gives Claude Code persistent memory via an Obsidian-compatible k
|
|
|
7
7
|
Requires [Bun](https://bun.sh/) and [Claude Code](https://docs.anthropic.com/en/docs/claude-code).
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
|
|
10
|
+
bun install -g @bennys001/claude-code-memory && ccm --init
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
This scaffolds the vault at `~/.ccm/knowledge-base/`, registers it with Obsidian (if installed), and adds the MCP server to Claude Code.
|
|
13
|
+
This installs the `ccm` binary globally, scaffolds the vault at `~/.ccm/knowledge-base/`, registers it with Obsidian (if installed), and adds the MCP server to Claude Code.
|
|
14
14
|
|
|
15
|
-
###
|
|
15
|
+
### Update
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
ccm --update
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Uninstall
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
ccm --uninstall
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Removes the MCP server registration, Obsidian vault registration, and the global binary. Prompts before deleting the vault.
|
|
28
|
+
|
|
29
|
+
### Manual MCP setup
|
|
16
30
|
|
|
17
31
|
If `--init` can't reach the `claude` CLI, register manually:
|
|
18
32
|
|
|
19
33
|
```bash
|
|
20
|
-
claude mcp add --transport stdio --scope user ccm --
|
|
34
|
+
claude mcp add --transport stdio --scope user ccm -- ccm --stdio
|
|
21
35
|
```
|
|
22
36
|
|
|
23
37
|
## MCP Tools
|
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.2",
|
|
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,12 +866,47 @@ function registerResearchTool(server, entries, vaultPath) {
|
|
|
866
866
|
});
|
|
867
867
|
}
|
|
868
868
|
|
|
869
|
-
// src/index.ts
|
|
870
|
-
import { spawn as spawn2 } from "child_process";
|
|
871
|
-
|
|
872
869
|
// src/cli/claude-code.ts
|
|
873
870
|
import { spawn } from "child_process";
|
|
874
|
-
var SERVER_CMD = ["
|
|
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
|
+
}
|
|
875
910
|
var REGISTER_ARGS = [
|
|
876
911
|
"mcp",
|
|
877
912
|
"add",
|
|
@@ -884,7 +919,15 @@ var REGISTER_ARGS = [
|
|
|
884
919
|
...SERVER_CMD
|
|
885
920
|
];
|
|
886
921
|
var MANUAL_COMMAND = `claude mcp add --transport stdio --scope user ccm -- ${SERVER_CMD.join(" ")}`;
|
|
887
|
-
function
|
|
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();
|
|
888
931
|
return new Promise((resolve4) => {
|
|
889
932
|
let stdout = "";
|
|
890
933
|
let stderr = "";
|
|
@@ -1085,6 +1128,18 @@ async function registerVaultWithObsidian(vaultPath, configPath = DEFAULT_CONFIG_
|
|
|
1085
1128
|
await writeFile2(configPath, JSON.stringify(config, null, 2));
|
|
1086
1129
|
return { registered: true, vaultId };
|
|
1087
1130
|
}
|
|
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;
|
|
1142
|
+
}
|
|
1088
1143
|
|
|
1089
1144
|
// src/cli/init.ts
|
|
1090
1145
|
var VAULT_PATH = join6(homedir3(), ".ccm", "knowledge-base");
|
|
@@ -1126,6 +1181,12 @@ async function executeInit() {
|
|
|
1126
1181
|
detail: obsidianResult.reason
|
|
1127
1182
|
});
|
|
1128
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
|
+
}
|
|
1129
1190
|
const mcpResult = await registerMcpServer();
|
|
1130
1191
|
if (mcpResult.success) {
|
|
1131
1192
|
steps.push({ name: "Claude Code MCP", status: "created", detail: mcpResult.output });
|
|
@@ -1169,6 +1230,8 @@ function formatInitSummary(result) {
|
|
|
1169
1230
|
}
|
|
1170
1231
|
|
|
1171
1232
|
// src/index.ts
|
|
1233
|
+
import { rm } from "fs/promises";
|
|
1234
|
+
import { createInterface } from "readline";
|
|
1172
1235
|
var VAULT_PATH2 = join7(homedir4(), ".ccm", "knowledge-base");
|
|
1173
1236
|
function parseCliArgs() {
|
|
1174
1237
|
const args = process.argv.slice(2);
|
|
@@ -1176,19 +1239,27 @@ function parseCliArgs() {
|
|
|
1176
1239
|
return "version";
|
|
1177
1240
|
if (args.includes("--update"))
|
|
1178
1241
|
return "update";
|
|
1242
|
+
if (args.includes("--uninstall"))
|
|
1243
|
+
return "uninstall";
|
|
1179
1244
|
if (args.includes("--init"))
|
|
1180
1245
|
return "init";
|
|
1181
1246
|
if (args.includes("--stdio"))
|
|
1182
1247
|
return "serve";
|
|
1248
|
+
if (!process.stdin.isTTY)
|
|
1249
|
+
return "serve";
|
|
1183
1250
|
return "help";
|
|
1184
1251
|
}
|
|
1185
1252
|
function printHelp() {
|
|
1186
1253
|
console.log(`${C.bold}claude-code-memory${C.reset} ${C.dim}(ccm)${C.reset} \u2014 Persistent memory for Claude Code
|
|
1187
1254
|
|
|
1188
1255
|
${C.bold}Usage:${C.reset}
|
|
1189
|
-
${C.cyan}
|
|
1190
|
-
${C.cyan}ccm --update${C.reset}
|
|
1191
|
-
${C.cyan}ccm --
|
|
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}
|
|
1192
1263
|
|
|
1193
1264
|
${C.dim}Vault:${C.reset} ~/.ccm/knowledge-base/
|
|
1194
1265
|
${C.dim}Docs:${C.reset} https://github.com/bennys001/claude-code-memory`);
|
|
@@ -1200,18 +1271,6 @@ async function fetchLatestVersion() {
|
|
|
1200
1271
|
const data = await res.json();
|
|
1201
1272
|
return data.version;
|
|
1202
1273
|
}
|
|
1203
|
-
function runCommand(cmd, args) {
|
|
1204
|
-
return new Promise((resolve4, reject) => {
|
|
1205
|
-
const proc = spawn2(cmd, args, { stdio: "inherit" });
|
|
1206
|
-
proc.on("error", reject);
|
|
1207
|
-
proc.on("close", (code) => {
|
|
1208
|
-
if (code === 0)
|
|
1209
|
-
resolve4();
|
|
1210
|
-
else
|
|
1211
|
-
reject(new Error(`${cmd} ${args.join(" ")} exited with code ${code}`));
|
|
1212
|
-
});
|
|
1213
|
-
});
|
|
1214
|
-
}
|
|
1215
1274
|
async function runUpdate() {
|
|
1216
1275
|
console.log(`${C.dim}Checking for updates...${C.reset}`);
|
|
1217
1276
|
const latest = await fetchLatestVersion();
|
|
@@ -1221,12 +1280,50 @@ async function runUpdate() {
|
|
|
1221
1280
|
}
|
|
1222
1281
|
console.log(`${C.dim}v${package_default.version}${C.reset} \u2192 ${C.green}v${latest}${C.reset}
|
|
1223
1282
|
`);
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
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
|
+
}
|
|
1227
1291
|
console.log(`
|
|
1228
1292
|
${C.green}Updated to v${latest}${C.reset}`);
|
|
1229
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
|
+
}
|
|
1230
1327
|
async function runInit() {
|
|
1231
1328
|
const result = await executeInit();
|
|
1232
1329
|
console.log(formatInitSummary(result));
|
|
@@ -1268,6 +1365,11 @@ if (cli === "version") {
|
|
|
1268
1365
|
console.error("Fatal:", err);
|
|
1269
1366
|
process.exit(1);
|
|
1270
1367
|
});
|
|
1368
|
+
} else if (cli === "uninstall") {
|
|
1369
|
+
runUninstall().catch((err) => {
|
|
1370
|
+
console.error("Fatal:", err);
|
|
1371
|
+
process.exit(1);
|
|
1372
|
+
});
|
|
1271
1373
|
} else if (cli === "init") {
|
|
1272
1374
|
runInit().catch((err) => {
|
|
1273
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.2",
|
|
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",
|