coding-friend-cli 1.32.0 → 1.32.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.
@@ -6,14 +6,14 @@ import {
6
6
  getMemoryMcpStatus,
7
7
  memoryConfigMenu,
8
8
  writeMemoryMcpEntry
9
- } from "./chunk-U7IVVN45.js";
10
- import {
11
- getLibPath
12
- } from "./chunk-RZRT7NGT.js";
9
+ } from "./chunk-5W7ZOVDU.js";
13
10
  import {
14
11
  loadConfig,
15
12
  resolveMemoryDir
16
13
  } from "./chunk-GTX6I57V.js";
14
+ import {
15
+ getLibPath
16
+ } from "./chunk-RZRT7NGT.js";
17
17
  import {
18
18
  showConfigHint
19
19
  } from "./chunk-HPNRQYLM.js";
@@ -34,17 +34,74 @@ import {
34
34
  } from "./chunk-5UVDWG5L.js";
35
35
 
36
36
  // src/commands/memory.ts
37
- import { existsSync, readdirSync, statSync, rmSync } from "fs";
38
- import { join, resolve, sep } from "path";
37
+ import { existsSync as existsSync2, readdirSync, statSync, rmSync } from "fs";
38
+ import { join as join2, resolve, sep } from "path";
39
39
  import { homedir } from "os";
40
40
  import { confirm } from "@inquirer/prompts";
41
+
42
+ // src/lib/mcp-state.ts
43
+ import { existsSync } from "fs";
44
+ import { join } from "path";
41
45
  import chalk from "chalk";
46
+ function warnStaleMcpJson(memoryDir) {
47
+ const localMcpPath = join(process.cwd(), ".mcp.json");
48
+ if (!existsSync(localMcpPath)) return;
49
+ const mcpJson = readJson(localMcpPath);
50
+ if (mcpJson === null) {
51
+ log.warn(".mcp.json exists but could not be parsed \u2014 check for syntax errors.");
52
+ return;
53
+ }
54
+ const state = detectMemoryMcpState(mcpJson, existsSync);
55
+ if (state.kind === "stale" || state.kind === "legacy-valid") {
56
+ if (memoryDir) {
57
+ writeMemoryMcpEntry(memoryDir);
58
+ if (state.kind === "stale") {
59
+ log.success("Auto-updated stale .mcp.json to version-stable npx format.");
60
+ } else {
61
+ log.success("Updated .mcp.json to version-stable npx format.");
62
+ }
63
+ console.log();
64
+ } else if (state.kind === "stale") {
65
+ console.log(chalk.yellow(`\u26A0 Stale MCP config detected in .mcp.json`));
66
+ console.log(chalk.dim(` Path no longer exists: ${state.path}`));
67
+ console.log(chalk.dim(` Run "cf memory mcp" to update to the new format.`));
68
+ console.log();
69
+ } else {
70
+ console.log(chalk.cyan(`\u2139 .mcp.json uses an absolute path for coding-friend-memory.`));
71
+ console.log(chalk.dim(` Consider running "cf memory mcp" to switch to the version-stable format.`));
72
+ console.log();
73
+ }
74
+ }
75
+ }
76
+ function detectMemoryMcpState(mcpJson, pathExists) {
77
+ if (!mcpJson) return { kind: "none" };
78
+ const servers = mcpJson.mcpServers;
79
+ if (!servers) return { kind: "none" };
80
+ const entry = servers["coding-friend-memory"];
81
+ if (!entry) return { kind: "none" };
82
+ const command = entry.command;
83
+ if (!command) return { kind: "none" };
84
+ if (command === "npx") return { kind: "npx" };
85
+ if (command === "node") {
86
+ const args = entry.args;
87
+ const serverPath = args?.[0];
88
+ if (!serverPath) return { kind: "none" };
89
+ if (!pathExists(serverPath)) {
90
+ return { kind: "stale", path: serverPath };
91
+ }
92
+ return { kind: "legacy-valid", path: serverPath };
93
+ }
94
+ return { kind: "none" };
95
+ }
96
+
97
+ // src/commands/memory.ts
98
+ import chalk2 from "chalk";
42
99
  function countMdFiles(dir) {
43
- if (!existsSync(dir)) return 0;
100
+ if (!existsSync2(dir)) return 0;
44
101
  let count = 0;
45
102
  for (const entry of readdirSync(dir, { withFileTypes: true })) {
46
103
  if (entry.isDirectory()) {
47
- count += countMdFiles(join(dir, entry.name));
104
+ count += countMdFiles(join2(dir, entry.name));
48
105
  } else if (entry.name.endsWith(".md") && entry.name !== "README.md") {
49
106
  count++;
50
107
  }
@@ -64,7 +121,7 @@ function truncateError(text) {
64
121
  return [...head, ` ... (${skipped} lines omitted) ...`, ...tail].join("\n");
65
122
  }
66
123
  function ensureMemoryBuilt(mcpDir) {
67
- if (!existsSync(join(mcpDir, "node_modules"))) {
124
+ if (!existsSync2(join2(mcpDir, "node_modules"))) {
68
125
  log.step("Installing memory server dependencies (one-time setup)...");
69
126
  const result = runWithStderr("npm", ["install"], { cwd: mcpDir });
70
127
  if (result.exitCode !== 0) {
@@ -74,7 +131,7 @@ function ensureMemoryBuilt(mcpDir) {
74
131
  }
75
132
  log.success("Done.");
76
133
  }
77
- if (!existsSync(join(mcpDir, "dist"))) {
134
+ if (!existsSync2(join2(mcpDir, "dist"))) {
78
135
  log.step("Building memory server...");
79
136
  const result = runWithStderr("npm", ["run", "build"], { cwd: mcpDir });
80
137
  if (result.exitCode !== 0) {
@@ -86,23 +143,23 @@ function ensureMemoryBuilt(mcpDir) {
86
143
  }
87
144
  }
88
145
  function printMemoryMcpConfig(serverPath, memoryDir) {
89
- console.log(chalk.dim("Add this to your MCP client config:"));
146
+ console.log(chalk2.dim("Add this to your MCP client config:"));
90
147
  console.log();
91
148
  console.log(
92
- chalk.yellow.bold("--- Claude Code (.mcp.json in project root) ---")
149
+ chalk2.yellow.bold("--- Claude Code (.mcp.json in project root) ---")
93
150
  );
94
151
  console.log(`
95
152
  {
96
153
  "mcpServers": {
97
154
  "coding-friend-memory": {
98
- "command": "node",
99
- "args": ["${serverPath}", "${memoryDir}"]
155
+ "command": "npx",
156
+ "args": ["-y", "coding-friend-cli", "mcp-serve", "${memoryDir}"]
100
157
  }
101
158
  }
102
159
  }`);
103
160
  console.log();
104
161
  console.log(
105
- chalk.yellow.bold(
162
+ chalk2.yellow.bold(
106
163
  "--- Claude Desktop / Claude Chat (claude_desktop_config.json) ---"
107
164
  )
108
165
  );
@@ -116,39 +173,39 @@ function printMemoryMcpConfig(serverPath, memoryDir) {
116
173
  }
117
174
  }`);
118
175
  console.log();
119
- console.log(chalk.yellow.bold("--- Generic MCP client ---"));
176
+ console.log(chalk2.yellow.bold("--- Generic MCP client ---"));
120
177
  console.log(`
121
178
  Server command: node ${serverPath} ${memoryDir}
122
179
  Transport: stdio`);
123
180
  console.log();
124
- console.log(chalk.yellow.bold("--- Available tools ---"));
181
+ console.log(chalk2.yellow.bold("--- Available tools ---"));
125
182
  console.log();
126
183
  console.log(
127
- ` ${chalk.white("memory_store")} ${chalk.dim("Store a new memory")}`
184
+ ` ${chalk2.white("memory_store")} ${chalk2.dim("Store a new memory")}`
128
185
  );
129
186
  console.log(
130
- ` ${chalk.white("memory_search")} ${chalk.dim("Search memories (keyword match)")}`
187
+ ` ${chalk2.white("memory_search")} ${chalk2.dim("Search memories (keyword match)")}`
131
188
  );
132
189
  console.log(
133
- ` ${chalk.white("memory_retrieve")} ${chalk.dim("Get a specific memory by ID")}`
190
+ ` ${chalk2.white("memory_retrieve")} ${chalk2.dim("Get a specific memory by ID")}`
134
191
  );
135
192
  console.log(
136
- ` ${chalk.white("memory_list")} ${chalk.dim("List memories with filtering")}`
193
+ ` ${chalk2.white("memory_list")} ${chalk2.dim("List memories with filtering")}`
137
194
  );
138
195
  console.log(
139
- ` ${chalk.white("memory_update")} ${chalk.dim("Update existing memory")}`
196
+ ` ${chalk2.white("memory_update")} ${chalk2.dim("Update existing memory")}`
140
197
  );
141
198
  console.log(
142
- ` ${chalk.white("memory_delete")} ${chalk.dim("Delete a memory")}`
199
+ ` ${chalk2.white("memory_delete")} ${chalk2.dim("Delete a memory")}`
143
200
  );
144
201
  console.log();
145
- console.log(chalk.yellow.bold("--- Resources ---"));
202
+ console.log(chalk2.yellow.bold("--- Resources ---"));
146
203
  console.log();
147
204
  console.log(
148
- ` ${chalk.white("memory://index")} ${chalk.dim("Browse all memories")}`
205
+ ` ${chalk2.white("memory://index")} ${chalk2.dim("Browse all memories")}`
149
206
  );
150
207
  console.log(
151
- ` ${chalk.white("memory://stats")} ${chalk.dim("Storage statistics")}`
208
+ ` ${chalk2.white("memory://stats")} ${chalk2.dim("Storage statistics")}`
152
209
  );
153
210
  console.log();
154
211
  log.warn(
@@ -166,43 +223,43 @@ async function memoryStatusCommand() {
166
223
  const docCount = countMdFiles(memoryDir);
167
224
  const mcpDir = getLibPath("cf-memory");
168
225
  ensureMemoryBuilt(mcpDir);
169
- const { isDaemonRunning, getDaemonInfo } = await import(join(mcpDir, "dist/daemon/process.js"));
170
- const { areSqliteDepsAvailable } = await import(join(mcpDir, "dist/lib/lazy-install.js"));
226
+ const { isDaemonRunning, getDaemonInfo } = await import(join2(mcpDir, "dist/daemon/process.js"));
227
+ const { areSqliteDepsAvailable } = await import(join2(mcpDir, "dist/lib/lazy-install.js"));
171
228
  const sqliteAvailable = areSqliteDepsAvailable();
172
229
  const running = await isDaemonRunning();
173
230
  const daemonInfo = getDaemonInfo();
174
231
  let tierLabel;
175
232
  if (sqliteAvailable) {
176
- tierLabel = chalk.cyan("Tier 1 (SQLite + Hybrid)");
233
+ tierLabel = chalk2.cyan("Tier 1 (SQLite + Hybrid)");
177
234
  } else if (running) {
178
- tierLabel = chalk.cyan("Tier 2 (MiniSearch + Daemon)");
235
+ tierLabel = chalk2.cyan("Tier 2 (MiniSearch + Daemon)");
179
236
  } else {
180
- tierLabel = chalk.cyan("Tier 3 (Markdown)");
237
+ tierLabel = chalk2.cyan("Tier 3 (Markdown)");
181
238
  }
182
239
  printBanner("\u{1F9E0} Coding Friend Memory");
183
240
  console.log();
184
241
  log.info(`Tier: ${tierLabel}`);
185
- log.info(`Memory dir: ${chalk.cyan(memoryDir)}`);
186
- log.info(`Memories in this dir: ${chalk.green(String(docCount))}`);
242
+ log.info(`Memory dir: ${chalk2.cyan(memoryDir)}`);
243
+ log.info(`Memories in this dir: ${chalk2.green(String(docCount))}`);
187
244
  if (running && daemonInfo) {
188
245
  const uptime = (Date.now() - daemonInfo.startedAt) / 1e3;
189
246
  log.info(
190
- `Daemon: ${chalk.green("running")} (PID ${daemonInfo.pid}, uptime ${formatUptime(uptime)}) ${chalk.dim('Turn it off by "cf memory stop-daemon"')}`
247
+ `Daemon: ${chalk2.green("running")} (PID ${daemonInfo.pid}, uptime ${formatUptime(uptime)}) ${chalk2.dim('Turn it off by "cf memory stop-daemon"')}`
191
248
  );
192
249
  } else if (sqliteAvailable) {
193
250
  log.info(
194
- `Daemon: ${chalk.dim("stopped")} ${chalk.dim("(not needed \u2014 Tier 1 uses SQLite directly)")}`
251
+ `Daemon: ${chalk2.dim("stopped")} ${chalk2.dim("(not needed \u2014 Tier 1 uses SQLite directly)")}`
195
252
  );
196
253
  } else {
197
254
  log.info(
198
- `Daemon: ${chalk.dim("stopped")} ${chalk.dim('(run "cf memory start-daemon" for Tier 2 search)')}`
255
+ `Daemon: ${chalk2.dim("stopped")} ${chalk2.dim('(run "cf memory start-daemon" for Tier 2 search)')}`
199
256
  );
200
257
  }
201
258
  if (sqliteAvailable) {
202
- log.info(`SQLite deps: ${chalk.green("installed")}`);
259
+ log.info(`SQLite deps: ${chalk2.green("installed")}`);
203
260
  } else {
204
261
  log.info(
205
- `SQLite deps: ${chalk.dim("not installed")} (run "cf memory init" to enable Tier 1)`
262
+ `SQLite deps: ${chalk2.dim("not installed")} (run "cf memory init" to enable Tier 1)`
206
263
  );
207
264
  }
208
265
  const config = loadConfig();
@@ -210,33 +267,33 @@ async function memoryStatusCommand() {
210
267
  if (embeddingConfig?.provider || embeddingConfig?.model) {
211
268
  const provider = embeddingConfig.provider ?? "transformers";
212
269
  const model = embeddingConfig.model ?? (provider === "ollama" ? "all-minilm:l6-v2" : "Xenova/all-MiniLM-L6-v2");
213
- log.info(`Embedding: ${chalk.cyan(model)} ${chalk.dim(`(${provider})`)}`);
270
+ log.info(`Embedding: ${chalk2.cyan(model)} ${chalk2.dim(`(${provider})`)}`);
214
271
  }
215
272
  const mcpStatus = getMemoryMcpStatus();
216
273
  if (mcpStatus.configured && mcpStatus.scope === "local") {
217
274
  log.info(
218
- `MCP: ${chalk.green("configured")} ${chalk.dim("(local .mcp.json)")}`
275
+ `MCP: ${chalk2.green("configured")} ${chalk2.dim("(local .mcp.json)")}`
219
276
  );
220
277
  } else if (mcpStatus.configured && mcpStatus.scope === "global") {
221
278
  log.info(
222
- `MCP: ${chalk.green("configured")} ${chalk.dim("(global ~/.claude/.mcp.json)")} ${chalk.yellow("\u26A0 global config uses a fixed path \u2014 only works for one project")}`
279
+ `MCP: ${chalk2.green("configured")} ${chalk2.dim("(global ~/.claude/.mcp.json)")} ${chalk2.yellow("\u26A0 global config uses a fixed path \u2014 only works for one project")}`
223
280
  );
224
281
  } else {
225
282
  log.info(
226
- `MCP: ${chalk.dim("not configured in this project")} ${chalk.dim('(run "cf memory init" or add manually via "cf memory mcp")')}`
283
+ `MCP: ${chalk2.dim("not configured in this project")} ${chalk2.dim('(run "cf memory init" or add manually via "cf memory mcp")')}`
227
284
  );
228
285
  }
229
286
  const autoCapture = config.memory?.autoCapture ?? false;
230
287
  log.info(
231
- `Auto-capture: ${autoCapture ? chalk.green("on") : chalk.dim("off")}`
288
+ `Auto-capture: ${autoCapture ? chalk2.green("on") : chalk2.dim("off")}`
232
289
  );
233
- if (existsSync(memoryDir)) {
290
+ if (existsSync2(memoryDir)) {
234
291
  const categories = readdirSync(memoryDir, { withFileTypes: true }).filter((d) => d.isDirectory() && !d.name.startsWith(".")).map((d) => {
235
- const catCount = countMdFiles(join(memoryDir, d.name));
292
+ const catCount = countMdFiles(join2(memoryDir, d.name));
236
293
  return `${d.name} (${catCount})`;
237
294
  }).filter((s) => !s.endsWith("(0)"));
238
295
  if (categories.length > 0) {
239
- log.info(`Categories: ${chalk.dim(categories.join(", "))}`);
296
+ log.info(`Categories: ${chalk2.dim(categories.join(", "))}`);
240
297
  }
241
298
  }
242
299
  console.log();
@@ -245,7 +302,7 @@ async function memoryStatusCommand() {
245
302
  }
246
303
  async function memorySearchCommand(query) {
247
304
  const memoryDir = getMemoryDir();
248
- if (!existsSync(memoryDir)) {
305
+ if (!existsSync2(memoryDir)) {
249
306
  log.error(`Memory dir not found: ${memoryDir}`);
250
307
  log.dim("Run `cf init` to create project folders.");
251
308
  process.exit(1);
@@ -257,7 +314,7 @@ async function memorySearchCommand(query) {
257
314
  [
258
315
  "-e",
259
316
  `
260
- import { MarkdownBackend } from ${JSON.stringify(join(mcpDir, "dist/backends/markdown.js"))};
317
+ import { MarkdownBackend } from ${JSON.stringify(join2(mcpDir, "dist/backends/markdown.js"))};
261
318
  const backend = new MarkdownBackend(${JSON.stringify(memoryDir)});
262
319
  const results = await backend.search({ query: process.env.CF_SEARCH_QUERY, limit: 10 });
263
320
  for (const r of results) {
@@ -280,7 +337,7 @@ async function memoryListCommand(opts) {
280
337
  return memoryListProjectsCommand();
281
338
  }
282
339
  const memoryDir = getMemoryDir();
283
- if (!existsSync(memoryDir)) {
340
+ if (!existsSync2(memoryDir)) {
284
341
  log.info(`No memory directory found at: ${memoryDir}`);
285
342
  log.dim(
286
343
  "This folder has no memories yet. Use --projects to list all project databases."
@@ -297,7 +354,7 @@ async function memoryListCommand(opts) {
297
354
  [
298
355
  "-e",
299
356
  `
300
- import { MarkdownBackend } from ${JSON.stringify(join(mcpDir, "dist/backends/markdown.js"))};
357
+ import { MarkdownBackend } from ${JSON.stringify(join2(mcpDir, "dist/backends/markdown.js"))};
301
358
  const backend = new MarkdownBackend(${JSON.stringify(memoryDir)});
302
359
  const metas = await backend.list({});
303
360
  if (metas.length === 0) { console.log("No memories found."); process.exit(0); }
@@ -333,7 +390,7 @@ async function memoryStartDaemonCommand() {
333
390
  const memoryDir = getMemoryDir();
334
391
  const mcpDir = getLibPath("cf-memory");
335
392
  ensureMemoryBuilt(mcpDir);
336
- const { isDaemonRunning, getDaemonInfo, spawnDaemon } = await import(join(mcpDir, "dist/daemon/process.js"));
393
+ const { isDaemonRunning, getDaemonInfo, spawnDaemon } = await import(join2(mcpDir, "dist/daemon/process.js"));
337
394
  if (await isDaemonRunning()) {
338
395
  const info = getDaemonInfo();
339
396
  log.info(`Daemon already running (PID ${info?.pid})`);
@@ -345,7 +402,7 @@ async function memoryStartDaemonCommand() {
345
402
  const result = await spawnDaemon(memoryDir, embedding, {});
346
403
  if (result) {
347
404
  log.success(`Daemon started (PID ${result.pid})`);
348
- log.info(`Watching ${chalk.cyan(memoryDir)} for changes`);
405
+ log.info(`Watching ${chalk2.cyan(memoryDir)} for changes`);
349
406
  } else {
350
407
  log.error("Daemon did not start within 3 seconds");
351
408
  process.exit(1);
@@ -354,7 +411,7 @@ async function memoryStartDaemonCommand() {
354
411
  async function memoryStopDaemonCommand() {
355
412
  const mcpDir = getLibPath("cf-memory");
356
413
  ensureMemoryBuilt(mcpDir);
357
- const { stopDaemon, isDaemonRunning } = await import(join(mcpDir, "dist/daemon/process.js"));
414
+ const { stopDaemon, isDaemonRunning } = await import(join2(mcpDir, "dist/daemon/process.js"));
358
415
  if (!await isDaemonRunning()) {
359
416
  log.info("Daemon is not running.");
360
417
  return;
@@ -371,10 +428,10 @@ async function memoryRebuildCommand() {
371
428
  const memoryDir = getMemoryDir();
372
429
  const mcpDir = getLibPath("cf-memory");
373
430
  ensureMemoryBuilt(mcpDir);
374
- const { areSqliteDepsAvailable } = await import(join(mcpDir, "dist/lib/lazy-install.js"));
431
+ const { areSqliteDepsAvailable } = await import(join2(mcpDir, "dist/lib/lazy-install.js"));
375
432
  if (areSqliteDepsAvailable()) {
376
433
  log.step("Rebuilding SQLite index + embeddings...");
377
- const { SqliteBackend } = await import(join(mcpDir, "dist/backends/sqlite/index.js"));
434
+ const { SqliteBackend } = await import(join2(mcpDir, "dist/backends/sqlite/index.js"));
378
435
  const config = loadConfig();
379
436
  const embedding = config.memory?.embedding;
380
437
  const opts = embedding ? { embedding, skipVec: false } : { skipVec: false };
@@ -384,7 +441,7 @@ async function memoryRebuildCommand() {
384
441
  const stats = await backend.stats();
385
442
  log.success(`Rebuilt: ${stats.total} memories indexed.`);
386
443
  if (backend.isVecEnabled()) {
387
- log.info(`Vector search: ${chalk.green("enabled")}`);
444
+ log.info(`Vector search: ${chalk2.green("enabled")}`);
388
445
  }
389
446
  if (!backend.isRebuildNeeded()) {
390
447
  log.info("Embedding dimensions: up to date");
@@ -394,14 +451,14 @@ async function memoryRebuildCommand() {
394
451
  }
395
452
  return;
396
453
  }
397
- const { isDaemonRunning, getDaemonPaths } = await import(join(mcpDir, "dist/daemon/process.js"));
454
+ const { isDaemonRunning, getDaemonPaths } = await import(join2(mcpDir, "dist/daemon/process.js"));
398
455
  if (!await isDaemonRunning()) {
399
456
  log.info("No SQLite deps and daemon not running. Nothing to rebuild.");
400
457
  log.dim("Install Tier 1 deps: cf memory init");
401
458
  log.dim("Or start the daemon: cf memory start-daemon");
402
459
  return;
403
460
  }
404
- const { DaemonClient } = await import(join(mcpDir, "dist/lib/daemon-client.js"));
461
+ const { DaemonClient } = await import(join2(mcpDir, "dist/lib/daemon-client.js"));
405
462
  const paths = getDaemonPaths();
406
463
  const client = new DaemonClient(paths.socketPath);
407
464
  log.step("Rebuilding search index via daemon...");
@@ -418,7 +475,7 @@ function getDbPath(memoryDir) {
418
475
  const stripped = resolved.replace(/\/docs\/memory$/, "").replace(/\/memory$/, "");
419
476
  const id = stripped.replace(/\//g, "-");
420
477
  const home = homedir();
421
- const dbPath = join(
478
+ const dbPath = join2(
422
479
  home,
423
480
  ".coding-friend",
424
481
  "memory",
@@ -426,7 +483,7 @@ function getDbPath(memoryDir) {
426
483
  id,
427
484
  "db.sqlite"
428
485
  );
429
- return existsSync(dbPath) ? dbPath : null;
486
+ return existsSync2(dbPath) ? dbPath : null;
430
487
  } catch {
431
488
  return null;
432
489
  }
@@ -435,7 +492,7 @@ async function ensureSqliteDepsIfNeeded(mcpDir) {
435
492
  const config = loadConfig();
436
493
  const tier = config.memory?.tier ?? "auto";
437
494
  if (tier === "markdown" || tier === "lite") return true;
438
- const { ensureDeps, areSqliteDepsAvailable } = await import(join(mcpDir, "dist/lib/lazy-install.js"));
495
+ const { ensureDeps, areSqliteDepsAvailable } = await import(join2(mcpDir, "dist/lib/lazy-install.js"));
439
496
  if (areSqliteDepsAvailable()) return true;
440
497
  log.step("Installing SQLite dependencies...");
441
498
  const installed = await ensureDeps({
@@ -506,7 +563,7 @@ async function memoryInitWizard(memoryDir, mcpDir) {
506
563
  }
507
564
  const depsOk = await ensureSqliteDepsIfNeeded(mcpDir);
508
565
  if (!depsOk) return;
509
- if (!existsSync(memoryDir)) {
566
+ if (!existsSync2(memoryDir)) {
510
567
  log.info(
511
568
  "No memory directory found. Memories will be indexed as they're created."
512
569
  );
@@ -522,7 +579,7 @@ async function memoryInitWizard(memoryDir, mcpDir) {
522
579
  return;
523
580
  }
524
581
  log.step(`Importing ${docCount} existing memories into SQLite...`);
525
- const { SqliteBackend } = await import(join(mcpDir, "dist/backends/sqlite/index.js"));
582
+ const { SqliteBackend } = await import(join2(mcpDir, "dist/backends/sqlite/index.js"));
526
583
  const embedding = config.memory?.embedding;
527
584
  const backend = new SqliteBackend(memoryDir, {
528
585
  skipVec: false,
@@ -533,7 +590,7 @@ async function memoryInitWizard(memoryDir, mcpDir) {
533
590
  const stats = await backend.stats();
534
591
  log.success(`Imported ${stats.total} memories. DB: ${backend.getDbPath()}`);
535
592
  log.info(
536
- `Vector search: ${backend.isVecEnabled() ? chalk.green("enabled") : chalk.dim("disabled (sqlite-vec not available)")}`
593
+ `Vector search: ${backend.isVecEnabled() ? chalk2.green("enabled") : chalk2.dim("disabled (sqlite-vec not available)")}`
537
594
  );
538
595
  } finally {
539
596
  await backend.close();
@@ -542,13 +599,13 @@ async function memoryInitWizard(memoryDir, mcpDir) {
542
599
  console.log();
543
600
  log.success('Memory initialized! Run "cf memory status" to verify.');
544
601
  log.info(
545
- `Tip: Run ${chalk.cyan("/cf-scan")} in Claude Code to populate memory with project knowledge.`
602
+ `Tip: Run ${chalk2.cyan("/cf-scan")} in Claude Code to populate memory with project knowledge.`
546
603
  );
547
604
  }
548
- async function setupMemoryMcp(memoryDir, mcpDir) {
605
+ async function setupMemoryMcp(memoryDir, _mcpDir) {
549
606
  const mcpStatus = getMemoryMcpStatus();
550
607
  if (mcpStatus.configured && mcpStatus.scope === "local") {
551
- log.info(`MCP: ${chalk.green("already configured")} in .mcp.json`);
608
+ log.info(`MCP: ${chalk2.green("already configured")} in .mcp.json`);
552
609
  return;
553
610
  }
554
611
  console.log();
@@ -564,14 +621,7 @@ async function setupMemoryMcp(memoryDir, mcpDir) {
564
621
  log.dim('Skipped. Run "cf memory mcp" anytime to get the config.');
565
622
  return;
566
623
  }
567
- const serverPath = join(mcpDir, "dist", "index.js");
568
- if (!existsSync(serverPath)) {
569
- log.warn(
570
- "cf-memory not built yet. Run `cf memory mcp` after building to get the config."
571
- );
572
- return;
573
- }
574
- writeMemoryMcpEntry(serverPath, memoryDir);
624
+ writeMemoryMcpEntry(memoryDir);
575
625
  }
576
626
  async function memoryInitCommand() {
577
627
  const memoryDir = getMemoryDir();
@@ -604,7 +654,7 @@ async function memoryConfigCommand() {
604
654
  }
605
655
  function getProjectsBaseDir() {
606
656
  const home = homedir();
607
- return join(home, ".coding-friend", "memory", "projects");
657
+ return join2(home, ".coding-friend", "memory", "projects");
608
658
  }
609
659
  function formatSize(bytes) {
610
660
  if (bytes < 1024) return `${bytes} B`;
@@ -622,9 +672,9 @@ function formatDate(raw) {
622
672
  }
623
673
  function dirSize(dir) {
624
674
  let total = 0;
625
- if (!existsSync(dir)) return 0;
675
+ if (!existsSync2(dir)) return 0;
626
676
  for (const entry of readdirSync(dir, { withFileTypes: true })) {
627
- const p = join(dir, entry.name);
677
+ const p = join2(dir, entry.name);
628
678
  if (entry.isFile()) {
629
679
  total += statSync(p).size;
630
680
  } else if (entry.isDirectory()) {
@@ -634,7 +684,7 @@ function dirSize(dir) {
634
684
  return total;
635
685
  }
636
686
  function getProjectInfo(projectDir, projectId, mcpDir, knownSourceDir) {
637
- const dbPath = join(projectDir, "db.sqlite");
687
+ const dbPath = join2(projectDir, "db.sqlite");
638
688
  const size = dirSize(projectDir);
639
689
  const info = {
640
690
  id: projectId,
@@ -643,7 +693,7 @@ function getProjectInfo(projectDir, projectId, mcpDir, knownSourceDir) {
643
693
  size,
644
694
  lastUpdated: null
645
695
  };
646
- if (!existsSync(dbPath)) return info;
696
+ if (!existsSync2(dbPath)) return info;
647
697
  try {
648
698
  const backfillDir = knownSourceDir ? JSON.stringify(knownSourceDir) : "null";
649
699
  const result = run(
@@ -684,7 +734,7 @@ async function memoryListProjectsCommand() {
684
734
  const baseDir = getProjectsBaseDir();
685
735
  const mcpDir = getLibPath("cf-memory");
686
736
  ensureMemoryBuilt(mcpDir);
687
- if (!existsSync(baseDir)) {
737
+ if (!existsSync2(baseDir)) {
688
738
  log.info("No memory projects found.");
689
739
  log.dim('Run "cf memory init" in a project to create one.');
690
740
  return;
@@ -695,35 +745,35 @@ async function memoryListProjectsCommand() {
695
745
  return;
696
746
  }
697
747
  const currentMemoryDir = resolve(getMemoryDir());
698
- const { projectId } = await import(join(mcpDir, "dist/backends/sqlite/index.js"));
748
+ const { projectId } = await import(join2(mcpDir, "dist/backends/sqlite/index.js"));
699
749
  const currentProjectId = projectId(currentMemoryDir);
700
750
  log.step(`Scanning ${dirs.length} project(s)...
701
751
  `);
702
752
  const projects = [];
703
753
  for (const id of dirs) {
704
754
  const knownDir = id === currentProjectId ? currentMemoryDir : void 0;
705
- projects.push(getProjectInfo(join(baseDir, id), id, mcpDir, knownDir));
755
+ projects.push(getProjectInfo(join2(baseDir, id), id, mcpDir, knownDir));
706
756
  }
707
757
  projects.sort((a, b) => b.size - a.size);
708
758
  const totalSize = projects.reduce((sum, p) => sum + p.size, 0);
709
759
  const idxW = String(projects.length).length;
710
760
  const header = `${"#".padStart(idxW)} ${"SIZE".padStart(10)} ${"MEMS".padStart(4)} ${"PROJECT ID".padEnd(12)} ${"UPDATED".padEnd(16)} PATH`;
711
- console.log(chalk.bold(header));
712
- console.log(chalk.dim("-".repeat(header.length + 10)));
761
+ console.log(chalk2.bold(header));
762
+ console.log(chalk2.dim("-".repeat(header.length + 10)));
713
763
  projects.forEach((p, i) => {
714
- const idx = chalk.dim(String(i + 1).padStart(idxW));
715
- const sizeStr = chalk.yellow(formatSize(p.size).padStart(10));
716
- const memCount = chalk.green(String(p.memories).padStart(4));
717
- const idStr = chalk.cyan(p.id.padEnd(12));
718
- const dateStr = p.lastUpdated ? formatDate(p.lastUpdated).padEnd(16) : chalk.dim("n/a".padEnd(16));
719
- const pathStr = p.sourceDir ? chalk.dim(p.sourceDir) : chalk.dim("(unknown)");
764
+ const idx = chalk2.dim(String(i + 1).padStart(idxW));
765
+ const sizeStr = chalk2.yellow(formatSize(p.size).padStart(10));
766
+ const memCount = chalk2.green(String(p.memories).padStart(4));
767
+ const idStr = chalk2.cyan(p.id.padEnd(12));
768
+ const dateStr = p.lastUpdated ? formatDate(p.lastUpdated).padEnd(16) : chalk2.dim("n/a".padEnd(16));
769
+ const pathStr = p.sourceDir ? chalk2.dim(p.sourceDir) : chalk2.dim("(unknown)");
720
770
  console.log(
721
771
  `${idx} ${sizeStr} ${memCount} ${idStr} ${dateStr} ${pathStr}`
722
772
  );
723
773
  });
724
774
  console.log();
725
775
  console.log(
726
- chalk.bold(
776
+ chalk2.bold(
727
777
  `Total: ${projects.length} project(s), ${formatSize(totalSize)}`
728
778
  )
729
779
  );
@@ -731,7 +781,7 @@ async function memoryListProjectsCommand() {
731
781
  }
732
782
  async function memoryRmCommand(opts) {
733
783
  const baseDir = getProjectsBaseDir();
734
- if (!existsSync(baseDir)) {
784
+ if (!existsSync2(baseDir)) {
735
785
  log.info("No memory projects found. Nothing to remove.");
736
786
  return;
737
787
  }
@@ -741,9 +791,9 @@ async function memoryRmCommand(opts) {
741
791
  const dirs = readdirSync(baseDir, { withFileTypes: true }).filter((d) => d.isDirectory() && !d.name.startsWith(".")).map((d) => d.name);
742
792
  const orphaned = [];
743
793
  for (const id of dirs) {
744
- const projectDir = join(baseDir, id);
794
+ const projectDir = join2(baseDir, id);
745
795
  const info = getProjectInfo(projectDir, id, mcpDir);
746
- if (info.sourceDir && !existsSync(info.sourceDir)) {
796
+ if (info.sourceDir && !existsSync2(info.sourceDir)) {
747
797
  orphaned.push({
748
798
  id,
749
799
  reason: `source dir missing: ${info.sourceDir}`,
@@ -767,7 +817,7 @@ async function memoryRmCommand(opts) {
767
817
  );
768
818
  console.log();
769
819
  for (const o of orphaned) {
770
- console.log(` ${chalk.cyan(o.id)} ${chalk.dim(o.reason)}`);
820
+ console.log(` ${chalk2.cyan(o.id)} ${chalk2.dim(o.reason)}`);
771
821
  }
772
822
  console.log();
773
823
  const ok = await confirm({
@@ -779,7 +829,7 @@ async function memoryRmCommand(opts) {
779
829
  return;
780
830
  }
781
831
  for (const o of orphaned) {
782
- rmSync(join(baseDir, o.id), { recursive: true, force: true });
832
+ rmSync(join2(baseDir, o.id), { recursive: true, force: true });
783
833
  }
784
834
  log.success(
785
835
  `Deleted ${orphaned.length} orphaned project(s) (${formatSize(totalSize)}).`
@@ -795,7 +845,7 @@ async function memoryRmCommand(opts) {
795
845
  return;
796
846
  }
797
847
  const totalSize = dirs.reduce(
798
- (sum, d) => sum + dirSize(join(baseDir, d.name)),
848
+ (sum, d) => sum + dirSize(join2(baseDir, d.name)),
799
849
  0
800
850
  );
801
851
  log.warn(
@@ -812,19 +862,19 @@ async function memoryRmCommand(opts) {
812
862
  return;
813
863
  }
814
864
  for (const d of dirs) {
815
- rmSync(join(baseDir, d.name), { recursive: true, force: true });
865
+ rmSync(join2(baseDir, d.name), { recursive: true, force: true });
816
866
  }
817
867
  log.success(`Deleted ${dirs.length} project database(s).`);
818
868
  return;
819
869
  }
820
870
  if (opts.projectId) {
821
- const projectDir = join(baseDir, opts.projectId);
871
+ const projectDir = join2(baseDir, opts.projectId);
822
872
  const resolved = resolve(projectDir);
823
873
  if (!resolved.startsWith(resolve(baseDir) + sep)) {
824
874
  log.error("Invalid project ID.");
825
875
  process.exit(1);
826
876
  }
827
- if (!existsSync(projectDir)) {
877
+ if (!existsSync2(projectDir)) {
828
878
  log.error(`Project "${opts.projectId}" not found.`);
829
879
  log.dim('Run "cf memory list --projects" to see available projects.');
830
880
  process.exit(1);
@@ -855,11 +905,14 @@ async function memoryMcpCommand() {
855
905
  const memoryDir = getMemoryDir();
856
906
  const mcpDir = getLibPath("cf-memory");
857
907
  ensureMemoryBuilt(mcpDir);
858
- const serverPath = join(mcpDir, "dist", "index.js");
908
+ warnStaleMcpJson(memoryDir);
909
+ const serverPath = join2(mcpDir, "dist", "index.js");
859
910
  printMemoryMcpConfig(serverPath, memoryDir);
860
911
  }
861
912
 
862
913
  export {
914
+ warnStaleMcpJson,
915
+ detectMemoryMcpState,
863
916
  ensureMemoryBuilt,
864
917
  printMemoryMcpConfig,
865
918
  memoryStatusCommand,
@@ -1,9 +1,9 @@
1
- import {
2
- getLibPath
3
- } from "./chunk-RZRT7NGT.js";
4
1
  import {
5
2
  resolveMemoryDir
6
3
  } from "./chunk-GTX6I57V.js";
4
+ import {
5
+ getLibPath
6
+ } from "./chunk-RZRT7NGT.js";
7
7
  import {
8
8
  BACK,
9
9
  askScope,
@@ -24,7 +24,6 @@ import {
24
24
  } from "./chunk-5UVDWG5L.js";
25
25
 
26
26
  // src/lib/memory-prompts.ts
27
- import { existsSync } from "fs";
28
27
  import { homedir } from "os";
29
28
  import { confirm, input, select } from "@inquirer/prompts";
30
29
  import chalk from "chalk";
@@ -219,7 +218,7 @@ async function editMemoryEmbedding(globalCfg, localCfg) {
219
218
  if (ollamaUrl) embedding.ollamaUrl = ollamaUrl;
220
219
  writeMemoryField(scope, "embedding", embedding);
221
220
  }
222
- function writeMemoryMcpEntry(serverPath, memoryDir) {
221
+ function writeMemoryMcpEntry(memoryDir) {
223
222
  const mcpPath = join(process.cwd(), ".mcp.json");
224
223
  const existing = readJson(mcpPath) ?? {};
225
224
  const servers = existing.mcpServers ?? {};
@@ -228,8 +227,8 @@ function writeMemoryMcpEntry(serverPath, memoryDir) {
228
227
  mcpServers: {
229
228
  ...servers,
230
229
  "coding-friend-memory": {
231
- command: "node",
232
- args: [serverPath, memoryDir]
230
+ command: "npx",
231
+ args: ["-y", "coding-friend-cli", "mcp-serve", memoryDir]
233
232
  }
234
233
  }
235
234
  });
@@ -261,24 +260,8 @@ async function editMemoryMcp() {
261
260
  });
262
261
  if (!reconfigure) return;
263
262
  }
264
- let mcpDir;
265
- try {
266
- mcpDir = getLibPath("cf-memory");
267
- } catch {
268
- log.warn(
269
- "cf-memory package not found. Install the CLI first: npm i -g coding-friend-cli"
270
- );
271
- return;
272
- }
273
- const serverPath = join(mcpDir, "dist", "index.js");
274
- if (!existsSync(serverPath)) {
275
- log.warn(
276
- 'cf-memory not built yet. Run "cf memory mcp" after building to get the config.'
277
- );
278
- return;
279
- }
280
263
  const memoryDir = resolveMemoryDir();
281
- writeMemoryMcpEntry(serverPath, memoryDir);
264
+ writeMemoryMcpEntry(memoryDir);
282
265
  }
283
266
  async function memoryConfigMenu(opts) {
284
267
  while (true) {
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  memoryConfigMenu
3
- } from "./chunk-U7IVVN45.js";
4
- import "./chunk-RZRT7NGT.js";
3
+ } from "./chunk-5W7ZOVDU.js";
5
4
  import "./chunk-GTX6I57V.js";
5
+ import "./chunk-RZRT7NGT.js";
6
6
  import {
7
7
  findStatuslineHookPath,
8
8
  getCurrentAccountEmail,
package/dist/index.js CHANGED
@@ -30,21 +30,25 @@ program.command("enable").description("Re-enable the Coding Friend plugin").opti
30
30
  await enableCommand(opts);
31
31
  });
32
32
  program.command("init").description("Initialize coding-friend in current project").action(async () => {
33
- const { initCommand } = await import("./init-H2EOLWJ5.js");
33
+ const { initCommand } = await import("./init-3UITY4LD.js");
34
34
  await initCommand();
35
35
  });
36
36
  program.command("config").description("Manage Coding Friend configuration").action(async () => {
37
- const { configCommand } = await import("./config-OBCZNDKV.js");
37
+ const { configCommand } = await import("./config-FUEEFM5N.js");
38
38
  await configCommand();
39
39
  });
40
40
  program.command("host").description("Build and serve learning docs as a static website").argument("[path]", "path to docs folder").option("-p, --port <port>", "port number", "3333").action(async (path, opts) => {
41
- const { hostCommand } = await import("./host-N3GQ6OJM.js");
41
+ const { hostCommand } = await import("./host-RNYPAE4D.js");
42
42
  await hostCommand(path, opts);
43
43
  });
44
44
  program.command("mcp").description("Setup MCP server for learning docs").argument("[path]", "path to docs folder").action(async (path) => {
45
- const { mcpCommand } = await import("./mcp-G4FEXMZW.js");
45
+ const { mcpCommand } = await import("./mcp-LJ5NX6XE.js");
46
46
  await mcpCommand(path);
47
47
  });
48
+ program.command("mcp-serve").description("Start the cf-memory MCP server (used internally by npx)").argument("<memoryDir>", "path to memory directory").action(async (memoryDir) => {
49
+ const { mcpServeCommand } = await import("./mcp-serve-3FEPFVVQ.js");
50
+ await mcpServeCommand(memoryDir);
51
+ });
48
52
  program.command("permission").description("Manage Claude Code permission rules for Coding Friend").option("--all", "Apply all recommended permissions without prompts").option("--user", "Save to user-level settings (~/.claude/settings.json)").option(
49
53
  "--project",
50
54
  "Save to project-level settings (.claude/settings.local.json)"
@@ -61,7 +65,7 @@ program.command("update").description("Update coding-friend plugin, CLI, and sta
61
65
  await updateCommand(opts);
62
66
  });
63
67
  program.command("status").description("Show comprehensive Coding Friend status").action(async () => {
64
- const { statusCommand } = await import("./status-EFEXM3ZM.js");
68
+ const { statusCommand } = await import("./status-FU5GR3MP.js");
65
69
  await statusCommand();
66
70
  });
67
71
  var session = program.command("session").description("Save and load Claude Code sessions across machines");
@@ -100,43 +104,43 @@ Memory subcommands:
100
104
  memory mcp Show MCP server setup instructions`
101
105
  );
102
106
  memory.command("status").description("Show memory system status").action(async () => {
103
- const { memoryStatusCommand } = await import("./memory-SO33RAI5.js");
107
+ const { memoryStatusCommand } = await import("./memory-2ZD4WU3S.js");
104
108
  await memoryStatusCommand();
105
109
  });
106
110
  memory.command("search").description("Search memories by query").argument("<query>", "search query").action(async (query) => {
107
- const { memorySearchCommand } = await import("./memory-SO33RAI5.js");
111
+ const { memorySearchCommand } = await import("./memory-2ZD4WU3S.js");
108
112
  await memorySearchCommand(query);
109
113
  });
110
114
  memory.command("list").description(
111
115
  "List memories in current project, or all projects with --projects"
112
116
  ).option("--projects", "List all project databases with size and metadata").action(async (opts) => {
113
- const { memoryListCommand } = await import("./memory-SO33RAI5.js");
117
+ const { memoryListCommand } = await import("./memory-2ZD4WU3S.js");
114
118
  await memoryListCommand(opts);
115
119
  });
116
120
  memory.command("init").description(
117
121
  "Initialize memory system \u2014 interactive wizard (first time) or config menu"
118
122
  ).action(async () => {
119
- const { memoryInitCommand } = await import("./memory-SO33RAI5.js");
123
+ const { memoryInitCommand } = await import("./memory-2ZD4WU3S.js");
120
124
  await memoryInitCommand();
121
125
  });
122
126
  memory.command("config").description("Configure memory system settings").action(async () => {
123
- const { memoryConfigCommand } = await import("./memory-SO33RAI5.js");
127
+ const { memoryConfigCommand } = await import("./memory-2ZD4WU3S.js");
124
128
  await memoryConfigCommand();
125
129
  });
126
130
  memory.command("start-daemon").description("Start the memory daemon (Tier 2 \u2014 MiniSearch)").action(async () => {
127
- const { memoryStartDaemonCommand } = await import("./memory-SO33RAI5.js");
131
+ const { memoryStartDaemonCommand } = await import("./memory-2ZD4WU3S.js");
128
132
  await memoryStartDaemonCommand();
129
133
  });
130
134
  memory.command("stop-daemon").description("Stop the memory daemon").action(async () => {
131
- const { memoryStopDaemonCommand } = await import("./memory-SO33RAI5.js");
135
+ const { memoryStopDaemonCommand } = await import("./memory-2ZD4WU3S.js");
132
136
  await memoryStopDaemonCommand();
133
137
  });
134
138
  memory.command("rebuild").description("Rebuild the daemon search index").action(async () => {
135
- const { memoryRebuildCommand } = await import("./memory-SO33RAI5.js");
139
+ const { memoryRebuildCommand } = await import("./memory-2ZD4WU3S.js");
136
140
  await memoryRebuildCommand();
137
141
  });
138
142
  memory.command("mcp").description("Show MCP server setup instructions").action(async () => {
139
- const { memoryMcpCommand } = await import("./memory-SO33RAI5.js");
143
+ const { memoryMcpCommand } = await import("./memory-2ZD4WU3S.js");
140
144
  await memoryMcpCommand();
141
145
  });
142
146
  memory.command("rm").description("Remove a project database").option("--project-id <id>", "Project ID to remove").option("--all", "Remove all project databases").option(
@@ -144,7 +148,7 @@ memory.command("rm").description("Remove a project database").option("--project-
144
148
  "Remove orphaned projects (source dir missing or 0 memories)"
145
149
  ).action(
146
150
  async (opts) => {
147
- const { memoryRmCommand } = await import("./memory-SO33RAI5.js");
151
+ const { memoryRmCommand } = await import("./memory-2ZD4WU3S.js");
148
152
  await memoryRmCommand(opts);
149
153
  }
150
154
  );
@@ -2,14 +2,14 @@ import {
2
2
  ensureMemoryBuilt,
3
3
  isMemoryInitialized,
4
4
  memoryInitWizard
5
- } from "./chunk-5OXEUKOE.js";
5
+ } from "./chunk-355AR2X5.js";
6
6
  import {
7
7
  memoryConfigMenu
8
- } from "./chunk-U7IVVN45.js";
8
+ } from "./chunk-5W7ZOVDU.js";
9
+ import "./chunk-GTX6I57V.js";
9
10
  import {
10
11
  getLibPath
11
12
  } from "./chunk-RZRT7NGT.js";
12
- import "./chunk-GTX6I57V.js";
13
13
  import {
14
14
  findStatuslineHookPath,
15
15
  getCurrentAccountEmail,
@@ -1,15 +1,17 @@
1
1
  import {
2
+ detectMemoryMcpState,
2
3
  ensureMemoryBuilt,
3
- printMemoryMcpConfig
4
- } from "./chunk-5OXEUKOE.js";
5
- import "./chunk-U7IVVN45.js";
6
- import {
7
- getLibPath
8
- } from "./chunk-RZRT7NGT.js";
4
+ printMemoryMcpConfig,
5
+ warnStaleMcpJson
6
+ } from "./chunk-355AR2X5.js";
7
+ import "./chunk-5W7ZOVDU.js";
9
8
  import {
10
9
  resolveDocsDir,
11
10
  resolveMemoryDir
12
11
  } from "./chunk-GTX6I57V.js";
12
+ import {
13
+ getLibPath
14
+ } from "./chunk-RZRT7NGT.js";
13
15
  import "./chunk-DHH6SRXV.js";
14
16
  import "./chunk-HPNRQYLM.js";
15
17
  import {
@@ -38,6 +40,7 @@ function countMdFiles(dir) {
38
40
  return count;
39
41
  }
40
42
  async function mcpCommand(path) {
43
+ warnStaleMcpJson(resolveMemoryDir());
41
44
  const docsDir = resolveDocsDir(path);
42
45
  const mcpDir = getLibPath("learn-mcp");
43
46
  if (!existsSync(docsDir)) {
@@ -152,5 +155,6 @@ function printMemoryMcp() {
152
155
  printMemoryMcpConfig(serverPath, memoryDir);
153
156
  }
154
157
  export {
158
+ detectMemoryMcpState,
155
159
  mcpCommand
156
160
  };
@@ -0,0 +1,27 @@
1
+ import {
2
+ getLibPath
3
+ } from "./chunk-RZRT7NGT.js";
4
+ import {
5
+ log
6
+ } from "./chunk-NREZK463.js";
7
+
8
+ // src/commands/mcp-serve.ts
9
+ import { spawn } from "child_process";
10
+ import { join } from "path";
11
+ async function mcpServeCommand(memoryDir) {
12
+ const mcpDir = getLibPath("cf-memory");
13
+ const serverPath = join(mcpDir, "dist", "index.js");
14
+ const child = spawn("node", [serverPath, memoryDir], {
15
+ stdio: "inherit"
16
+ });
17
+ child.on("error", (err) => {
18
+ log.error(`Failed to start memory MCP server: ${err.message}`);
19
+ process.exit(1);
20
+ });
21
+ child.on("exit", (code) => {
22
+ process.exit(code ?? 0);
23
+ });
24
+ }
25
+ export {
26
+ mcpServeCommand
27
+ };
@@ -13,10 +13,10 @@ import {
13
13
  memoryStatusCommand,
14
14
  memoryStopDaemonCommand,
15
15
  printMemoryMcpConfig
16
- } from "./chunk-5OXEUKOE.js";
17
- import "./chunk-U7IVVN45.js";
18
- import "./chunk-RZRT7NGT.js";
16
+ } from "./chunk-355AR2X5.js";
17
+ import "./chunk-5W7ZOVDU.js";
19
18
  import "./chunk-GTX6I57V.js";
19
+ import "./chunk-RZRT7NGT.js";
20
20
  import "./chunk-DHH6SRXV.js";
21
21
  import "./chunk-HPNRQYLM.js";
22
22
  import "./chunk-EVGXUDX4.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coding-friend-cli",
3
- "version": "1.32.0",
3
+ "version": "1.32.1",
4
4
  "description": "CLI for coding-friend — host learning docs, setup MCP server, initialize projects",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,9 +1,9 @@
1
- import {
2
- getLibPath
3
- } from "./chunk-RZRT7NGT.js";
4
1
  import {
5
2
  resolveDocsDir
6
3
  } from "./chunk-GTX6I57V.js";
4
+ import {
5
+ getLibPath
6
+ } from "./chunk-RZRT7NGT.js";
7
7
  import "./chunk-DHH6SRXV.js";
8
8
  import {
9
9
  run,
@@ -1,9 +1,9 @@
1
- import {
2
- getLibPath
3
- } from "./chunk-RZRT7NGT.js";
4
1
  import {
5
2
  resolveMemoryDir
6
3
  } from "./chunk-GTX6I57V.js";
4
+ import {
5
+ getLibPath
6
+ } from "./chunk-RZRT7NGT.js";
7
7
  import {
8
8
  getCliVersion,
9
9
  getLatestCliVersion,