@colbymchenry/cmem 0.2.33 → 0.2.36

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 CHANGED
@@ -62,6 +62,8 @@ Ever closed your terminal and lost that perfect Claude conversation? The one whe
62
62
 
63
63
  🔄 **Automatic Sync** — A background daemon watches your Claude Code sessions and keeps everything indexed in real-time.
64
64
 
65
+ 💾 **Never Lost** — Every conversation is automatically backed up. Even if Claude Code clears its storage, cmem restores your sessions instantly when you resume them.
66
+
65
67
  📦 **100% Local & Private** — Everything runs on your machine. No cloud services, no API keys, no external servers. Just SQLite + local AI embeddings.
66
68
 
67
69
  ## Quick Start
@@ -215,6 +217,7 @@ Browse sessions organized by project folder.
215
217
  All data is stored locally in `~/.cmem/`:
216
218
  - `sessions.db` — SQLite database with vector embeddings
217
219
  - `models/` — Downloaded embedding model (~130MB)
220
+ - `backups/` — Full copies of all conversation JSONLs (auto-restored if Claude deletes them)
218
221
 
219
222
  Claude Code sessions are read from `~/.claude/`.
220
223
 
package/dist/cli.js CHANGED
@@ -17,9 +17,9 @@ __export(install_exports, {
17
17
  uninstallCommand: () => uninstallCommand
18
18
  });
19
19
  import chalk9 from "chalk";
20
- import { writeFileSync, unlinkSync, existsSync as existsSync8, mkdirSync as mkdirSync2 } from "fs";
20
+ import { writeFileSync, unlinkSync, existsSync as existsSync9, mkdirSync as mkdirSync2 } from "fs";
21
21
  import { homedir as homedir2 } from "os";
22
- import { join as join5, dirname as dirname4 } from "path";
22
+ import { join as join5, dirname as dirname5 } from "path";
23
23
  import { execSync as execSync2 } from "child_process";
24
24
  function getCmemPath() {
25
25
  try {
@@ -32,7 +32,7 @@ function getCmemPath() {
32
32
  function getNodeBinDir() {
33
33
  try {
34
34
  const nodePath = execSync2("which node", { encoding: "utf-8" }).trim();
35
- return dirname4(nodePath);
35
+ return dirname5(nodePath);
36
36
  } catch {
37
37
  return "/usr/local/bin";
38
38
  }
@@ -84,16 +84,16 @@ async function installCommand() {
84
84
  return;
85
85
  }
86
86
  console.log(chalk9.cyan("Installing cmem watch daemon...\n"));
87
- if (!existsSync8(LAUNCH_AGENTS_DIR)) {
87
+ if (!existsSync9(LAUNCH_AGENTS_DIR)) {
88
88
  mkdirSync2(LAUNCH_AGENTS_DIR, { recursive: true });
89
89
  }
90
90
  const cmemDir = join5(homedir2(), ".cmem");
91
- if (!existsSync8(cmemDir)) {
91
+ if (!existsSync9(cmemDir)) {
92
92
  mkdirSync2(cmemDir, { recursive: true });
93
93
  }
94
94
  const cmemPath = getCmemPath();
95
95
  console.log(chalk9.dim(`Using cmem at: ${cmemPath}`));
96
- if (existsSync8(PLIST_PATH)) {
96
+ if (existsSync9(PLIST_PATH)) {
97
97
  console.log(chalk9.yellow("LaunchAgent already exists. Unloading first..."));
98
98
  try {
99
99
  execSync2(`launchctl unload "${PLIST_PATH}"`, { stdio: "ignore" });
@@ -126,7 +126,7 @@ async function uninstallCommand() {
126
126
  return;
127
127
  }
128
128
  console.log(chalk9.cyan("Uninstalling cmem watch daemon...\n"));
129
- if (!existsSync8(PLIST_PATH)) {
129
+ if (!existsSync9(PLIST_PATH)) {
130
130
  console.log(chalk9.yellow("LaunchAgent not found. Nothing to uninstall."));
131
131
  return;
132
132
  }
@@ -152,7 +152,7 @@ async function statusCommand() {
152
152
  return;
153
153
  }
154
154
  console.log(chalk9.cyan("cmem watch daemon status\n"));
155
- if (!existsSync8(PLIST_PATH)) {
155
+ if (!existsSync9(PLIST_PATH)) {
156
156
  console.log(chalk9.yellow("Status: Not installed"));
157
157
  console.log(chalk9.dim("Run: cmem install"));
158
158
  return;
@@ -195,8 +195,8 @@ var init_install = __esm({
195
195
  import { program } from "commander";
196
196
  import { render } from "ink";
197
197
  import React2 from "react";
198
- import { existsSync as existsSync10, readFileSync as readFileSync4 } from "fs";
199
- import { join as join7, dirname as dirname6 } from "path";
198
+ import { existsSync as existsSync11, readFileSync as readFileSync4 } from "fs";
199
+ import { join as join7, dirname as dirname7 } from "path";
200
200
  import { fileURLToPath as fileURLToPath2 } from "url";
201
201
  import { spawn as spawn2 } from "child_process";
202
202
 
@@ -205,12 +205,84 @@ import { useState as useState2, useEffect as useEffect2, useCallback as useCallb
205
205
  import { Box as Box6, Text as Text6, useInput, useApp } from "ink";
206
206
  import TextInput2 from "ink-text-input";
207
207
  import Spinner from "ink-spinner";
208
- import { basename as basename4, dirname as dirname2 } from "path";
209
- import { existsSync as existsSync5 } from "fs";
208
+ import { basename as basename5, dirname as dirname3 } from "path";
209
+ import { existsSync as existsSync6 } from "fs";
210
+
211
+ // src/utils/config.ts
212
+ import { homedir } from "os";
213
+ import { join, basename, dirname } from "path";
214
+ import { mkdirSync, existsSync, copyFileSync } from "fs";
215
+ var CMEM_DIR = join(homedir(), ".cmem");
216
+ var DB_PATH = join(CMEM_DIR, "sessions.db");
217
+ var MODELS_DIR = join(CMEM_DIR, "models");
218
+ var BACKUPS_DIR = join(CMEM_DIR, "backups");
219
+ var CLAUDE_DIR = join(homedir(), ".claude");
220
+ var CLAUDE_PROJECTS_DIR = join(CLAUDE_DIR, "projects");
221
+ var CLAUDE_SESSIONS_DIR = join(CLAUDE_DIR, "sessions");
222
+ var EMBEDDING_MODEL = "nomic-ai/nomic-embed-text-v1.5";
223
+ var EMBEDDING_DIMENSIONS = 768;
224
+ var MAX_EMBEDDING_CHARS = 8e3;
225
+ var MAX_MESSAGE_PREVIEW_CHARS = 500;
226
+ var MAX_MESSAGES_FOR_CONTEXT = 20;
227
+ function ensureCmemDir() {
228
+ if (!existsSync(CMEM_DIR)) {
229
+ mkdirSync(CMEM_DIR, { recursive: true });
230
+ }
231
+ }
232
+ function ensureModelsDir() {
233
+ ensureCmemDir();
234
+ if (!existsSync(MODELS_DIR)) {
235
+ mkdirSync(MODELS_DIR, { recursive: true });
236
+ }
237
+ }
238
+ function ensureBackupsDir() {
239
+ ensureCmemDir();
240
+ if (!existsSync(BACKUPS_DIR)) {
241
+ mkdirSync(BACKUPS_DIR, { recursive: true });
242
+ }
243
+ }
244
+ function getBackupPath(sourceFile) {
245
+ const projectDir = basename(dirname(sourceFile));
246
+ const sessionFile = basename(sourceFile);
247
+ return join(BACKUPS_DIR, projectDir, sessionFile);
248
+ }
249
+ function backupSessionFile(sourceFile) {
250
+ try {
251
+ if (!existsSync(sourceFile)) return false;
252
+ ensureBackupsDir();
253
+ const backupPath = getBackupPath(sourceFile);
254
+ const backupDir = dirname(backupPath);
255
+ if (!existsSync(backupDir)) {
256
+ mkdirSync(backupDir, { recursive: true });
257
+ }
258
+ copyFileSync(sourceFile, backupPath);
259
+ return true;
260
+ } catch {
261
+ return false;
262
+ }
263
+ }
264
+ function hasBackup(sourceFile) {
265
+ const backupPath = getBackupPath(sourceFile);
266
+ return existsSync(backupPath);
267
+ }
268
+ function restoreFromBackup(sourceFile) {
269
+ try {
270
+ const backupPath = getBackupPath(sourceFile);
271
+ if (!existsSync(backupPath)) return false;
272
+ const sourceDir = dirname(sourceFile);
273
+ if (!existsSync(sourceDir)) {
274
+ mkdirSync(sourceDir, { recursive: true });
275
+ }
276
+ copyFileSync(backupPath, sourceFile);
277
+ return true;
278
+ } catch {
279
+ return false;
280
+ }
281
+ }
210
282
 
211
283
  // src/ui/components/Header.tsx
212
284
  import { Box, Text } from "ink";
213
- import { basename } from "path";
285
+ import { basename as basename2 } from "path";
214
286
  import { jsx, jsxs } from "react/jsx-runtime";
215
287
  var Header = ({ embeddingsReady, projectFilter }) => {
216
288
  return /* @__PURE__ */ jsxs(Box, { marginBottom: 1, justifyContent: "space-between", children: [
@@ -218,7 +290,7 @@ var Header = ({ embeddingsReady, projectFilter }) => {
218
290
  /* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "cmem" }),
219
291
  projectFilter && /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
220
292
  " \u{1F4C1} ",
221
- basename(projectFilter)
293
+ basename2(projectFilter)
222
294
  ] }),
223
295
  !embeddingsReady && /* @__PURE__ */ jsx(Text, { color: "yellow", dimColor: true, children: " (loading model...)" })
224
296
  ] }),
@@ -251,7 +323,7 @@ var SearchInput = ({
251
323
 
252
324
  // src/ui/components/SessionList.tsx
253
325
  import { Box as Box3, Text as Text3 } from "ink";
254
- import { basename as basename2 } from "path";
326
+ import { basename as basename3 } from "path";
255
327
 
256
328
  // src/utils/format.ts
257
329
  function formatTimeAgo(timestamp) {
@@ -362,7 +434,7 @@ var SessionList = ({
362
434
  var SessionItem = ({ session, isSelected }) => {
363
435
  const hasCustomTitle = !!session.customTitle;
364
436
  const displayTitle = truncate(session.customTitle || session.title, 38);
365
- const folderName = session.projectPath ? truncate(basename2(session.projectPath), 38) : "";
437
+ const folderName = session.projectPath ? truncate(basename3(session.projectPath), 38) : "";
366
438
  const msgs = String(session.messageCount).padStart(3);
367
439
  const updated = formatTimeAgo(session.updatedAt);
368
440
  const getTitleColor = () => {
@@ -524,33 +596,6 @@ import Database from "better-sqlite3";
524
596
  import * as sqliteVec from "sqlite-vec";
525
597
  import { existsSync as existsSync3 } from "fs";
526
598
 
527
- // src/utils/config.ts
528
- import { homedir } from "os";
529
- import { join } from "path";
530
- import { mkdirSync, existsSync } from "fs";
531
- var CMEM_DIR = join(homedir(), ".cmem");
532
- var DB_PATH = join(CMEM_DIR, "sessions.db");
533
- var MODELS_DIR = join(CMEM_DIR, "models");
534
- var CLAUDE_DIR = join(homedir(), ".claude");
535
- var CLAUDE_PROJECTS_DIR = join(CLAUDE_DIR, "projects");
536
- var CLAUDE_SESSIONS_DIR = join(CLAUDE_DIR, "sessions");
537
- var EMBEDDING_MODEL = "nomic-ai/nomic-embed-text-v1.5";
538
- var EMBEDDING_DIMENSIONS = 768;
539
- var MAX_EMBEDDING_CHARS = 8e3;
540
- var MAX_MESSAGE_PREVIEW_CHARS = 500;
541
- var MAX_MESSAGES_FOR_CONTEXT = 20;
542
- function ensureCmemDir() {
543
- if (!existsSync(CMEM_DIR)) {
544
- mkdirSync(CMEM_DIR, { recursive: true });
545
- }
546
- }
547
- function ensureModelsDir() {
548
- ensureCmemDir();
549
- if (!existsSync(MODELS_DIR)) {
550
- mkdirSync(MODELS_DIR, { recursive: true });
551
- }
552
- }
553
-
554
599
  // src/parser/index.ts
555
600
  import { readFileSync, readdirSync, existsSync as existsSync2, statSync } from "fs";
556
601
  import { join as join2 } from "path";
@@ -1308,6 +1353,19 @@ function createEmbeddingText(title, summary, messages) {
1308
1353
  }
1309
1354
 
1310
1355
  // src/ui/hooks/useSessions.ts
1356
+ import { existsSync as existsSync5 } from "fs";
1357
+ function isRecoverable(session) {
1358
+ if (!session.sourceFile) return false;
1359
+ if (existsSync5(session.sourceFile)) return true;
1360
+ if (hasBackup(session.sourceFile)) return true;
1361
+ return false;
1362
+ }
1363
+ function ensureBackedUp(session) {
1364
+ if (!session.sourceFile) return;
1365
+ if (existsSync5(session.sourceFile) && !hasBackup(session.sourceFile)) {
1366
+ backupSessionFile(session.sourceFile);
1367
+ }
1368
+ }
1311
1369
  function useSessions(options = {}) {
1312
1370
  const [sessions, setSessions] = useState([]);
1313
1371
  const [allSessions, setAllSessions] = useState([]);
@@ -1372,13 +1430,15 @@ function useSessions(options = {}) {
1372
1430
  const loadSessions = useCallback(() => {
1373
1431
  try {
1374
1432
  const loaded = projectFilter ? listHumanSessionsByProject(projectFilter) : listHumanSessions();
1433
+ loaded.forEach(ensureBackedUp);
1434
+ const recoverable = loaded.filter(isRecoverable);
1375
1435
  const favIds = getFavoriteSessionIds();
1376
1436
  const orderMap = getProjectOrders();
1377
1437
  setFavoriteSessionIds(favIds);
1378
1438
  setProjectOrderMap(orderMap);
1379
1439
  setHasFavSessions(hasFavoriteSessions());
1380
1440
  setHasCustomOrder(hasCustomProjectOrder());
1381
- const sorted = smartSort(loaded, favIds);
1441
+ const sorted = smartSort(recoverable, favIds);
1382
1442
  setAllSessions(sorted);
1383
1443
  setSessions(sorted);
1384
1444
  if (!projectFilter) {
@@ -1579,34 +1639,50 @@ var App = ({ onResume, projectFilter: initialProjectFilter }) => {
1579
1639
  const session = currentSessions2[selectedIndex];
1580
1640
  if (!session) return;
1581
1641
  if (session.sourceFile) {
1582
- const filename = basename4(session.sourceFile);
1642
+ if (!existsSync6(session.sourceFile)) {
1643
+ if (hasBackup(session.sourceFile)) {
1644
+ const restored = restoreFromBackup(session.sourceFile);
1645
+ if (restored) {
1646
+ setStatusMessage("Restored session from backup");
1647
+ } else {
1648
+ setStatusMessage("Failed to restore session from backup");
1649
+ return;
1650
+ }
1651
+ } else {
1652
+ setStatusMessage("Session file deleted and no backup - cannot resume");
1653
+ return;
1654
+ }
1655
+ }
1656
+ const filename = basename5(session.sourceFile);
1583
1657
  const claudeSessionId = filename.replace(".jsonl", "");
1584
- const projectDirName = basename4(dirname2(session.sourceFile));
1585
- let projectPath = null;
1586
- if (projectDirName.startsWith("-")) {
1587
- const segments = projectDirName.substring(1).split("-");
1588
- let currentPath = "";
1589
- let remainingSegments = [...segments];
1590
- while (remainingSegments.length > 0) {
1591
- let found = false;
1592
- for (let i = remainingSegments.length; i > 0; i--) {
1593
- const testSegment = remainingSegments.slice(0, i).join("-");
1594
- const testPath = currentPath + "/" + testSegment;
1595
- if (existsSync5(testPath)) {
1596
- currentPath = testPath;
1597
- remainingSegments = remainingSegments.slice(i);
1598
- found = true;
1658
+ let projectPath = session.projectPath;
1659
+ if (!projectPath) {
1660
+ const projectDirName = basename5(dirname3(session.sourceFile));
1661
+ if (projectDirName.startsWith("-")) {
1662
+ const segments = projectDirName.substring(1).split("-");
1663
+ let currentPath = "";
1664
+ let remainingSegments = [...segments];
1665
+ while (remainingSegments.length > 0) {
1666
+ let found = false;
1667
+ for (let i = remainingSegments.length; i > 0; i--) {
1668
+ const testSegment = remainingSegments.slice(0, i).join("-");
1669
+ const testPath = currentPath + "/" + testSegment;
1670
+ if (existsSync6(testPath)) {
1671
+ currentPath = testPath;
1672
+ remainingSegments = remainingSegments.slice(i);
1673
+ found = true;
1674
+ break;
1675
+ }
1676
+ }
1677
+ if (!found) {
1678
+ currentPath = currentPath + "/" + remainingSegments.join("-");
1599
1679
  break;
1600
1680
  }
1601
1681
  }
1602
- if (!found) {
1603
- currentPath = currentPath + "/" + remainingSegments.join("-");
1604
- break;
1682
+ if (currentPath && existsSync6(currentPath)) {
1683
+ projectPath = currentPath;
1605
1684
  }
1606
1685
  }
1607
- if (currentPath && existsSync5(currentPath)) {
1608
- projectPath = currentPath;
1609
- }
1610
1686
  }
1611
1687
  if (onResume) {
1612
1688
  onResume(claudeSessionId, projectPath);
@@ -1819,7 +1895,7 @@ var App = ({ onResume, projectFilter: initialProjectFilter }) => {
1819
1895
  }
1820
1896
  ) : currentView === "project-sessions" && selectedProjectPath ? /* @__PURE__ */ jsxs6(Box6, { children: [
1821
1897
  /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Projects \u2192 " }),
1822
- /* @__PURE__ */ jsx6(Text6, { color: "blue", children: basename4(selectedProjectPath) })
1898
+ /* @__PURE__ */ jsx6(Text6, { color: "blue", children: basename5(selectedProjectPath) })
1823
1899
  ] }) : /* @__PURE__ */ jsx6(Box6, { children: /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Browse projects below" }) }),
1824
1900
  currentView === "projects" ? /* @__PURE__ */ jsx6(
1825
1901
  ProjectList,
@@ -2208,7 +2284,7 @@ async function deleteCommand(id) {
2208
2284
 
2209
2285
  // src/commands/stats.ts
2210
2286
  import chalk6 from "chalk";
2211
- import { statSync as statSync2, existsSync as existsSync6 } from "fs";
2287
+ import { statSync as statSync2, existsSync as existsSync7 } from "fs";
2212
2288
  async function statsCommand() {
2213
2289
  console.log(chalk6.cyan("cmem Storage Statistics\n"));
2214
2290
  const stats = getStats();
@@ -2216,7 +2292,7 @@ async function statsCommand() {
2216
2292
  console.log(` Sessions: ${formatNumber(stats.sessionCount)}`);
2217
2293
  console.log(` Messages: ${formatNumber(stats.messageCount)}`);
2218
2294
  console.log(` Embeddings: ${formatNumber(stats.embeddingCount)}`);
2219
- if (existsSync6(DB_PATH)) {
2295
+ if (existsSync7(DB_PATH)) {
2220
2296
  const dbStats = statSync2(DB_PATH);
2221
2297
  console.log(` DB Size: ${formatBytes(dbStats.size)}`);
2222
2298
  }
@@ -2243,8 +2319,8 @@ async function statsCommand() {
2243
2319
  // src/commands/watch.ts
2244
2320
  import chalk7 from "chalk";
2245
2321
  import chokidar from "chokidar";
2246
- import { statSync as statSync3, existsSync as existsSync7, readFileSync as readFileSync2, readdirSync as readdirSync2 } from "fs";
2247
- import { join as join4, dirname as dirname3, basename as basename5 } from "path";
2322
+ import { statSync as statSync3, existsSync as existsSync8, readFileSync as readFileSync2, readdirSync as readdirSync2 } from "fs";
2323
+ import { join as join4, dirname as dirname4, basename as basename6 } from "path";
2248
2324
  var spinnerFrames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
2249
2325
  var Spinner2 = class {
2250
2326
  interval = null;
@@ -2378,7 +2454,7 @@ async function watchCommand(options) {
2378
2454
  }
2379
2455
  function findAllSessionFiles(dir) {
2380
2456
  const files = [];
2381
- if (!existsSync7(dir)) return files;
2457
+ if (!existsSync8(dir)) return files;
2382
2458
  function scanDir(currentDir, depth = 0) {
2383
2459
  if (depth > 10) return;
2384
2460
  try {
@@ -2419,8 +2495,8 @@ async function processSessionFile(filePath, embeddingsReady, embedThreshold, ver
2419
2495
  const stats = statSync3(filePath);
2420
2496
  const fileMtime = stats.mtime.toISOString();
2421
2497
  const existingSession = getSessionBySourceFile(filePath);
2422
- const sessionId_from_file = basename5(filePath, ".jsonl");
2423
- const agentMessages = loadSubagentMessages2(dirname3(filePath), sessionId_from_file);
2498
+ const sessionId_from_file = basename6(filePath, ".jsonl");
2499
+ const agentMessages = loadSubagentMessages2(dirname4(filePath), sessionId_from_file);
2424
2500
  const allMessages = [...messages, ...agentMessages];
2425
2501
  const contentLength = allMessages.reduce((sum, m) => sum + m.content.length, 0);
2426
2502
  const firstUserMsg = messages.find((m) => m.role === "user");
@@ -2489,6 +2565,10 @@ async function processSessionFile(filePath, embeddingsReady, embedThreshold, ver
2489
2565
  }
2490
2566
  }
2491
2567
  }
2568
+ const backedUp = backupSessionFile(filePath);
2569
+ if (verbose && backedUp) {
2570
+ console.log(chalk7.dim(` Backed up: ${basename6(filePath)}`));
2571
+ }
2492
2572
  return isNew;
2493
2573
  } catch (err) {
2494
2574
  if (verbose) console.log(chalk7.red(`Error processing ${filePath}:`), err);
@@ -2497,7 +2577,7 @@ async function processSessionFile(filePath, embeddingsReady, embedThreshold, ver
2497
2577
  }
2498
2578
  function loadSubagentMessages2(projectDirPath, parentSessionId) {
2499
2579
  const subagentsDir = join4(projectDirPath, parentSessionId, "subagents");
2500
- if (!existsSync7(subagentsDir)) return [];
2580
+ if (!existsSync8(subagentsDir)) return [];
2501
2581
  const messages = [];
2502
2582
  try {
2503
2583
  const agentFiles = readdirSync2(subagentsDir).filter((f) => f.endsWith(".jsonl"));
@@ -2511,9 +2591,9 @@ function loadSubagentMessages2(projectDirPath, parentSessionId) {
2511
2591
  return messages;
2512
2592
  }
2513
2593
  function getProjectPathFromIndex(filePath, sessionId) {
2514
- const projectDir = dirname3(filePath);
2594
+ const projectDir = dirname4(filePath);
2515
2595
  const indexPath = join4(projectDir, "sessions-index.json");
2516
- if (!existsSync7(indexPath)) return null;
2596
+ if (!existsSync8(indexPath)) return null;
2517
2597
  try {
2518
2598
  const content = readFileSync2(indexPath, "utf-8");
2519
2599
  const index = JSON.parse(content);
@@ -3123,13 +3203,13 @@ init_install();
3123
3203
  // src/commands/setup.ts
3124
3204
  import chalk10 from "chalk";
3125
3205
  import { execSync as execSync3 } from "child_process";
3126
- import { existsSync as existsSync9, readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3, readdirSync as readdirSync3, statSync as statSync4 } from "fs";
3206
+ import { existsSync as existsSync10, readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3, readdirSync as readdirSync3, statSync as statSync4 } from "fs";
3127
3207
  import { homedir as homedir3 } from "os";
3128
- import { join as join6, dirname as dirname5, basename as basename6 } from "path";
3208
+ import { join as join6, dirname as dirname6, basename as basename7 } from "path";
3129
3209
  import { fileURLToPath } from "url";
3130
3210
  import { createInterface } from "readline";
3131
3211
  var __filename = fileURLToPath(import.meta.url);
3132
- var __dirname = dirname5(__filename);
3212
+ var __dirname = dirname6(__filename);
3133
3213
  var CLAUDE_JSON_PATH = join6(homedir3(), ".claude.json");
3134
3214
  var CLAUDE_SETTINGS_PATH = join6(homedir3(), ".claude", "settings.json");
3135
3215
  var CMEM_DIR2 = join6(homedir3(), ".cmem");
@@ -3253,7 +3333,7 @@ function isGloballyInstalled() {
3253
3333
  function getCmemVersion() {
3254
3334
  try {
3255
3335
  const packagePath = join6(__dirname, "..", "package.json");
3256
- if (existsSync9(packagePath)) {
3336
+ if (existsSync10(packagePath)) {
3257
3337
  const pkg = JSON.parse(readFileSync3(packagePath, "utf-8"));
3258
3338
  return pkg.version || "0.1.0";
3259
3339
  }
@@ -3339,7 +3419,7 @@ async function setupCommand() {
3339
3419
  }
3340
3420
  }
3341
3421
  console.log("");
3342
- const daemonInstalled = existsSync9(
3422
+ const daemonInstalled = existsSync10(
3343
3423
  join6(homedir3(), "Library", "LaunchAgents", "com.cmem.watch.plist")
3344
3424
  );
3345
3425
  const isUpdating = installedVersion && installedVersion !== currentVersion;
@@ -3404,7 +3484,7 @@ async function setupCommand() {
3404
3484
  console.log(chalk10.yellow(" Initial session indexing"));
3405
3485
  console.log(chalk10.dim(" Scanning and indexing your existing Claude Code conversations\n"));
3406
3486
  await indexExistingSessions();
3407
- if (!existsSync9(CMEM_DIR2)) {
3487
+ if (!existsSync10(CMEM_DIR2)) {
3408
3488
  mkdirSync3(CMEM_DIR2, { recursive: true });
3409
3489
  }
3410
3490
  writeFileSync2(SETUP_MARKER, (/* @__PURE__ */ new Date()).toISOString());
@@ -3421,7 +3501,7 @@ async function setupCommand() {
3421
3501
  console.log(chalk10.dim(" get_session Retrieve full history"));
3422
3502
  console.log(chalk10.dim(" list_sessions Browse recent sessions"));
3423
3503
  if (process.platform === "darwin") {
3424
- const plistExists = existsSync9(join6(homedir3(), "Library", "LaunchAgents", "com.cmem.watch.plist"));
3504
+ const plistExists = existsSync10(join6(homedir3(), "Library", "LaunchAgents", "com.cmem.watch.plist"));
3425
3505
  if (plistExists) {
3426
3506
  console.log(chalk10.green("\n \u{1F680} Daemon is now syncing your sessions in the background!"));
3427
3507
  }
@@ -3429,7 +3509,7 @@ async function setupCommand() {
3429
3509
  console.log("");
3430
3510
  }
3431
3511
  function isMcpConfigured() {
3432
- if (!existsSync9(CLAUDE_JSON_PATH)) {
3512
+ if (!existsSync10(CLAUDE_JSON_PATH)) {
3433
3513
  return false;
3434
3514
  }
3435
3515
  try {
@@ -3442,7 +3522,7 @@ function isMcpConfigured() {
3442
3522
  function configureMcpServer() {
3443
3523
  try {
3444
3524
  let claudeJson = {};
3445
- if (existsSync9(CLAUDE_JSON_PATH)) {
3525
+ if (existsSync10(CLAUDE_JSON_PATH)) {
3446
3526
  try {
3447
3527
  claudeJson = JSON.parse(readFileSync3(CLAUDE_JSON_PATH, "utf-8"));
3448
3528
  } catch {
@@ -3458,12 +3538,12 @@ function configureMcpServer() {
3458
3538
  args: ["mcp"]
3459
3539
  };
3460
3540
  writeFileSync2(CLAUDE_JSON_PATH, JSON.stringify(claudeJson, null, 2) + "\n");
3461
- const claudeDir = dirname5(CLAUDE_SETTINGS_PATH);
3462
- if (!existsSync9(claudeDir)) {
3541
+ const claudeDir = dirname6(CLAUDE_SETTINGS_PATH);
3542
+ if (!existsSync10(claudeDir)) {
3463
3543
  mkdirSync3(claudeDir, { recursive: true });
3464
3544
  }
3465
3545
  let settings = {};
3466
- if (existsSync9(CLAUDE_SETTINGS_PATH)) {
3546
+ if (existsSync10(CLAUDE_SETTINGS_PATH)) {
3467
3547
  try {
3468
3548
  settings = JSON.parse(readFileSync3(CLAUDE_SETTINGS_PATH, "utf-8"));
3469
3549
  } catch {
@@ -3490,7 +3570,7 @@ function configureMcpServer() {
3490
3570
  }
3491
3571
  function shouldRunSetup() {
3492
3572
  const isNpx = isRunningViaNpx();
3493
- const setupComplete = existsSync9(SETUP_MARKER);
3573
+ const setupComplete = existsSync10(SETUP_MARKER);
3494
3574
  const isGlobal = isGloballyInstalled();
3495
3575
  if (isNpx) return true;
3496
3576
  if (!isGlobal && !setupComplete) return true;
@@ -3503,7 +3583,7 @@ function shouldRunSetup() {
3503
3583
  }
3504
3584
  function findAllSessionFiles2(dir) {
3505
3585
  const files = [];
3506
- if (!existsSync9(dir)) return files;
3586
+ if (!existsSync10(dir)) return files;
3507
3587
  function scanDir(currentDir, depth = 0) {
3508
3588
  if (depth > 10) return;
3509
3589
  try {
@@ -3535,7 +3615,7 @@ async function indexSessionFile(filePath, embeddingsReady) {
3535
3615
  const title = firstUserMsg ? generateTitle(firstUserMsg.content) : "Untitled Session";
3536
3616
  const summary = generateSummary(messages);
3537
3617
  const rawData = JSON.stringify({ filePath, messages, mtime: fileMtime });
3538
- const sessionId_from_file = basename6(filePath, ".jsonl");
3618
+ const sessionId_from_file = basename7(filePath, ".jsonl");
3539
3619
  const sessionId = createSession({
3540
3620
  title,
3541
3621
  summary,
@@ -3601,9 +3681,9 @@ var sessionToResume = null;
3601
3681
  function getVersion() {
3602
3682
  try {
3603
3683
  const __filename2 = fileURLToPath2(import.meta.url);
3604
- const __dirname2 = dirname6(__filename2);
3684
+ const __dirname2 = dirname7(__filename2);
3605
3685
  const packagePath = join7(__dirname2, "..", "package.json");
3606
- if (existsSync10(packagePath)) {
3686
+ if (existsSync11(packagePath)) {
3607
3687
  const pkg = JSON.parse(readFileSync4(packagePath, "utf-8"));
3608
3688
  return pkg.version || "0.1.0";
3609
3689
  }