claude-mem-lite 2.77.0 → 2.78.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.
@@ -10,7 +10,7 @@
10
10
  "plugins": [
11
11
  {
12
12
  "name": "claude-mem-lite",
13
- "version": "2.77.0",
13
+ "version": "2.78.0",
14
14
  "source": "./",
15
15
  "description": "Lightweight persistent memory system for Claude Code — FTS5 search, episode batching, error-triggered recall"
16
16
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-mem-lite",
3
- "version": "2.77.0",
3
+ "version": "2.78.0",
4
4
  "description": "Lightweight persistent memory system for Claude Code — FTS5 search, episode batching, error-triggered recall",
5
5
  "author": {
6
6
  "name": "sdsrss"
package/.mcp.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "mcpServers": {
3
- "mem": {
3
+ "mem-lite": {
4
4
  "command": "node",
5
5
  "args": [
6
6
  "${CLAUDE_PLUGIN_ROOT}/scripts/launch.mjs"
package/README.md CHANGED
@@ -159,7 +159,7 @@ Source files stay in the cloned repo. Update via `git pull && node install.mjs i
159
159
  ### What happens during installation
160
160
 
161
161
  1. **Install dependencies** -- `npm install --omit=dev` (compiles native `better-sqlite3`)
162
- 2. **Register MCP server** -- `mem` server with 16 tools (search, recent, recall, timeline, get, save, update, stats, delete, compress, maintain, export, fts_check, browse, registry, use)
162
+ 2. **Register MCP server** -- `mem-lite` server with 16 tools (search, recent, recall, timeline, get, save, update, stats, delete, compress, maintain, export, fts_check, browse, registry, use). The pre-v2.78 generic server name `mem` is renamed to `mem-lite` for namespace hygiene; the tool names themselves (`mem_search`, `mem_recall`, ...) are unchanged.
163
163
  3. **Configure hooks** -- `PostToolUse`, `SessionStart`, `Stop`, `UserPromptSubmit` lifecycle hooks
164
164
  4. **Create data directory** -- `~/.claude-mem-lite/` (hidden) for database, runtime, and managed resource files
165
165
  5. **Auto-migrate** -- If `~/.claude-mem/` (original claude-mem) or `~/claude-mem-lite/` (pre-v0.5 unhidden) exists, migrates database and runtime files to `~/.claude-mem-lite/`, preserving the original untouched
@@ -303,7 +303,7 @@ Slash commands `/adopt` and `/unadopt` wrap the same CLI.
303
303
  in the adopted project).
304
304
  - The MCP server instructions are built once at server boot and MCP has no
305
305
  "push" protocol — the `WHEN TO USE` / `Decision rules` trim only applies
306
- after Claude Code restarts and re-spawns the mem MCP server. A single
306
+ after Claude Code restarts and re-spawns the mem-lite MCP server. A single
307
307
  `/exit` + fresh session is enough. Same caveat applies to `unadopt`.
308
308
 
309
309
  **Safety:**
package/README.zh-CN.md CHANGED
@@ -146,7 +146,7 @@ node install.mjs install
146
146
  ### 安装过程
147
147
 
148
148
  1. **安装依赖** -- `npm install --omit=dev`(编译原生 `better-sqlite3`)
149
- 2. **注册 MCP 服务器** -- `mem` 服务器,包含 15 个工具(search、recent、recall、timeline、get、save、update、stats、delete、compress、maintain、export、fts_check、browse、registry
149
+ 2. **注册 MCP 服务器** -- `mem-lite` 服务器,包含 15 个工具(search、recent、recall、timeline、get、save、update、stats、delete、compress、maintain、export、fts_check、browse、registry)。v2.78 前服务器名为通用的 `mem`,现已改名为 `mem-lite` 避免与用户其它 `.mcp.json` 冲突;工具名(`mem_search`/`mem_recall` 等)保持不变。
150
150
  3. **配置钩子** -- `PostToolUse`、`PreToolUse`、`SessionStart`、`Stop`、`UserPromptSubmit` 生命周期钩子
151
151
  4. **创建数据目录** -- `~/.claude-mem-lite/`(隐藏目录),存放数据库、运行时和托管资源文件
152
152
  5. **自动迁移** -- 自动检测 `~/.claude-mem/`(原版 claude-mem)或 `~/claude-mem-lite/`(v0.5 前的非隐藏目录),将数据库和运行时文件迁移到 `~/.claude-mem-lite/`,原目录保持不变
@@ -282,7 +282,7 @@ Slash 命令 `/adopt` 和 `/unadopt` 是上述 CLI 的包装。
282
282
  后缀)**下一次 SessionStart** 生效(adopt 的项目下任一新会话)。
283
283
  - MCP server instructions 是**服务启动时构建一次**,MCP 协议无 "push" 机制,
284
284
  所以 `WHEN TO USE` / `Decision rules` 两段的瘦身**只在 Claude Code 重启后**
285
- 才生效(mem MCP 服务被重新 spawn)。`/exit` 一次再开新会话即可。`unadopt`
285
+ 才生效(mem-lite MCP 服务被重新 spawn)。`/exit` 一次再开新会话即可。`unadopt`
286
286
  同理。
287
287
 
288
288
  **安全性:**
package/commands/adopt.md CHANGED
@@ -52,7 +52,7 @@ session. After running `adopt`:
52
52
  on the next SessionStart.
53
53
  - MCP-instructions trim (`WHEN TO USE` / `Decision rules` sections) only
54
54
  takes effect after Claude Code itself restarts (or at least re-attaches
55
- the mem MCP server). If you still see the verbose MCP instructions after
55
+ the mem-lite MCP server). If you still see the verbose MCP instructions after
56
56
  adopt, a `/exit` + fresh session is enough.
57
57
 
58
58
  Same caveat applies in reverse for `/unadopt`.
package/hook-update.mjs CHANGED
@@ -311,16 +311,23 @@ export function installExtractedRelease(sourceDir, targetDir = INSTALL_DIR) {
311
311
  rmSync(stagingDir, { recursive: true, force: true });
312
312
  rmSync(backupDir, { recursive: true, force: true });
313
313
 
314
- // Post-update migration: clean stale global MCP if plugin handles it
314
+ // Post-update migration: clean stale global MCPs if plugin handles it.
315
+ // Both "mem" (legacy, pre-v2.78) and "mem-lite" (current) are purged so a
316
+ // user who manually ran `claude mcp add` in either era doesn't end up with
317
+ // duplicate global + plugin registrations after the rename.
315
318
  try {
316
319
  if (isPluginMode()) {
317
320
  const claudeJsonPath = join(homedir(), '.claude.json');
318
321
  const cfg = JSON.parse(readFileSync(claudeJsonPath, 'utf8'));
319
- if (cfg.mcpServers?.mem) {
320
- delete cfg.mcpServers.mem;
321
- writeFileSync(claudeJsonPath, JSON.stringify(cfg, null, 2) + '\n');
322
- debugLog('DEBUG', 'hook-update', 'Post-update: removed stale global MCP "mem"');
322
+ let changed = false;
323
+ for (const k of ['mem', 'mem-lite']) {
324
+ if (cfg.mcpServers?.[k]) {
325
+ delete cfg.mcpServers[k];
326
+ changed = true;
327
+ debugLog('DEBUG', 'hook-update', `Post-update: removed stale global MCP "${k}"`);
328
+ }
323
329
  }
330
+ if (changed) writeFileSync(claudeJsonPath, JSON.stringify(cfg, null, 2) + '\n');
324
331
  }
325
332
  } catch (e) { debugCatch(e, 'post-update-mcp-dedup'); }
326
333
 
package/hook.mjs CHANGED
@@ -51,6 +51,7 @@ import {
51
51
  bumpCitationAccess,
52
52
  computeCiteRecall,
53
53
  applyCitationDecay,
54
+ hasMainThreadAssistantText,
54
55
  } from './lib/citation-tracker.mjs';
55
56
  import { extractTailAssistantText, extractStructuredSummary } from './lib/summary-extractor.mjs';
56
57
  import { searchRelevantMemories, formatMemoryLine } from './hook-memory.mjs';
@@ -537,9 +538,20 @@ async function handleStop() {
537
538
  try {
538
539
  const injected = extractAllInjected(transcriptPath);
539
540
  if (injected.size > 0) {
540
- const citedMain = extractCitationsFromTranscript(transcriptPath, { mainOnly: true });
541
- const r = applyCitationDecay(db, project, injected, citedMain, sessionId);
542
- debugLog('DEBUG', 'handleStop', `citation-decay: touched=${r.touched} promoted=${r.promoted} demoted=${r.demoted}`);
541
+ // Text-floor gate: skip decay on tool-only Stops. Without this,
542
+ // a turn that ends on tool_use locks every injected obs as
543
+ // uncited (last_decided_session_id set), so a later turn that
544
+ // cites correctly can't undo the verdict. Per CLAUDE.md the
545
+ // contract is "NEXT time you produce user-facing text," so a
546
+ // session with zero main-thread text gets a free pass — the
547
+ // next Stop in the same session will re-evaluate.
548
+ if (!hasMainThreadAssistantText(transcriptPath)) {
549
+ debugLog('DEBUG', 'handleStop', `citation-decay: skipped (no main-thread assistant text yet, injected=${injected.size})`);
550
+ } else {
551
+ const citedMain = extractCitationsFromTranscript(transcriptPath, { mainOnly: true });
552
+ const r = applyCitationDecay(db, project, injected, citedMain, sessionId);
553
+ debugLog('DEBUG', 'handleStop', `citation-decay: touched=${r.touched} promoted=${r.promoted} demoted=${r.demoted}`);
554
+ }
543
555
  }
544
556
  } catch (e) { debugCatch(e, 'handleStop-citation-decay'); }
545
557
 
package/install.mjs CHANGED
@@ -428,10 +428,12 @@ async function install() {
428
428
  }
429
429
 
430
430
  // 3. Register MCP server (skip if plugin system already handles it)
431
- // Plugin MCP must stay at root .mcp.json so Claude Code registers plugin:*:mem.
432
- // Duplicate mem registrations in practice come from old global install.mjs state
431
+ // Plugin MCP must stay at root .mcp.json so Claude Code registers plugin:*:mem-lite.
432
+ // Duplicate registrations in practice come from old global install.mjs state
433
433
  // (claude mcp add) or stale marketplace copies, not from the cache root itself.
434
- // Global registration via `claude mcp add` creates a DUPLICATE mcp__mem__* server.
434
+ // Global registration via `claude mcp add` creates a DUPLICATE mcp__mem-lite__* server.
435
+ // The legacy generic name "mem" (pre-v2.78) is also purged so a user who installed in
436
+ // either era ends up with a single canonical "mem-lite" registration.
435
437
  // Detect plugin mode: installed_plugins.json has our entry → plugin handles MCP.
436
438
  const installedPluginsPath = join(homedir(), '.claude', 'plugins', 'installed_plugins.json');
437
439
  let pluginHandlesMcp = false;
@@ -442,18 +444,26 @@ async function install() {
442
444
 
443
445
  if (pluginHandlesMcp) {
444
446
  log('MCP server: plugin system handles registration (skipping global)');
445
- // Clean up stale global registration if it exists (from older install.mjs versions)
446
- try { execFileSync('claude', ['mcp', 'remove', '-s', 'user', 'mem'], { stdio: 'pipe' }); ok('Removed stale global MCP registration'); } catch {}
447
+ // Clean up stale global registrations (both legacy "mem" and current "mem-lite")
448
+ for (const name of ['mem', 'mem-lite']) {
449
+ try {
450
+ execFileSync('claude', ['mcp', 'remove', '-s', 'user', name], { stdio: 'pipe' });
451
+ ok(`Removed stale global MCP "${name}"`);
452
+ } catch {}
453
+ }
447
454
  } else {
448
455
  log('Registering MCP server...');
449
456
  try {
450
- try { execFileSync('claude', ['mcp', 'remove', '-s', 'user', 'mem'], { stdio: 'pipe' }); } catch {}
451
- execFileSync('claude', ['mcp', 'add', '-s', 'user', '-t', 'stdio', 'mem', '--', 'node', SERVER_PATH], { stdio: 'pipe' });
452
- try { execFileSync('claude', ['mcp', 'remove', '-s', 'project', 'mem'], { stdio: 'pipe' }); } catch {}
453
- ok('MCP server registered: mem');
457
+ // Purge legacy "mem" and any pre-existing "mem-lite" before re-registering
458
+ for (const name of ['mem', 'mem-lite']) {
459
+ try { execFileSync('claude', ['mcp', 'remove', '-s', 'user', name], { stdio: 'pipe' }); } catch {}
460
+ try { execFileSync('claude', ['mcp', 'remove', '-s', 'project', name], { stdio: 'pipe' }); } catch {}
461
+ }
462
+ execFileSync('claude', ['mcp', 'add', '-s', 'user', '-t', 'stdio', 'mem-lite', '--', 'node', SERVER_PATH], { stdio: 'pipe' });
463
+ ok('MCP server registered: mem-lite');
454
464
  } catch (e) {
455
465
  fail('MCP registration failed: ' + e.message);
456
- warn('Try manually: claude mcp add -s user -t stdio mem -- node ' + SERVER_PATH);
466
+ warn('Try manually: claude mcp add -s user -t stdio mem-lite -- node ' + SERVER_PATH);
457
467
  }
458
468
  }
459
469
 
@@ -933,13 +943,18 @@ async function install() {
933
943
  async function uninstall() {
934
944
  console.log('\nclaude-mem-lite uninstaller\n');
935
945
 
936
- // 1. Remove MCP (legacy hook-based install)
937
- try {
938
- execFileSync('claude', ['mcp', 'remove', '-s', 'user', 'mem'], { stdio: 'pipe' });
939
- ok('MCP server removed');
940
- } catch {
941
- warn('MCP server not found or already removed');
946
+ // 1. Remove MCP (legacy hook-based install).
947
+ // Try both the legacy "mem" (pre-v2.78) and current "mem-lite" names so a user
948
+ // who installed in either era ends up clean.
949
+ let removedAny = false;
950
+ for (const name of ['mem', 'mem-lite']) {
951
+ try {
952
+ execFileSync('claude', ['mcp', 'remove', '-s', 'user', name], { stdio: 'pipe' });
953
+ ok(`MCP server removed: ${name}`);
954
+ removedAny = true;
955
+ } catch {}
942
956
  }
957
+ if (!removedAny) warn('MCP server not found or already removed');
943
958
 
944
959
  // 1b. Remove CLI symlink
945
960
  for (const binDir of [join(homedir(), '.local', 'bin'), '/usr/local/bin']) {
@@ -1068,7 +1083,11 @@ async function status() {
1068
1083
  // MCP
1069
1084
  try {
1070
1085
  const list = execFileSync('claude', ['mcp', 'list'], { encoding: 'utf8' });
1071
- const registered = list.includes('mem:') || list.includes('mem ');
1086
+ // Accept either the current "mem-lite" registration or the legacy "mem"
1087
+ // name (pre-v2.78) so a user mid-upgrade still sees a green status until
1088
+ // setup.sh / install.mjs purges the legacy entry on next run.
1089
+ const registered = list.includes('mem-lite:') || list.includes('mem-lite ')
1090
+ || list.includes('mem:') || /\bmem\b\s/.test(list);
1072
1091
  push(registered ? 'ok' : 'fail', 'mcp', registered ? 'MCP server: registered' : 'MCP server: not registered', { registered });
1073
1092
  } catch {
1074
1093
  push('warn', 'mcp', 'Could not check MCP status', { registered: null });
@@ -266,6 +266,39 @@ export function extractAllInjected(transcriptPath) {
266
266
  ]);
267
267
  }
268
268
 
269
+ /**
270
+ * True iff the transcript contains at least one non-whitespace text block from
271
+ * a main-thread assistant turn. Gates the citation-decay loop so a tool-only
272
+ * Stop doesn't lock an injection as "uncited" before the model has had a
273
+ * chance to produce user-facing text. Per CLAUDE.md the cite contract is
274
+ * "NEXT time you produce user-facing text" — not "same turn." Without this
275
+ * gate, a turn that ends on tool_use sees applyCitationDecay run, set
276
+ * last_decided_session_id, and freeze the verdict at uncited even though a
277
+ * later turn in the same session would have cited correctly.
278
+ *
279
+ * @param {string|null|undefined} transcriptPath
280
+ * @returns {boolean}
281
+ */
282
+ export function hasMainThreadAssistantText(transcriptPath) {
283
+ if (!transcriptPath || !existsSync(transcriptPath)) return false;
284
+ let raw;
285
+ try { raw = readFileSync(transcriptPath, 'utf8'); } catch { return false; }
286
+ for (const line of raw.split('\n')) {
287
+ if (!line.trim()) continue;
288
+ let entry;
289
+ try { entry = JSON.parse(line); } catch { continue; }
290
+ if (entry.type !== 'assistant' || !entry.message) continue;
291
+ if (entry.isSidechain === true) continue;
292
+ const content = entry.message.content;
293
+ if (!Array.isArray(content)) continue;
294
+ for (const block of content) {
295
+ if (block.type !== 'text' || typeof block.text !== 'string') continue;
296
+ if (block.text.trim().length > 0) return true;
297
+ }
298
+ }
299
+ return false;
300
+ }
301
+
269
302
  const IMPORTANCE_CAP = 3;
270
303
  const IMPORTANCE_FLOOR = 0;
271
304
  const UNCITED_STREAK_THRESHOLD = 3;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-mem-lite",
3
- "version": "2.77.0",
3
+ "version": "2.78.0",
4
4
  "description": "Lightweight persistent memory system for Claude Code",
5
5
  "type": "module",
6
6
  "packageManager": "npm@10.9.2",
@@ -51,7 +51,7 @@ case "$tool" in
51
51
  exit 0
52
52
  ;;
53
53
  # Prefix filters
54
- mem_*|mcp__mem__*|mcp__plugin_claude-mem-lite*|mcp__sequential*|mcp__plugin_context7*)
54
+ mem_*|mcp__mem__*|mcp__mem-lite__*|mcp__plugin_claude-mem-lite*|mcp__sequential*|mcp__plugin_context7*)
55
55
  exit 0
56
56
  ;;
57
57
  esac
package/scripts/setup.sh CHANGED
@@ -87,29 +87,36 @@ if [[ ! -d "$ROOT/node_modules/better-sqlite3" ]]; then
87
87
  fi
88
88
  fi
89
89
 
90
- # 7. MCP cleanup: idempotently clean stale registrations from pre-2.10 direct installs.
91
- # This runs on every plugin SessionStart because old global mem entries may still
90
+ # 7. MCP cleanup: idempotently clean stale registrations from older installs.
91
+ # This runs on every plugin SessionStart because old global entries may still
92
92
  # exist even after an earlier migration marker was written.
93
- # Before 2.10: old direct installs left a global mem MCP alongside plugin MCP.
94
- # - Global mcpServers.mem in ~/.claude.json (from old install.mjs)
95
- # - Possibly stale marketplace root .mcp.json (from old git clone)
93
+ # - Pre-2.10: direct installs left a global "mem" MCP alongside plugin MCP.
94
+ # - Pre-2.78: plugin and global registrations used the generic name "mem";
95
+ # v2.78 renamed to "mem-lite" any stale global "mem" must be purged so
96
+ # Claude Code doesn't surface duplicate (old "mem" + new "mem-lite") tool
97
+ # prefixes side-by-side.
96
98
  # Root .mcp.json in the installed plugin cache is required for Claude Code to
97
99
  # register plugin MCP; only stale global/marketplace copies should be removed.
98
- MCP_MIGRATION="$DATA_DIR/runtime/.mcp-dedup-v2.10.4"
100
+ MCP_MIGRATION="$DATA_DIR/runtime/.mcp-dedup-v2.78"
99
101
  if [[ -n "${CLAUDE_PLUGIN_ROOT:-}" ]]; then
100
102
  CLAUDE_JSON="$HOME/.claude.json" node -e '
101
103
  const fs = require("fs");
102
104
  let changed = false;
103
- // Remove stale global MCP registration (plugin .mcp.json handles it)
105
+ // Remove stale global MCP registrations (plugin .mcp.json handles it).
106
+ // Both "mem" (legacy, pre-v2.78) and "mem-lite" (current) are purged from
107
+ // user-global scope when running inside the plugin — the plugin manifest
108
+ // is the single source of truth.
104
109
  try {
105
110
  const p = process.env.CLAUDE_JSON;
106
111
  const d = JSON.parse(fs.readFileSync(p, "utf8"));
107
- if (d.mcpServers?.mem) {
108
- delete d.mcpServers.mem;
109
- fs.writeFileSync(p, JSON.stringify(d, null, 2) + "\n");
110
- process.stderr.write("✓ Removed stale global MCP \"mem\" (plugin handles it)\n");
111
- changed = true;
112
+ for (const k of ["mem", "mem-lite"]) {
113
+ if (d.mcpServers?.[k]) {
114
+ delete d.mcpServers[k];
115
+ process.stderr.write(`✓ Removed stale global MCP "${k}" (plugin handles it)\n`);
116
+ changed = true;
117
+ }
112
118
  }
119
+ if (changed) fs.writeFileSync(p, JSON.stringify(d, null, 2) + "\n");
113
120
  } catch {}
114
121
  // NOTE: Do NOT touch marketplace .mcp.json — Claude Code copies it from
115
122
  // marketplace → plugin cache on updates. Clearing it causes the cache
package/server.mjs CHANGED
@@ -12,7 +12,7 @@ import { ensureDb, DB_PATH, REGISTRY_DB_PATH } from './schema.mjs';
12
12
  import { reRankWithContext, markSuperseded, autoBoostIfNeeded, runIdleCleanup, buildServerInstructions } from './server-internals.mjs';
13
13
  import { searchObservationsHybrid, findFtsAnchor } from './search-engine.mjs';
14
14
  import { scrubRecord } from './lib/scrub-record.mjs';
15
- import { effectiveQuiet } from './hook-shared.mjs';
15
+ import { effectiveQuiet, RUNTIME_DIR } from './hook-shared.mjs';
16
16
  import { computeTier, TIER_CASE_SQL, tierSqlParams } from './tier.mjs';
17
17
  import { memSearchSchema, memRecentSchema, memTimelineSchema, memGetSchema, memDeleteSchema, memSaveSchema, memStatsSchema, memCompressSchema, memMaintainSchema, memOptimizeSchema, memUpdateSchema, memExportSchema, memRecallSchema, memFtsCheckSchema, memRegistrySchema, memBrowseSchema, memUseSchema, memDeferSchema, memDeferListSchema, memDeferDropSchema, tools as TOOL_DEFS } from './tool-schemas.mjs';
18
18
 
@@ -43,7 +43,7 @@ const { version: PKG_VERSION } = require('./package.json');
43
43
 
44
44
  // ─── Database ───────────────────────────────────────────────────────────────
45
45
 
46
- import { rmSync, existsSync, readFileSync } from 'fs';
46
+ import { rmSync, existsSync, readFileSync, appendFileSync, mkdirSync } from 'fs';
47
47
 
48
48
  let db;
49
49
  try {
@@ -127,7 +127,7 @@ if (process.env.CLAUDE_MEM_QUIET_TRACE !== '0') {
127
127
  }
128
128
 
129
129
  const server = new McpServer(
130
- { name: 'claude-mem-lite', version: PKG_VERSION },
130
+ { name: 'mem-lite', version: PKG_VERSION },
131
131
  { instructions: buildServerInstructions(_quiet) },
132
132
  );
133
133
 
@@ -2267,5 +2267,24 @@ process.on('unhandledRejection', (err) => { debugCatch(err, 'unhandledRejection'
2267
2267
 
2268
2268
  // ─── Start Server ───────────────────────────────────────────────────────────
2269
2269
 
2270
+ // Spawn telemetry — appends one JSON line per process start so we can diagnose
2271
+ // dual-registration (plugin namespace + local .mcp.json could both spawn the
2272
+ // server in one Claude Code session). Two records with close timestamps and
2273
+ // the same ppid is the smoking gun. Never throws — telemetry must not block
2274
+ // startup. Disable with MEM_DISABLE_SPAWN_LOG=1.
2275
+ if (process.env.MEM_DISABLE_SPAWN_LOG !== '1') {
2276
+ try {
2277
+ if (!existsSync(RUNTIME_DIR)) mkdirSync(RUNTIME_DIR, { recursive: true });
2278
+ const line = JSON.stringify({
2279
+ ts: new Date().toISOString(),
2280
+ pid: process.pid,
2281
+ ppid: process.ppid,
2282
+ argv1: process.argv[1] || '',
2283
+ version: PKG_VERSION,
2284
+ }) + '\n';
2285
+ appendFileSync(join(RUNTIME_DIR, 'mcp-spawns.log'), line, { mode: 0o600 });
2286
+ } catch { /* never block startup on telemetry failure */ }
2287
+ }
2288
+
2270
2289
  const transport = new StdioServerTransport();
2271
2290
  await server.connect(transport);
package/skip-tools.mjs CHANGED
@@ -14,7 +14,8 @@ export const SKIP_TOOLS = new Set([
14
14
  /** Prefix patterns — tools starting with these are also skipped */
15
15
  export const SKIP_PREFIXES = [
16
16
  'mem_',
17
- 'mcp__mem__',
17
+ 'mcp__mem__', // legacy global MCP name (pre-rename)
18
+ 'mcp__mem-lite__', // current global MCP name (post-rename v2.78+)
18
19
  'mcp__plugin_claude-mem-lite',
19
20
  'mcp__sequential',
20
21
  'mcp__plugin_context7',