codemem 0.20.0-alpha.1 → 0.20.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.opencode/plugin/codemem.js +1 -1
- package/LICENSE +21 -0
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +63 -63
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
|
|
14
14
|
const TRUTHY_VALUES = ["1", "true", "yes"];
|
|
15
15
|
const DISABLED_VALUES = ["0", "false", "off"];
|
|
16
|
-
const PINNED_BACKEND_VERSION = "0.20.0-alpha.
|
|
16
|
+
const PINNED_BACKEND_VERSION = "0.20.0-alpha.2";
|
|
17
17
|
const DEFAULT_UVX_SOURCE = `codemem==${PINNED_BACKEND_VERSION}`;
|
|
18
18
|
|
|
19
19
|
const normalizeEnvValue = (value) => (value || "").toLowerCase();
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Adam Kunicki
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.js
CHANGED
|
@@ -359,7 +359,7 @@ var importMemoriesCommand = new Command("import-memories").configureHelp(helpSty
|
|
|
359
359
|
//#region src/commands/mcp.ts
|
|
360
360
|
var mcpCommand = new Command("mcp").configureHelp(helpStyle).description("Start the MCP stdio server").option("--db <path>", "database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)").action(async (opts) => {
|
|
361
361
|
if (opts.db) process.env.CODEMEM_DB = opts.db;
|
|
362
|
-
await import("@codemem/mcp
|
|
362
|
+
await import("@codemem/mcp");
|
|
363
363
|
});
|
|
364
364
|
//#endregion
|
|
365
365
|
//#region src/commands/memory.ts
|
|
@@ -578,7 +578,7 @@ async function stopExistingViewer(dbPath) {
|
|
|
578
578
|
} catch {}
|
|
579
579
|
}
|
|
580
580
|
var serveCommand = new Command("serve").configureHelp(helpStyle).description("Start the viewer server").option("--db <path>", "database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)").option("--host <host>", "bind host", "127.0.0.1").option("--port <port>", "bind port", "38888").option("--background", "run under a caller-managed background process").option("--stop", "stop an existing viewer process").option("--restart", "restart an existing viewer process").action(async (opts) => {
|
|
581
|
-
const { createApp, closeStore, getStore } = await import("@codemem/
|
|
581
|
+
const { createApp, closeStore, getStore } = await import("@codemem/server");
|
|
582
582
|
const { serve } = await import("@hono/node-server");
|
|
583
583
|
const dbPath = resolveDbPath(opts.db);
|
|
584
584
|
if (opts.stop || opts.restart) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/help-style.ts","../src/commands/claude-hook-ingest.ts","../src/commands/db.ts","../src/commands/enqueue-raw-event.ts","../src/commands/export-memories.ts","../src/commands/import-memories.ts","../src/commands/mcp.ts","../src/commands/memory.ts","../src/commands/pack.ts","../src/commands/recent.ts","../src/commands/search.ts","../src/commands/serve.ts","../src/commands/setup.ts","../src/commands/stats.ts","../src/commands/sync.ts","../src/commands/version.ts","../src/index.ts"],"sourcesContent":["/**\n * Shared Commander help style configuration.\n *\n * Applied to every Command instance so subcommand --help\n * output gets the same colors as the root.\n */\n\nimport { styleText } from \"node:util\";\nimport type { HelpConfiguration } from \"commander\";\n\nexport const helpStyle: HelpConfiguration = {\n\tstyleTitle: (str) => styleText(\"bold\", str),\n\tstyleCommandText: (str) => styleText(\"cyan\", str),\n\tstyleCommandDescription: (str) => str,\n\tstyleDescriptionText: (str) => styleText(\"dim\", str),\n\tstyleOptionText: (str) => styleText(\"green\", str),\n\tstyleOptionTerm: (str) => styleText(\"green\", str),\n\tstyleSubcommandText: (str) => styleText(\"cyan\", str),\n\tstyleArgumentText: (str) => styleText(\"yellow\", str),\n};\n","/**\n * codemem claude-hook-ingest — read a single Claude Code hook payload\n * from stdin and enqueue it for processing.\n *\n * Ports codemem/commands/claude_hook_runtime_cmds.py with an HTTP-first\n * strategy: try POST /api/claude-hooks (viewer must be running), then\n * fall back to direct raw-event enqueue via the local store.\n *\n * Usage (from Claude hooks config):\n * echo '{\"hook_event_name\":\"Stop\",\"session_id\":\"...\",\"last_assistant_message\":\"...\"}' \\\n * | codemem claude-hook-ingest\n */\n\nimport { readFileSync } from \"node:fs\";\nimport {\n\tbuildRawEventEnvelopeFromHook,\n\tconnect,\n\tloadSqliteVec,\n\tresolveDbPath,\n\tstripPrivateObj,\n} from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\n/** Try to POST the hook payload to the running viewer server. */\nasync function tryHttpIngest(\n\tpayload: Record<string, unknown>,\n\thost: string,\n\tport: number,\n): Promise<{ ok: boolean; inserted: number; skipped: number }> {\n\tconst url = `http://${host}:${port}/api/claude-hooks`;\n\tconst controller = new AbortController();\n\tconst timeout = setTimeout(() => controller.abort(), 5000);\n\ttry {\n\t\tconst res = await fetch(url, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify(payload),\n\t\t\tsignal: controller.signal,\n\t\t});\n\t\tif (!res.ok) return { ok: false, inserted: 0, skipped: 0 };\n\t\tconst body = (await res.json()) as Record<string, unknown>;\n\t\treturn {\n\t\t\tok: true,\n\t\t\tinserted: Number(body.inserted ?? 0),\n\t\t\tskipped: Number(body.skipped ?? 0),\n\t\t};\n\t} catch {\n\t\treturn { ok: false, inserted: 0, skipped: 0 };\n\t} finally {\n\t\tclearTimeout(timeout);\n\t}\n}\n\n/** Fall back to direct raw-event enqueue via the local SQLite store. */\nfunction directEnqueue(\n\tpayload: Record<string, unknown>,\n\tdbPath: string,\n): { inserted: number; skipped: number } {\n\tconst envelope = buildRawEventEnvelopeFromHook(payload);\n\tif (!envelope) return { inserted: 0, skipped: 1 };\n\n\tconst db = connect(dbPath);\n\ttry {\n\t\ttry {\n\t\t\tloadSqliteVec(db);\n\t\t} catch {\n\t\t\t// sqlite-vec not available — non-fatal for raw event enqueue\n\t\t}\n\t\tconst strippedPayload = stripPrivateObj(envelope.payload) as Record<string, unknown>;\n\t\tconst existing = db\n\t\t\t.prepare(\n\t\t\t\t\"SELECT 1 FROM raw_events WHERE source = ? AND stream_id = ? AND event_id = ? LIMIT 1\",\n\t\t\t)\n\t\t\t.get(envelope.source, envelope.session_stream_id, envelope.event_id);\n\t\tif (existing) return { inserted: 0, skipped: 0 };\n\n\t\tdb.prepare(\n\t\t\t`INSERT INTO raw_events(\n\t\t\t\tsource, stream_id, opencode_session_id, event_id, event_seq,\n\t\t\t\tevent_type, ts_wall_ms, payload_json, created_at\n\t\t\t) VALUES (?, ?, ?, ?, (\n\t\t\t\tSELECT COALESCE(MAX(event_seq), 0) + 1\n\t\t\t\tFROM raw_events WHERE source = ? AND stream_id = ?\n\t\t\t), ?, ?, ?, datetime('now'))`,\n\t\t).run(\n\t\t\tenvelope.source,\n\t\t\tenvelope.session_stream_id,\n\t\t\tenvelope.opencode_session_id,\n\t\t\tenvelope.event_id,\n\t\t\tenvelope.source,\n\t\t\tenvelope.session_stream_id,\n\t\t\t\"claude.hook\",\n\t\t\tenvelope.ts_wall_ms,\n\t\t\tJSON.stringify(strippedPayload),\n\t\t);\n\n\t\t// Query actual max event_seq for this stream to keep session metadata in sync\n\t\tconst maxSeqRow = db\n\t\t\t.prepare(\n\t\t\t\t\"SELECT COALESCE(MAX(event_seq), 0) AS max_seq FROM raw_events WHERE source = ? AND stream_id = ?\",\n\t\t\t)\n\t\t\t.get(envelope.source, envelope.session_stream_id) as { max_seq: number };\n\t\tconst currentMaxSeq = maxSeqRow.max_seq;\n\n\t\t// Upsert session metadata with accurate sequence tracking\n\t\tdb.prepare(\n\t\t\t`INSERT INTO raw_event_sessions(\n\t\t\t\tsource, stream_id, opencode_session_id, cwd, project, started_at,\n\t\t\t\tlast_seen_ts_wall_ms, last_received_event_seq, last_flushed_event_seq, updated_at\n\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, -1, datetime('now'))\n\t\t\tON CONFLICT(source, stream_id) DO UPDATE SET\n\t\t\t\tcwd = COALESCE(excluded.cwd, cwd),\n\t\t\t\tproject = COALESCE(excluded.project, project),\n\t\t\t\tstarted_at = COALESCE(excluded.started_at, started_at),\n\t\t\t\tlast_seen_ts_wall_ms = MAX(COALESCE(excluded.last_seen_ts_wall_ms, 0), COALESCE(last_seen_ts_wall_ms, 0)),\n\t\t\t\tlast_received_event_seq = MAX(excluded.last_received_event_seq, last_received_event_seq),\n\t\t\t\tupdated_at = datetime('now')`,\n\t\t).run(\n\t\t\tenvelope.source,\n\t\t\tenvelope.session_stream_id,\n\t\t\tenvelope.opencode_session_id,\n\t\t\tenvelope.cwd,\n\t\t\tenvelope.project,\n\t\t\tenvelope.started_at,\n\t\t\tenvelope.ts_wall_ms,\n\t\t\tcurrentMaxSeq,\n\t\t);\n\n\t\treturn { inserted: 1, skipped: 0 };\n\t} finally {\n\t\tdb.close();\n\t}\n}\n\nexport const claudeHookIngestCommand = new Command(\"claude-hook-ingest\")\n\t.configureHelp(helpStyle)\n\t.description(\"Ingest a Claude Code hook payload from stdin\")\n\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.option(\"--host <host>\", \"viewer server host\", \"127.0.0.1\")\n\t.option(\"--port <port>\", \"viewer server port\", \"38888\")\n\t.action(async (opts: { db?: string; host: string; port: string }) => {\n\t\t// Read payload from stdin\n\t\tlet raw: string;\n\t\ttry {\n\t\t\traw = readFileSync(0, \"utf8\").trim();\n\t\t} catch {\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\t\tif (!raw) {\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\n\t\tlet payload: Record<string, unknown>;\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(raw) as unknown;\n\t\t\tif (parsed == null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tpayload = parsed as Record<string, unknown>;\n\t\t} catch {\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\n\t\tconst port = Number.parseInt(opts.port, 10);\n\t\tconst host = opts.host;\n\n\t\t// Strategy 1: try HTTP POST to running viewer\n\t\tconst httpResult = await tryHttpIngest(payload, host, port);\n\t\tif (httpResult.ok) {\n\t\t\tconsole.log(\n\t\t\t\tJSON.stringify({ inserted: httpResult.inserted, skipped: httpResult.skipped, via: \"http\" }),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// Strategy 2: direct local enqueue\n\t\ttry {\n\t\t\tconst dbPath = resolveDbPath(opts.db);\n\t\t\tconst directResult = directEnqueue(payload, dbPath);\n\t\t\tconsole.log(JSON.stringify({ ...directResult, via: \"direct\" }));\n\t\t} catch {\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\t});\n","import * as p from \"@clack/prompts\";\nimport {\n\tgetRawEventStatus,\n\tinitDatabase,\n\trawEventsGate,\n\tretryRawEventFailures,\n\tvacuumDatabase,\n} from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nexport const dbCommand = new Command(\"db\")\n\t.configureHelp(helpStyle)\n\t.description(\"Database maintenance\");\n\ndbCommand\n\t.addCommand(\n\t\tnew Command(\"init\")\n\t\t\t.configureHelp(helpStyle)\n\t\t\t.description(\"Verify the SQLite database is present and schema-ready\")\n\t\t\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t\t.action((opts: { db?: string }) => {\n\t\t\t\tconst result = initDatabase(opts.db);\n\t\t\t\tp.intro(\"codemem db init\");\n\t\t\t\tp.log.success(`Database ready: ${result.path}`);\n\t\t\t\tp.outro(`Size: ${result.sizeBytes.toLocaleString()} bytes`);\n\t\t\t}),\n\t)\n\t.addCommand(\n\t\tnew Command(\"vacuum\")\n\t\t\t.configureHelp(helpStyle)\n\t\t\t.description(\"Run VACUUM on the SQLite database\")\n\t\t\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t\t.action((opts: { db?: string }) => {\n\t\t\t\tconst result = vacuumDatabase(opts.db);\n\t\t\t\tp.intro(\"codemem db vacuum\");\n\t\t\t\tp.log.success(`Vacuumed: ${result.path}`);\n\t\t\t\tp.outro(`Size: ${result.sizeBytes.toLocaleString()} bytes`);\n\t\t\t}),\n\t)\n\t.addCommand(\n\t\tnew Command(\"raw-events-status\")\n\t\t\t.configureHelp(helpStyle)\n\t\t\t.description(\"Show pending raw-event backlog by source stream\")\n\t\t\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t\t.option(\"-n, --limit <n>\", \"max rows to show\", \"25\")\n\t\t\t.option(\"--json\", \"output as JSON\")\n\t\t\t.action((opts: { db?: string; limit: string; json?: boolean }) => {\n\t\t\t\tconst result = getRawEventStatus(opts.db, Number.parseInt(opts.limit, 10) || 25);\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.intro(\"codemem db raw-events-status\");\n\t\t\t\tp.log.info(\n\t\t\t\t\t`Totals: ${result.totals.pending.toLocaleString()} pending across ${result.totals.sessions.toLocaleString()} session(s)`,\n\t\t\t\t);\n\t\t\t\tif (result.items.length === 0) {\n\t\t\t\t\tp.outro(\"No pending raw events\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfor (const item of result.items) {\n\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t`${item.source}:${item.stream_id} pending=${Math.max(0, item.last_received_event_seq - item.last_flushed_event_seq)} ` +\n\t\t\t\t\t\t\t`received=${item.last_received_event_seq} flushed=${item.last_flushed_event_seq} project=${item.project ?? \"\"}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tp.outro(\"done\");\n\t\t\t}),\n\t)\n\t.addCommand(\n\t\tnew Command(\"raw-events-retry\")\n\t\t\t.configureHelp(helpStyle)\n\t\t\t.description(\"Requeue failed raw-event flush batches\")\n\t\t\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t\t.option(\"-n, --limit <n>\", \"max failed batches to requeue\", \"25\")\n\t\t\t.action((opts: { db?: string; limit: string }) => {\n\t\t\t\tconst result = retryRawEventFailures(opts.db, Number.parseInt(opts.limit, 10) || 25);\n\t\t\t\tp.intro(\"codemem db raw-events-retry\");\n\t\t\t\tp.outro(`Requeued ${result.retried.toLocaleString()} failed batch(es)`);\n\t\t\t}),\n\t)\n\t.addCommand(\n\t\tnew Command(\"raw-events-gate\")\n\t\t\t.configureHelp(helpStyle)\n\t\t\t.description(\"Validate raw-event reliability thresholds (non-zero exit on failure)\")\n\t\t\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t\t.option(\"--min-flush-success-rate <rate>\", \"minimum flush success rate\", \"0.95\")\n\t\t\t.option(\"--max-dropped-event-rate <rate>\", \"maximum dropped event rate\", \"0.05\")\n\t\t\t.option(\"--min-session-boundary-accuracy <rate>\", \"minimum session boundary accuracy\", \"0.9\")\n\t\t\t.option(\"--window-hours <hours>\", \"lookback window in hours\", \"24\")\n\t\t\t.option(\"--json\", \"output as JSON\")\n\t\t\t.action(\n\t\t\t\t(opts: {\n\t\t\t\t\tdb?: string;\n\t\t\t\t\tminFlushSuccessRate: string;\n\t\t\t\t\tmaxDroppedEventRate: string;\n\t\t\t\t\tminSessionBoundaryAccuracy: string;\n\t\t\t\t\twindowHours: string;\n\t\t\t\t\tjson?: boolean;\n\t\t\t\t}) => {\n\t\t\t\t\tconst result = rawEventsGate(opts.db, {\n\t\t\t\t\t\tminFlushSuccessRate: Number.parseFloat(opts.minFlushSuccessRate),\n\t\t\t\t\t\tmaxDroppedEventRate: Number.parseFloat(opts.maxDroppedEventRate),\n\t\t\t\t\t\tminSessionBoundaryAccuracy: Number.parseFloat(opts.minSessionBoundaryAccuracy),\n\t\t\t\t\t\twindowHours: Number.parseFloat(opts.windowHours),\n\t\t\t\t\t});\n\n\t\t\t\t\tif (opts.json) {\n\t\t\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\t\t\tif (!result.passed) process.exitCode = 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tp.intro(\"codemem db raw-events-gate\");\n\t\t\t\t\tp.log.info(\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t`flush_success_rate: ${result.metrics.rates.flush_success_rate.toFixed(4)}`,\n\t\t\t\t\t\t\t`dropped_event_rate: ${result.metrics.rates.dropped_event_rate.toFixed(4)}`,\n\t\t\t\t\t\t\t`session_boundary_accuracy: ${result.metrics.rates.session_boundary_accuracy.toFixed(4)}`,\n\t\t\t\t\t\t\t`window_hours: ${result.metrics.window_hours ?? \"all\"}`,\n\t\t\t\t\t\t].join(\"\\n\"),\n\t\t\t\t\t);\n\n\t\t\t\t\tif (result.passed) {\n\t\t\t\t\t\tp.outro(\"reliability gate passed\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor (const f of result.failures) {\n\t\t\t\t\t\t\tp.log.error(f);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tp.outro(\"reliability gate FAILED\");\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t),\n\t);\n","import { MemoryStore, resolveDbPath, stripPrivateObj } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nconst SESSION_ID_KEYS = [\n\t\"session_stream_id\",\n\t\"session_id\",\n\t\"stream_id\",\n\t\"opencode_session_id\",\n] as const;\n\nfunction resolveSessionStreamId(payload: Record<string, unknown>): string | null {\n\tconst values = new Map<string, string>();\n\tfor (const key of SESSION_ID_KEYS) {\n\t\tconst value = payload[key];\n\t\tif (typeof value !== \"string\") continue;\n\t\tconst text = value.trim();\n\t\tif (text) values.set(key, text);\n\t}\n\tif (values.size === 0) return null;\n\tconst unique = new Set(values.values());\n\tif (unique.size > 1) throw new Error(\"conflicting session id fields\");\n\tfor (const key of SESSION_ID_KEYS) {\n\t\tconst value = values.get(key);\n\t\tif (value) return value;\n\t}\n\treturn null;\n}\n\nasync function readStdinJson(): Promise<Record<string, unknown>> {\n\tconst chunks: Buffer[] = [];\n\tfor await (const chunk of process.stdin) {\n\t\tchunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));\n\t}\n\tconst raw = Buffer.concat(chunks).toString(\"utf-8\").trim();\n\tif (!raw) throw new Error(\"stdin JSON required\");\n\tconst parsed = JSON.parse(raw) as unknown;\n\tif (parsed == null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(\"payload must be an object\");\n\t}\n\treturn parsed as Record<string, unknown>;\n}\n\nexport const enqueueRawEventCommand = new Command(\"enqueue-raw-event\")\n\t.configureHelp(helpStyle)\n\t.description(\"Enqueue one raw event from stdin into the durable queue\")\n\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.action(async (opts: { db?: string }) => {\n\t\tconst payload = await readStdinJson();\n\t\tconst sessionId = resolveSessionStreamId(payload);\n\t\tif (!sessionId) throw new Error(\"session id required\");\n\t\tif (sessionId.startsWith(\"msg_\")) throw new Error(\"invalid session id\");\n\n\t\tconst eventType = typeof payload.event_type === \"string\" ? payload.event_type.trim() : \"\";\n\t\tif (!eventType) throw new Error(\"event_type required\");\n\n\t\tconst cwd = typeof payload.cwd === \"string\" ? payload.cwd : null;\n\t\tconst project = typeof payload.project === \"string\" ? payload.project : null;\n\t\tconst startedAt = typeof payload.started_at === \"string\" ? payload.started_at : null;\n\t\tconst tsWallMs = Number.isFinite(Number(payload.ts_wall_ms))\n\t\t\t? Math.floor(Number(payload.ts_wall_ms))\n\t\t\t: null;\n\t\tconst tsMonoMs = Number.isFinite(Number(payload.ts_mono_ms))\n\t\t\t? Number(payload.ts_mono_ms)\n\t\t\t: null;\n\t\tconst eventId = typeof payload.event_id === \"string\" ? payload.event_id.trim() : \"\";\n\t\tconst eventPayload =\n\t\t\tpayload.payload && typeof payload.payload === \"object\" && !Array.isArray(payload.payload)\n\t\t\t\t? (stripPrivateObj(payload.payload) as Record<string, unknown>)\n\t\t\t\t: {};\n\n\t\tconst store = new MemoryStore(resolveDbPath(opts.db));\n\t\ttry {\n\t\t\tstore.updateRawEventSessionMeta({\n\t\t\t\topencodeSessionId: sessionId,\n\t\t\t\tsource: \"opencode\",\n\t\t\t\tcwd,\n\t\t\t\tproject,\n\t\t\t\tstartedAt,\n\t\t\t\tlastSeenTsWallMs: tsWallMs,\n\t\t\t});\n\t\t\tstore.recordRawEventsBatch(sessionId, [\n\t\t\t\t{\n\t\t\t\t\tevent_id: eventId,\n\t\t\t\t\tevent_type: eventType,\n\t\t\t\t\tpayload: eventPayload,\n\t\t\t\t\tts_wall_ms: tsWallMs,\n\t\t\t\t\tts_mono_ms: tsMonoMs,\n\t\t\t\t},\n\t\t\t]);\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t});\n","import { writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { exportMemories, resolveDbPath } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nfunction expandUserPath(value: string): string {\n\treturn value.startsWith(\"~/\") ? join(homedir(), value.slice(2)) : value;\n}\n\nexport const exportMemoriesCommand = new Command(\"export-memories\")\n\t.configureHelp(helpStyle)\n\t.description(\"Export memories to a JSON file for sharing or backup\")\n\t.argument(\"<output>\", \"output file path (use '-' for stdout)\")\n\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.option(\"--project <project>\", \"filter by project (defaults to git repo root)\")\n\t.option(\"--all-projects\", \"export all projects\")\n\t.option(\"--include-inactive\", \"include deactivated memories\")\n\t.option(\"--since <iso>\", \"only export memories created after this ISO timestamp\")\n\t.action(\n\t\t(\n\t\t\toutput: string,\n\t\t\topts: {\n\t\t\t\tdb?: string;\n\t\t\t\tproject?: string;\n\t\t\t\tallProjects?: boolean;\n\t\t\t\tincludeInactive?: boolean;\n\t\t\t\tsince?: string;\n\t\t\t},\n\t\t) => {\n\t\t\tconst payload = exportMemories({\n\t\t\t\tdbPath: resolveDbPath(opts.db),\n\t\t\t\tproject: opts.project,\n\t\t\t\tallProjects: opts.allProjects,\n\t\t\t\tincludeInactive: opts.includeInactive,\n\t\t\t\tsince: opts.since,\n\t\t\t});\n\t\t\tconst text = `${JSON.stringify(payload, null, 2)}\\n`;\n\t\t\tif (output === \"-\") {\n\t\t\t\tprocess.stdout.write(text);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst outputPath = expandUserPath(output);\n\t\t\twriteFileSync(outputPath, text, \"utf8\");\n\t\t\tp.intro(\"codemem export-memories\");\n\t\t\tp.log.success(\n\t\t\t\t[\n\t\t\t\t\t`Output: ${outputPath}`,\n\t\t\t\t\t`Sessions: ${payload.sessions.length.toLocaleString()}`,\n\t\t\t\t\t`Memories: ${payload.memory_items.length.toLocaleString()}`,\n\t\t\t\t\t`Summaries: ${payload.session_summaries.length.toLocaleString()}`,\n\t\t\t\t\t`Prompts: ${payload.user_prompts.length.toLocaleString()}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t);\n\t\t\tp.outro(\"done\");\n\t\t},\n\t);\n","import * as p from \"@clack/prompts\";\nimport type { ExportPayload } from \"@codemem/core\";\nimport { importMemories, readImportPayload, resolveDbPath } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nexport const importMemoriesCommand = new Command(\"import-memories\")\n\t.configureHelp(helpStyle)\n\t.description(\"Import memories from an exported JSON file\")\n\t.argument(\"<inputFile>\", \"input JSON file (use '-' for stdin)\")\n\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.option(\"--remap-project <path>\", \"remap all projects to this path on import\")\n\t.option(\"--dry-run\", \"preview import without writing\")\n\t.action((inputFile: string, opts: { db?: string; remapProject?: string; dryRun?: boolean }) => {\n\t\tlet payload: ExportPayload;\n\t\ttry {\n\t\t\tpayload = readImportPayload(inputFile);\n\t\t} catch (error) {\n\t\t\tp.log.error(error instanceof Error ? error.message : \"Invalid import file\");\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\n\t\tp.intro(\"codemem import-memories\");\n\t\tp.log.info(\n\t\t\t[\n\t\t\t\t`Export version: ${payload.version}`,\n\t\t\t\t`Exported at: ${payload.exported_at}`,\n\t\t\t\t`Sessions: ${payload.sessions.length.toLocaleString()}`,\n\t\t\t\t`Memories: ${payload.memory_items.length.toLocaleString()}`,\n\t\t\t\t`Summaries: ${payload.session_summaries.length.toLocaleString()}`,\n\t\t\t\t`Prompts: ${payload.user_prompts.length.toLocaleString()}`,\n\t\t\t].join(\"\\n\"),\n\t\t);\n\n\t\tconst result = importMemories(payload, {\n\t\t\tdbPath: resolveDbPath(opts.db),\n\t\t\tremapProject: opts.remapProject,\n\t\t\tdryRun: opts.dryRun,\n\t\t});\n\n\t\tif (result.dryRun) {\n\t\t\tp.outro(\"dry run complete\");\n\t\t\treturn;\n\t\t}\n\t\tp.log.success(\n\t\t\t[\n\t\t\t\t`Imported sessions: ${result.sessions.toLocaleString()}`,\n\t\t\t\t`Imported prompts: ${result.user_prompts.toLocaleString()}`,\n\t\t\t\t`Imported memories: ${result.memory_items.toLocaleString()}`,\n\t\t\t\t`Imported summaries: ${result.session_summaries.toLocaleString()}`,\n\t\t\t].join(\"\\n\"),\n\t\t);\n\t\tp.outro(\"done\");\n\t});\n","import { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nexport const mcpCommand = new Command(\"mcp\")\n\t.configureHelp(helpStyle)\n\t.description(\"Start the MCP stdio server\")\n\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.action(async (opts: { db?: string }) => {\n\t\tif (opts.db) process.env.CODEMEM_DB = opts.db;\n\t\t// Dynamic import — MCP server is its own entry point\n\t\tawait import(\"@codemem/mcp-server\");\n\t});\n","/**\n * Memory management CLI commands — show, forget, remember.\n *\n * Ports codemem/commands/memory_cmds.py (show_cmd, forget_cmd, remember_cmd).\n * Compact and inject are deferred — compact requires the summarizer pipeline,\n * and inject is just pack_text output which the existing pack command covers.\n */\n\nimport * as p from \"@clack/prompts\";\nimport { MemoryStore, resolveDbPath, resolveProject } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\n/** Parse a strict positive integer, rejecting prefixes like \"12abc\". */\nfunction parseStrictPositiveId(value: string): number | null {\n\tif (!/^\\d+$/.test(value.trim())) return null;\n\tconst n = Number(value.trim());\n\treturn Number.isFinite(n) && n >= 1 && Number.isInteger(n) ? n : null;\n}\n\nexport const memoryCommand = new Command(\"memory\")\n\t.configureHelp(helpStyle)\n\t.description(\"Memory item management\");\n\n// codemem memory show <id>\nmemoryCommand.addCommand(\n\tnew Command(\"show\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Print a memory item as JSON\")\n\t\t.argument(\"<id>\", \"memory ID\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.action((idStr: string, opts: { db?: string }) => {\n\t\t\tconst memoryId = parseStrictPositiveId(idStr);\n\t\t\tif (memoryId === null) {\n\t\t\t\tp.log.error(`Invalid memory ID: ${idStr}`);\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db));\n\t\t\ttry {\n\t\t\t\tconst item = store.get(memoryId);\n\t\t\t\tif (!item) {\n\t\t\t\t\tp.log.error(`Memory ${memoryId} not found`);\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconsole.log(JSON.stringify(item, null, 2));\n\t\t\t} finally {\n\t\t\t\tstore.close();\n\t\t\t}\n\t\t}),\n);\n\n// codemem memory forget <id>\nmemoryCommand.addCommand(\n\tnew Command(\"forget\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Deactivate a memory item\")\n\t\t.argument(\"<id>\", \"memory ID\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.action((idStr: string, opts: { db?: string }) => {\n\t\t\tconst memoryId = parseStrictPositiveId(idStr);\n\t\t\tif (memoryId === null) {\n\t\t\t\tp.log.error(`Invalid memory ID: ${idStr}`);\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db));\n\t\t\ttry {\n\t\t\t\tstore.forget(memoryId);\n\t\t\t\tp.log.success(`Memory ${memoryId} marked inactive`);\n\t\t\t} finally {\n\t\t\t\tstore.close();\n\t\t\t}\n\t\t}),\n);\n\n// codemem memory remember --kind <kind> --title <title> --body <body>\nmemoryCommand.addCommand(\n\tnew Command(\"remember\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Manually add a memory item\")\n\t\t.requiredOption(\"-k, --kind <kind>\", \"memory kind (discovery, decision, feature, bugfix, etc.)\")\n\t\t.requiredOption(\"-t, --title <title>\", \"memory title\")\n\t\t.requiredOption(\"-b, --body <body>\", \"memory body text\")\n\t\t.option(\"--tags <tags...>\", \"tags (space-separated)\")\n\t\t.option(\"--project <project>\", \"project name (defaults to git repo root)\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.action(\n\t\t\t(opts: {\n\t\t\t\tkind: string;\n\t\t\t\ttitle: string;\n\t\t\t\tbody: string;\n\t\t\t\ttags?: string[];\n\t\t\t\tproject?: string;\n\t\t\t\tdb?: string;\n\t\t\t}) => {\n\t\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db));\n\t\t\t\tlet sessionId: number | null = null;\n\t\t\t\ttry {\n\t\t\t\t\tconst project = resolveProject(process.cwd(), opts.project ?? null);\n\t\t\t\t\tsessionId = store.startSession({\n\t\t\t\t\t\tcwd: process.cwd(),\n\t\t\t\t\t\tproject,\n\t\t\t\t\t\tuser: process.env.USER ?? \"unknown\",\n\t\t\t\t\t\ttoolVersion: \"manual\",\n\t\t\t\t\t\tmetadata: { manual: true },\n\t\t\t\t\t});\n\t\t\t\t\tconst memId = store.remember(sessionId, opts.kind, opts.title, opts.body, 0.5, opts.tags);\n\t\t\t\t\tstore.endSession(sessionId, { manual: true });\n\t\t\t\t\tp.log.success(`Stored memory ${memId}`);\n\t\t\t\t} catch (err) {\n\t\t\t\t\t// Always close the session even if remember() throws (e.g. invalid kind)\n\t\t\t\t\tif (sessionId !== null) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tstore.endSession(sessionId, { manual: true, error: true });\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// ignore — already in error path\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthrow err;\n\t\t\t\t} finally {\n\t\t\t\t\tstore.close();\n\t\t\t\t}\n\t\t\t},\n\t\t),\n);\n","import * as p from \"@clack/prompts\";\nimport { MemoryStore, resolveDbPath } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nexport const packCommand = new Command(\"pack\")\n\t.configureHelp(helpStyle)\n\t.description(\"Build a context-aware memory pack\")\n\t.argument(\"<context>\", \"context string to search for\")\n\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.option(\"-n, --limit <n>\", \"max items\", \"10\")\n\t.option(\"--budget <tokens>\", \"token budget\")\n\t.option(\"--json\", \"output as JSON\")\n\t.action(\n\t\t(context: string, opts: { db?: string; limit: string; budget?: string; json?: boolean }) => {\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db));\n\t\t\ttry {\n\t\t\t\tconst limit = Number.parseInt(opts.limit, 10) || 10;\n\t\t\t\tconst budget = opts.budget ? Number.parseInt(opts.budget, 10) : undefined;\n\t\t\t\tconst result = store.buildMemoryPack(context, limit, budget);\n\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tp.intro(`Memory pack for \"${context}\"`);\n\n\t\t\t\tif (result.items.length === 0) {\n\t\t\t\t\tp.log.warn(\"No relevant memories found.\");\n\t\t\t\t\tp.outro(\"done\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst m = result.metrics;\n\t\t\t\tp.log.info(\n\t\t\t\t\t`${m.total_items} items, ~${m.pack_tokens} tokens` +\n\t\t\t\t\t\t(m.fallback_used ? \" (fallback)\" : \"\") +\n\t\t\t\t\t\t` [fts:${m.sources.fts} sem:${m.sources.semantic} fuzzy:${m.sources.fuzzy}]`,\n\t\t\t\t);\n\n\t\t\t\tfor (const item of result.items) {\n\t\t\t\t\tp.log.step(`#${item.id} ${item.kind} ${item.title}`);\n\t\t\t\t}\n\n\t\t\t\tp.note(result.pack_text, \"pack_text\");\n\n\t\t\t\tp.outro(\"done\");\n\t\t\t} finally {\n\t\t\t\tstore.close();\n\t\t\t}\n\t\t},\n\t);\n","import { MemoryStore, resolveDbPath } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nexport const recentCommand = new Command(\"recent\")\n\t.configureHelp(helpStyle)\n\t.description(\"Show recent memories\")\n\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.option(\"--limit <n>\", \"max results\", \"5\")\n\t.option(\"--kind <kind>\", \"filter by memory kind\")\n\t.action((opts: { db?: string; limit: string; kind?: string }) => {\n\t\tconst store = new MemoryStore(resolveDbPath(opts.db));\n\t\ttry {\n\t\t\tconst limit = Math.max(1, Number.parseInt(opts.limit, 10) || 5);\n\t\t\tconst filters = opts.kind ? { kind: opts.kind } : undefined;\n\t\t\tconst items = store.recent(limit, filters);\n\t\t\tfor (const item of items) {\n\t\t\t\tconsole.log(`#${item.id} [${item.kind}] ${item.title}`);\n\t\t\t}\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t});\n","import * as p from \"@clack/prompts\";\nimport { MemoryStore, resolveDbPath } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nexport const searchCommand = new Command(\"search\")\n\t.configureHelp(helpStyle)\n\t.description(\"Search memories by query\")\n\t.argument(\"<query>\", \"search query\")\n\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.option(\"-n, --limit <n>\", \"max results\", \"10\")\n\t.option(\"--kind <kind>\", \"filter by memory kind\")\n\t.option(\"--json\", \"output as JSON\")\n\t.action((query: string, opts: { db?: string; limit: string; kind?: string; json?: boolean }) => {\n\t\tconst store = new MemoryStore(resolveDbPath(opts.db));\n\t\ttry {\n\t\t\tconst limit = Number.parseInt(opts.limit, 10) || 10;\n\t\t\tconst filters = opts.kind ? { kind: opts.kind } : undefined;\n\t\t\tconst results = store.search(query, limit, filters);\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(results, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (results.length === 0) {\n\t\t\t\tp.log.warn(\"No results found.\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tp.intro(`${results.length} result(s) for \"${query}\"`);\n\n\t\t\tfor (const item of results) {\n\t\t\t\tconst score = item.score.toFixed(3);\n\t\t\t\tconst age = timeSince(item.created_at);\n\t\t\t\tconst preview =\n\t\t\t\t\titem.body_text.length > 120 ? `${item.body_text.slice(0, 120)}…` : item.body_text;\n\n\t\t\t\tp.log.message(\n\t\t\t\t\t[`#${item.id} ${item.kind} ${age} [${score}]`, item.title, preview].join(\"\\n\"),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tp.outro(\"done\");\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t});\n\nfunction timeSince(isoDate: string): string {\n\tconst ms = Date.now() - new Date(isoDate).getTime();\n\tconst days = Math.floor(ms / 86_400_000);\n\tif (days === 0) return \"today\";\n\tif (days === 1) return \"1d ago\";\n\tif (days < 30) return `${days}d ago`;\n\tconst months = Math.floor(days / 30);\n\treturn `${months}mo ago`;\n}\n","import { existsSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport {\n\tObserverClient,\n\tRawEventSweeper,\n\treadCodememConfigFile,\n\tresolveDbPath,\n\trunSyncDaemon,\n} from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nfunction pidFilePath(dbPath: string): string {\n\treturn join(dirname(dbPath), \"viewer.pid\");\n}\n\ninterface ViewerPidRecord {\n\tpid: number;\n\thost: string;\n\tport: number;\n}\n\nfunction readViewerPidRecord(dbPath: string): ViewerPidRecord | null {\n\tconst pidPath = pidFilePath(dbPath);\n\tif (!existsSync(pidPath)) return null;\n\tconst raw = readFileSync(pidPath, \"utf-8\").trim();\n\ttry {\n\t\tconst parsed = JSON.parse(raw) as Partial<ViewerPidRecord>;\n\t\tif (\n\t\t\ttypeof parsed.pid === \"number\" &&\n\t\t\ttypeof parsed.host === \"string\" &&\n\t\t\ttypeof parsed.port === \"number\"\n\t\t) {\n\t\t\treturn { pid: parsed.pid, host: parsed.host, port: parsed.port };\n\t\t}\n\t} catch {\n\t\tconst pid = Number.parseInt(raw, 10);\n\t\tif (Number.isFinite(pid) && pid > 0) {\n\t\t\treturn { pid, host: \"127.0.0.1\", port: 38888 };\n\t\t}\n\t}\n\treturn null;\n}\n\nasync function respondsLikeCodememViewer(record: ViewerPidRecord): Promise<boolean> {\n\ttry {\n\t\tconst controller = new AbortController();\n\t\tconst timer = setTimeout(() => controller.abort(), 1000);\n\t\tconst res = await fetch(`http://${record.host}:${record.port}/api/stats`, {\n\t\t\tsignal: controller.signal,\n\t\t});\n\t\tclearTimeout(timer);\n\t\treturn res.ok;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nasync function waitForProcessExit(pid: number, timeoutMs = 5000): Promise<void> {\n\tconst deadline = Date.now() + timeoutMs;\n\twhile (Date.now() < deadline) {\n\t\ttry {\n\t\t\tprocess.kill(pid, 0);\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 100));\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nasync function stopExistingViewer(dbPath: string): Promise<void> {\n\tconst pidPath = pidFilePath(dbPath);\n\tconst record = readViewerPidRecord(dbPath);\n\tif (!record) return;\n\t// Only signal the process if the recorded endpoint still looks like codemem.\n\tif (await respondsLikeCodememViewer(record)) {\n\t\ttry {\n\t\t\tprocess.kill(record.pid, \"SIGTERM\");\n\t\t\tawait waitForProcessExit(record.pid);\n\t\t} catch {\n\t\t\t// stale pidfile or already exited\n\t\t}\n\t}\n\ttry {\n\t\trmSync(pidPath);\n\t} catch {\n\t\t// ignore\n\t}\n}\n\nexport const serveCommand = new Command(\"serve\")\n\t.configureHelp(helpStyle)\n\t.description(\"Start the viewer server\")\n\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.option(\"--host <host>\", \"bind host\", \"127.0.0.1\")\n\t.option(\"--port <port>\", \"bind port\", \"38888\")\n\t.option(\"--background\", \"run under a caller-managed background process\")\n\t.option(\"--stop\", \"stop an existing viewer process\")\n\t.option(\"--restart\", \"restart an existing viewer process\")\n\t.action(\n\t\tasync (opts: {\n\t\t\tdb?: string;\n\t\t\thost: string;\n\t\t\tport: string;\n\t\t\tbackground?: boolean;\n\t\t\tstop?: boolean;\n\t\t\trestart?: boolean;\n\t\t}) => {\n\t\t\t// Dynamic import to avoid loading hono/server deps for non-serve commands\n\t\t\tconst { createApp, closeStore, getStore } = await import(\"@codemem/viewer-server\");\n\t\t\tconst { serve } = await import(\"@hono/node-server\");\n\n\t\t\tconst dbPath = resolveDbPath(opts.db);\n\t\t\tif (opts.stop || opts.restart) {\n\t\t\t\tawait stopExistingViewer(dbPath);\n\t\t\t\tif (opts.stop && !opts.restart) return;\n\t\t\t}\n\t\t\tprocess.env.CODEMEM_DB = dbPath;\n\n\t\t\tconst port = Number.parseInt(opts.port, 10);\n\t\t\t// Start the raw event sweeper — shares the same store as the viewer\n\t\t\tconst observer = new ObserverClient();\n\t\t\tconst sweeper = new RawEventSweeper(getStore(), { observer });\n\t\t\tsweeper.start();\n\n\t\t\t// Start the sync daemon if enabled — shares the same DB path.\n\t\t\t// Uses an AbortController so serve shutdown cleanly stops sync.\n\t\t\tconst syncAbort = new AbortController();\n\t\t\tlet syncRunning = false;\n\t\t\tconst config = readCodememConfigFile();\n\t\t\tconst syncEnabled =\n\t\t\t\tconfig.sync_enabled === true ||\n\t\t\t\tprocess.env.CODEMEM_SYNC_ENABLED?.toLowerCase() === \"true\" ||\n\t\t\t\tprocess.env.CODEMEM_SYNC_ENABLED === \"1\";\n\n\t\t\tif (syncEnabled) {\n\t\t\t\tsyncRunning = true;\n\t\t\t\tconst syncIntervalS =\n\t\t\t\t\ttypeof config.sync_interval_s === \"number\" ? config.sync_interval_s : 120;\n\t\t\t\trunSyncDaemon({\n\t\t\t\t\tdbPath,\n\t\t\t\t\tintervalS: syncIntervalS,\n\t\t\t\t\thost: opts.host,\n\t\t\t\t\tport,\n\t\t\t\t\tsignal: syncAbort.signal,\n\t\t\t\t})\n\t\t\t\t\t.catch((err: unknown) => {\n\t\t\t\t\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\t\t\t\t\tp.log.error(`Sync daemon failed: ${msg}`);\n\t\t\t\t\t\t// Non-fatal — viewer continues without sync\n\t\t\t\t\t})\n\t\t\t\t\t.finally(() => {\n\t\t\t\t\t\tsyncRunning = false;\n\t\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst app = createApp({ storeFactory: getStore, sweeper });\n\t\t\tconst pidPath = pidFilePath(dbPath);\n\n\t\t\tconst server = serve({ fetch: app.fetch, hostname: opts.host, port }, (info) => {\n\t\t\t\twriteFileSync(\n\t\t\t\t\tpidPath,\n\t\t\t\t\tJSON.stringify({ pid: process.pid, host: opts.host, port }),\n\t\t\t\t\t\"utf-8\",\n\t\t\t\t);\n\t\t\t\tp.intro(\"codemem viewer\");\n\t\t\t\tp.log.success(`Listening on http://${info.address}:${info.port}`);\n\t\t\t\tp.log.info(`Database: ${dbPath}`);\n\t\t\t\tp.log.step(\"Raw event sweeper started\");\n\t\t\t\tif (syncRunning) p.log.step(\"Sync daemon started\");\n\t\t\t});\n\n\t\t\tconst shutdown = async () => {\n\t\t\t\tp.outro(\"shutting down\");\n\t\t\t\t// Stop sync daemon via abort signal\n\t\t\t\tsyncAbort.abort();\n\t\t\t\t// Stop sweeper first and wait for any in-flight tick to drain.\n\t\t\t\tawait sweeper.stop();\n\t\t\t\t// Close HTTP server, wait for in-flight requests to drain\n\t\t\t\tserver.close(() => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\trmSync(pidPath);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// ignore\n\t\t\t\t\t}\n\t\t\t\t\tcloseStore();\n\t\t\t\t\tprocess.exit(0);\n\t\t\t\t});\n\t\t\t\t// Force exit after 5s if graceful shutdown stalls\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\trmSync(pidPath);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// ignore\n\t\t\t\t\t}\n\t\t\t\t\tcloseStore();\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t}, 5000).unref();\n\t\t\t};\n\t\t\tprocess.on(\"SIGINT\", () => {\n\t\t\t\tvoid shutdown();\n\t\t\t});\n\t\t\tprocess.on(\"SIGTERM\", () => {\n\t\t\t\tvoid shutdown();\n\t\t\t});\n\t\t},\n\t);\n","/**\n * codemem setup — one-command installation for OpenCode plugin + MCP config.\n *\n * Replaces Python's install_plugin_cmd + install_mcp_cmd.\n *\n * What it does:\n * 1. Copies the plugin file to ~/.config/opencode/plugin/codemem.js\n * 2. Adds/updates the MCP entry in ~/.config/opencode/opencode.json\n * 3. Copies the compat lib to ~/.config/opencode/lib/compat.js\n *\n * Designed to be safe to run repeatedly (idempotent unless --force).\n */\n\nimport { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { stripJsonComments, stripTrailingCommas, VERSION } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nfunction opencodeConfigDir(): string {\n\treturn join(homedir(), \".config\", \"opencode\");\n}\n\nfunction claudeConfigDir(): string {\n\treturn join(homedir(), \".claude\");\n}\n\n/**\n * Find the plugin source file — walk up from this module's location\n * to find the .opencode/plugin/codemem.js in the package tree.\n */\nfunction findPluginSource(): string | null {\n\t// In the built CLI, __dirname is packages/cli/dist or similar.\n\t// The plugin lives at the repo/package root under .opencode/plugin/codemem.js\n\tlet dir = dirname(import.meta.url.replace(\"file://\", \"\"));\n\tfor (let i = 0; i < 6; i++) {\n\t\tconst candidate = join(dir, \".opencode\", \"plugin\", \"codemem.js\");\n\t\tif (existsSync(candidate)) return candidate;\n\t\t// Check node_modules/codemem/.opencode/plugin/codemem.js (unscoped)\n\t\tconst nmCandidate = join(dir, \"node_modules\", \"codemem\", \".opencode\", \"plugin\", \"codemem.js\");\n\t\tif (existsSync(nmCandidate)) return nmCandidate;\n\t\t// Legacy: node_modules/@kunickiaj/codemem/.opencode/plugin/codemem.js\n\t\tconst legacyCandidate = join(\n\t\t\tdir,\n\t\t\t\"node_modules\",\n\t\t\t\"@kunickiaj\",\n\t\t\t\"codemem\",\n\t\t\t\".opencode\",\n\t\t\t\"plugin\",\n\t\t\t\"codemem.js\",\n\t\t);\n\t\tif (existsSync(legacyCandidate)) return legacyCandidate;\n\t\tconst parent = dirname(dir);\n\t\tif (parent === dir) break;\n\t\tdir = parent;\n\t}\n\treturn null;\n}\n\nfunction findCompatSource(): string | null {\n\tlet dir = dirname(import.meta.url.replace(\"file://\", \"\"));\n\tfor (let i = 0; i < 6; i++) {\n\t\tconst candidate = join(dir, \".opencode\", \"lib\", \"compat.js\");\n\t\tif (existsSync(candidate)) return candidate;\n\t\tconst nmCandidate = join(dir, \"node_modules\", \"codemem\", \".opencode\", \"lib\", \"compat.js\");\n\t\tif (existsSync(nmCandidate)) return nmCandidate;\n\t\tconst legacyCandidate = join(\n\t\t\tdir,\n\t\t\t\"node_modules\",\n\t\t\t\"@kunickiaj\",\n\t\t\t\"codemem\",\n\t\t\t\".opencode\",\n\t\t\t\"lib\",\n\t\t\t\"compat.js\",\n\t\t);\n\t\tif (existsSync(legacyCandidate)) return legacyCandidate;\n\t\tconst parent = dirname(dir);\n\t\tif (parent === dir) break;\n\t\tdir = parent;\n\t}\n\treturn null;\n}\n\nfunction loadJsoncConfig(path: string): Record<string, unknown> {\n\tif (!existsSync(path)) return {};\n\tconst raw = readFileSync(path, \"utf-8\");\n\ttry {\n\t\treturn JSON.parse(raw) as Record<string, unknown>;\n\t} catch {\n\t\tconst cleaned = stripTrailingCommas(stripJsonComments(raw));\n\t\treturn JSON.parse(cleaned) as Record<string, unknown>;\n\t}\n}\n\nfunction writeJsonConfig(path: string, data: Record<string, unknown>): void {\n\tmkdirSync(dirname(path), { recursive: true });\n\twriteFileSync(path, `${JSON.stringify(data, null, 2)}\\n`, \"utf-8\");\n}\n\nfunction installPlugin(force: boolean): boolean {\n\tconst source = findPluginSource();\n\tif (!source) {\n\t\tp.log.error(\"Plugin file not found in package tree\");\n\t\treturn false;\n\t}\n\n\tconst destDir = join(opencodeConfigDir(), \"plugin\");\n\tconst dest = join(destDir, \"codemem.js\");\n\n\tif (existsSync(dest) && !force) {\n\t\tp.log.info(`Plugin already installed at ${dest}`);\n\t} else {\n\t\tmkdirSync(destDir, { recursive: true });\n\t\tcopyFileSync(source, dest);\n\t\tp.log.success(`Plugin installed: ${dest}`);\n\t}\n\n\t// Always install/update compat lib (plugin imports ../lib/compat.js)\n\tconst compatSource = findCompatSource();\n\tif (compatSource) {\n\t\tconst compatDir = join(opencodeConfigDir(), \"lib\");\n\t\tmkdirSync(compatDir, { recursive: true });\n\t\tcopyFileSync(compatSource, join(compatDir, \"compat.js\"));\n\t}\n\n\treturn true;\n}\n\nfunction installMcp(force: boolean): boolean {\n\tconst configPath = join(opencodeConfigDir(), \"opencode.json\");\n\tlet config: Record<string, unknown>;\n\ttry {\n\t\tconfig = loadJsoncConfig(configPath);\n\t} catch (err) {\n\t\tp.log.error(\n\t\t\t`Failed to parse ${configPath}: ${err instanceof Error ? err.message : String(err)}`,\n\t\t);\n\t\treturn false;\n\t}\n\n\tlet mcpConfig = config.mcp as Record<string, unknown> | undefined;\n\tif (mcpConfig == null || typeof mcpConfig !== \"object\" || Array.isArray(mcpConfig)) {\n\t\tmcpConfig = {};\n\t}\n\n\tif (\"codemem\" in mcpConfig && !force) {\n\t\tp.log.info(`MCP entry already exists in ${configPath}`);\n\t\treturn true;\n\t}\n\n\tmcpConfig.codemem = {\n\t\ttype: \"local\",\n\t\tcommand: [\"npx\", \"codemem\", \"mcp\"],\n\t\tenabled: true,\n\t};\n\tconfig.mcp = mcpConfig;\n\n\ttry {\n\t\twriteJsonConfig(configPath, config);\n\t\tp.log.success(`MCP entry installed: ${configPath}`);\n\t} catch (err) {\n\t\tp.log.error(\n\t\t\t`Failed to write ${configPath}: ${err instanceof Error ? err.message : String(err)}`,\n\t\t);\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nfunction installClaudeMcp(force: boolean): boolean {\n\tconst settingsPath = join(claudeConfigDir(), \"settings.json\");\n\tlet settings: Record<string, unknown>;\n\ttry {\n\t\tsettings = loadJsoncConfig(settingsPath);\n\t} catch {\n\t\tsettings = {};\n\t}\n\n\tlet mcpServers = settings.mcpServers as Record<string, unknown> | undefined;\n\tif (mcpServers == null || typeof mcpServers !== \"object\" || Array.isArray(mcpServers)) {\n\t\tmcpServers = {};\n\t}\n\n\tif (\"codemem\" in mcpServers && !force) {\n\t\tp.log.info(`Claude MCP entry already exists in ${settingsPath}`);\n\t\treturn true;\n\t}\n\n\tmcpServers.codemem = {\n\t\tcommand: \"npx\",\n\t\targs: [\"codemem\", \"mcp\"],\n\t};\n\tsettings.mcpServers = mcpServers;\n\n\ttry {\n\t\twriteJsonConfig(settingsPath, settings);\n\t\tp.log.success(`Claude MCP entry installed: ${settingsPath}`);\n\t} catch (err) {\n\t\tp.log.error(\n\t\t\t`Failed to write ${settingsPath}: ${err instanceof Error ? err.message : String(err)}`,\n\t\t);\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nexport const setupCommand = new Command(\"setup\")\n\t.configureHelp(helpStyle)\n\t.description(\"Install codemem plugin + MCP config for OpenCode and Claude Code\")\n\t.option(\"--force\", \"overwrite existing installations\")\n\t.option(\"--opencode-only\", \"only install for OpenCode\")\n\t.option(\"--claude-only\", \"only install for Claude Code\")\n\t.action((opts: { force?: boolean; opencodeOnly?: boolean; claudeOnly?: boolean }) => {\n\t\tp.intro(`codemem setup v${VERSION}`);\n\t\tconst force = opts.force ?? false;\n\t\tlet ok = true;\n\n\t\tif (!opts.claudeOnly) {\n\t\t\tp.log.step(\"Installing OpenCode plugin...\");\n\t\t\tok = installPlugin(force) && ok;\n\t\t\tp.log.step(\"Installing OpenCode MCP config...\");\n\t\t\tok = installMcp(force) && ok;\n\t\t}\n\n\t\tif (!opts.opencodeOnly) {\n\t\t\tp.log.step(\"Installing Claude Code MCP config...\");\n\t\t\tok = installClaudeMcp(force) && ok;\n\t\t}\n\n\t\tif (ok) {\n\t\t\tp.outro(\"Setup complete — restart your editor to load the plugin\");\n\t\t} else {\n\t\t\tp.outro(\"Setup completed with warnings\");\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\t});\n","import * as p from \"@clack/prompts\";\nimport { MemoryStore, resolveDbPath } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nfunction fmtPct(n: number): string {\n\treturn `${Math.round(n * 100)}%`;\n}\n\nfunction fmtTokens(n: number): string {\n\tif (n >= 1_000_000_000) return `~${(n / 1_000_000_000).toFixed(1)}B`;\n\tif (n >= 1_000_000) return `~${(n / 1_000_000).toFixed(1)}M`;\n\tif (n >= 1_000) return `~${(n / 1_000).toFixed(0)}K`;\n\treturn `${n}`;\n}\n\nexport const statsCommand = new Command(\"stats\")\n\t.configureHelp(helpStyle)\n\t.description(\"Show database statistics\")\n\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.option(\"--json\", \"output as JSON\")\n\t.action((opts: { db?: string; json?: boolean }) => {\n\t\tconst store = new MemoryStore(resolveDbPath(opts.db));\n\t\ttry {\n\t\t\tconst result = store.stats();\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst db = result.database;\n\t\t\tconst sizeMb = (db.size_bytes / 1_048_576).toFixed(1);\n\n\t\t\tp.intro(\"codemem stats\");\n\n\t\t\tp.log.info([`Path: ${db.path}`, `Size: ${sizeMb} MB`].join(\"\\n\"));\n\n\t\t\tp.log.success(\n\t\t\t\t[\n\t\t\t\t\t`Sessions: ${db.sessions.toLocaleString()}`,\n\t\t\t\t\t`Memories: ${db.active_memory_items.toLocaleString()} active / ${db.memory_items.toLocaleString()} total`,\n\t\t\t\t\t`Tags: ${db.tags_filled.toLocaleString()} filled (${fmtPct(db.tags_coverage)} of active)`,\n\t\t\t\t\t`Artifacts: ${db.artifacts.toLocaleString()}`,\n\t\t\t\t\t`Vectors: ${db.vector_rows.toLocaleString()} (${fmtPct(db.vector_coverage)} coverage)`,\n\t\t\t\t\t`Raw events: ${db.raw_events.toLocaleString()}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t);\n\n\t\t\tif (result.usage.events.length > 0) {\n\t\t\t\tconst lines = result.usage.events.map((e: (typeof result.usage.events)[number]) => {\n\t\t\t\t\tconst parts = [`${e.event}: ${e.count.toLocaleString()}`];\n\t\t\t\t\tif (e.tokens_read > 0) parts.push(`read ${fmtTokens(e.tokens_read)} tokens`);\n\t\t\t\t\tif (e.tokens_saved > 0) parts.push(`est. saved ${fmtTokens(e.tokens_saved)} tokens`);\n\t\t\t\t\treturn ` ${parts.join(\", \")}`;\n\t\t\t\t});\n\n\t\t\t\tconst t = result.usage.totals;\n\t\t\t\tlines.push(\"\");\n\t\t\t\tlines.push(\n\t\t\t\t\t` Total: ${t.events.toLocaleString()} events, read ${fmtTokens(t.tokens_read)} tokens, est. saved ${fmtTokens(t.tokens_saved)} tokens`,\n\t\t\t\t);\n\n\t\t\t\tp.log.step(`Usage\\n${lines.join(\"\\n\")}`);\n\t\t\t}\n\n\t\t\tp.outro(\"done\");\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t});\n","/**\n * Sync CLI commands — enable/disable/status/peers/connect.\n */\n\nimport * as p from \"@clack/prompts\";\nimport {\n\tensureDeviceIdentity,\n\tMemoryStore,\n\treadCodememConfigFile,\n\tresolveDbPath,\n\tschema,\n\twriteCodememConfigFile,\n} from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { desc } from \"drizzle-orm\";\nimport { drizzle } from \"drizzle-orm/better-sqlite3\";\nimport { helpStyle } from \"../help-style.js\";\n\nexport const syncCommand = new Command(\"sync\")\n\t.configureHelp(helpStyle)\n\t.description(\"Sync configuration and peer management\");\n\n// codemem sync status\nsyncCommand.addCommand(\n\tnew Command(\"status\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Show sync configuration and peer summary\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.option(\"--json\", \"output as JSON\")\n\t\t.action((opts: { db?: string; json?: boolean }) => {\n\t\t\tconst config = readCodememConfigFile();\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db));\n\t\t\ttry {\n\t\t\t\tconst d = drizzle(store.db, { schema });\n\t\t\t\tconst deviceRow = d\n\t\t\t\t\t.select({\n\t\t\t\t\t\tdevice_id: schema.syncDevice.device_id,\n\t\t\t\t\t\tfingerprint: schema.syncDevice.fingerprint,\n\t\t\t\t\t})\n\t\t\t\t\t.from(schema.syncDevice)\n\t\t\t\t\t.limit(1)\n\t\t\t\t\t.get();\n\t\t\t\tconst peers = d\n\t\t\t\t\t.select({\n\t\t\t\t\t\tpeer_device_id: schema.syncPeers.peer_device_id,\n\t\t\t\t\t\tname: schema.syncPeers.name,\n\t\t\t\t\t\tlast_sync_at: schema.syncPeers.last_sync_at,\n\t\t\t\t\t\tlast_error: schema.syncPeers.last_error,\n\t\t\t\t\t})\n\t\t\t\t\t.from(schema.syncPeers)\n\t\t\t\t\t.all();\n\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\tJSON.stringify(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tenabled: config.sync_enabled === true,\n\t\t\t\t\t\t\t\thost: config.sync_host ?? \"0.0.0.0\",\n\t\t\t\t\t\t\t\tport: config.sync_port ?? 7337,\n\t\t\t\t\t\t\t\tinterval_s: config.sync_interval_s ?? 120,\n\t\t\t\t\t\t\t\tdevice_id: deviceRow?.device_id ?? null,\n\t\t\t\t\t\t\t\tfingerprint: deviceRow?.fingerprint ?? null,\n\t\t\t\t\t\t\t\tcoordinator_url: config.sync_coordinator_url ?? null,\n\t\t\t\t\t\t\t\tpeers: peers.map((peer) => ({\n\t\t\t\t\t\t\t\t\tdevice_id: peer.peer_device_id,\n\t\t\t\t\t\t\t\t\tname: peer.name,\n\t\t\t\t\t\t\t\t\tlast_sync: peer.last_sync_at,\n\t\t\t\t\t\t\t\t\tstatus: peer.last_error ?? \"ok\",\n\t\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t2,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tp.intro(\"codemem sync status\");\n\t\t\t\tp.log.info(\n\t\t\t\t\t[\n\t\t\t\t\t\t`Enabled: ${config.sync_enabled === true ? \"yes\" : \"no\"}`,\n\t\t\t\t\t\t`Host: ${config.sync_host ?? \"0.0.0.0\"}`,\n\t\t\t\t\t\t`Port: ${config.sync_port ?? 7337}`,\n\t\t\t\t\t\t`Interval: ${config.sync_interval_s ?? 120}s`,\n\t\t\t\t\t\t`Coordinator: ${config.sync_coordinator_url ?? \"(not configured)\"}`,\n\t\t\t\t\t].join(\"\\n\"),\n\t\t\t\t);\n\t\t\t\tif (deviceRow) {\n\t\t\t\t\tp.log.info(`Device ID: ${deviceRow.device_id}\\nFingerprint: ${deviceRow.fingerprint}`);\n\t\t\t\t} else {\n\t\t\t\t\tp.log.warn(\"Device identity not initialized (run `codemem sync enable`)\");\n\t\t\t\t}\n\t\t\t\tif (peers.length === 0) {\n\t\t\t\t\tp.log.info(\"Peers: none\");\n\t\t\t\t} else {\n\t\t\t\t\tfor (const peer of peers) {\n\t\t\t\t\t\tconst label = peer.name || peer.peer_device_id;\n\t\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t\t` ${label}: last_sync=${peer.last_sync_at ?? \"never\"}, status=${peer.last_error ?? \"ok\"}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tp.outro(`${peers.length} peer(s)`);\n\t\t\t} finally {\n\t\t\t\tstore.close();\n\t\t\t}\n\t\t}),\n);\n\n// codemem sync enable\nsyncCommand.addCommand(\n\tnew Command(\"enable\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Enable sync and initialize device identity\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.option(\"--host <host>\", \"sync listen host\")\n\t\t.option(\"--port <port>\", \"sync listen port\")\n\t\t.option(\"--interval <seconds>\", \"sync interval in seconds\")\n\t\t.action((opts: { db?: string; host?: string; port?: string; interval?: string }) => {\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db));\n\t\t\ttry {\n\t\t\t\tconst [deviceId, fingerprint] = ensureDeviceIdentity(store.db);\n\t\t\t\tconst config = readCodememConfigFile();\n\t\t\t\tconfig.sync_enabled = true;\n\t\t\t\tif (opts.host) config.sync_host = opts.host;\n\t\t\t\tif (opts.port) config.sync_port = Number.parseInt(opts.port, 10);\n\t\t\t\tif (opts.interval) config.sync_interval_s = Number.parseInt(opts.interval, 10);\n\t\t\t\twriteCodememConfigFile(config);\n\n\t\t\t\tp.intro(\"codemem sync enable\");\n\t\t\t\tp.log.success(\n\t\t\t\t\t[\n\t\t\t\t\t\t`Device ID: ${deviceId}`,\n\t\t\t\t\t\t`Fingerprint: ${fingerprint}`,\n\t\t\t\t\t\t`Host: ${config.sync_host ?? \"0.0.0.0\"}`,\n\t\t\t\t\t\t`Port: ${config.sync_port ?? 7337}`,\n\t\t\t\t\t\t`Interval: ${config.sync_interval_s ?? 120}s`,\n\t\t\t\t\t].join(\"\\n\"),\n\t\t\t\t);\n\t\t\t\tp.outro(\"Sync enabled — restart `codemem serve` to activate\");\n\t\t\t} finally {\n\t\t\t\tstore.close();\n\t\t\t}\n\t\t}),\n);\n\n// codemem sync disable\nsyncCommand.addCommand(\n\tnew Command(\"disable\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Disable sync without deleting keys or peers\")\n\t\t.action(() => {\n\t\t\tconst config = readCodememConfigFile();\n\t\t\tconfig.sync_enabled = false;\n\t\t\twriteCodememConfigFile(config);\n\t\t\tp.intro(\"codemem sync disable\");\n\t\t\tp.outro(\"Sync disabled — restart `codemem serve` to take effect\");\n\t\t}),\n);\n\n// codemem sync peers\nsyncCommand.addCommand(\n\tnew Command(\"peers\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"List known sync peers\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.option(\"--json\", \"output as JSON\")\n\t\t.action((opts: { db?: string; json?: boolean }) => {\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db));\n\t\t\ttry {\n\t\t\t\tconst d = drizzle(store.db, { schema });\n\t\t\t\tconst peers = d\n\t\t\t\t\t.select({\n\t\t\t\t\t\tpeer_device_id: schema.syncPeers.peer_device_id,\n\t\t\t\t\t\tname: schema.syncPeers.name,\n\t\t\t\t\t\taddresses: schema.syncPeers.addresses_json,\n\t\t\t\t\t\tlast_sync_at: schema.syncPeers.last_sync_at,\n\t\t\t\t\t\tlast_error: schema.syncPeers.last_error,\n\t\t\t\t\t})\n\t\t\t\t\t.from(schema.syncPeers)\n\t\t\t\t\t.orderBy(desc(schema.syncPeers.last_sync_at))\n\t\t\t\t\t.all();\n\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify(peers, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tp.intro(\"codemem sync peers\");\n\t\t\t\tif (peers.length === 0) {\n\t\t\t\t\tp.outro(\"No peers configured\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfor (const peer of peers) {\n\t\t\t\t\tconst label = peer.name || peer.peer_device_id;\n\t\t\t\t\tconst addrs = peer.addresses || \"(no addresses)\";\n\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t`${label}\\n addresses: ${addrs}\\n last_sync: ${peer.last_sync_at ?? \"never\"}\\n status: ${peer.last_error ?? \"ok\"}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tp.outro(`${peers.length} peer(s)`);\n\t\t\t} finally {\n\t\t\t\tstore.close();\n\t\t\t}\n\t\t}),\n);\n\n// codemem sync connect <coordinator-url>\nsyncCommand.addCommand(\n\tnew Command(\"connect\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Configure coordinator URL for cloud sync\")\n\t\t.argument(\"<url>\", \"coordinator URL (e.g. https://coordinator.example.com)\")\n\t\t.option(\"--group <group>\", \"sync group ID\")\n\t\t.action((url: string, opts: { group?: string }) => {\n\t\t\tconst config = readCodememConfigFile();\n\t\t\tconfig.sync_coordinator_url = url.trim();\n\t\t\tif (opts.group) config.sync_coordinator_group = opts.group.trim();\n\t\t\twriteCodememConfigFile(config);\n\t\t\tp.intro(\"codemem sync connect\");\n\t\t\tp.log.success(`Coordinator: ${url.trim()}`);\n\t\t\tif (opts.group) p.log.info(`Group: ${opts.group.trim()}`);\n\t\t\tp.outro(\"Restart `codemem serve` to activate coordinator sync\");\n\t\t}),\n);\n","import { VERSION } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nexport const versionCommand = new Command(\"version\")\n\t.configureHelp(helpStyle)\n\t.description(\"Print codemem version\")\n\t.action(() => {\n\t\tconsole.log(VERSION);\n\t});\n","#!/usr/bin/env node\n\n/**\n * @codemem/cli — CLI entry point.\n *\n * Commands:\n * codemem stats → database statistics\n * codemem search → FTS5 memory search\n * codemem pack → context-aware memory pack\n * codemem serve → viewer server\n * codemem mcp → MCP stdio server\n */\n\nimport { VERSION } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport omelette from \"omelette\";\nimport { claudeHookIngestCommand } from \"./commands/claude-hook-ingest.js\";\nimport { dbCommand } from \"./commands/db.js\";\nimport { enqueueRawEventCommand } from \"./commands/enqueue-raw-event.js\";\nimport { exportMemoriesCommand } from \"./commands/export-memories.js\";\nimport { importMemoriesCommand } from \"./commands/import-memories.js\";\nimport { mcpCommand } from \"./commands/mcp.js\";\nimport { memoryCommand } from \"./commands/memory.js\";\nimport { packCommand } from \"./commands/pack.js\";\nimport { recentCommand } from \"./commands/recent.js\";\nimport { searchCommand } from \"./commands/search.js\";\nimport { serveCommand } from \"./commands/serve.js\";\nimport { setupCommand } from \"./commands/setup.js\";\nimport { statsCommand } from \"./commands/stats.js\";\nimport { syncCommand } from \"./commands/sync.js\";\nimport { versionCommand } from \"./commands/version.js\";\nimport { helpStyle } from \"./help-style.js\";\n\n// Shell completion (bash/zsh/fish)\nconst completion = omelette(\"codemem <command>\");\ncompletion.on(\"command\", ({ reply }) => {\n\treply([\n\t\t\"claude-hook-ingest\",\n\t\t\"db\",\n\t\t\"export-memories\",\n\t\t\"memory\",\n\t\t\"import-memories\",\n\t\t\"setup\",\n\t\t\"sync\",\n\t\t\"stats\",\n\t\t\"recent\",\n\t\t\"search\",\n\t\t\"pack\",\n\t\t\"serve\",\n\t\t\"mcp\",\n\t\t\"enqueue-raw-event\",\n\t\t\"version\",\n\t\t\"help\",\n\t\t\"--help\",\n\t\t\"--version\",\n\t]);\n});\ncompletion.init();\n\n// `codemem --setup-completion` installs shell completion\nif (process.argv.includes(\"--setup-completion\")) {\n\tcompletion.setupShellInitFile();\n\tprocess.exit(0);\n}\n// `codemem --cleanup-completion` removes it\nif (process.argv.includes(\"--cleanup-completion\")) {\n\tcompletion.cleanupShellInitFile();\n\tprocess.exit(0);\n}\n\nconst program = new Command();\n\nprogram\n\t.name(\"codemem\")\n\t.description(\"codemem — persistent memory for AI coding agents\")\n\t.version(VERSION)\n\t.configureHelp(helpStyle);\n\nprogram.addCommand(serveCommand);\nprogram.addCommand(mcpCommand);\nprogram.addCommand(claudeHookIngestCommand);\nprogram.addCommand(dbCommand);\nprogram.addCommand(exportMemoriesCommand);\nprogram.addCommand(importMemoriesCommand);\nprogram.addCommand(statsCommand);\nprogram.addCommand(recentCommand);\nprogram.addCommand(searchCommand);\nprogram.addCommand(packCommand);\nprogram.addCommand(memoryCommand);\nprogram.addCommand(syncCommand);\nprogram.addCommand(setupCommand);\nprogram.addCommand(enqueueRawEventCommand);\nprogram.addCommand(versionCommand);\n\nprogram.parse();\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/help-style.ts","../src/commands/claude-hook-ingest.ts","../src/commands/db.ts","../src/commands/enqueue-raw-event.ts","../src/commands/export-memories.ts","../src/commands/import-memories.ts","../src/commands/mcp.ts","../src/commands/memory.ts","../src/commands/pack.ts","../src/commands/recent.ts","../src/commands/search.ts","../src/commands/serve.ts","../src/commands/setup.ts","../src/commands/stats.ts","../src/commands/sync.ts","../src/commands/version.ts","../src/index.ts"],"sourcesContent":["/**\n * Shared Commander help style configuration.\n *\n * Applied to every Command instance so subcommand --help\n * output gets the same colors as the root.\n */\n\nimport { styleText } from \"node:util\";\nimport type { HelpConfiguration } from \"commander\";\n\nexport const helpStyle: HelpConfiguration = {\n\tstyleTitle: (str) => styleText(\"bold\", str),\n\tstyleCommandText: (str) => styleText(\"cyan\", str),\n\tstyleCommandDescription: (str) => str,\n\tstyleDescriptionText: (str) => styleText(\"dim\", str),\n\tstyleOptionText: (str) => styleText(\"green\", str),\n\tstyleOptionTerm: (str) => styleText(\"green\", str),\n\tstyleSubcommandText: (str) => styleText(\"cyan\", str),\n\tstyleArgumentText: (str) => styleText(\"yellow\", str),\n};\n","/**\n * codemem claude-hook-ingest — read a single Claude Code hook payload\n * from stdin and enqueue it for processing.\n *\n * Ports codemem/commands/claude_hook_runtime_cmds.py with an HTTP-first\n * strategy: try POST /api/claude-hooks (viewer must be running), then\n * fall back to direct raw-event enqueue via the local store.\n *\n * Usage (from Claude hooks config):\n * echo '{\"hook_event_name\":\"Stop\",\"session_id\":\"...\",\"last_assistant_message\":\"...\"}' \\\n * | codemem claude-hook-ingest\n */\n\nimport { readFileSync } from \"node:fs\";\nimport {\n\tbuildRawEventEnvelopeFromHook,\n\tconnect,\n\tloadSqliteVec,\n\tresolveDbPath,\n\tstripPrivateObj,\n} from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\n/** Try to POST the hook payload to the running viewer server. */\nasync function tryHttpIngest(\n\tpayload: Record<string, unknown>,\n\thost: string,\n\tport: number,\n): Promise<{ ok: boolean; inserted: number; skipped: number }> {\n\tconst url = `http://${host}:${port}/api/claude-hooks`;\n\tconst controller = new AbortController();\n\tconst timeout = setTimeout(() => controller.abort(), 5000);\n\ttry {\n\t\tconst res = await fetch(url, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify(payload),\n\t\t\tsignal: controller.signal,\n\t\t});\n\t\tif (!res.ok) return { ok: false, inserted: 0, skipped: 0 };\n\t\tconst body = (await res.json()) as Record<string, unknown>;\n\t\treturn {\n\t\t\tok: true,\n\t\t\tinserted: Number(body.inserted ?? 0),\n\t\t\tskipped: Number(body.skipped ?? 0),\n\t\t};\n\t} catch {\n\t\treturn { ok: false, inserted: 0, skipped: 0 };\n\t} finally {\n\t\tclearTimeout(timeout);\n\t}\n}\n\n/** Fall back to direct raw-event enqueue via the local SQLite store. */\nfunction directEnqueue(\n\tpayload: Record<string, unknown>,\n\tdbPath: string,\n): { inserted: number; skipped: number } {\n\tconst envelope = buildRawEventEnvelopeFromHook(payload);\n\tif (!envelope) return { inserted: 0, skipped: 1 };\n\n\tconst db = connect(dbPath);\n\ttry {\n\t\ttry {\n\t\t\tloadSqliteVec(db);\n\t\t} catch {\n\t\t\t// sqlite-vec not available — non-fatal for raw event enqueue\n\t\t}\n\t\tconst strippedPayload = stripPrivateObj(envelope.payload) as Record<string, unknown>;\n\t\tconst existing = db\n\t\t\t.prepare(\n\t\t\t\t\"SELECT 1 FROM raw_events WHERE source = ? AND stream_id = ? AND event_id = ? LIMIT 1\",\n\t\t\t)\n\t\t\t.get(envelope.source, envelope.session_stream_id, envelope.event_id);\n\t\tif (existing) return { inserted: 0, skipped: 0 };\n\n\t\tdb.prepare(\n\t\t\t`INSERT INTO raw_events(\n\t\t\t\tsource, stream_id, opencode_session_id, event_id, event_seq,\n\t\t\t\tevent_type, ts_wall_ms, payload_json, created_at\n\t\t\t) VALUES (?, ?, ?, ?, (\n\t\t\t\tSELECT COALESCE(MAX(event_seq), 0) + 1\n\t\t\t\tFROM raw_events WHERE source = ? AND stream_id = ?\n\t\t\t), ?, ?, ?, datetime('now'))`,\n\t\t).run(\n\t\t\tenvelope.source,\n\t\t\tenvelope.session_stream_id,\n\t\t\tenvelope.opencode_session_id,\n\t\t\tenvelope.event_id,\n\t\t\tenvelope.source,\n\t\t\tenvelope.session_stream_id,\n\t\t\t\"claude.hook\",\n\t\t\tenvelope.ts_wall_ms,\n\t\t\tJSON.stringify(strippedPayload),\n\t\t);\n\n\t\t// Query actual max event_seq for this stream to keep session metadata in sync\n\t\tconst maxSeqRow = db\n\t\t\t.prepare(\n\t\t\t\t\"SELECT COALESCE(MAX(event_seq), 0) AS max_seq FROM raw_events WHERE source = ? AND stream_id = ?\",\n\t\t\t)\n\t\t\t.get(envelope.source, envelope.session_stream_id) as { max_seq: number };\n\t\tconst currentMaxSeq = maxSeqRow.max_seq;\n\n\t\t// Upsert session metadata with accurate sequence tracking\n\t\tdb.prepare(\n\t\t\t`INSERT INTO raw_event_sessions(\n\t\t\t\tsource, stream_id, opencode_session_id, cwd, project, started_at,\n\t\t\t\tlast_seen_ts_wall_ms, last_received_event_seq, last_flushed_event_seq, updated_at\n\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, -1, datetime('now'))\n\t\t\tON CONFLICT(source, stream_id) DO UPDATE SET\n\t\t\t\tcwd = COALESCE(excluded.cwd, cwd),\n\t\t\t\tproject = COALESCE(excluded.project, project),\n\t\t\t\tstarted_at = COALESCE(excluded.started_at, started_at),\n\t\t\t\tlast_seen_ts_wall_ms = MAX(COALESCE(excluded.last_seen_ts_wall_ms, 0), COALESCE(last_seen_ts_wall_ms, 0)),\n\t\t\t\tlast_received_event_seq = MAX(excluded.last_received_event_seq, last_received_event_seq),\n\t\t\t\tupdated_at = datetime('now')`,\n\t\t).run(\n\t\t\tenvelope.source,\n\t\t\tenvelope.session_stream_id,\n\t\t\tenvelope.opencode_session_id,\n\t\t\tenvelope.cwd,\n\t\t\tenvelope.project,\n\t\t\tenvelope.started_at,\n\t\t\tenvelope.ts_wall_ms,\n\t\t\tcurrentMaxSeq,\n\t\t);\n\n\t\treturn { inserted: 1, skipped: 0 };\n\t} finally {\n\t\tdb.close();\n\t}\n}\n\nexport const claudeHookIngestCommand = new Command(\"claude-hook-ingest\")\n\t.configureHelp(helpStyle)\n\t.description(\"Ingest a Claude Code hook payload from stdin\")\n\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.option(\"--host <host>\", \"viewer server host\", \"127.0.0.1\")\n\t.option(\"--port <port>\", \"viewer server port\", \"38888\")\n\t.action(async (opts: { db?: string; host: string; port: string }) => {\n\t\t// Read payload from stdin\n\t\tlet raw: string;\n\t\ttry {\n\t\t\traw = readFileSync(0, \"utf8\").trim();\n\t\t} catch {\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\t\tif (!raw) {\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\n\t\tlet payload: Record<string, unknown>;\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(raw) as unknown;\n\t\t\tif (parsed == null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tpayload = parsed as Record<string, unknown>;\n\t\t} catch {\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\n\t\tconst port = Number.parseInt(opts.port, 10);\n\t\tconst host = opts.host;\n\n\t\t// Strategy 1: try HTTP POST to running viewer\n\t\tconst httpResult = await tryHttpIngest(payload, host, port);\n\t\tif (httpResult.ok) {\n\t\t\tconsole.log(\n\t\t\t\tJSON.stringify({ inserted: httpResult.inserted, skipped: httpResult.skipped, via: \"http\" }),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// Strategy 2: direct local enqueue\n\t\ttry {\n\t\t\tconst dbPath = resolveDbPath(opts.db);\n\t\t\tconst directResult = directEnqueue(payload, dbPath);\n\t\t\tconsole.log(JSON.stringify({ ...directResult, via: \"direct\" }));\n\t\t} catch {\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\t});\n","import * as p from \"@clack/prompts\";\nimport {\n\tgetRawEventStatus,\n\tinitDatabase,\n\trawEventsGate,\n\tretryRawEventFailures,\n\tvacuumDatabase,\n} from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nexport const dbCommand = new Command(\"db\")\n\t.configureHelp(helpStyle)\n\t.description(\"Database maintenance\");\n\ndbCommand\n\t.addCommand(\n\t\tnew Command(\"init\")\n\t\t\t.configureHelp(helpStyle)\n\t\t\t.description(\"Verify the SQLite database is present and schema-ready\")\n\t\t\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t\t.action((opts: { db?: string }) => {\n\t\t\t\tconst result = initDatabase(opts.db);\n\t\t\t\tp.intro(\"codemem db init\");\n\t\t\t\tp.log.success(`Database ready: ${result.path}`);\n\t\t\t\tp.outro(`Size: ${result.sizeBytes.toLocaleString()} bytes`);\n\t\t\t}),\n\t)\n\t.addCommand(\n\t\tnew Command(\"vacuum\")\n\t\t\t.configureHelp(helpStyle)\n\t\t\t.description(\"Run VACUUM on the SQLite database\")\n\t\t\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t\t.action((opts: { db?: string }) => {\n\t\t\t\tconst result = vacuumDatabase(opts.db);\n\t\t\t\tp.intro(\"codemem db vacuum\");\n\t\t\t\tp.log.success(`Vacuumed: ${result.path}`);\n\t\t\t\tp.outro(`Size: ${result.sizeBytes.toLocaleString()} bytes`);\n\t\t\t}),\n\t)\n\t.addCommand(\n\t\tnew Command(\"raw-events-status\")\n\t\t\t.configureHelp(helpStyle)\n\t\t\t.description(\"Show pending raw-event backlog by source stream\")\n\t\t\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t\t.option(\"-n, --limit <n>\", \"max rows to show\", \"25\")\n\t\t\t.option(\"--json\", \"output as JSON\")\n\t\t\t.action((opts: { db?: string; limit: string; json?: boolean }) => {\n\t\t\t\tconst result = getRawEventStatus(opts.db, Number.parseInt(opts.limit, 10) || 25);\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.intro(\"codemem db raw-events-status\");\n\t\t\t\tp.log.info(\n\t\t\t\t\t`Totals: ${result.totals.pending.toLocaleString()} pending across ${result.totals.sessions.toLocaleString()} session(s)`,\n\t\t\t\t);\n\t\t\t\tif (result.items.length === 0) {\n\t\t\t\t\tp.outro(\"No pending raw events\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfor (const item of result.items) {\n\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t`${item.source}:${item.stream_id} pending=${Math.max(0, item.last_received_event_seq - item.last_flushed_event_seq)} ` +\n\t\t\t\t\t\t\t`received=${item.last_received_event_seq} flushed=${item.last_flushed_event_seq} project=${item.project ?? \"\"}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tp.outro(\"done\");\n\t\t\t}),\n\t)\n\t.addCommand(\n\t\tnew Command(\"raw-events-retry\")\n\t\t\t.configureHelp(helpStyle)\n\t\t\t.description(\"Requeue failed raw-event flush batches\")\n\t\t\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t\t.option(\"-n, --limit <n>\", \"max failed batches to requeue\", \"25\")\n\t\t\t.action((opts: { db?: string; limit: string }) => {\n\t\t\t\tconst result = retryRawEventFailures(opts.db, Number.parseInt(opts.limit, 10) || 25);\n\t\t\t\tp.intro(\"codemem db raw-events-retry\");\n\t\t\t\tp.outro(`Requeued ${result.retried.toLocaleString()} failed batch(es)`);\n\t\t\t}),\n\t)\n\t.addCommand(\n\t\tnew Command(\"raw-events-gate\")\n\t\t\t.configureHelp(helpStyle)\n\t\t\t.description(\"Validate raw-event reliability thresholds (non-zero exit on failure)\")\n\t\t\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t\t.option(\"--min-flush-success-rate <rate>\", \"minimum flush success rate\", \"0.95\")\n\t\t\t.option(\"--max-dropped-event-rate <rate>\", \"maximum dropped event rate\", \"0.05\")\n\t\t\t.option(\"--min-session-boundary-accuracy <rate>\", \"minimum session boundary accuracy\", \"0.9\")\n\t\t\t.option(\"--window-hours <hours>\", \"lookback window in hours\", \"24\")\n\t\t\t.option(\"--json\", \"output as JSON\")\n\t\t\t.action(\n\t\t\t\t(opts: {\n\t\t\t\t\tdb?: string;\n\t\t\t\t\tminFlushSuccessRate: string;\n\t\t\t\t\tmaxDroppedEventRate: string;\n\t\t\t\t\tminSessionBoundaryAccuracy: string;\n\t\t\t\t\twindowHours: string;\n\t\t\t\t\tjson?: boolean;\n\t\t\t\t}) => {\n\t\t\t\t\tconst result = rawEventsGate(opts.db, {\n\t\t\t\t\t\tminFlushSuccessRate: Number.parseFloat(opts.minFlushSuccessRate),\n\t\t\t\t\t\tmaxDroppedEventRate: Number.parseFloat(opts.maxDroppedEventRate),\n\t\t\t\t\t\tminSessionBoundaryAccuracy: Number.parseFloat(opts.minSessionBoundaryAccuracy),\n\t\t\t\t\t\twindowHours: Number.parseFloat(opts.windowHours),\n\t\t\t\t\t});\n\n\t\t\t\t\tif (opts.json) {\n\t\t\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\t\t\tif (!result.passed) process.exitCode = 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tp.intro(\"codemem db raw-events-gate\");\n\t\t\t\t\tp.log.info(\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t`flush_success_rate: ${result.metrics.rates.flush_success_rate.toFixed(4)}`,\n\t\t\t\t\t\t\t`dropped_event_rate: ${result.metrics.rates.dropped_event_rate.toFixed(4)}`,\n\t\t\t\t\t\t\t`session_boundary_accuracy: ${result.metrics.rates.session_boundary_accuracy.toFixed(4)}`,\n\t\t\t\t\t\t\t`window_hours: ${result.metrics.window_hours ?? \"all\"}`,\n\t\t\t\t\t\t].join(\"\\n\"),\n\t\t\t\t\t);\n\n\t\t\t\t\tif (result.passed) {\n\t\t\t\t\t\tp.outro(\"reliability gate passed\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor (const f of result.failures) {\n\t\t\t\t\t\t\tp.log.error(f);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tp.outro(\"reliability gate FAILED\");\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t),\n\t);\n","import { MemoryStore, resolveDbPath, stripPrivateObj } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nconst SESSION_ID_KEYS = [\n\t\"session_stream_id\",\n\t\"session_id\",\n\t\"stream_id\",\n\t\"opencode_session_id\",\n] as const;\n\nfunction resolveSessionStreamId(payload: Record<string, unknown>): string | null {\n\tconst values = new Map<string, string>();\n\tfor (const key of SESSION_ID_KEYS) {\n\t\tconst value = payload[key];\n\t\tif (typeof value !== \"string\") continue;\n\t\tconst text = value.trim();\n\t\tif (text) values.set(key, text);\n\t}\n\tif (values.size === 0) return null;\n\tconst unique = new Set(values.values());\n\tif (unique.size > 1) throw new Error(\"conflicting session id fields\");\n\tfor (const key of SESSION_ID_KEYS) {\n\t\tconst value = values.get(key);\n\t\tif (value) return value;\n\t}\n\treturn null;\n}\n\nasync function readStdinJson(): Promise<Record<string, unknown>> {\n\tconst chunks: Buffer[] = [];\n\tfor await (const chunk of process.stdin) {\n\t\tchunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));\n\t}\n\tconst raw = Buffer.concat(chunks).toString(\"utf-8\").trim();\n\tif (!raw) throw new Error(\"stdin JSON required\");\n\tconst parsed = JSON.parse(raw) as unknown;\n\tif (parsed == null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(\"payload must be an object\");\n\t}\n\treturn parsed as Record<string, unknown>;\n}\n\nexport const enqueueRawEventCommand = new Command(\"enqueue-raw-event\")\n\t.configureHelp(helpStyle)\n\t.description(\"Enqueue one raw event from stdin into the durable queue\")\n\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.action(async (opts: { db?: string }) => {\n\t\tconst payload = await readStdinJson();\n\t\tconst sessionId = resolveSessionStreamId(payload);\n\t\tif (!sessionId) throw new Error(\"session id required\");\n\t\tif (sessionId.startsWith(\"msg_\")) throw new Error(\"invalid session id\");\n\n\t\tconst eventType = typeof payload.event_type === \"string\" ? payload.event_type.trim() : \"\";\n\t\tif (!eventType) throw new Error(\"event_type required\");\n\n\t\tconst cwd = typeof payload.cwd === \"string\" ? payload.cwd : null;\n\t\tconst project = typeof payload.project === \"string\" ? payload.project : null;\n\t\tconst startedAt = typeof payload.started_at === \"string\" ? payload.started_at : null;\n\t\tconst tsWallMs = Number.isFinite(Number(payload.ts_wall_ms))\n\t\t\t? Math.floor(Number(payload.ts_wall_ms))\n\t\t\t: null;\n\t\tconst tsMonoMs = Number.isFinite(Number(payload.ts_mono_ms))\n\t\t\t? Number(payload.ts_mono_ms)\n\t\t\t: null;\n\t\tconst eventId = typeof payload.event_id === \"string\" ? payload.event_id.trim() : \"\";\n\t\tconst eventPayload =\n\t\t\tpayload.payload && typeof payload.payload === \"object\" && !Array.isArray(payload.payload)\n\t\t\t\t? (stripPrivateObj(payload.payload) as Record<string, unknown>)\n\t\t\t\t: {};\n\n\t\tconst store = new MemoryStore(resolveDbPath(opts.db));\n\t\ttry {\n\t\t\tstore.updateRawEventSessionMeta({\n\t\t\t\topencodeSessionId: sessionId,\n\t\t\t\tsource: \"opencode\",\n\t\t\t\tcwd,\n\t\t\t\tproject,\n\t\t\t\tstartedAt,\n\t\t\t\tlastSeenTsWallMs: tsWallMs,\n\t\t\t});\n\t\t\tstore.recordRawEventsBatch(sessionId, [\n\t\t\t\t{\n\t\t\t\t\tevent_id: eventId,\n\t\t\t\t\tevent_type: eventType,\n\t\t\t\t\tpayload: eventPayload,\n\t\t\t\t\tts_wall_ms: tsWallMs,\n\t\t\t\t\tts_mono_ms: tsMonoMs,\n\t\t\t\t},\n\t\t\t]);\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t});\n","import { writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { exportMemories, resolveDbPath } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nfunction expandUserPath(value: string): string {\n\treturn value.startsWith(\"~/\") ? join(homedir(), value.slice(2)) : value;\n}\n\nexport const exportMemoriesCommand = new Command(\"export-memories\")\n\t.configureHelp(helpStyle)\n\t.description(\"Export memories to a JSON file for sharing or backup\")\n\t.argument(\"<output>\", \"output file path (use '-' for stdout)\")\n\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.option(\"--project <project>\", \"filter by project (defaults to git repo root)\")\n\t.option(\"--all-projects\", \"export all projects\")\n\t.option(\"--include-inactive\", \"include deactivated memories\")\n\t.option(\"--since <iso>\", \"only export memories created after this ISO timestamp\")\n\t.action(\n\t\t(\n\t\t\toutput: string,\n\t\t\topts: {\n\t\t\t\tdb?: string;\n\t\t\t\tproject?: string;\n\t\t\t\tallProjects?: boolean;\n\t\t\t\tincludeInactive?: boolean;\n\t\t\t\tsince?: string;\n\t\t\t},\n\t\t) => {\n\t\t\tconst payload = exportMemories({\n\t\t\t\tdbPath: resolveDbPath(opts.db),\n\t\t\t\tproject: opts.project,\n\t\t\t\tallProjects: opts.allProjects,\n\t\t\t\tincludeInactive: opts.includeInactive,\n\t\t\t\tsince: opts.since,\n\t\t\t});\n\t\t\tconst text = `${JSON.stringify(payload, null, 2)}\\n`;\n\t\t\tif (output === \"-\") {\n\t\t\t\tprocess.stdout.write(text);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst outputPath = expandUserPath(output);\n\t\t\twriteFileSync(outputPath, text, \"utf8\");\n\t\t\tp.intro(\"codemem export-memories\");\n\t\t\tp.log.success(\n\t\t\t\t[\n\t\t\t\t\t`Output: ${outputPath}`,\n\t\t\t\t\t`Sessions: ${payload.sessions.length.toLocaleString()}`,\n\t\t\t\t\t`Memories: ${payload.memory_items.length.toLocaleString()}`,\n\t\t\t\t\t`Summaries: ${payload.session_summaries.length.toLocaleString()}`,\n\t\t\t\t\t`Prompts: ${payload.user_prompts.length.toLocaleString()}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t);\n\t\t\tp.outro(\"done\");\n\t\t},\n\t);\n","import * as p from \"@clack/prompts\";\nimport type { ExportPayload } from \"@codemem/core\";\nimport { importMemories, readImportPayload, resolveDbPath } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nexport const importMemoriesCommand = new Command(\"import-memories\")\n\t.configureHelp(helpStyle)\n\t.description(\"Import memories from an exported JSON file\")\n\t.argument(\"<inputFile>\", \"input JSON file (use '-' for stdin)\")\n\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.option(\"--remap-project <path>\", \"remap all projects to this path on import\")\n\t.option(\"--dry-run\", \"preview import without writing\")\n\t.action((inputFile: string, opts: { db?: string; remapProject?: string; dryRun?: boolean }) => {\n\t\tlet payload: ExportPayload;\n\t\ttry {\n\t\t\tpayload = readImportPayload(inputFile);\n\t\t} catch (error) {\n\t\t\tp.log.error(error instanceof Error ? error.message : \"Invalid import file\");\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\n\t\tp.intro(\"codemem import-memories\");\n\t\tp.log.info(\n\t\t\t[\n\t\t\t\t`Export version: ${payload.version}`,\n\t\t\t\t`Exported at: ${payload.exported_at}`,\n\t\t\t\t`Sessions: ${payload.sessions.length.toLocaleString()}`,\n\t\t\t\t`Memories: ${payload.memory_items.length.toLocaleString()}`,\n\t\t\t\t`Summaries: ${payload.session_summaries.length.toLocaleString()}`,\n\t\t\t\t`Prompts: ${payload.user_prompts.length.toLocaleString()}`,\n\t\t\t].join(\"\\n\"),\n\t\t);\n\n\t\tconst result = importMemories(payload, {\n\t\t\tdbPath: resolveDbPath(opts.db),\n\t\t\tremapProject: opts.remapProject,\n\t\t\tdryRun: opts.dryRun,\n\t\t});\n\n\t\tif (result.dryRun) {\n\t\t\tp.outro(\"dry run complete\");\n\t\t\treturn;\n\t\t}\n\t\tp.log.success(\n\t\t\t[\n\t\t\t\t`Imported sessions: ${result.sessions.toLocaleString()}`,\n\t\t\t\t`Imported prompts: ${result.user_prompts.toLocaleString()}`,\n\t\t\t\t`Imported memories: ${result.memory_items.toLocaleString()}`,\n\t\t\t\t`Imported summaries: ${result.session_summaries.toLocaleString()}`,\n\t\t\t].join(\"\\n\"),\n\t\t);\n\t\tp.outro(\"done\");\n\t});\n","import { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nexport const mcpCommand = new Command(\"mcp\")\n\t.configureHelp(helpStyle)\n\t.description(\"Start the MCP stdio server\")\n\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.action(async (opts: { db?: string }) => {\n\t\tif (opts.db) process.env.CODEMEM_DB = opts.db;\n\t\t// Dynamic import — MCP server is its own entry point\n\t\tawait import(\"@codemem/mcp\");\n\t});\n","/**\n * Memory management CLI commands — show, forget, remember.\n *\n * Ports codemem/commands/memory_cmds.py (show_cmd, forget_cmd, remember_cmd).\n * Compact and inject are deferred — compact requires the summarizer pipeline,\n * and inject is just pack_text output which the existing pack command covers.\n */\n\nimport * as p from \"@clack/prompts\";\nimport { MemoryStore, resolveDbPath, resolveProject } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\n/** Parse a strict positive integer, rejecting prefixes like \"12abc\". */\nfunction parseStrictPositiveId(value: string): number | null {\n\tif (!/^\\d+$/.test(value.trim())) return null;\n\tconst n = Number(value.trim());\n\treturn Number.isFinite(n) && n >= 1 && Number.isInteger(n) ? n : null;\n}\n\nexport const memoryCommand = new Command(\"memory\")\n\t.configureHelp(helpStyle)\n\t.description(\"Memory item management\");\n\n// codemem memory show <id>\nmemoryCommand.addCommand(\n\tnew Command(\"show\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Print a memory item as JSON\")\n\t\t.argument(\"<id>\", \"memory ID\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.action((idStr: string, opts: { db?: string }) => {\n\t\t\tconst memoryId = parseStrictPositiveId(idStr);\n\t\t\tif (memoryId === null) {\n\t\t\t\tp.log.error(`Invalid memory ID: ${idStr}`);\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db));\n\t\t\ttry {\n\t\t\t\tconst item = store.get(memoryId);\n\t\t\t\tif (!item) {\n\t\t\t\t\tp.log.error(`Memory ${memoryId} not found`);\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconsole.log(JSON.stringify(item, null, 2));\n\t\t\t} finally {\n\t\t\t\tstore.close();\n\t\t\t}\n\t\t}),\n);\n\n// codemem memory forget <id>\nmemoryCommand.addCommand(\n\tnew Command(\"forget\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Deactivate a memory item\")\n\t\t.argument(\"<id>\", \"memory ID\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.action((idStr: string, opts: { db?: string }) => {\n\t\t\tconst memoryId = parseStrictPositiveId(idStr);\n\t\t\tif (memoryId === null) {\n\t\t\t\tp.log.error(`Invalid memory ID: ${idStr}`);\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db));\n\t\t\ttry {\n\t\t\t\tstore.forget(memoryId);\n\t\t\t\tp.log.success(`Memory ${memoryId} marked inactive`);\n\t\t\t} finally {\n\t\t\t\tstore.close();\n\t\t\t}\n\t\t}),\n);\n\n// codemem memory remember --kind <kind> --title <title> --body <body>\nmemoryCommand.addCommand(\n\tnew Command(\"remember\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Manually add a memory item\")\n\t\t.requiredOption(\"-k, --kind <kind>\", \"memory kind (discovery, decision, feature, bugfix, etc.)\")\n\t\t.requiredOption(\"-t, --title <title>\", \"memory title\")\n\t\t.requiredOption(\"-b, --body <body>\", \"memory body text\")\n\t\t.option(\"--tags <tags...>\", \"tags (space-separated)\")\n\t\t.option(\"--project <project>\", \"project name (defaults to git repo root)\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.action(\n\t\t\t(opts: {\n\t\t\t\tkind: string;\n\t\t\t\ttitle: string;\n\t\t\t\tbody: string;\n\t\t\t\ttags?: string[];\n\t\t\t\tproject?: string;\n\t\t\t\tdb?: string;\n\t\t\t}) => {\n\t\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db));\n\t\t\t\tlet sessionId: number | null = null;\n\t\t\t\ttry {\n\t\t\t\t\tconst project = resolveProject(process.cwd(), opts.project ?? null);\n\t\t\t\t\tsessionId = store.startSession({\n\t\t\t\t\t\tcwd: process.cwd(),\n\t\t\t\t\t\tproject,\n\t\t\t\t\t\tuser: process.env.USER ?? \"unknown\",\n\t\t\t\t\t\ttoolVersion: \"manual\",\n\t\t\t\t\t\tmetadata: { manual: true },\n\t\t\t\t\t});\n\t\t\t\t\tconst memId = store.remember(sessionId, opts.kind, opts.title, opts.body, 0.5, opts.tags);\n\t\t\t\t\tstore.endSession(sessionId, { manual: true });\n\t\t\t\t\tp.log.success(`Stored memory ${memId}`);\n\t\t\t\t} catch (err) {\n\t\t\t\t\t// Always close the session even if remember() throws (e.g. invalid kind)\n\t\t\t\t\tif (sessionId !== null) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tstore.endSession(sessionId, { manual: true, error: true });\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// ignore — already in error path\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthrow err;\n\t\t\t\t} finally {\n\t\t\t\t\tstore.close();\n\t\t\t\t}\n\t\t\t},\n\t\t),\n);\n","import * as p from \"@clack/prompts\";\nimport { MemoryStore, resolveDbPath } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nexport const packCommand = new Command(\"pack\")\n\t.configureHelp(helpStyle)\n\t.description(\"Build a context-aware memory pack\")\n\t.argument(\"<context>\", \"context string to search for\")\n\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.option(\"-n, --limit <n>\", \"max items\", \"10\")\n\t.option(\"--budget <tokens>\", \"token budget\")\n\t.option(\"--json\", \"output as JSON\")\n\t.action(\n\t\t(context: string, opts: { db?: string; limit: string; budget?: string; json?: boolean }) => {\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db));\n\t\t\ttry {\n\t\t\t\tconst limit = Number.parseInt(opts.limit, 10) || 10;\n\t\t\t\tconst budget = opts.budget ? Number.parseInt(opts.budget, 10) : undefined;\n\t\t\t\tconst result = store.buildMemoryPack(context, limit, budget);\n\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tp.intro(`Memory pack for \"${context}\"`);\n\n\t\t\t\tif (result.items.length === 0) {\n\t\t\t\t\tp.log.warn(\"No relevant memories found.\");\n\t\t\t\t\tp.outro(\"done\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst m = result.metrics;\n\t\t\t\tp.log.info(\n\t\t\t\t\t`${m.total_items} items, ~${m.pack_tokens} tokens` +\n\t\t\t\t\t\t(m.fallback_used ? \" (fallback)\" : \"\") +\n\t\t\t\t\t\t` [fts:${m.sources.fts} sem:${m.sources.semantic} fuzzy:${m.sources.fuzzy}]`,\n\t\t\t\t);\n\n\t\t\t\tfor (const item of result.items) {\n\t\t\t\t\tp.log.step(`#${item.id} ${item.kind} ${item.title}`);\n\t\t\t\t}\n\n\t\t\t\tp.note(result.pack_text, \"pack_text\");\n\n\t\t\t\tp.outro(\"done\");\n\t\t\t} finally {\n\t\t\t\tstore.close();\n\t\t\t}\n\t\t},\n\t);\n","import { MemoryStore, resolveDbPath } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nexport const recentCommand = new Command(\"recent\")\n\t.configureHelp(helpStyle)\n\t.description(\"Show recent memories\")\n\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.option(\"--limit <n>\", \"max results\", \"5\")\n\t.option(\"--kind <kind>\", \"filter by memory kind\")\n\t.action((opts: { db?: string; limit: string; kind?: string }) => {\n\t\tconst store = new MemoryStore(resolveDbPath(opts.db));\n\t\ttry {\n\t\t\tconst limit = Math.max(1, Number.parseInt(opts.limit, 10) || 5);\n\t\t\tconst filters = opts.kind ? { kind: opts.kind } : undefined;\n\t\t\tconst items = store.recent(limit, filters);\n\t\t\tfor (const item of items) {\n\t\t\t\tconsole.log(`#${item.id} [${item.kind}] ${item.title}`);\n\t\t\t}\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t});\n","import * as p from \"@clack/prompts\";\nimport { MemoryStore, resolveDbPath } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nexport const searchCommand = new Command(\"search\")\n\t.configureHelp(helpStyle)\n\t.description(\"Search memories by query\")\n\t.argument(\"<query>\", \"search query\")\n\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.option(\"-n, --limit <n>\", \"max results\", \"10\")\n\t.option(\"--kind <kind>\", \"filter by memory kind\")\n\t.option(\"--json\", \"output as JSON\")\n\t.action((query: string, opts: { db?: string; limit: string; kind?: string; json?: boolean }) => {\n\t\tconst store = new MemoryStore(resolveDbPath(opts.db));\n\t\ttry {\n\t\t\tconst limit = Number.parseInt(opts.limit, 10) || 10;\n\t\t\tconst filters = opts.kind ? { kind: opts.kind } : undefined;\n\t\t\tconst results = store.search(query, limit, filters);\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(results, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (results.length === 0) {\n\t\t\t\tp.log.warn(\"No results found.\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tp.intro(`${results.length} result(s) for \"${query}\"`);\n\n\t\t\tfor (const item of results) {\n\t\t\t\tconst score = item.score.toFixed(3);\n\t\t\t\tconst age = timeSince(item.created_at);\n\t\t\t\tconst preview =\n\t\t\t\t\titem.body_text.length > 120 ? `${item.body_text.slice(0, 120)}…` : item.body_text;\n\n\t\t\t\tp.log.message(\n\t\t\t\t\t[`#${item.id} ${item.kind} ${age} [${score}]`, item.title, preview].join(\"\\n\"),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tp.outro(\"done\");\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t});\n\nfunction timeSince(isoDate: string): string {\n\tconst ms = Date.now() - new Date(isoDate).getTime();\n\tconst days = Math.floor(ms / 86_400_000);\n\tif (days === 0) return \"today\";\n\tif (days === 1) return \"1d ago\";\n\tif (days < 30) return `${days}d ago`;\n\tconst months = Math.floor(days / 30);\n\treturn `${months}mo ago`;\n}\n","import { existsSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport {\n\tObserverClient,\n\tRawEventSweeper,\n\treadCodememConfigFile,\n\tresolveDbPath,\n\trunSyncDaemon,\n} from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nfunction pidFilePath(dbPath: string): string {\n\treturn join(dirname(dbPath), \"viewer.pid\");\n}\n\ninterface ViewerPidRecord {\n\tpid: number;\n\thost: string;\n\tport: number;\n}\n\nfunction readViewerPidRecord(dbPath: string): ViewerPidRecord | null {\n\tconst pidPath = pidFilePath(dbPath);\n\tif (!existsSync(pidPath)) return null;\n\tconst raw = readFileSync(pidPath, \"utf-8\").trim();\n\ttry {\n\t\tconst parsed = JSON.parse(raw) as Partial<ViewerPidRecord>;\n\t\tif (\n\t\t\ttypeof parsed.pid === \"number\" &&\n\t\t\ttypeof parsed.host === \"string\" &&\n\t\t\ttypeof parsed.port === \"number\"\n\t\t) {\n\t\t\treturn { pid: parsed.pid, host: parsed.host, port: parsed.port };\n\t\t}\n\t} catch {\n\t\tconst pid = Number.parseInt(raw, 10);\n\t\tif (Number.isFinite(pid) && pid > 0) {\n\t\t\treturn { pid, host: \"127.0.0.1\", port: 38888 };\n\t\t}\n\t}\n\treturn null;\n}\n\nasync function respondsLikeCodememViewer(record: ViewerPidRecord): Promise<boolean> {\n\ttry {\n\t\tconst controller = new AbortController();\n\t\tconst timer = setTimeout(() => controller.abort(), 1000);\n\t\tconst res = await fetch(`http://${record.host}:${record.port}/api/stats`, {\n\t\t\tsignal: controller.signal,\n\t\t});\n\t\tclearTimeout(timer);\n\t\treturn res.ok;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nasync function waitForProcessExit(pid: number, timeoutMs = 5000): Promise<void> {\n\tconst deadline = Date.now() + timeoutMs;\n\twhile (Date.now() < deadline) {\n\t\ttry {\n\t\t\tprocess.kill(pid, 0);\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 100));\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nasync function stopExistingViewer(dbPath: string): Promise<void> {\n\tconst pidPath = pidFilePath(dbPath);\n\tconst record = readViewerPidRecord(dbPath);\n\tif (!record) return;\n\t// Only signal the process if the recorded endpoint still looks like codemem.\n\tif (await respondsLikeCodememViewer(record)) {\n\t\ttry {\n\t\t\tprocess.kill(record.pid, \"SIGTERM\");\n\t\t\tawait waitForProcessExit(record.pid);\n\t\t} catch {\n\t\t\t// stale pidfile or already exited\n\t\t}\n\t}\n\ttry {\n\t\trmSync(pidPath);\n\t} catch {\n\t\t// ignore\n\t}\n}\n\nexport const serveCommand = new Command(\"serve\")\n\t.configureHelp(helpStyle)\n\t.description(\"Start the viewer server\")\n\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.option(\"--host <host>\", \"bind host\", \"127.0.0.1\")\n\t.option(\"--port <port>\", \"bind port\", \"38888\")\n\t.option(\"--background\", \"run under a caller-managed background process\")\n\t.option(\"--stop\", \"stop an existing viewer process\")\n\t.option(\"--restart\", \"restart an existing viewer process\")\n\t.action(\n\t\tasync (opts: {\n\t\t\tdb?: string;\n\t\t\thost: string;\n\t\t\tport: string;\n\t\t\tbackground?: boolean;\n\t\t\tstop?: boolean;\n\t\t\trestart?: boolean;\n\t\t}) => {\n\t\t\t// Dynamic import to avoid loading hono/server deps for non-serve commands\n\t\t\tconst { createApp, closeStore, getStore } = await import(\"@codemem/server\");\n\t\t\tconst { serve } = await import(\"@hono/node-server\");\n\n\t\t\tconst dbPath = resolveDbPath(opts.db);\n\t\t\tif (opts.stop || opts.restart) {\n\t\t\t\tawait stopExistingViewer(dbPath);\n\t\t\t\tif (opts.stop && !opts.restart) return;\n\t\t\t}\n\t\t\tprocess.env.CODEMEM_DB = dbPath;\n\n\t\t\tconst port = Number.parseInt(opts.port, 10);\n\t\t\t// Start the raw event sweeper — shares the same store as the viewer\n\t\t\tconst observer = new ObserverClient();\n\t\t\tconst sweeper = new RawEventSweeper(getStore(), { observer });\n\t\t\tsweeper.start();\n\n\t\t\t// Start the sync daemon if enabled — shares the same DB path.\n\t\t\t// Uses an AbortController so serve shutdown cleanly stops sync.\n\t\t\tconst syncAbort = new AbortController();\n\t\t\tlet syncRunning = false;\n\t\t\tconst config = readCodememConfigFile();\n\t\t\tconst syncEnabled =\n\t\t\t\tconfig.sync_enabled === true ||\n\t\t\t\tprocess.env.CODEMEM_SYNC_ENABLED?.toLowerCase() === \"true\" ||\n\t\t\t\tprocess.env.CODEMEM_SYNC_ENABLED === \"1\";\n\n\t\t\tif (syncEnabled) {\n\t\t\t\tsyncRunning = true;\n\t\t\t\tconst syncIntervalS =\n\t\t\t\t\ttypeof config.sync_interval_s === \"number\" ? config.sync_interval_s : 120;\n\t\t\t\trunSyncDaemon({\n\t\t\t\t\tdbPath,\n\t\t\t\t\tintervalS: syncIntervalS,\n\t\t\t\t\thost: opts.host,\n\t\t\t\t\tport,\n\t\t\t\t\tsignal: syncAbort.signal,\n\t\t\t\t})\n\t\t\t\t\t.catch((err: unknown) => {\n\t\t\t\t\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\t\t\t\t\tp.log.error(`Sync daemon failed: ${msg}`);\n\t\t\t\t\t\t// Non-fatal — viewer continues without sync\n\t\t\t\t\t})\n\t\t\t\t\t.finally(() => {\n\t\t\t\t\t\tsyncRunning = false;\n\t\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst app = createApp({ storeFactory: getStore, sweeper });\n\t\t\tconst pidPath = pidFilePath(dbPath);\n\n\t\t\tconst server = serve({ fetch: app.fetch, hostname: opts.host, port }, (info) => {\n\t\t\t\twriteFileSync(\n\t\t\t\t\tpidPath,\n\t\t\t\t\tJSON.stringify({ pid: process.pid, host: opts.host, port }),\n\t\t\t\t\t\"utf-8\",\n\t\t\t\t);\n\t\t\t\tp.intro(\"codemem viewer\");\n\t\t\t\tp.log.success(`Listening on http://${info.address}:${info.port}`);\n\t\t\t\tp.log.info(`Database: ${dbPath}`);\n\t\t\t\tp.log.step(\"Raw event sweeper started\");\n\t\t\t\tif (syncRunning) p.log.step(\"Sync daemon started\");\n\t\t\t});\n\n\t\t\tconst shutdown = async () => {\n\t\t\t\tp.outro(\"shutting down\");\n\t\t\t\t// Stop sync daemon via abort signal\n\t\t\t\tsyncAbort.abort();\n\t\t\t\t// Stop sweeper first and wait for any in-flight tick to drain.\n\t\t\t\tawait sweeper.stop();\n\t\t\t\t// Close HTTP server, wait for in-flight requests to drain\n\t\t\t\tserver.close(() => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\trmSync(pidPath);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// ignore\n\t\t\t\t\t}\n\t\t\t\t\tcloseStore();\n\t\t\t\t\tprocess.exit(0);\n\t\t\t\t});\n\t\t\t\t// Force exit after 5s if graceful shutdown stalls\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\trmSync(pidPath);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// ignore\n\t\t\t\t\t}\n\t\t\t\t\tcloseStore();\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t}, 5000).unref();\n\t\t\t};\n\t\t\tprocess.on(\"SIGINT\", () => {\n\t\t\t\tvoid shutdown();\n\t\t\t});\n\t\t\tprocess.on(\"SIGTERM\", () => {\n\t\t\t\tvoid shutdown();\n\t\t\t});\n\t\t},\n\t);\n","/**\n * codemem setup — one-command installation for OpenCode plugin + MCP config.\n *\n * Replaces Python's install_plugin_cmd + install_mcp_cmd.\n *\n * What it does:\n * 1. Copies the plugin file to ~/.config/opencode/plugin/codemem.js\n * 2. Adds/updates the MCP entry in ~/.config/opencode/opencode.json\n * 3. Copies the compat lib to ~/.config/opencode/lib/compat.js\n *\n * Designed to be safe to run repeatedly (idempotent unless --force).\n */\n\nimport { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { stripJsonComments, stripTrailingCommas, VERSION } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nfunction opencodeConfigDir(): string {\n\treturn join(homedir(), \".config\", \"opencode\");\n}\n\nfunction claudeConfigDir(): string {\n\treturn join(homedir(), \".claude\");\n}\n\n/**\n * Find the plugin source file — walk up from this module's location\n * to find the .opencode/plugin/codemem.js in the package tree.\n */\nfunction findPluginSource(): string | null {\n\t// In the built CLI, __dirname is packages/cli/dist or similar.\n\t// The plugin lives at the repo/package root under .opencode/plugin/codemem.js\n\tlet dir = dirname(import.meta.url.replace(\"file://\", \"\"));\n\tfor (let i = 0; i < 6; i++) {\n\t\tconst candidate = join(dir, \".opencode\", \"plugin\", \"codemem.js\");\n\t\tif (existsSync(candidate)) return candidate;\n\t\t// Check node_modules/codemem/.opencode/plugin/codemem.js (unscoped)\n\t\tconst nmCandidate = join(dir, \"node_modules\", \"codemem\", \".opencode\", \"plugin\", \"codemem.js\");\n\t\tif (existsSync(nmCandidate)) return nmCandidate;\n\t\t// Legacy: node_modules/@kunickiaj/codemem/.opencode/plugin/codemem.js\n\t\tconst legacyCandidate = join(\n\t\t\tdir,\n\t\t\t\"node_modules\",\n\t\t\t\"@kunickiaj\",\n\t\t\t\"codemem\",\n\t\t\t\".opencode\",\n\t\t\t\"plugin\",\n\t\t\t\"codemem.js\",\n\t\t);\n\t\tif (existsSync(legacyCandidate)) return legacyCandidate;\n\t\tconst parent = dirname(dir);\n\t\tif (parent === dir) break;\n\t\tdir = parent;\n\t}\n\treturn null;\n}\n\nfunction findCompatSource(): string | null {\n\tlet dir = dirname(import.meta.url.replace(\"file://\", \"\"));\n\tfor (let i = 0; i < 6; i++) {\n\t\tconst candidate = join(dir, \".opencode\", \"lib\", \"compat.js\");\n\t\tif (existsSync(candidate)) return candidate;\n\t\tconst nmCandidate = join(dir, \"node_modules\", \"codemem\", \".opencode\", \"lib\", \"compat.js\");\n\t\tif (existsSync(nmCandidate)) return nmCandidate;\n\t\tconst legacyCandidate = join(\n\t\t\tdir,\n\t\t\t\"node_modules\",\n\t\t\t\"@kunickiaj\",\n\t\t\t\"codemem\",\n\t\t\t\".opencode\",\n\t\t\t\"lib\",\n\t\t\t\"compat.js\",\n\t\t);\n\t\tif (existsSync(legacyCandidate)) return legacyCandidate;\n\t\tconst parent = dirname(dir);\n\t\tif (parent === dir) break;\n\t\tdir = parent;\n\t}\n\treturn null;\n}\n\nfunction loadJsoncConfig(path: string): Record<string, unknown> {\n\tif (!existsSync(path)) return {};\n\tconst raw = readFileSync(path, \"utf-8\");\n\ttry {\n\t\treturn JSON.parse(raw) as Record<string, unknown>;\n\t} catch {\n\t\tconst cleaned = stripTrailingCommas(stripJsonComments(raw));\n\t\treturn JSON.parse(cleaned) as Record<string, unknown>;\n\t}\n}\n\nfunction writeJsonConfig(path: string, data: Record<string, unknown>): void {\n\tmkdirSync(dirname(path), { recursive: true });\n\twriteFileSync(path, `${JSON.stringify(data, null, 2)}\\n`, \"utf-8\");\n}\n\nfunction installPlugin(force: boolean): boolean {\n\tconst source = findPluginSource();\n\tif (!source) {\n\t\tp.log.error(\"Plugin file not found in package tree\");\n\t\treturn false;\n\t}\n\n\tconst destDir = join(opencodeConfigDir(), \"plugin\");\n\tconst dest = join(destDir, \"codemem.js\");\n\n\tif (existsSync(dest) && !force) {\n\t\tp.log.info(`Plugin already installed at ${dest}`);\n\t} else {\n\t\tmkdirSync(destDir, { recursive: true });\n\t\tcopyFileSync(source, dest);\n\t\tp.log.success(`Plugin installed: ${dest}`);\n\t}\n\n\t// Always install/update compat lib (plugin imports ../lib/compat.js)\n\tconst compatSource = findCompatSource();\n\tif (compatSource) {\n\t\tconst compatDir = join(opencodeConfigDir(), \"lib\");\n\t\tmkdirSync(compatDir, { recursive: true });\n\t\tcopyFileSync(compatSource, join(compatDir, \"compat.js\"));\n\t}\n\n\treturn true;\n}\n\nfunction installMcp(force: boolean): boolean {\n\tconst configPath = join(opencodeConfigDir(), \"opencode.json\");\n\tlet config: Record<string, unknown>;\n\ttry {\n\t\tconfig = loadJsoncConfig(configPath);\n\t} catch (err) {\n\t\tp.log.error(\n\t\t\t`Failed to parse ${configPath}: ${err instanceof Error ? err.message : String(err)}`,\n\t\t);\n\t\treturn false;\n\t}\n\n\tlet mcpConfig = config.mcp as Record<string, unknown> | undefined;\n\tif (mcpConfig == null || typeof mcpConfig !== \"object\" || Array.isArray(mcpConfig)) {\n\t\tmcpConfig = {};\n\t}\n\n\tif (\"codemem\" in mcpConfig && !force) {\n\t\tp.log.info(`MCP entry already exists in ${configPath}`);\n\t\treturn true;\n\t}\n\n\tmcpConfig.codemem = {\n\t\ttype: \"local\",\n\t\tcommand: [\"npx\", \"codemem\", \"mcp\"],\n\t\tenabled: true,\n\t};\n\tconfig.mcp = mcpConfig;\n\n\ttry {\n\t\twriteJsonConfig(configPath, config);\n\t\tp.log.success(`MCP entry installed: ${configPath}`);\n\t} catch (err) {\n\t\tp.log.error(\n\t\t\t`Failed to write ${configPath}: ${err instanceof Error ? err.message : String(err)}`,\n\t\t);\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nfunction installClaudeMcp(force: boolean): boolean {\n\tconst settingsPath = join(claudeConfigDir(), \"settings.json\");\n\tlet settings: Record<string, unknown>;\n\ttry {\n\t\tsettings = loadJsoncConfig(settingsPath);\n\t} catch {\n\t\tsettings = {};\n\t}\n\n\tlet mcpServers = settings.mcpServers as Record<string, unknown> | undefined;\n\tif (mcpServers == null || typeof mcpServers !== \"object\" || Array.isArray(mcpServers)) {\n\t\tmcpServers = {};\n\t}\n\n\tif (\"codemem\" in mcpServers && !force) {\n\t\tp.log.info(`Claude MCP entry already exists in ${settingsPath}`);\n\t\treturn true;\n\t}\n\n\tmcpServers.codemem = {\n\t\tcommand: \"npx\",\n\t\targs: [\"codemem\", \"mcp\"],\n\t};\n\tsettings.mcpServers = mcpServers;\n\n\ttry {\n\t\twriteJsonConfig(settingsPath, settings);\n\t\tp.log.success(`Claude MCP entry installed: ${settingsPath}`);\n\t} catch (err) {\n\t\tp.log.error(\n\t\t\t`Failed to write ${settingsPath}: ${err instanceof Error ? err.message : String(err)}`,\n\t\t);\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nexport const setupCommand = new Command(\"setup\")\n\t.configureHelp(helpStyle)\n\t.description(\"Install codemem plugin + MCP config for OpenCode and Claude Code\")\n\t.option(\"--force\", \"overwrite existing installations\")\n\t.option(\"--opencode-only\", \"only install for OpenCode\")\n\t.option(\"--claude-only\", \"only install for Claude Code\")\n\t.action((opts: { force?: boolean; opencodeOnly?: boolean; claudeOnly?: boolean }) => {\n\t\tp.intro(`codemem setup v${VERSION}`);\n\t\tconst force = opts.force ?? false;\n\t\tlet ok = true;\n\n\t\tif (!opts.claudeOnly) {\n\t\t\tp.log.step(\"Installing OpenCode plugin...\");\n\t\t\tok = installPlugin(force) && ok;\n\t\t\tp.log.step(\"Installing OpenCode MCP config...\");\n\t\t\tok = installMcp(force) && ok;\n\t\t}\n\n\t\tif (!opts.opencodeOnly) {\n\t\t\tp.log.step(\"Installing Claude Code MCP config...\");\n\t\t\tok = installClaudeMcp(force) && ok;\n\t\t}\n\n\t\tif (ok) {\n\t\t\tp.outro(\"Setup complete — restart your editor to load the plugin\");\n\t\t} else {\n\t\t\tp.outro(\"Setup completed with warnings\");\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\t});\n","import * as p from \"@clack/prompts\";\nimport { MemoryStore, resolveDbPath } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nfunction fmtPct(n: number): string {\n\treturn `${Math.round(n * 100)}%`;\n}\n\nfunction fmtTokens(n: number): string {\n\tif (n >= 1_000_000_000) return `~${(n / 1_000_000_000).toFixed(1)}B`;\n\tif (n >= 1_000_000) return `~${(n / 1_000_000).toFixed(1)}M`;\n\tif (n >= 1_000) return `~${(n / 1_000).toFixed(0)}K`;\n\treturn `${n}`;\n}\n\nexport const statsCommand = new Command(\"stats\")\n\t.configureHelp(helpStyle)\n\t.description(\"Show database statistics\")\n\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.option(\"--json\", \"output as JSON\")\n\t.action((opts: { db?: string; json?: boolean }) => {\n\t\tconst store = new MemoryStore(resolveDbPath(opts.db));\n\t\ttry {\n\t\t\tconst result = store.stats();\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst db = result.database;\n\t\t\tconst sizeMb = (db.size_bytes / 1_048_576).toFixed(1);\n\n\t\t\tp.intro(\"codemem stats\");\n\n\t\t\tp.log.info([`Path: ${db.path}`, `Size: ${sizeMb} MB`].join(\"\\n\"));\n\n\t\t\tp.log.success(\n\t\t\t\t[\n\t\t\t\t\t`Sessions: ${db.sessions.toLocaleString()}`,\n\t\t\t\t\t`Memories: ${db.active_memory_items.toLocaleString()} active / ${db.memory_items.toLocaleString()} total`,\n\t\t\t\t\t`Tags: ${db.tags_filled.toLocaleString()} filled (${fmtPct(db.tags_coverage)} of active)`,\n\t\t\t\t\t`Artifacts: ${db.artifacts.toLocaleString()}`,\n\t\t\t\t\t`Vectors: ${db.vector_rows.toLocaleString()} (${fmtPct(db.vector_coverage)} coverage)`,\n\t\t\t\t\t`Raw events: ${db.raw_events.toLocaleString()}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t);\n\n\t\t\tif (result.usage.events.length > 0) {\n\t\t\t\tconst lines = result.usage.events.map((e: (typeof result.usage.events)[number]) => {\n\t\t\t\t\tconst parts = [`${e.event}: ${e.count.toLocaleString()}`];\n\t\t\t\t\tif (e.tokens_read > 0) parts.push(`read ${fmtTokens(e.tokens_read)} tokens`);\n\t\t\t\t\tif (e.tokens_saved > 0) parts.push(`est. saved ${fmtTokens(e.tokens_saved)} tokens`);\n\t\t\t\t\treturn ` ${parts.join(\", \")}`;\n\t\t\t\t});\n\n\t\t\t\tconst t = result.usage.totals;\n\t\t\t\tlines.push(\"\");\n\t\t\t\tlines.push(\n\t\t\t\t\t` Total: ${t.events.toLocaleString()} events, read ${fmtTokens(t.tokens_read)} tokens, est. saved ${fmtTokens(t.tokens_saved)} tokens`,\n\t\t\t\t);\n\n\t\t\t\tp.log.step(`Usage\\n${lines.join(\"\\n\")}`);\n\t\t\t}\n\n\t\t\tp.outro(\"done\");\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t});\n","/**\n * Sync CLI commands — enable/disable/status/peers/connect.\n */\n\nimport * as p from \"@clack/prompts\";\nimport {\n\tensureDeviceIdentity,\n\tMemoryStore,\n\treadCodememConfigFile,\n\tresolveDbPath,\n\tschema,\n\twriteCodememConfigFile,\n} from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { desc } from \"drizzle-orm\";\nimport { drizzle } from \"drizzle-orm/better-sqlite3\";\nimport { helpStyle } from \"../help-style.js\";\n\nexport const syncCommand = new Command(\"sync\")\n\t.configureHelp(helpStyle)\n\t.description(\"Sync configuration and peer management\");\n\n// codemem sync status\nsyncCommand.addCommand(\n\tnew Command(\"status\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Show sync configuration and peer summary\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.option(\"--json\", \"output as JSON\")\n\t\t.action((opts: { db?: string; json?: boolean }) => {\n\t\t\tconst config = readCodememConfigFile();\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db));\n\t\t\ttry {\n\t\t\t\tconst d = drizzle(store.db, { schema });\n\t\t\t\tconst deviceRow = d\n\t\t\t\t\t.select({\n\t\t\t\t\t\tdevice_id: schema.syncDevice.device_id,\n\t\t\t\t\t\tfingerprint: schema.syncDevice.fingerprint,\n\t\t\t\t\t})\n\t\t\t\t\t.from(schema.syncDevice)\n\t\t\t\t\t.limit(1)\n\t\t\t\t\t.get();\n\t\t\t\tconst peers = d\n\t\t\t\t\t.select({\n\t\t\t\t\t\tpeer_device_id: schema.syncPeers.peer_device_id,\n\t\t\t\t\t\tname: schema.syncPeers.name,\n\t\t\t\t\t\tlast_sync_at: schema.syncPeers.last_sync_at,\n\t\t\t\t\t\tlast_error: schema.syncPeers.last_error,\n\t\t\t\t\t})\n\t\t\t\t\t.from(schema.syncPeers)\n\t\t\t\t\t.all();\n\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\tJSON.stringify(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tenabled: config.sync_enabled === true,\n\t\t\t\t\t\t\t\thost: config.sync_host ?? \"0.0.0.0\",\n\t\t\t\t\t\t\t\tport: config.sync_port ?? 7337,\n\t\t\t\t\t\t\t\tinterval_s: config.sync_interval_s ?? 120,\n\t\t\t\t\t\t\t\tdevice_id: deviceRow?.device_id ?? null,\n\t\t\t\t\t\t\t\tfingerprint: deviceRow?.fingerprint ?? null,\n\t\t\t\t\t\t\t\tcoordinator_url: config.sync_coordinator_url ?? null,\n\t\t\t\t\t\t\t\tpeers: peers.map((peer) => ({\n\t\t\t\t\t\t\t\t\tdevice_id: peer.peer_device_id,\n\t\t\t\t\t\t\t\t\tname: peer.name,\n\t\t\t\t\t\t\t\t\tlast_sync: peer.last_sync_at,\n\t\t\t\t\t\t\t\t\tstatus: peer.last_error ?? \"ok\",\n\t\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t2,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tp.intro(\"codemem sync status\");\n\t\t\t\tp.log.info(\n\t\t\t\t\t[\n\t\t\t\t\t\t`Enabled: ${config.sync_enabled === true ? \"yes\" : \"no\"}`,\n\t\t\t\t\t\t`Host: ${config.sync_host ?? \"0.0.0.0\"}`,\n\t\t\t\t\t\t`Port: ${config.sync_port ?? 7337}`,\n\t\t\t\t\t\t`Interval: ${config.sync_interval_s ?? 120}s`,\n\t\t\t\t\t\t`Coordinator: ${config.sync_coordinator_url ?? \"(not configured)\"}`,\n\t\t\t\t\t].join(\"\\n\"),\n\t\t\t\t);\n\t\t\t\tif (deviceRow) {\n\t\t\t\t\tp.log.info(`Device ID: ${deviceRow.device_id}\\nFingerprint: ${deviceRow.fingerprint}`);\n\t\t\t\t} else {\n\t\t\t\t\tp.log.warn(\"Device identity not initialized (run `codemem sync enable`)\");\n\t\t\t\t}\n\t\t\t\tif (peers.length === 0) {\n\t\t\t\t\tp.log.info(\"Peers: none\");\n\t\t\t\t} else {\n\t\t\t\t\tfor (const peer of peers) {\n\t\t\t\t\t\tconst label = peer.name || peer.peer_device_id;\n\t\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t\t` ${label}: last_sync=${peer.last_sync_at ?? \"never\"}, status=${peer.last_error ?? \"ok\"}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tp.outro(`${peers.length} peer(s)`);\n\t\t\t} finally {\n\t\t\t\tstore.close();\n\t\t\t}\n\t\t}),\n);\n\n// codemem sync enable\nsyncCommand.addCommand(\n\tnew Command(\"enable\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Enable sync and initialize device identity\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.option(\"--host <host>\", \"sync listen host\")\n\t\t.option(\"--port <port>\", \"sync listen port\")\n\t\t.option(\"--interval <seconds>\", \"sync interval in seconds\")\n\t\t.action((opts: { db?: string; host?: string; port?: string; interval?: string }) => {\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db));\n\t\t\ttry {\n\t\t\t\tconst [deviceId, fingerprint] = ensureDeviceIdentity(store.db);\n\t\t\t\tconst config = readCodememConfigFile();\n\t\t\t\tconfig.sync_enabled = true;\n\t\t\t\tif (opts.host) config.sync_host = opts.host;\n\t\t\t\tif (opts.port) config.sync_port = Number.parseInt(opts.port, 10);\n\t\t\t\tif (opts.interval) config.sync_interval_s = Number.parseInt(opts.interval, 10);\n\t\t\t\twriteCodememConfigFile(config);\n\n\t\t\t\tp.intro(\"codemem sync enable\");\n\t\t\t\tp.log.success(\n\t\t\t\t\t[\n\t\t\t\t\t\t`Device ID: ${deviceId}`,\n\t\t\t\t\t\t`Fingerprint: ${fingerprint}`,\n\t\t\t\t\t\t`Host: ${config.sync_host ?? \"0.0.0.0\"}`,\n\t\t\t\t\t\t`Port: ${config.sync_port ?? 7337}`,\n\t\t\t\t\t\t`Interval: ${config.sync_interval_s ?? 120}s`,\n\t\t\t\t\t].join(\"\\n\"),\n\t\t\t\t);\n\t\t\t\tp.outro(\"Sync enabled — restart `codemem serve` to activate\");\n\t\t\t} finally {\n\t\t\t\tstore.close();\n\t\t\t}\n\t\t}),\n);\n\n// codemem sync disable\nsyncCommand.addCommand(\n\tnew Command(\"disable\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Disable sync without deleting keys or peers\")\n\t\t.action(() => {\n\t\t\tconst config = readCodememConfigFile();\n\t\t\tconfig.sync_enabled = false;\n\t\t\twriteCodememConfigFile(config);\n\t\t\tp.intro(\"codemem sync disable\");\n\t\t\tp.outro(\"Sync disabled — restart `codemem serve` to take effect\");\n\t\t}),\n);\n\n// codemem sync peers\nsyncCommand.addCommand(\n\tnew Command(\"peers\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"List known sync peers\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.option(\"--json\", \"output as JSON\")\n\t\t.action((opts: { db?: string; json?: boolean }) => {\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db));\n\t\t\ttry {\n\t\t\t\tconst d = drizzle(store.db, { schema });\n\t\t\t\tconst peers = d\n\t\t\t\t\t.select({\n\t\t\t\t\t\tpeer_device_id: schema.syncPeers.peer_device_id,\n\t\t\t\t\t\tname: schema.syncPeers.name,\n\t\t\t\t\t\taddresses: schema.syncPeers.addresses_json,\n\t\t\t\t\t\tlast_sync_at: schema.syncPeers.last_sync_at,\n\t\t\t\t\t\tlast_error: schema.syncPeers.last_error,\n\t\t\t\t\t})\n\t\t\t\t\t.from(schema.syncPeers)\n\t\t\t\t\t.orderBy(desc(schema.syncPeers.last_sync_at))\n\t\t\t\t\t.all();\n\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify(peers, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tp.intro(\"codemem sync peers\");\n\t\t\t\tif (peers.length === 0) {\n\t\t\t\t\tp.outro(\"No peers configured\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfor (const peer of peers) {\n\t\t\t\t\tconst label = peer.name || peer.peer_device_id;\n\t\t\t\t\tconst addrs = peer.addresses || \"(no addresses)\";\n\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t`${label}\\n addresses: ${addrs}\\n last_sync: ${peer.last_sync_at ?? \"never\"}\\n status: ${peer.last_error ?? \"ok\"}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tp.outro(`${peers.length} peer(s)`);\n\t\t\t} finally {\n\t\t\t\tstore.close();\n\t\t\t}\n\t\t}),\n);\n\n// codemem sync connect <coordinator-url>\nsyncCommand.addCommand(\n\tnew Command(\"connect\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Configure coordinator URL for cloud sync\")\n\t\t.argument(\"<url>\", \"coordinator URL (e.g. https://coordinator.example.com)\")\n\t\t.option(\"--group <group>\", \"sync group ID\")\n\t\t.action((url: string, opts: { group?: string }) => {\n\t\t\tconst config = readCodememConfigFile();\n\t\t\tconfig.sync_coordinator_url = url.trim();\n\t\t\tif (opts.group) config.sync_coordinator_group = opts.group.trim();\n\t\t\twriteCodememConfigFile(config);\n\t\t\tp.intro(\"codemem sync connect\");\n\t\t\tp.log.success(`Coordinator: ${url.trim()}`);\n\t\t\tif (opts.group) p.log.info(`Group: ${opts.group.trim()}`);\n\t\t\tp.outro(\"Restart `codemem serve` to activate coordinator sync\");\n\t\t}),\n);\n","import { VERSION } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nexport const versionCommand = new Command(\"version\")\n\t.configureHelp(helpStyle)\n\t.description(\"Print codemem version\")\n\t.action(() => {\n\t\tconsole.log(VERSION);\n\t});\n","#!/usr/bin/env node\n\n/**\n * @codemem/cli — CLI entry point.\n *\n * Commands:\n * codemem stats → database statistics\n * codemem search → FTS5 memory search\n * codemem pack → context-aware memory pack\n * codemem serve → viewer server\n * codemem mcp → MCP stdio server\n */\n\nimport { VERSION } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport omelette from \"omelette\";\nimport { claudeHookIngestCommand } from \"./commands/claude-hook-ingest.js\";\nimport { dbCommand } from \"./commands/db.js\";\nimport { enqueueRawEventCommand } from \"./commands/enqueue-raw-event.js\";\nimport { exportMemoriesCommand } from \"./commands/export-memories.js\";\nimport { importMemoriesCommand } from \"./commands/import-memories.js\";\nimport { mcpCommand } from \"./commands/mcp.js\";\nimport { memoryCommand } from \"./commands/memory.js\";\nimport { packCommand } from \"./commands/pack.js\";\nimport { recentCommand } from \"./commands/recent.js\";\nimport { searchCommand } from \"./commands/search.js\";\nimport { serveCommand } from \"./commands/serve.js\";\nimport { setupCommand } from \"./commands/setup.js\";\nimport { statsCommand } from \"./commands/stats.js\";\nimport { syncCommand } from \"./commands/sync.js\";\nimport { versionCommand } from \"./commands/version.js\";\nimport { helpStyle } from \"./help-style.js\";\n\n// Shell completion (bash/zsh/fish)\nconst completion = omelette(\"codemem <command>\");\ncompletion.on(\"command\", ({ reply }) => {\n\treply([\n\t\t\"claude-hook-ingest\",\n\t\t\"db\",\n\t\t\"export-memories\",\n\t\t\"memory\",\n\t\t\"import-memories\",\n\t\t\"setup\",\n\t\t\"sync\",\n\t\t\"stats\",\n\t\t\"recent\",\n\t\t\"search\",\n\t\t\"pack\",\n\t\t\"serve\",\n\t\t\"mcp\",\n\t\t\"enqueue-raw-event\",\n\t\t\"version\",\n\t\t\"help\",\n\t\t\"--help\",\n\t\t\"--version\",\n\t]);\n});\ncompletion.init();\n\n// `codemem --setup-completion` installs shell completion\nif (process.argv.includes(\"--setup-completion\")) {\n\tcompletion.setupShellInitFile();\n\tprocess.exit(0);\n}\n// `codemem --cleanup-completion` removes it\nif (process.argv.includes(\"--cleanup-completion\")) {\n\tcompletion.cleanupShellInitFile();\n\tprocess.exit(0);\n}\n\nconst program = new Command();\n\nprogram\n\t.name(\"codemem\")\n\t.description(\"codemem — persistent memory for AI coding agents\")\n\t.version(VERSION)\n\t.configureHelp(helpStyle);\n\nprogram.addCommand(serveCommand);\nprogram.addCommand(mcpCommand);\nprogram.addCommand(claudeHookIngestCommand);\nprogram.addCommand(dbCommand);\nprogram.addCommand(exportMemoriesCommand);\nprogram.addCommand(importMemoriesCommand);\nprogram.addCommand(statsCommand);\nprogram.addCommand(recentCommand);\nprogram.addCommand(searchCommand);\nprogram.addCommand(packCommand);\nprogram.addCommand(memoryCommand);\nprogram.addCommand(syncCommand);\nprogram.addCommand(setupCommand);\nprogram.addCommand(enqueueRawEventCommand);\nprogram.addCommand(versionCommand);\n\nprogram.parse();\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,64 +1,64 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
2
|
+
"name": "codemem",
|
|
3
|
+
"version": "0.20.0-alpha.2",
|
|
4
|
+
"description": "Memory layer for AI coding agents — search, recall, and sync context across sessions",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"codemem": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist/",
|
|
11
|
+
".opencode/plugin/",
|
|
12
|
+
".opencode/lib/",
|
|
13
|
+
"README.md",
|
|
14
|
+
"LICENSE"
|
|
15
|
+
],
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@clack/prompts": "^1.1.0",
|
|
18
|
+
"@hono/node-server": "^1.14.3",
|
|
19
|
+
"commander": "^14.0.3",
|
|
20
|
+
"drizzle-orm": "^0.45.1",
|
|
21
|
+
"omelette": "^0.4.17",
|
|
22
|
+
"@codemem/core": "^0.20.0-alpha.2",
|
|
23
|
+
"@codemem/server": "^0.20.0-alpha.2",
|
|
24
|
+
"@codemem/mcp": "^0.20.0-alpha.2"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/node": "^25.5.0",
|
|
28
|
+
"@types/omelette": "^0.4.5",
|
|
29
|
+
"tsx": "^4.21.0",
|
|
30
|
+
"typescript": "^5.8.2",
|
|
31
|
+
"vite": "^8.0.0",
|
|
32
|
+
"vitest": "^3.1.4"
|
|
33
|
+
},
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=22"
|
|
36
|
+
},
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "git+https://github.com/kunickiaj/codemem.git"
|
|
40
|
+
},
|
|
41
|
+
"homepage": "https://github.com/kunickiaj/codemem",
|
|
42
|
+
"bugs": {
|
|
43
|
+
"url": "https://github.com/kunickiaj/codemem/issues"
|
|
44
|
+
},
|
|
45
|
+
"license": "MIT",
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
},
|
|
49
|
+
"keywords": [
|
|
50
|
+
"codemem",
|
|
51
|
+
"memory",
|
|
52
|
+
"ai",
|
|
53
|
+
"coding",
|
|
54
|
+
"agent",
|
|
55
|
+
"mcp",
|
|
56
|
+
"opencode",
|
|
57
|
+
"claude"
|
|
58
|
+
],
|
|
59
|
+
"scripts": {
|
|
60
|
+
"clean": "rm -rf dist",
|
|
61
|
+
"build": "pnpm exec vite build --ssr src/index.ts --outDir dist",
|
|
62
|
+
"typecheck": "pnpm exec tsc --noEmit"
|
|
63
|
+
}
|
|
64
|
+
}
|