codemem 0.20.0-alpha.3 → 0.20.0-alpha.4
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.
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { appendFile, mkdir } from "node:fs/promises";
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
3
|
import { dirname } from "node:path";
|
|
3
4
|
import { createHash } from "node:crypto";
|
|
5
|
+
import { spawn as nodeSpawn, execSync } from "node:child_process";
|
|
4
6
|
import { tool } from "@opencode-ai/plugin";
|
|
5
7
|
|
|
6
8
|
import {
|
|
@@ -13,8 +15,7 @@ import {
|
|
|
13
15
|
|
|
14
16
|
const TRUTHY_VALUES = ["1", "true", "yes"];
|
|
15
17
|
const DISABLED_VALUES = ["0", "false", "off"];
|
|
16
|
-
const PINNED_BACKEND_VERSION = "0.20.0-alpha.
|
|
17
|
-
const DEFAULT_UVX_SOURCE = `codemem==${PINNED_BACKEND_VERSION}`;
|
|
18
|
+
const PINNED_BACKEND_VERSION = "0.20.0-alpha.4";
|
|
18
19
|
|
|
19
20
|
const normalizeEnvValue = (value) => (value || "").toLowerCase();
|
|
20
21
|
const envHasValue = (value, truthyValues) =>
|
|
@@ -22,6 +23,8 @@ const envHasValue = (value, truthyValues) =>
|
|
|
22
23
|
const envNotDisabled = (value) =>
|
|
23
24
|
!DISABLED_VALUES.includes(normalizeEnvValue(value));
|
|
24
25
|
|
|
26
|
+
const DEFAULT_LOG_PATH = (homeDir, cwd) => `${homeDir || cwd}/.codemem/plugin.log`;
|
|
27
|
+
|
|
25
28
|
const resolveLogPath = (logPathEnvRaw, cwd, homeDir) => {
|
|
26
29
|
const logPathEnv = normalizeEnvValue(logPathEnvRaw);
|
|
27
30
|
const logEnabled = !!logPathEnvRaw && !DISABLED_VALUES.includes(logPathEnv);
|
|
@@ -29,11 +32,14 @@ const resolveLogPath = (logPathEnvRaw, cwd, homeDir) => {
|
|
|
29
32
|
return null;
|
|
30
33
|
}
|
|
31
34
|
if (["true", "yes", "1"].includes(logPathEnv)) {
|
|
32
|
-
return
|
|
35
|
+
return DEFAULT_LOG_PATH(homeDir, cwd);
|
|
33
36
|
}
|
|
34
37
|
return logPathEnvRaw;
|
|
35
38
|
};
|
|
36
39
|
|
|
40
|
+
/** Path for error/warning logging — always available regardless of debug flag. */
|
|
41
|
+
const resolveErrorLogPath = (cwd, homeDir) => DEFAULT_LOG_PATH(homeDir, cwd);
|
|
42
|
+
|
|
37
43
|
const createLogLine = (logPath) => async (line) => {
|
|
38
44
|
if (!logPath) {
|
|
39
45
|
return;
|
|
@@ -46,9 +52,15 @@ const createLogLine = (logPath) => async (line) => {
|
|
|
46
52
|
}
|
|
47
53
|
};
|
|
48
54
|
|
|
49
|
-
const createDebugLogger = ({ debug, client, logTimeoutMs, getLogLine }) =>
|
|
55
|
+
const createDebugLogger = ({ debug, client, logTimeoutMs, getLogLine, getErrorLogLine }) =>
|
|
50
56
|
async (level, message, extra = {}) => {
|
|
51
|
-
|
|
57
|
+
// Always log errors and warnings to the error log path
|
|
58
|
+
const alwaysLog = level === "error" || level === "warn";
|
|
59
|
+
if (alwaysLog) {
|
|
60
|
+
const extraStr = Object.keys(extra).length > 0 ? ` ${JSON.stringify(extra)}` : "";
|
|
61
|
+
await getErrorLogLine()(`[${level}] ${message}${extraStr}`);
|
|
62
|
+
}
|
|
63
|
+
if (!debug && !alwaysLog) {
|
|
52
64
|
return;
|
|
53
65
|
}
|
|
54
66
|
try {
|
|
@@ -387,22 +399,16 @@ const detectRunner = ({ cwd, envRunner }) => {
|
|
|
387
399
|
if (envRunner) {
|
|
388
400
|
return envRunner;
|
|
389
401
|
}
|
|
390
|
-
//
|
|
402
|
+
// Prefer the TS codemem if installed globally, fall back to npx
|
|
391
403
|
try {
|
|
392
|
-
const
|
|
393
|
-
if (
|
|
394
|
-
|
|
395
|
-
`${cwd}/pyproject.toml`,
|
|
396
|
-
"utf-8"
|
|
397
|
-
);
|
|
398
|
-
if (content.includes('name = "codemem"')) {
|
|
399
|
-
return "uv";
|
|
400
|
-
}
|
|
404
|
+
const versionOutput = execSync("codemem --version", { encoding: "utf-8", timeout: 3000 }).trim();
|
|
405
|
+
if (versionOutput === PINNED_BACKEND_VERSION || versionOutput.startsWith("0.2")) {
|
|
406
|
+
return "codemem";
|
|
401
407
|
}
|
|
402
|
-
} catch
|
|
403
|
-
//
|
|
408
|
+
} catch {
|
|
409
|
+
// not on PATH or timed out
|
|
404
410
|
}
|
|
405
|
-
return "
|
|
411
|
+
return "npx";
|
|
406
412
|
};
|
|
407
413
|
|
|
408
414
|
/**
|
|
@@ -418,28 +424,21 @@ const tsCliAvailable = (cliPath) => {
|
|
|
418
424
|
};
|
|
419
425
|
|
|
420
426
|
const buildRunnerArgs = ({ runner, runnerFrom, runnerFromExplicit }) => {
|
|
421
|
-
if (runner === "
|
|
422
|
-
|
|
423
|
-
return ["--from", runnerFrom, "codemem"];
|
|
424
|
-
}
|
|
425
|
-
return [runnerFrom || "codemem"];
|
|
427
|
+
if (runner === "codemem") {
|
|
428
|
+
return [];
|
|
426
429
|
}
|
|
427
|
-
if (runner === "
|
|
428
|
-
|
|
430
|
+
if (runner === "npx") {
|
|
431
|
+
const pkg = runnerFromExplicit ? runnerFrom : `codemem@${PINNED_BACKEND_VERSION}`;
|
|
432
|
+
return ["-y", pkg];
|
|
429
433
|
}
|
|
430
434
|
if (runner === "node") {
|
|
431
|
-
// TS CLI — runnerFrom points to the built CLI entry or repo root.
|
|
432
|
-
// Default: packages/cli/dist/index.js relative to repo root.
|
|
433
435
|
const cliPath = runnerFromExplicit
|
|
434
436
|
? runnerFrom
|
|
435
|
-
:
|
|
437
|
+
: join(runnerFrom, "packages/cli/dist/index.js");
|
|
436
438
|
return [cliPath];
|
|
437
439
|
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
return ["-y", pkg];
|
|
441
|
-
}
|
|
442
|
-
return [];
|
|
440
|
+
// Custom runner via CODEMEM_RUNNER env — pass through as-is
|
|
441
|
+
return runnerFromExplicit ? [runnerFrom] : [];
|
|
443
442
|
};
|
|
444
443
|
|
|
445
444
|
export const OpencodeMemPlugin = async ({
|
|
@@ -466,12 +465,15 @@ export const OpencodeMemPlugin = async ({
|
|
|
466
465
|
);
|
|
467
466
|
const logPathEnvRaw = process.env.CODEMEM_PLUGIN_LOG || "";
|
|
468
467
|
const logPath = resolveLogPath(logPathEnvRaw, cwd, process.env.HOME);
|
|
468
|
+
const errorLogPath = resolveErrorLogPath(cwd, process.env.HOME);
|
|
469
469
|
const logLine = createLogLine(logPath);
|
|
470
|
+
const errorLogLine = createLogLine(errorLogPath);
|
|
470
471
|
const log = createDebugLogger({
|
|
471
472
|
debug,
|
|
472
473
|
client,
|
|
473
474
|
logTimeoutMs,
|
|
474
475
|
getLogLine: () => logLine,
|
|
476
|
+
getErrorLogLine: () => errorLogLine,
|
|
475
477
|
});
|
|
476
478
|
const pluginIgnored = envHasValue(
|
|
477
479
|
process.env.CODEMEM_PLUGIN_IGNORE,
|
|
@@ -481,17 +483,12 @@ export const OpencodeMemPlugin = async ({
|
|
|
481
483
|
return {};
|
|
482
484
|
}
|
|
483
485
|
|
|
484
|
-
// Determine runner mode:
|
|
485
|
-
// - If CODEMEM_RUNNER is set, use that ("uvx", "uv", "node", "npx")
|
|
486
|
-
// - If we're in a directory with pyproject.toml containing codemem, use "uv" (dev mode)
|
|
487
|
-
// - Otherwise, use "uvx" with a package source pinned to plugin version
|
|
488
486
|
const runner = detectRunner({
|
|
489
487
|
cwd,
|
|
490
488
|
envRunner: process.env.CODEMEM_RUNNER,
|
|
491
489
|
});
|
|
492
490
|
const runnerFromExplicit = Boolean(String(process.env.CODEMEM_RUNNER_FROM || "").trim());
|
|
493
|
-
const
|
|
494
|
-
const runnerFrom = process.env.CODEMEM_RUNNER_FROM || defaultRunnerFrom;
|
|
491
|
+
const runnerFrom = process.env.CODEMEM_RUNNER_FROM || cwd;
|
|
495
492
|
const runnerArgs = buildRunnerArgs({ runner, runnerFrom, runnerFromExplicit });
|
|
496
493
|
const viewerEnabled = envNotDisabled(process.env.CODEMEM_VIEWER || "1");
|
|
497
494
|
const viewerAutoStart = envNotDisabled(
|
|
@@ -999,76 +996,73 @@ export const OpencodeMemPlugin = async ({
|
|
|
999
996
|
|
|
1000
997
|
const startViewer = () => {
|
|
1001
998
|
if (!viewerEnabled || !viewerAutoStart || viewerStarted) {
|
|
999
|
+
if (viewerStarted) logLine("viewer already started, skipping auto-start").catch(() => {});
|
|
1002
1000
|
return;
|
|
1003
1001
|
}
|
|
1004
1002
|
viewerStarted = true;
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1003
|
+
const cmd = [runner, ...runnerArgs, "serve", "start"];
|
|
1004
|
+
logLine(`auto-starting viewer: ${cmd.join(" ")}`).catch(() => {});
|
|
1005
|
+
try {
|
|
1006
|
+
const child = nodeSpawn(cmd[0], cmd.slice(1), {
|
|
1007
|
+
cwd,
|
|
1008
|
+
env: process.env,
|
|
1009
|
+
detached: true,
|
|
1010
|
+
stdio: "ignore",
|
|
1011
|
+
});
|
|
1012
|
+
child.on("error", (err) => {
|
|
1013
|
+
logLine(`viewer spawn error: ${err.message}`).catch(() => {});
|
|
1014
|
+
});
|
|
1015
|
+
child.unref();
|
|
1016
|
+
} catch (err) {
|
|
1017
|
+
logLine(`viewer spawn failed: ${err}`).catch(() => {});
|
|
1018
|
+
}
|
|
1013
1019
|
};
|
|
1014
1020
|
|
|
1015
1021
|
const runCommand = async (cmd, options = {}) => {
|
|
1016
1022
|
const { stdinText = null } = options;
|
|
1017
|
-
const
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1023
|
+
const [command, ...args] = cmd;
|
|
1024
|
+
return new Promise((resolve) => {
|
|
1025
|
+
const proc = nodeSpawn(command, args, {
|
|
1026
|
+
cwd,
|
|
1027
|
+
env: process.env,
|
|
1028
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
1029
|
+
});
|
|
1030
|
+
let stdout = "";
|
|
1031
|
+
let stderr = "";
|
|
1032
|
+
proc.stdout.on("data", (chunk) => { stdout += chunk; });
|
|
1033
|
+
proc.stderr.on("data", (chunk) => { stderr += chunk; });
|
|
1034
|
+
if (typeof stdinText === "string") {
|
|
1035
|
+
try {
|
|
1036
|
+
proc.stdin.write(stdinText);
|
|
1037
|
+
} catch (stdinErr) {
|
|
1038
|
+
try { proc.kill(); } catch { /* ignore */ }
|
|
1039
|
+
resolve({ exitCode: 1, stdout: "", stderr: `stdin write failed: ${String(stdinErr)}` });
|
|
1040
|
+
return;
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1027
1043
|
try {
|
|
1028
|
-
proc.stdin.
|
|
1044
|
+
proc.stdin.end();
|
|
1029
1045
|
} catch (stdinErr) {
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
try {
|
|
1034
|
-
proc.stdin.end();
|
|
1035
|
-
} catch (stdinErr) {
|
|
1036
|
-
if (!stdinFailure) {
|
|
1037
|
-
stdinFailure = `stdin close failed: ${String(stdinErr)}`;
|
|
1046
|
+
try { proc.kill(); } catch { /* ignore */ }
|
|
1047
|
+
resolve({ exitCode: 1, stdout: "", stderr: `stdin close failed: ${String(stdinErr)}` });
|
|
1048
|
+
return;
|
|
1038
1049
|
}
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1050
|
+
let timer = null;
|
|
1051
|
+
if (Number.isFinite(commandTimeout) && commandTimeout > 0) {
|
|
1052
|
+
timer = setTimeout(() => {
|
|
1053
|
+
try { proc.kill(); } catch { /* ignore */ }
|
|
1054
|
+
resolve({ exitCode: null, stdout, stderr: "timeout" });
|
|
1055
|
+
}, commandTimeout);
|
|
1045
1056
|
}
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
return resultPromise;
|
|
1055
|
-
}
|
|
1056
|
-
let timer = null;
|
|
1057
|
-
const timeoutPromise = new Promise((resolve) => {
|
|
1058
|
-
timer = setTimeout(() => {
|
|
1059
|
-
try {
|
|
1060
|
-
proc.kill();
|
|
1061
|
-
} catch (err) {
|
|
1062
|
-
// ignore
|
|
1063
|
-
}
|
|
1064
|
-
resolve({ exitCode: null, stdout: "", stderr: "timeout" });
|
|
1065
|
-
}, commandTimeout);
|
|
1057
|
+
proc.once("exit", (exitCode) => {
|
|
1058
|
+
if (timer) clearTimeout(timer);
|
|
1059
|
+
resolve({ exitCode, stdout, stderr });
|
|
1060
|
+
});
|
|
1061
|
+
proc.once("error", (err) => {
|
|
1062
|
+
if (timer) clearTimeout(timer);
|
|
1063
|
+
resolve({ exitCode: 1, stdout: "", stderr: String(err) });
|
|
1064
|
+
});
|
|
1066
1065
|
});
|
|
1067
|
-
const result = await Promise.race([resultPromise, timeoutPromise]);
|
|
1068
|
-
if (timer) {
|
|
1069
|
-
clearTimeout(timer);
|
|
1070
|
-
}
|
|
1071
|
-
return result;
|
|
1072
1066
|
};
|
|
1073
1067
|
|
|
1074
1068
|
const runCli = async (args, options = {}) =>
|
|
@@ -1097,7 +1091,7 @@ export const OpencodeMemPlugin = async ({
|
|
|
1097
1091
|
if (!viewerEnabled || !viewerAutoStart || !viewerStarted) {
|
|
1098
1092
|
return { attempted: false, ok: false };
|
|
1099
1093
|
}
|
|
1100
|
-
const restartResult = await runCli(["serve", "
|
|
1094
|
+
const restartResult = await runCli(["serve", "restart"]);
|
|
1101
1095
|
if (restartResult?.exitCode === 0) {
|
|
1102
1096
|
await logLine("compat.auto_update_viewer_restart ok");
|
|
1103
1097
|
return { attempted: true, ok: true };
|
|
@@ -1191,7 +1185,7 @@ export const OpencodeMemPlugin = async ({
|
|
|
1191
1185
|
);
|
|
1192
1186
|
if (viewerRestart.attempted && !viewerRestart.ok) {
|
|
1193
1187
|
await showToast(
|
|
1194
|
-
"Backend updated, but viewer restart failed. Run `codemem serve
|
|
1188
|
+
"Backend updated, but viewer restart failed. Run `codemem serve restart`.",
|
|
1195
1189
|
"warning"
|
|
1196
1190
|
);
|
|
1197
1191
|
}
|
|
@@ -1341,25 +1335,17 @@ export const OpencodeMemPlugin = async ({
|
|
|
1341
1335
|
}
|
|
1342
1336
|
viewerStarted = false;
|
|
1343
1337
|
await logLine("viewer stop requested");
|
|
1344
|
-
await runCli(["serve", "
|
|
1338
|
+
await runCli(["serve", "stop"]);
|
|
1345
1339
|
};
|
|
1346
1340
|
|
|
1347
1341
|
// Get version info (commit hash) for debugging
|
|
1348
1342
|
let version = "unknown";
|
|
1349
1343
|
try {
|
|
1350
|
-
|
|
1351
|
-
cmd: ["git", "rev-parse", "--short", "HEAD"],
|
|
1344
|
+
version = execSync("git rev-parse --short HEAD", {
|
|
1352
1345
|
cwd: runnerFrom,
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
});
|
|
1356
|
-
const gitResult = await Promise.race([
|
|
1357
|
-
new Response(gitProc.stdout).text(),
|
|
1358
|
-
new Promise((resolve) => setTimeout(() => resolve("timeout"), 500)),
|
|
1359
|
-
]);
|
|
1360
|
-
if (typeof gitResult === "string" && gitResult !== "timeout") {
|
|
1361
|
-
version = gitResult.trim();
|
|
1362
|
-
}
|
|
1346
|
+
timeout: 500,
|
|
1347
|
+
encoding: "utf-8",
|
|
1348
|
+
}).trim();
|
|
1363
1349
|
} catch (err) {
|
|
1364
1350
|
// Ignore - version will remain 'unknown'
|
|
1365
1351
|
}
|
|
@@ -1836,7 +1822,6 @@ export const OpencodeMemPlugin = async ({
|
|
|
1836
1822
|
export default OpencodeMemPlugin;
|
|
1837
1823
|
export const __testUtils = {
|
|
1838
1824
|
PINNED_BACKEND_VERSION,
|
|
1839
|
-
DEFAULT_UVX_SOURCE,
|
|
1840
1825
|
buildRunnerArgs,
|
|
1841
1826
|
appendWorkingSetFileArgs,
|
|
1842
1827
|
extractApplyPatchPaths,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmKpC,eAAO,MAAM,YAAY,SA6BtB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1014,17 +1014,15 @@ function claudeConfigDir() {
|
|
|
1014
1014
|
}
|
|
1015
1015
|
/**
|
|
1016
1016
|
* Find the plugin source file — walk up from this module's location
|
|
1017
|
-
* to find the .opencode/
|
|
1017
|
+
* to find the .opencode/plugins/codemem.js in the package tree.
|
|
1018
1018
|
*/
|
|
1019
1019
|
function findPluginSource() {
|
|
1020
1020
|
let dir = dirname(import.meta.url.replace("file://", ""));
|
|
1021
1021
|
for (let i = 0; i < 6; i++) {
|
|
1022
|
-
const candidate = join(dir, ".opencode", "
|
|
1022
|
+
const candidate = join(dir, ".opencode", "plugins", "codemem.js");
|
|
1023
1023
|
if (existsSync(candidate)) return candidate;
|
|
1024
|
-
const nmCandidate = join(dir, "node_modules", "codemem", ".opencode", "
|
|
1024
|
+
const nmCandidate = join(dir, "node_modules", "codemem", ".opencode", "plugins", "codemem.js");
|
|
1025
1025
|
if (existsSync(nmCandidate)) return nmCandidate;
|
|
1026
|
-
const legacyCandidate = join(dir, "node_modules", "@kunickiaj", "codemem", ".opencode", "plugin", "codemem.js");
|
|
1027
|
-
if (existsSync(legacyCandidate)) return legacyCandidate;
|
|
1028
1026
|
const parent = dirname(dir);
|
|
1029
1027
|
if (parent === dir) break;
|
|
1030
1028
|
dir = parent;
|
|
@@ -1052,7 +1050,7 @@ function installPlugin(force) {
|
|
|
1052
1050
|
p.log.error("Plugin file not found in package tree");
|
|
1053
1051
|
return false;
|
|
1054
1052
|
}
|
|
1055
|
-
const destDir = join(opencodeConfigDir(), "
|
|
1053
|
+
const destDir = join(opencodeConfigDir(), "plugins");
|
|
1056
1054
|
const dest = join(destDir, "codemem.js");
|
|
1057
1055
|
if (existsSync(dest) && !force) p.log.info(`Plugin already installed at ${dest}`);
|
|
1058
1056
|
else {
|
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-invocation.ts","../src/commands/serve.ts","../src/commands/setup-config.ts","../src/commands/setup.ts","../src/commands/stats.ts","../src/commands/sync-helpers.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(\"--db-path <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; dbPath?: 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 ?? opts.dbPath);\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 { statSync } from \"node:fs\";\nimport * as p from \"@clack/prompts\";\nimport {\n\tconnect,\n\tgetRawEventStatus,\n\tinitDatabase,\n\tMemoryStore,\n\trawEventsGate,\n\tresolveDbPath,\n\tretryRawEventFailures,\n\tvacuumDatabase,\n} from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nfunction formatBytes(bytes: number): string {\n\tif (bytes < 1024) return `${bytes} B`;\n\tif (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n\treturn `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\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.option(\"--db-path <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t\t.action((opts: { db?: string; dbPath?: string }) => {\n\t\t\t\tconst result = initDatabase(opts.db ?? opts.dbPath);\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.option(\"--db-path <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t\t.action((opts: { db?: string; dbPath?: string }) => {\n\t\t\t\tconst result = vacuumDatabase(opts.db ?? opts.dbPath);\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(\"--db-path <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; dbPath?: string; limit: string; json?: boolean }) => {\n\t\t\t\tconst result = getRawEventStatus(\n\t\t\t\t\topts.db ?? opts.dbPath,\n\t\t\t\t\tNumber.parseInt(opts.limit, 10) || 25,\n\t\t\t\t);\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(\"--db-path <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; dbPath?: string; limit: string }) => {\n\t\t\t\tconst result = retryRawEventFailures(\n\t\t\t\t\topts.db ?? opts.dbPath,\n\t\t\t\t\tNumber.parseInt(opts.limit, 10) || 25,\n\t\t\t\t);\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(\"--db-path <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\tdbPath?: 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 ?? opts.dbPath, {\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\t.addCommand(\n\t\tnew Command(\"rename-project\")\n\t\t\t.configureHelp(helpStyle)\n\t\t\t.description(\"Rename a project across sessions and related tables\")\n\t\t\t.argument(\"<old-name>\", \"current project name\")\n\t\t\t.argument(\"<new-name>\", \"new project name\")\n\t\t\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t\t.option(\"--db-path <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t\t.option(\"--apply\", \"apply changes (default is dry-run)\")\n\t\t\t.action(\n\t\t\t\t(\n\t\t\t\t\toldName: string,\n\t\t\t\t\tnewName: string,\n\t\t\t\t\topts: { db?: string; dbPath?: string; apply?: boolean },\n\t\t\t\t) => {\n\t\t\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst dryRun = !opts.apply;\n\t\t\t\t\t\tconst escapedOld = oldName.replace(/%/g, \"\\\\%\").replace(/_/g, \"\\\\_\");\n\t\t\t\t\t\tconst suffixPattern = `%/${escapedOld}`;\n\t\t\t\t\t\tconst tables = [\"sessions\", \"raw_event_sessions\"] as const;\n\t\t\t\t\t\tconst counts: Record<string, number> = {};\n\t\t\t\t\t\tconst run = () => {\n\t\t\t\t\t\t\tfor (const table of tables) {\n\t\t\t\t\t\t\t\tconst rows = store.db\n\t\t\t\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t\t\t\t`SELECT COUNT(*) as cnt FROM ${table} WHERE project = ? OR project LIKE ? ESCAPE '\\\\'`,\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t.get(oldName, suffixPattern) as { cnt: number };\n\t\t\t\t\t\t\t\tcounts[table] = rows.cnt;\n\t\t\t\t\t\t\t\tif (!dryRun && rows.cnt > 0) {\n\t\t\t\t\t\t\t\t\tstore.db\n\t\t\t\t\t\t\t\t\t\t.prepare(`UPDATE ${table} SET project = ? WHERE project = ?`)\n\t\t\t\t\t\t\t\t\t\t.run(newName, oldName);\n\t\t\t\t\t\t\t\t\tstore.db\n\t\t\t\t\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t\t\t\t\t`UPDATE ${table} SET project = ? WHERE project LIKE ? ESCAPE '\\\\' AND project != ?`,\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t.run(newName, suffixPattern, newName);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\t\t\t\t\t\tif (dryRun) {\n\t\t\t\t\t\t\trun();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tstore.db.transaction(run)();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst action = dryRun ? \"Will rename\" : \"Renamed\";\n\t\t\t\t\t\tp.intro(\"codemem db rename-project\");\n\t\t\t\t\t\tp.log.info(`${action} ${oldName} → ${newName}`);\n\t\t\t\t\t\tp.log.info(\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t`Sessions: ${counts.sessions}`,\n\t\t\t\t\t\t\t\t`Raw event sessions: ${counts.raw_event_sessions}`,\n\t\t\t\t\t\t\t].join(\"\\n\"),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (dryRun) {\n\t\t\t\t\t\t\tp.outro(\"Pass --apply to execute\");\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tp.outro(\"done\");\n\t\t\t\t\t\t}\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tstore.close();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t),\n\t)\n\t.addCommand(\n\t\tnew Command(\"normalize-projects\")\n\t\t\t.configureHelp(helpStyle)\n\t\t\t.description(\"Normalize path-like project identifiers to their basename\")\n\t\t\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t\t.option(\"--db-path <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t\t.option(\"--apply\", \"apply changes (default is dry-run)\")\n\t\t\t.action((opts: { db?: string; dbPath?: string; apply?: boolean }) => {\n\t\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\n\t\t\t\ttry {\n\t\t\t\t\tconst dryRun = !opts.apply;\n\t\t\t\t\tconst tables = [\"sessions\", \"raw_event_sessions\"] as const;\n\t\t\t\t\tconst rewrites: Map<string, string> = new Map();\n\t\t\t\t\tconst counts: Record<string, number> = {};\n\n\t\t\t\t\tconst run = () => {\n\t\t\t\t\t\tfor (const table of tables) {\n\t\t\t\t\t\t\tconst projects = store.db\n\t\t\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t\t\t`SELECT DISTINCT project FROM ${table} WHERE project IS NOT NULL AND project LIKE '%/%'`,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t.all() as Array<{ project: string }>;\n\t\t\t\t\t\t\tlet updated = 0;\n\t\t\t\t\t\t\tfor (const row of projects) {\n\t\t\t\t\t\t\t\tconst basename = row.project.split(\"/\").pop() ?? row.project;\n\t\t\t\t\t\t\t\tif (basename !== row.project) {\n\t\t\t\t\t\t\t\t\trewrites.set(row.project, basename);\n\t\t\t\t\t\t\t\t\tif (!dryRun) {\n\t\t\t\t\t\t\t\t\t\tconst info = store.db\n\t\t\t\t\t\t\t\t\t\t\t.prepare(`UPDATE ${table} SET project = ? WHERE project = ?`)\n\t\t\t\t\t\t\t\t\t\t\t.run(basename, row.project);\n\t\t\t\t\t\t\t\t\t\tupdated += info.changes;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tconst cnt = store.db\n\t\t\t\t\t\t\t\t\t\t\t.prepare(`SELECT COUNT(*) as cnt FROM ${table} WHERE project = ?`)\n\t\t\t\t\t\t\t\t\t\t\t.get(row.project) as { cnt: number };\n\t\t\t\t\t\t\t\t\t\tupdated += cnt.cnt;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcounts[table] = updated;\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\tif (dryRun) {\n\t\t\t\t\t\trun();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstore.db.transaction(run)();\n\t\t\t\t\t}\n\n\t\t\t\t\tp.intro(\"codemem db normalize-projects\");\n\t\t\t\t\tp.log.info(`Dry run: ${dryRun}`);\n\t\t\t\t\tp.log.info(\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t`Sessions to update: ${counts.sessions}`,\n\t\t\t\t\t\t\t`Raw event sessions to update: ${counts.raw_event_sessions}`,\n\t\t\t\t\t\t].join(\"\\n\"),\n\t\t\t\t\t);\n\t\t\t\t\tif (rewrites.size > 0) {\n\t\t\t\t\t\tp.log.info(\"Rewritten paths:\");\n\t\t\t\t\t\tfor (const [from, to] of [...rewrites.entries()].sort()) {\n\t\t\t\t\t\t\tp.log.message(` ${from} → ${to}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (dryRun) {\n\t\t\t\t\t\tp.outro(\"Pass --apply to execute\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\tp.outro(\"done\");\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\tstore.close();\n\t\t\t\t}\n\t\t\t}),\n\t)\n\t.addCommand(\n\t\tnew Command(\"size-report\")\n\t\t\t.configureHelp(helpStyle)\n\t\t\t.description(\"Show SQLite file size and major storage consumers\")\n\t\t\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t\t.option(\"--db-path <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t\t.option(\"--limit <n>\", \"number of largest tables/indexes to show\", \"12\")\n\t\t\t.option(\"--json\", \"output as JSON\")\n\t\t\t.action((opts: { db?: string; dbPath?: string; limit: string; json?: boolean }) => {\n\t\t\t\tconst dbPath = resolveDbPath(opts.db ?? opts.dbPath);\n\t\t\t\tconst db = connect(dbPath);\n\t\t\t\ttry {\n\t\t\t\t\tconst limit = Math.max(1, Number.parseInt(opts.limit, 10) || 12);\n\t\t\t\t\tconst fileSizeBytes = statSync(dbPath).size;\n\t\t\t\t\tconst pageInfo = db\n\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t\"SELECT page_count * page_size as total FROM pragma_page_count, pragma_page_size\",\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.get() as { total: number } | undefined;\n\t\t\t\t\tconst freePages = db.prepare(\"SELECT freelist_count FROM pragma_freelist_count\").get() as\n\t\t\t\t\t\t| { freelist_count: number }\n\t\t\t\t\t\t| undefined;\n\t\t\t\t\tconst pageSize = db.prepare(\"PRAGMA page_size\").get() as\n\t\t\t\t\t\t| { page_size: number }\n\t\t\t\t\t\t| undefined;\n\t\t\t\t\tconst tables = db\n\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t`SELECT name, SUM(pgsize) as size_bytes\n\t\t\t\t\t\t\t FROM dbstat\n\t\t\t\t\t\t\t GROUP BY name\n\t\t\t\t\t\t\t ORDER BY size_bytes DESC\n\t\t\t\t\t\t\t LIMIT ?`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.all(limit) as Array<{ name: string; size_bytes: number }>;\n\n\t\t\t\t\tif (opts.json) {\n\t\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t\tJSON.stringify(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfile_size_bytes: fileSizeBytes,\n\t\t\t\t\t\t\t\t\tdb_size_bytes: pageInfo?.total ?? 0,\n\t\t\t\t\t\t\t\t\tfree_bytes: (freePages?.freelist_count ?? 0) * (pageSize?.page_size ?? 4096),\n\t\t\t\t\t\t\t\t\ttables: tables.map((t) => ({ name: t.name, size_bytes: t.size_bytes })),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t\t2,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tp.intro(\"codemem db size-report\");\n\t\t\t\t\tp.log.info(\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t`File size: ${formatBytes(fileSizeBytes)}`,\n\t\t\t\t\t\t\t`DB size: ${formatBytes(pageInfo?.total ?? 0)}`,\n\t\t\t\t\t\t\t`Free space: ${formatBytes((freePages?.freelist_count ?? 0) * (pageSize?.page_size ?? 4096))}`,\n\t\t\t\t\t\t].join(\"\\n\"),\n\t\t\t\t\t);\n\t\t\t\t\tif (tables.length > 0) {\n\t\t\t\t\t\tp.log.info(\"Largest objects:\");\n\t\t\t\t\t\tfor (const t of tables) {\n\t\t\t\t\t\t\tp.log.message(` ${t.name.padEnd(40)} ${formatBytes(t.size_bytes).padStart(10)}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tp.outro(\"done\");\n\t\t\t\t} finally {\n\t\t\t\t\tdb.close();\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.option(\"--db-path <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.action(async (opts: { db?: string; dbPath?: 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 ?? opts.dbPath));\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(\"--db-path <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\tdbPath?: 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 ?? opts.dbPath),\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(\"--db-path <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(\n\t\t(\n\t\t\tinputFile: string,\n\t\t\topts: { db?: string; dbPath?: string; remapProject?: string; dryRun?: boolean },\n\t\t) => {\n\t\t\tlet payload: ExportPayload;\n\t\t\ttry {\n\t\t\t\tpayload = readImportPayload(inputFile);\n\t\t\t} catch (error) {\n\t\t\t\tp.log.error(error instanceof Error ? error.message : \"Invalid import file\");\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tp.intro(\"codemem import-memories\");\n\t\t\tp.log.info(\n\t\t\t\t[\n\t\t\t\t\t`Export version: ${payload.version}`,\n\t\t\t\t\t`Exported at: ${payload.exported_at}`,\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\n\t\t\tconst result = importMemories(payload, {\n\t\t\t\tdbPath: resolveDbPath(opts.db ?? opts.dbPath),\n\t\t\t\tremapProject: opts.remapProject,\n\t\t\t\tdryRun: opts.dryRun,\n\t\t\t});\n\n\t\t\tif (result.dryRun) {\n\t\t\t\tp.outro(\"dry run complete\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.log.success(\n\t\t\t\t[\n\t\t\t\t\t`Imported sessions: ${result.sessions.toLocaleString()}`,\n\t\t\t\t\t`Imported prompts: ${result.user_prompts.toLocaleString()}`,\n\t\t\t\t\t`Imported memories: ${result.memory_items.toLocaleString()}`,\n\t\t\t\t\t`Imported summaries: ${result.session_summaries.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 { 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.option(\"--db-path <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.action(async (opts: { db?: string; dbPath?: string }) => {\n\t\tconst dbPath = opts.db ?? opts.dbPath;\n\t\tif (dbPath) process.env.CODEMEM_DB = dbPath;\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\nfunction showMemoryAction(idStr: string, opts: { db?: string; dbPath?: string }): void {\n\tconst memoryId = parseStrictPositiveId(idStr);\n\tif (memoryId === null) {\n\t\tp.log.error(`Invalid memory ID: ${idStr}`);\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\n\ttry {\n\t\tconst item = store.get(memoryId);\n\t\tif (!item) {\n\t\t\tp.log.error(`Memory ${memoryId} not found`);\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\t\tconsole.log(JSON.stringify(item, null, 2));\n\t} finally {\n\t\tstore.close();\n\t}\n}\n\nfunction forgetMemoryAction(idStr: string, opts: { db?: string; dbPath?: string }): void {\n\tconst memoryId = parseStrictPositiveId(idStr);\n\tif (memoryId === null) {\n\t\tp.log.error(`Invalid memory ID: ${idStr}`);\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\n\ttry {\n\t\tstore.forget(memoryId);\n\t\tp.log.success(`Memory ${memoryId} marked inactive`);\n\t} finally {\n\t\tstore.close();\n\t}\n}\n\ninterface RememberMemoryOptions {\n\tkind: string;\n\ttitle: string;\n\tbody: string;\n\ttags?: string[];\n\tproject?: string;\n\tdb?: string;\n\tdbPath?: string;\n}\n\nfunction rememberMemoryAction(opts: RememberMemoryOptions): void {\n\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\n\tlet sessionId: number | null = null;\n\ttry {\n\t\tconst project = resolveProject(process.cwd(), opts.project ?? null);\n\t\tsessionId = store.startSession({\n\t\t\tcwd: process.cwd(),\n\t\t\tproject,\n\t\t\tuser: process.env.USER ?? \"unknown\",\n\t\t\ttoolVersion: \"manual\",\n\t\t\tmetadata: { manual: true },\n\t\t});\n\t\tconst memId = store.remember(sessionId, opts.kind, opts.title, opts.body, 0.5, opts.tags);\n\t\tstore.endSession(sessionId, { manual: true });\n\t\tp.log.success(`Stored memory ${memId}`);\n\t} catch (err) {\n\t\tif (sessionId !== null) {\n\t\t\ttry {\n\t\t\t\tstore.endSession(sessionId, { manual: true, error: true });\n\t\t\t} catch {\n\t\t\t\t// ignore — already in error path\n\t\t\t}\n\t\t}\n\t\tthrow err;\n\t} finally {\n\t\tstore.close();\n\t}\n}\n\nfunction createShowMemoryCommand(): Command {\n\treturn new 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.option(\"--db-path <path>\", \"database path\")\n\t\t.action(showMemoryAction);\n}\n\nfunction createForgetMemoryCommand(): Command {\n\treturn new 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.option(\"--db-path <path>\", \"database path\")\n\t\t.action(forgetMemoryAction);\n}\n\nfunction createRememberMemoryCommand(): Command {\n\treturn new 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.option(\"--db-path <path>\", \"database path\")\n\t\t.action(rememberMemoryAction);\n}\n\nexport const showMemoryCommand = createShowMemoryCommand();\nexport const forgetMemoryCommand = createForgetMemoryCommand();\nexport const rememberMemoryCommand = createRememberMemoryCommand();\n\nexport const memoryCommand = new Command(\"memory\")\n\t.configureHelp(helpStyle)\n\t.description(\"Memory item management\");\n\nmemoryCommand.addCommand(createShowMemoryCommand());\nmemoryCommand.addCommand(createForgetMemoryCommand());\nmemoryCommand.addCommand(createRememberMemoryCommand());\n","import * as p from \"@clack/prompts\";\nimport { MemoryStore, resolveDbPath, resolveProject } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nfunction collectWorkingSetFile(value: string, previous: string[]): string[] {\n\treturn [...previous, value];\n}\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(\"--db-path <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(\"--token-budget <tokens>\", \"token budget\")\n\t.option(\n\t\t\"--working-set-file <path>\",\n\t\t\"recently modified file path used as ranking hint\",\n\t\tcollectWorkingSetFile,\n\t\t[],\n\t)\n\t.option(\"--project <project>\", \"project identifier (defaults to git repo root)\")\n\t.option(\"--all-projects\", \"search across all projects\")\n\t.option(\"--json\", \"output as JSON\")\n\t.action(\n\t\t(\n\t\t\tcontext: string,\n\t\t\topts: {\n\t\t\t\tdb?: string;\n\t\t\t\tdbPath?: string;\n\t\t\t\tlimit: string;\n\t\t\t\tbudget?: string;\n\t\t\t\ttokenBudget?: string;\n\t\t\t\tworkingSetFile?: string[];\n\t\t\t\tproject?: string;\n\t\t\t\tallProjects?: boolean;\n\t\t\t\tjson?: boolean;\n\t\t\t},\n\t\t) => {\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\n\t\t\ttry {\n\t\t\t\tconst limit = Number.parseInt(opts.limit, 10) || 10;\n\t\t\t\tconst budgetRaw = opts.tokenBudget ?? opts.budget;\n\t\t\t\tconst budget = budgetRaw ? Number.parseInt(budgetRaw, 10) : undefined;\n\t\t\t\tconst filters: { project?: string } = {};\n\t\t\t\tif (!opts.allProjects) {\n\t\t\t\t\tconst defaultProject = process.env.CODEMEM_PROJECT?.trim() || null;\n\t\t\t\t\tconst project = defaultProject || resolveProject(process.cwd(), opts.project ?? null);\n\t\t\t\t\tif (project) filters.project = project;\n\t\t\t\t}\n\t\t\t\tif ((opts.workingSetFile?.length ?? 0) > 0) {\n\t\t\t\t\tp.log.warn(\n\t\t\t\t\t\t\"--working-set-file is accepted for compatibility but is not yet used by the TS pack builder.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst result = store.buildMemoryPack(context, limit, budget, filters);\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, resolveProject } 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(\"--db-path <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.option(\"--limit <n>\", \"max results\", \"5\")\n\t.option(\"--project <project>\", \"project identifier (defaults to git repo root)\")\n\t.option(\"--all-projects\", \"search across all projects\")\n\t.option(\"--kind <kind>\", \"filter by memory kind\")\n\t.action(\n\t\t(opts: {\n\t\t\tdb?: string;\n\t\t\tdbPath?: string;\n\t\t\tlimit: string;\n\t\t\tproject?: string;\n\t\t\tallProjects?: boolean;\n\t\t\tkind?: string;\n\t\t}) => {\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\n\t\t\ttry {\n\t\t\t\tconst limit = Math.max(1, Number.parseInt(opts.limit, 10) || 5);\n\t\t\t\tconst filters: { kind?: string; project?: string } = {};\n\t\t\t\tif (opts.kind) filters.kind = opts.kind;\n\t\t\t\tif (!opts.allProjects) {\n\t\t\t\t\tconst defaultProject = process.env.CODEMEM_PROJECT?.trim() || null;\n\t\t\t\t\tconst project = defaultProject || resolveProject(process.cwd(), opts.project ?? null);\n\t\t\t\t\tif (project) filters.project = project;\n\t\t\t\t}\n\t\t\t\tconst items = store.recent(limit, filters);\n\t\t\t\tfor (const item of items) {\n\t\t\t\t\tconsole.log(`#${item.id} [${item.kind}] ${item.title}`);\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tstore.close();\n\t\t\t}\n\t\t},\n\t);\n","import * as p from \"@clack/prompts\";\nimport { MemoryStore, resolveDbPath, resolveProject } 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(\"--db-path <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.option(\"-n, --limit <n>\", \"max results\", \"5\")\n\t.option(\"--project <project>\", \"project identifier (defaults to git repo root)\")\n\t.option(\"--all-projects\", \"search across all projects\")\n\t.option(\"--kind <kind>\", \"filter by memory kind\")\n\t.option(\"--json\", \"output as JSON\")\n\t.action(\n\t\t(\n\t\t\tquery: string,\n\t\t\topts: {\n\t\t\t\tdb?: string;\n\t\t\t\tdbPath?: string;\n\t\t\t\tlimit: string;\n\t\t\t\tproject?: string;\n\t\t\t\tallProjects?: boolean;\n\t\t\t\tkind?: string;\n\t\t\t\tjson?: boolean;\n\t\t\t},\n\t\t) => {\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\n\t\t\ttry {\n\t\t\t\tconst limit = Math.max(1, Number.parseInt(opts.limit, 10) || 5);\n\t\t\t\tconst filters: { kind?: string; project?: string } = {};\n\t\t\t\tif (opts.kind) filters.kind = opts.kind;\n\t\t\t\tif (!opts.allProjects) {\n\t\t\t\t\tconst defaultProject = process.env.CODEMEM_PROJECT?.trim() || null;\n\t\t\t\t\tconst project = defaultProject || resolveProject(process.cwd(), opts.project ?? null);\n\t\t\t\t\tif (project) filters.project = project;\n\t\t\t\t}\n\t\t\t\tconst results = store.search(query, limit, filters);\n\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify(results, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (results.length === 0) {\n\t\t\t\t\tp.log.warn(\"No results found.\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tp.intro(`${results.length} result(s) for \"${query}\"`);\n\n\t\t\t\tfor (const item of results) {\n\t\t\t\t\tconst score = item.score.toFixed(3);\n\t\t\t\t\tconst age = timeSince(item.created_at);\n\t\t\t\t\tconst preview =\n\t\t\t\t\t\titem.body_text.length > 120 ? `${item.body_text.slice(0, 120)}…` : item.body_text;\n\n\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t[`#${item.id} ${item.kind} ${age} [${score}]`, item.title, preview].join(\"\\n\"),\n\t\t\t\t\t);\n\t\t\t\t}\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\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","export type ServeMode = \"start\" | \"stop\" | \"restart\";\n\nexport type ServeAction = ServeMode | undefined;\n\nexport interface LegacyServeOptions {\n\tdb?: string;\n\tdbPath?: string;\n\thost: string;\n\tport: string;\n\tbackground?: boolean;\n\tforeground?: boolean;\n\tstop?: boolean;\n\trestart?: boolean;\n}\n\nexport interface StartServeOptions {\n\tdb?: string;\n\tdbPath?: string;\n\thost: string;\n\tport: string;\n\tforeground?: boolean;\n}\n\nexport interface StopRestartServeOptions {\n\tdb?: string;\n\tdbPath?: string;\n\thost: string;\n\tport: string;\n}\n\nexport interface ResolvedServeInvocation {\n\tmode: ServeMode;\n\tdbPath: string | null;\n\thost: string;\n\tport: number;\n\tbackground: boolean;\n}\n\nfunction parsePort(rawPort: string): number {\n\tconst port = Number.parseInt(rawPort, 10);\n\tif (!Number.isFinite(port) || port < 1 || port > 65535) {\n\t\tthrow new Error(`Invalid port: ${rawPort}`);\n\t}\n\treturn port;\n}\n\nexport function resolveLegacyServeInvocation(opts: LegacyServeOptions): ResolvedServeInvocation {\n\tif (opts.stop && opts.restart) {\n\t\tthrow new Error(\"Use only one of --stop or --restart\");\n\t}\n\tif (opts.foreground && opts.background) {\n\t\tthrow new Error(\"Use only one of --background or --foreground\");\n\t}\n\tconst dbPath = opts.db ?? opts.dbPath ?? null;\n\treturn {\n\t\tmode: opts.stop ? \"stop\" : opts.restart ? \"restart\" : \"start\",\n\t\tdbPath,\n\t\thost: opts.host,\n\t\tport: parsePort(opts.port),\n\t\tbackground: opts.restart ? true : opts.background ? true : false,\n\t};\n}\n\nexport function resolveServeInvocation(\n\taction: ServeAction,\n\topts: LegacyServeOptions,\n): ResolvedServeInvocation {\n\tif (action === undefined) {\n\t\treturn resolveLegacyServeInvocation(opts);\n\t}\n\tif (opts.stop || opts.restart) {\n\t\tthrow new Error(\"Do not combine lifecycle flags with a serve action\");\n\t}\n\tif (action === \"start\") {\n\t\treturn resolveStartServeInvocation(opts);\n\t}\n\treturn resolveStopRestartInvocation(action, opts);\n}\n\nexport function resolveStartServeInvocation(opts: StartServeOptions): ResolvedServeInvocation {\n\tconst dbPath = opts.db ?? opts.dbPath ?? null;\n\treturn {\n\t\tmode: \"start\",\n\t\tdbPath,\n\t\thost: opts.host,\n\t\tport: parsePort(opts.port),\n\t\tbackground: !opts.foreground,\n\t};\n}\n\nexport function resolveStopRestartInvocation(\n\tmode: \"stop\" | \"restart\",\n\topts: StopRestartServeOptions,\n): ResolvedServeInvocation {\n\tconst dbPath = opts.db ?? opts.dbPath ?? null;\n\treturn {\n\t\tmode,\n\t\tdbPath,\n\t\thost: opts.host,\n\t\tport: parsePort(opts.port),\n\t\tbackground: mode === \"restart\",\n\t};\n}\n","import { spawn } from \"node:child_process\";\nimport { existsSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport net from \"node:net\";\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\";\nimport {\n\ttype LegacyServeOptions,\n\ttype ResolvedServeInvocation,\n\tresolveServeInvocation,\n\ttype ServeAction,\n} from \"./serve-invocation.js\";\n\ninterface ViewerPidRecord {\n\tpid: number;\n\thost: string;\n\tport: number;\n}\n\nfunction pidFilePath(dbPath: string): string {\n\treturn join(dirname(dbPath), \"viewer.pid\");\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\nfunction isProcessRunning(pid: number): boolean {\n\ttry {\n\t\tprocess.kill(pid, 0);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\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 isPortOpen(host: string, port: number): Promise<boolean> {\n\treturn new Promise((resolve) => {\n\t\tconst socket = net.createConnection({ host, port });\n\t\tconst done = (open: boolean) => {\n\t\t\tsocket.removeAllListeners();\n\t\t\tsocket.destroy();\n\t\t\tresolve(open);\n\t\t};\n\t\tsocket.setTimeout(300);\n\t\tsocket.once(\"connect\", () => done(true));\n\t\tsocket.once(\"timeout\", () => done(false));\n\t\tsocket.once(\"error\", () => done(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\tif (!isProcessRunning(pid)) return;\n\t\tawait new Promise((resolve) => setTimeout(resolve, 100));\n\t}\n}\n\nasync function stopExistingViewer(\n\tdbPath: string,\n): Promise<{ stopped: boolean; pid: number | null }> {\n\tconst pidPath = pidFilePath(dbPath);\n\tconst record = readViewerPidRecord(dbPath);\n\tif (!record) return { stopped: false, pid: null };\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\treturn { stopped: true, pid: record.pid };\n}\n\nexport function buildForegroundRunnerArgs(\n\tscriptPath: string,\n\tinvocation: ResolvedServeInvocation,\n\texecArgv: string[] = process.execArgv,\n): string[] {\n\tconst args = [\n\t\t...execArgv,\n\t\tscriptPath,\n\t\t\"serve\",\n\t\t\"start\",\n\t\t\"--foreground\",\n\t\t\"--host\",\n\t\tinvocation.host,\n\t\t\"--port\",\n\t\tString(invocation.port),\n\t];\n\tif (invocation.dbPath) {\n\t\targs.push(\"--db-path\", invocation.dbPath);\n\t}\n\treturn args;\n}\n\nasync function startBackgroundViewer(invocation: ResolvedServeInvocation): Promise<void> {\n\tif (await isPortOpen(invocation.host, invocation.port)) {\n\t\tp.log.warn(`Viewer already running at http://${invocation.host}:${invocation.port}`);\n\t\treturn;\n\t}\n\tconst scriptPath = process.argv[1];\n\tif (!scriptPath) throw new Error(\"Unable to resolve CLI entrypoint for background launch\");\n\tconst child = spawn(process.execPath, buildForegroundRunnerArgs(scriptPath, invocation), {\n\t\tcwd: process.cwd(),\n\t\tdetached: true,\n\t\tstdio: \"ignore\",\n\t\tenv: {\n\t\t\t...process.env,\n\t\t\t...(invocation.dbPath ? { CODEMEM_DB: invocation.dbPath } : {}),\n\t\t},\n\t});\n\tchild.unref();\n\tif (invocation.dbPath) {\n\t\twriteFileSync(\n\t\t\tpidFilePath(invocation.dbPath),\n\t\t\tJSON.stringify({ pid: child.pid, host: invocation.host, port: invocation.port }),\n\t\t\t\"utf-8\",\n\t\t);\n\t}\n\tp.intro(\"codemem viewer\");\n\tp.outro(\n\t\t`Viewer started in background (pid ${child.pid}) at http://${invocation.host}:${invocation.port}`,\n\t);\n}\n\nasync function startForegroundViewer(invocation: ResolvedServeInvocation): Promise<void> {\n\tconst { createApp, closeStore, getStore } = await import(\"@codemem/server\");\n\tconst { serve } = await import(\"@hono/node-server\");\n\n\tif (invocation.dbPath) process.env.CODEMEM_DB = invocation.dbPath;\n\tif (await isPortOpen(invocation.host, invocation.port)) {\n\t\tp.log.warn(`Viewer already running at http://${invocation.host}:${invocation.port}`);\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\n\tconst observer = new ObserverClient();\n\tconst sweeper = new RawEventSweeper(getStore(), { observer });\n\tsweeper.start();\n\n\tconst syncAbort = new AbortController();\n\tlet syncRunning = false;\n\tconst config = readCodememConfigFile();\n\tconst syncEnabled =\n\t\tconfig.sync_enabled === true ||\n\t\tprocess.env.CODEMEM_SYNC_ENABLED?.toLowerCase() === \"true\" ||\n\t\tprocess.env.CODEMEM_SYNC_ENABLED === \"1\";\n\n\tif (syncEnabled) {\n\t\tsyncRunning = true;\n\t\tconst syncIntervalS = typeof config.sync_interval_s === \"number\" ? config.sync_interval_s : 120;\n\t\trunSyncDaemon({\n\t\t\tdbPath: resolveDbPath(invocation.dbPath ?? undefined),\n\t\t\tintervalS: syncIntervalS,\n\t\t\thost: invocation.host,\n\t\t\tport: invocation.port,\n\t\t\tsignal: syncAbort.signal,\n\t\t})\n\t\t\t.catch((err: unknown) => {\n\t\t\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\t\t\tp.log.error(`Sync daemon failed: ${msg}`);\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\tsyncRunning = false;\n\t\t\t});\n\t}\n\n\tconst app = createApp({ storeFactory: getStore, sweeper });\n\tconst dbPath = resolveDbPath(invocation.dbPath ?? undefined);\n\tconst pidPath = pidFilePath(dbPath);\n\n\tconst server = serve(\n\t\t{ fetch: app.fetch, hostname: invocation.host, port: invocation.port },\n\t\t(info) => {\n\t\t\twriteFileSync(\n\t\t\t\tpidPath,\n\t\t\t\tJSON.stringify({ pid: process.pid, host: invocation.host, port: invocation.port }),\n\t\t\t\t\"utf-8\",\n\t\t\t);\n\t\t\tp.intro(\"codemem viewer\");\n\t\t\tp.log.success(`Listening on http://${info.address}:${info.port}`);\n\t\t\tp.log.info(`Database: ${dbPath}`);\n\t\t\tp.log.step(\"Raw event sweeper started\");\n\t\t\tif (syncRunning) p.log.step(\"Sync daemon started\");\n\t\t},\n\t);\n\n\tserver.on(\"error\", (err: NodeJS.ErrnoException) => {\n\t\tif (err.code === \"EADDRINUSE\") {\n\t\t\tp.log.warn(`Viewer already running at http://${invocation.host}:${invocation.port}`);\n\t\t} else {\n\t\t\tp.log.error(err.message);\n\t\t}\n\t\tprocess.exit(1);\n\t});\n\n\tconst shutdown = async () => {\n\t\tp.outro(\"shutting down\");\n\t\tsyncAbort.abort();\n\t\tawait sweeper.stop();\n\t\tserver.close(() => {\n\t\t\ttry {\n\t\t\t\trmSync(pidPath);\n\t\t\t} catch {\n\t\t\t\t// ignore\n\t\t\t}\n\t\t\tcloseStore();\n\t\t\tprocess.exit(0);\n\t\t});\n\t\tsetTimeout(() => {\n\t\t\ttry {\n\t\t\t\trmSync(pidPath);\n\t\t\t} catch {\n\t\t\t\t// ignore\n\t\t\t}\n\t\t\tcloseStore();\n\t\t\tprocess.exit(1);\n\t\t}, 5000).unref();\n\t};\n\tprocess.on(\"SIGINT\", () => {\n\t\tvoid shutdown();\n\t});\n\tprocess.on(\"SIGTERM\", () => {\n\t\tvoid shutdown();\n\t});\n}\n\nasync function runServeInvocation(invocation: ResolvedServeInvocation): Promise<void> {\n\tconst dbPath = resolveDbPath(invocation.dbPath ?? undefined);\n\tif (invocation.mode === \"stop\" || invocation.mode === \"restart\") {\n\t\tconst result = await stopExistingViewer(dbPath);\n\t\tif (result.stopped) {\n\t\t\tp.intro(\"codemem viewer\");\n\t\t\tp.log.success(`Stopped viewer${result.pid ? ` (pid ${result.pid})` : \"\"}`);\n\t\t\tif (invocation.mode === \"stop\") {\n\t\t\t\tp.outro(\"done\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else if (invocation.mode === \"stop\") {\n\t\t\tp.intro(\"codemem viewer\");\n\t\t\tp.outro(\"No background viewer found\");\n\t\t\treturn;\n\t\t}\n\t}\n\n\tif (invocation.mode === \"start\" || invocation.mode === \"restart\") {\n\t\tif (invocation.background) {\n\t\t\tawait startBackgroundViewer({ ...invocation, dbPath });\n\t\t\treturn;\n\t\t}\n\t\tawait startForegroundViewer({ ...invocation, dbPath });\n\t}\n}\n\nfunction addSharedServeOptions(command: Command): Command {\n\treturn command\n\t\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t.option(\"--db-path <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t.option(\"--host <host>\", \"bind host\", \"127.0.0.1\")\n\t\t.option(\"--port <port>\", \"bind port\", \"38888\");\n}\n\nexport const serveCommand = addSharedServeOptions(\n\tnew Command(\"serve\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Run or manage the viewer\")\n\t\t.argument(\"[action]\", \"lifecycle action (start|stop|restart)\"),\n)\n\t.option(\"--background\", \"run viewer in background\")\n\t.option(\"--foreground\", \"run viewer in foreground\")\n\t.option(\"--stop\", \"stop background viewer\")\n\t.option(\"--restart\", \"restart background viewer\")\n\t.action(async (action: string | undefined, opts: LegacyServeOptions) => {\n\t\tconst normalizedAction =\n\t\t\taction === undefined\n\t\t\t\t? undefined\n\t\t\t\t: action === \"start\" || action === \"stop\" || action === \"restart\"\n\t\t\t\t\t? (action as ServeAction)\n\t\t\t\t\t: null;\n\t\tif (normalizedAction === null) {\n\t\t\tp.log.error(`Unknown serve action: ${action}`);\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\t\tawait runServeInvocation(resolveServeInvocation(normalizedAction, opts));\n\t});\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { stripJsonComments, stripTrailingCommas } from \"@codemem/core\";\n\nexport function resolveOpencodeConfigPath(configDir: string): string {\n\tconst jsonPath = join(configDir, \"opencode.json\");\n\tif (existsSync(jsonPath)) return jsonPath;\n\tconst jsoncPath = join(configDir, \"opencode.jsonc\");\n\tif (existsSync(jsoncPath)) return jsoncPath;\n\treturn jsoncPath;\n}\n\nexport function 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\nexport function 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","/**\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 } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { VERSION } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport { loadJsoncConfig, resolveOpencodeConfigPath, writeJsonConfig } from \"./setup-config.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 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 = resolveOpencodeConfigPath(opencodeConfigDir());\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(\"--db-path <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.option(\"--json\", \"output as JSON\")\n\t.action((opts: { db?: string; dbPath?: string; json?: boolean }) => {\n\t\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\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","export interface SyncAttemptRow {\n\tpeer_device_id: string;\n\tok: number;\n\tops_in: number;\n\tops_out: number;\n\terror: string | null;\n\tfinished_at: string | null;\n}\n\nexport function formatSyncAttempt(row: SyncAttemptRow): string {\n\tconst status = row.ok ? \"ok\" : \"error\";\n\tconst error = String(row.error || \"\");\n\tconst suffix = error ? ` | ${error}` : \"\";\n\treturn `${row.peer_device_id}|${status}|in=${row.ops_in}|out=${row.ops_out}|${row.finished_at ?? \"\"}${suffix}`;\n}\n\nexport interface SyncLifecycleOptions {\n\tdb?: string;\n\tdbPath?: string;\n\thost?: string;\n\tport?: string;\n\tuser?: boolean;\n\tsystem?: boolean;\n}\n\nexport function buildServeLifecycleArgs(\n\taction: \"start\" | \"stop\" | \"restart\",\n\topts: SyncLifecycleOptions,\n\tscriptPath: string,\n\texecArgv: string[] = [],\n): string[] {\n\tif (!scriptPath) throw new Error(\"Unable to resolve CLI entrypoint for sync lifecycle command\");\n\tconst args = [...execArgv, scriptPath, \"serve\"];\n\tif (action === \"start\") {\n\t\targs.push(\"--restart\");\n\t} else if (action === \"stop\") {\n\t\targs.push(\"--stop\");\n\t} else {\n\t\targs.push(\"--restart\");\n\t}\n\tif (opts.db ?? opts.dbPath) args.push(\"--db-path\", opts.db ?? opts.dbPath ?? \"\");\n\tif (opts.host) args.push(\"--host\", opts.host);\n\tif (opts.port) args.push(\"--port\", opts.port);\n\treturn args;\n}\n\nexport function formatSyncOnceResult(\n\tpeerDeviceId: string,\n\tresult: { ok: boolean; error?: string },\n): string {\n\tif (result.ok) return `- ${peerDeviceId}: ok`;\n\tconst suffix = result.error ? `: ${result.error}` : \"\";\n\treturn `- ${peerDeviceId}: error${suffix}`;\n}\n\nexport function parseProjectList(value: string | undefined): string[] {\n\tif (!value) return [];\n\treturn value\n\t\t.split(\",\")\n\t\t.map((item) => item.trim())\n\t\t.filter(Boolean);\n}\n\ntype InterfaceMap = Record<\n\tstring,\n\tArray<{ address: string; family?: string | number; internal?: boolean }> | undefined\n>;\n\nexport function collectAdvertiseAddresses(\n\texplicitAddress: string | null,\n\tconfiguredHost: string | null,\n\tport: number,\n\tinterfaces: InterfaceMap,\n): string[] {\n\tif (explicitAddress && ![\"auto\", \"default\"].includes(explicitAddress.toLowerCase())) {\n\t\treturn [explicitAddress];\n\t}\n\tif (configuredHost && configuredHost !== \"0.0.0.0\") {\n\t\treturn [`${configuredHost}:${port}`];\n\t}\n\tconst addresses = Object.values(interfaces)\n\t\t.flatMap((entries) => entries ?? [])\n\t\t.filter((entry) => !entry.internal)\n\t\t.map((entry) => entry.address)\n\t\t.filter((address) => address && address !== \"127.0.0.1\" && address !== \"::1\")\n\t\t.map((address) => `${address}:${port}`);\n\treturn [...new Set(addresses)];\n}\n","/**\n * Sync CLI commands — enable/disable/status/peers/connect.\n */\n\nimport { spawn } from \"node:child_process\";\nimport { readFileSync } from \"node:fs\";\nimport net from \"node:net\";\nimport { networkInterfaces } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport * as p from \"@clack/prompts\";\nimport {\n\tensureDeviceIdentity,\n\tfingerprintPublicKey,\n\tloadPublicKey,\n\tMemoryStore,\n\treadCodememConfigFile,\n\tresolveDbPath,\n\trunSyncPass,\n\tschema,\n\tsetPeerProjectFilter,\n\tsyncPassPreflight,\n\tupdatePeerAddresses,\n\twriteCodememConfigFile,\n} from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { desc, eq } from \"drizzle-orm\";\nimport { drizzle } from \"drizzle-orm/better-sqlite3\";\nimport { helpStyle } from \"../help-style.js\";\nimport {\n\tbuildServeLifecycleArgs,\n\tcollectAdvertiseAddresses,\n\tformatSyncAttempt,\n\tformatSyncOnceResult,\n\tparseProjectList,\n\ttype SyncLifecycleOptions,\n} from \"./sync-helpers.js\";\n\nfunction parseAttemptsLimit(value: string): number {\n\tif (!/^\\d+$/.test(value.trim())) {\n\t\tthrow new Error(`Invalid --limit: ${value}`);\n\t}\n\treturn Number.parseInt(value, 10);\n}\n\ninterface SyncOnceOptions {\n\tdb?: string;\n\tdbPath?: string;\n\tpeer?: string;\n}\n\ninterface SyncPairOptions {\n\taccept?: string;\n\tacceptFile?: string;\n\tpayloadOnly?: boolean;\n\tname?: string;\n\taddress?: string;\n\tinclude?: string;\n\texclude?: string;\n\tall?: boolean;\n\tdefault?: boolean;\n\tdbPath?: string;\n}\n\nasync function portOpen(host: string, port: number): Promise<boolean> {\n\treturn new Promise((resolve) => {\n\t\tconst socket = net.createConnection({ host, port });\n\t\tconst done = (ok: boolean) => {\n\t\t\tsocket.removeAllListeners();\n\t\t\tsocket.destroy();\n\t\t\tresolve(ok);\n\t\t};\n\t\tsocket.setTimeout(300);\n\t\tsocket.once(\"connect\", () => done(true));\n\t\tsocket.once(\"timeout\", () => done(false));\n\t\tsocket.once(\"error\", () => done(false));\n\t});\n}\n\nfunction readViewerBinding(dbPath: string): { host: string; port: number } | null {\n\ttry {\n\t\tconst raw = readFileSync(join(dirname(dbPath), \"viewer.pid\"), \"utf8\");\n\t\tconst parsed = JSON.parse(raw) as Partial<{ host: string; port: number }>;\n\t\tif (typeof parsed.host === \"string\" && typeof parsed.port === \"number\") {\n\t\t\treturn { host: parsed.host, port: parsed.port };\n\t\t}\n\t} catch {\n\t\t// ignore malformed or missing pidfile\n\t}\n\treturn null;\n}\n\nfunction parseStoredAddressEndpoint(value: string): { host: string; port: number } | null {\n\ttry {\n\t\tconst normalized = value.includes(\"://\") ? value : `http://${value}`;\n\t\tconst url = new URL(normalized);\n\t\tconst port = url.port ? Number.parseInt(url.port, 10) : url.protocol === \"https:\" ? 443 : 80;\n\t\tif (!url.hostname || !Number.isFinite(port)) return null;\n\t\treturn { host: url.hostname, port };\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nasync function runServeLifecycle(\n\taction: \"start\" | \"stop\" | \"restart\",\n\topts: SyncLifecycleOptions,\n): Promise<void> {\n\tif (opts.user === false || opts.system === true) {\n\t\tp.log.warn(\n\t\t\t\"TS sync lifecycle currently manages the local viewer process, not separate user/system services.\",\n\t\t);\n\t}\n\tif (action === \"start\") {\n\t\tconst config = readCodememConfigFile();\n\t\tif (config.sync_enabled !== true) {\n\t\t\tp.log.error(\"Sync is disabled. Run `codemem sync enable` first.\");\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\t\tconst configuredHost = typeof config.sync_host === \"string\" ? config.sync_host : \"0.0.0.0\";\n\t\tconst configuredPort = typeof config.sync_port === \"number\" ? String(config.sync_port) : \"7337\";\n\t\topts.host ??= configuredHost;\n\t\topts.port ??= configuredPort;\n\t} else if (action === \"restart\") {\n\t\tconst config = readCodememConfigFile();\n\t\tconst configuredHost = typeof config.sync_host === \"string\" ? config.sync_host : \"0.0.0.0\";\n\t\tconst configuredPort = typeof config.sync_port === \"number\" ? String(config.sync_port) : \"7337\";\n\t\topts.host ??= configuredHost;\n\t\topts.port ??= configuredPort;\n\t}\n\tconst args = buildServeLifecycleArgs(action, opts, process.argv[1] ?? \"\", process.execArgv);\n\tawait new Promise<void>((resolve, reject) => {\n\t\tconst child = spawn(process.execPath, args, {\n\t\t\tcwd: process.cwd(),\n\t\t\tstdio: \"inherit\",\n\t\t\tenv: {\n\t\t\t\t...process.env,\n\t\t\t\t...((opts.db ?? opts.dbPath) ? { CODEMEM_DB: opts.db ?? opts.dbPath } : {}),\n\t\t\t},\n\t\t});\n\t\tchild.once(\"error\", reject);\n\t\tchild.once(\"exit\", (code) => {\n\t\t\tif (code && code !== 0) {\n\t\t\t\tprocess.exitCode = code;\n\t\t\t}\n\t\t\tresolve();\n\t\t});\n\t});\n}\n\nexport const syncCommand = new Command(\"sync\")\n\t.configureHelp(helpStyle)\n\t.description(\"Sync configuration and peer management\");\n\n// codemem sync attempts\nsyncCommand.addCommand(\n\tnew Command(\"attempts\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Show recent sync attempts\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.option(\"--db-path <path>\", \"database path\")\n\t\t.option(\"--limit <n>\", \"max attempts\", \"10\")\n\t\t.option(\"--json\", \"output as JSON\")\n\t\t.action((opts: { db?: string; dbPath?: string; limit: string; json?: boolean }) => {\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\n\t\t\ttry {\n\t\t\t\tconst d = drizzle(store.db, { schema });\n\t\t\t\tconst limit = parseAttemptsLimit(opts.limit);\n\t\t\t\tconst rows = d\n\t\t\t\t\t.select({\n\t\t\t\t\t\tpeer_device_id: schema.syncAttempts.peer_device_id,\n\t\t\t\t\t\tok: schema.syncAttempts.ok,\n\t\t\t\t\t\tops_in: schema.syncAttempts.ops_in,\n\t\t\t\t\t\tops_out: schema.syncAttempts.ops_out,\n\t\t\t\t\t\terror: schema.syncAttempts.error,\n\t\t\t\t\t\tfinished_at: schema.syncAttempts.finished_at,\n\t\t\t\t\t})\n\t\t\t\t\t.from(schema.syncAttempts)\n\t\t\t\t\t.orderBy(desc(schema.syncAttempts.finished_at))\n\t\t\t\t\t.limit(limit)\n\t\t\t\t\t.all();\n\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify(rows, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tfor (const row of rows) {\n\t\t\t\t\tconsole.log(formatSyncAttempt(row));\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tstore.close();\n\t\t\t}\n\t\t}),\n);\n\nsyncCommand.addCommand(\n\tnew Command(\"start\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Start sync daemon\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.option(\"--db-path <path>\", \"database path\")\n\t\t.option(\"--host <host>\", \"viewer host\")\n\t\t.option(\"--port <port>\", \"viewer port\")\n\t\t.option(\"--user\", \"accepted for compatibility\", true)\n\t\t.option(\"--system\", \"accepted for compatibility\")\n\t\t.action(async (opts: SyncLifecycleOptions) => {\n\t\t\tawait runServeLifecycle(\"start\", opts);\n\t\t}),\n);\n\nsyncCommand.addCommand(\n\tnew Command(\"stop\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Stop sync daemon\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.option(\"--db-path <path>\", \"database path\")\n\t\t.option(\"--host <host>\", \"viewer host\")\n\t\t.option(\"--port <port>\", \"viewer port\")\n\t\t.option(\"--user\", \"accepted for compatibility\", true)\n\t\t.option(\"--system\", \"accepted for compatibility\")\n\t\t.action(async (opts: SyncLifecycleOptions) => {\n\t\t\tawait runServeLifecycle(\"stop\", opts);\n\t\t}),\n);\n\nsyncCommand.addCommand(\n\tnew Command(\"restart\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Restart sync daemon\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.option(\"--db-path <path>\", \"database path\")\n\t\t.option(\"--host <host>\", \"viewer host\")\n\t\t.option(\"--port <port>\", \"viewer port\")\n\t\t.option(\"--user\", \"accepted for compatibility\", true)\n\t\t.option(\"--system\", \"accepted for compatibility\")\n\t\t.action(async (opts: SyncLifecycleOptions) => {\n\t\t\tawait runServeLifecycle(\"restart\", opts);\n\t\t}),\n);\n\nsyncCommand.addCommand(\n\tnew Command(\"once\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Run a single sync pass\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.option(\"--db-path <path>\", \"database path\")\n\t\t.option(\"--peer <peer>\", \"peer device id or name\")\n\t\t.action(async (opts: SyncOnceOptions) => {\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\n\t\t\ttry {\n\t\t\t\tsyncPassPreflight(store.db);\n\t\t\t\tconst d = drizzle(store.db, { schema });\n\t\t\t\tconst rows = opts.peer\n\t\t\t\t\t? (() => {\n\t\t\t\t\t\t\tconst deviceMatches = d\n\t\t\t\t\t\t\t\t.select({ peer_device_id: schema.syncPeers.peer_device_id })\n\t\t\t\t\t\t\t\t.from(schema.syncPeers)\n\t\t\t\t\t\t\t\t.where(eq(schema.syncPeers.peer_device_id, opts.peer))\n\t\t\t\t\t\t\t\t.all();\n\t\t\t\t\t\t\tif (deviceMatches.length > 0) return deviceMatches;\n\t\t\t\t\t\t\tconst nameMatches = d\n\t\t\t\t\t\t\t\t.select({ peer_device_id: schema.syncPeers.peer_device_id })\n\t\t\t\t\t\t\t\t.from(schema.syncPeers)\n\t\t\t\t\t\t\t\t.where(eq(schema.syncPeers.name, opts.peer))\n\t\t\t\t\t\t\t\t.all();\n\t\t\t\t\t\t\tif (nameMatches.length > 1) {\n\t\t\t\t\t\t\t\tp.log.error(`Peer name is ambiguous: ${opts.peer}`);\n\t\t\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\t\t\treturn [];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn nameMatches;\n\t\t\t\t\t\t})()\n\t\t\t\t\t: d\n\t\t\t\t\t\t\t.select({ peer_device_id: schema.syncPeers.peer_device_id })\n\t\t\t\t\t\t\t.from(schema.syncPeers)\n\t\t\t\t\t\t\t.all();\n\n\t\t\t\tif (rows.length === 0) {\n\t\t\t\t\tp.log.warn(\"No peers available for sync\");\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tlet hadFailure = false;\n\t\t\t\tfor (const row of rows) {\n\t\t\t\t\tconst result = await runSyncPass(store.db, row.peer_device_id);\n\t\t\t\t\tif (!result.ok) hadFailure = true;\n\t\t\t\t\tconsole.log(formatSyncOnceResult(row.peer_device_id, result));\n\t\t\t\t}\n\t\t\t\tif (hadFailure) {\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tstore.close();\n\t\t\t}\n\t\t}),\n);\n\nsyncCommand.addCommand(\n\tnew Command(\"pair\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Print pairing payload or accept a peer payload\")\n\t\t.option(\"--accept <json>\", \"accept pairing payload JSON from another device\")\n\t\t.option(\"--accept-file <path>\", \"accept pairing payload from file path, or '-' for stdin\")\n\t\t.option(\"--payload-only\", \"when generating pairing payload, print JSON only\")\n\t\t.option(\"--name <name>\", \"label for the peer\")\n\t\t.option(\"--address <host:port>\", \"override peer address (host:port)\")\n\t\t.option(\"--include <projects>\", \"outbound-only allowlist for accepted peer\")\n\t\t.option(\"--exclude <projects>\", \"outbound-only blocklist for accepted peer\")\n\t\t.option(\"--all\", \"with --accept, push all projects to that peer\")\n\t\t.option(\"--default\", \"with --accept, use default/global push filters\")\n\t\t.option(\"--db-path <path>\", \"database path\")\n\t\t.action(async (opts: SyncPairOptions) => {\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.dbPath));\n\t\t\ttry {\n\t\t\t\tconst acceptModeRequested = opts.accept != null || opts.acceptFile != null;\n\t\t\t\tif (opts.payloadOnly && acceptModeRequested) {\n\t\t\t\t\tp.log.error(\"--payload-only cannot be combined with --accept or --accept-file\");\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (opts.accept && opts.acceptFile) {\n\t\t\t\t\tp.log.error(\"Use only one of --accept or --accept-file\");\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tlet acceptText = opts.accept;\n\t\t\t\tif (opts.acceptFile) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tacceptText =\n\t\t\t\t\t\t\topts.acceptFile === \"-\"\n\t\t\t\t\t\t\t\t? await new Promise<string>((resolve, reject) => {\n\t\t\t\t\t\t\t\t\t\tlet text = \"\";\n\t\t\t\t\t\t\t\t\t\tprocess.stdin.setEncoding(\"utf8\");\n\t\t\t\t\t\t\t\t\t\tprocess.stdin.on(\"data\", (chunk) => {\n\t\t\t\t\t\t\t\t\t\t\ttext += chunk;\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\tprocess.stdin.on(\"end\", () => resolve(text));\n\t\t\t\t\t\t\t\t\t\tprocess.stdin.on(\"error\", reject);\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t: readFileSync(opts.acceptFile, \"utf8\");\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tp.log.error(\n\t\t\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t\t\t? `Failed to read pairing payload from ${opts.acceptFile}: ${error.message}`\n\t\t\t\t\t\t\t\t: `Failed to read pairing payload from ${opts.acceptFile}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (acceptModeRequested && !(acceptText ?? \"\").trim()) {\n\t\t\t\t\tp.log.error(\"Empty pairing payload; provide JSON via --accept or --accept-file\");\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (!acceptText && (opts.include || opts.exclude || opts.all || opts.default)) {\n\t\t\t\t\tp.log.error(\n\t\t\t\t\t\t\"Project filters are outbound-only and must be set on the device running --accept\",\n\t\t\t\t\t);\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (acceptText?.trim()) {\n\t\t\t\t\tif (opts.all && opts.default) {\n\t\t\t\t\t\tp.log.error(\"Use only one of --all or --default\");\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif ((opts.all || opts.default) && (opts.include || opts.exclude)) {\n\t\t\t\t\t\tp.log.error(\"--include/--exclude cannot be combined with --all/--default\");\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tlet payload: Record<string, unknown>;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tpayload = JSON.parse(acceptText) as Record<string, unknown>;\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tp.log.error(\n\t\t\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t\t\t? `Invalid pairing payload: ${error.message}`\n\t\t\t\t\t\t\t\t: \"Invalid pairing payload\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst deviceId = String(payload.device_id || \"\").trim();\n\t\t\t\t\tconst fingerprint = String(payload.fingerprint || \"\").trim();\n\t\t\t\t\tconst publicKey = String(payload.public_key || \"\").trim();\n\t\t\t\t\tconst resolvedAddresses = opts.address?.trim()\n\t\t\t\t\t\t? [opts.address.trim()]\n\t\t\t\t\t\t: Array.isArray(payload.addresses)\n\t\t\t\t\t\t\t? (payload.addresses as unknown[])\n\t\t\t\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t\t\t\t(item): item is string => typeof item === \"string\" && item.trim().length > 0,\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t.map((item) => item.trim())\n\t\t\t\t\t\t\t: [];\n\t\t\t\t\tif (!deviceId || !fingerprint || !publicKey || resolvedAddresses.length === 0) {\n\t\t\t\t\t\tp.log.error(\"Pairing payload missing device_id, fingerprint, public_key, or addresses\");\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (fingerprintPublicKey(publicKey) !== fingerprint) {\n\t\t\t\t\t\tp.log.error(\"Pairing payload fingerprint mismatch\");\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tupdatePeerAddresses(store.db, deviceId, resolvedAddresses, {\n\t\t\t\t\t\tname: opts.name,\n\t\t\t\t\t\tpinnedFingerprint: fingerprint,\n\t\t\t\t\t\tpublicKey,\n\t\t\t\t\t});\n\n\t\t\t\t\tif (opts.default) {\n\t\t\t\t\t\tsetPeerProjectFilter(store.db, deviceId, { include: null, exclude: null });\n\t\t\t\t\t} else if (opts.all || opts.include || opts.exclude) {\n\t\t\t\t\t\tsetPeerProjectFilter(store.db, deviceId, {\n\t\t\t\t\t\t\tinclude: opts.all ? [] : parseProjectList(opts.include),\n\t\t\t\t\t\t\texclude: opts.all ? [] : parseProjectList(opts.exclude),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tp.log.success(`Paired with ${deviceId}`);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst keysDir = process.env.CODEMEM_KEYS_DIR?.trim() || undefined;\n\t\t\t\tconst [deviceId, fingerprint] = ensureDeviceIdentity(store.db, { keysDir });\n\t\t\t\tconst publicKey = loadPublicKey(keysDir);\n\t\t\t\tif (!publicKey) {\n\t\t\t\t\tp.log.error(\"Public key missing\");\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst config = readCodememConfigFile();\n\t\t\t\tconst explicitAddress = opts.address?.trim();\n\t\t\t\tconst configuredHost = typeof config.sync_host === \"string\" ? config.sync_host : null;\n\t\t\t\tconst configuredPort = typeof config.sync_port === \"number\" ? config.sync_port : 7337;\n\t\t\t\tconst addresses = collectAdvertiseAddresses(\n\t\t\t\t\texplicitAddress ?? null,\n\t\t\t\t\tconfiguredHost,\n\t\t\t\t\tconfiguredPort,\n\t\t\t\t\tnetworkInterfaces(),\n\t\t\t\t);\n\t\t\t\tconst payload = {\n\t\t\t\t\tdevice_id: deviceId,\n\t\t\t\t\tfingerprint,\n\t\t\t\t\tpublic_key: publicKey,\n\t\t\t\t\taddress: addresses[0] ?? \"\",\n\t\t\t\t\taddresses,\n\t\t\t\t};\n\t\t\t\tconst payloadText = JSON.stringify(payload);\n\n\t\t\t\tif (opts.payloadOnly) {\n\t\t\t\t\tprocess.stdout.write(`${payloadText}\\n`);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst escaped = payloadText.replaceAll(\"'\", \"'\\\\''\");\n\t\t\t\tconsole.log(\"Pairing payload\");\n\t\t\t\tconsole.log(payloadText);\n\t\t\t\tconsole.log(\"On the other device, save this JSON to pairing.json, then run:\");\n\t\t\t\tconsole.log(\" codemem sync pair --accept-file pairing.json\");\n\t\t\t\tconsole.log(\"If you prefer inline JSON, run:\");\n\t\t\t\tconsole.log(` codemem sync pair --accept '${escaped}'`);\n\t\t\t\tconsole.log(\"For machine-friendly output next time, run:\");\n\t\t\t\tconsole.log(\" codemem sync pair --payload-only\");\n\t\t\t\tconsole.log(\n\t\t\t\t\t\"On the accepting device, --include/--exclude only control what it sends to peers.\",\n\t\t\t\t);\n\t\t\t\tconsole.log(\"This device does not yet enforce incoming project filters.\");\n\t\t\t} finally {\n\t\t\t\tstore.close();\n\t\t\t}\n\t\t}),\n);\n\nsyncCommand.addCommand(\n\tnew Command(\"doctor\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Diagnose common sync setup and connectivity issues\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.option(\"--db-path <path>\", \"database path\")\n\t\t.action(async (opts: { db?: string; dbPath?: string }) => {\n\t\t\tconst config = readCodememConfigFile();\n\t\t\tconst dbPath = resolveDbPath(opts.db ?? opts.dbPath);\n\t\t\tconst store = new MemoryStore(dbPath);\n\t\t\ttry {\n\t\t\t\tconst d = drizzle(store.db, { schema });\n\t\t\t\tconst device = d\n\t\t\t\t\t.select({ device_id: schema.syncDevice.device_id })\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 daemonState = d\n\t\t\t\t\t.select()\n\t\t\t\t\t.from(schema.syncDaemonState)\n\t\t\t\t\t.where(eq(schema.syncDaemonState.id, 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\taddresses_json: schema.syncPeers.addresses_json,\n\t\t\t\t\t\tpinned_fingerprint: schema.syncPeers.pinned_fingerprint,\n\t\t\t\t\t\tpublic_key: schema.syncPeers.public_key,\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\tconst issues: string[] = [];\n\t\t\t\tconst syncHost = typeof config.sync_host === \"string\" ? config.sync_host : \"0.0.0.0\";\n\t\t\t\tconst syncPort = typeof config.sync_port === \"number\" ? config.sync_port : 7337;\n\t\t\t\tconst viewerBinding = readViewerBinding(dbPath);\n\n\t\t\t\tconsole.log(\"Sync doctor\");\n\t\t\t\tconsole.log(`- Enabled: ${config.sync_enabled === true}`);\n\t\t\t\tconsole.log(`- Listen: ${syncHost}:${syncPort}`);\n\t\t\t\tconsole.log(`- mDNS: ${process.env.CODEMEM_SYNC_MDNS ? \"env-configured\" : \"default/off\"}`);\n\n\t\t\t\tconst reachable = viewerBinding\n\t\t\t\t\t? await portOpen(viewerBinding.host, viewerBinding.port)\n\t\t\t\t\t: false;\n\t\t\t\tconsole.log(`- Daemon: ${reachable ? \"running\" : \"not running\"}`);\n\t\t\t\tif (!reachable) issues.push(\"daemon not running\");\n\n\t\t\t\tif (!device) {\n\t\t\t\t\tconsole.log(\"- Identity: missing (run `codemem sync enable`)\");\n\t\t\t\t\tissues.push(\"identity missing\");\n\t\t\t\t} else {\n\t\t\t\t\tconsole.log(`- Identity: ${device.device_id}`);\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\tdaemonState?.last_error &&\n\t\t\t\t\t(!daemonState.last_ok_at || daemonState.last_ok_at < (daemonState.last_error_at ?? \"\"))\n\t\t\t\t) {\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t`- Daemon error: ${daemonState.last_error} (at ${daemonState.last_error_at ?? \"unknown\"})`,\n\t\t\t\t\t);\n\t\t\t\t\tissues.push(\"daemon error\");\n\t\t\t\t}\n\n\t\t\t\tif (peers.length === 0) {\n\t\t\t\t\tconsole.log(\"- Peers: none (pair a device first)\");\n\t\t\t\t\tissues.push(\"no peers\");\n\t\t\t\t} else {\n\t\t\t\t\tconsole.log(`- Peers: ${peers.length}`);\n\t\t\t\t\tfor (const peer of peers) {\n\t\t\t\t\t\tconst addresses = peer.addresses_json\n\t\t\t\t\t\t\t? (JSON.parse(peer.addresses_json) as string[])\n\t\t\t\t\t\t\t: [];\n\t\t\t\t\t\tconst endpoint = parseStoredAddressEndpoint(addresses[0] ?? \"\");\n\t\t\t\t\t\tconst reach = endpoint\n\t\t\t\t\t\t\t? (await portOpen(endpoint.host, endpoint.port))\n\t\t\t\t\t\t\t\t? \"ok\"\n\t\t\t\t\t\t\t\t: \"unreachable\"\n\t\t\t\t\t\t\t: \"unknown\";\n\t\t\t\t\t\tconst pinned = Boolean(peer.pinned_fingerprint);\n\t\t\t\t\t\tconst hasKey = Boolean(peer.public_key);\n\t\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t\t` - ${peer.peer_device_id}: addresses=${addresses.length} reach=${reach} pinned=${pinned} public_key=${hasKey}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (reach !== \"ok\") issues.push(`peer ${peer.peer_device_id} unreachable`);\n\t\t\t\t\t\tif (!pinned || !hasKey) issues.push(`peer ${peer.peer_device_id} not pinned`);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!config.sync_enabled) issues.push(\"sync is disabled\");\n\n\t\t\t\tif (issues.length > 0) {\n\t\t\t\t\tconsole.log(`WARN: ${[...new Set(issues)].slice(0, 3).join(\", \")}`);\n\t\t\t\t} else {\n\t\t\t\t\tconsole.log(\"OK: sync looks healthy\");\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tstore.close();\n\t\t\t}\n\t\t}),\n);\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(\"--db-path <path>\", \"database path\")\n\t\t.option(\"--json\", \"output as JSON\")\n\t\t.action((opts: { db?: string; dbPath?: string; json?: boolean }) => {\n\t\t\tconst config = readCodememConfigFile();\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\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(\"--db-path <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(\n\t\t\t(opts: { db?: string; dbPath?: string; host?: string; port?: string; interval?: string }) => {\n\t\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\n\t\t\t\ttry {\n\t\t\t\t\tconst [deviceId, fingerprint] = ensureDeviceIdentity(store.db);\n\t\t\t\t\tconst config = readCodememConfigFile();\n\t\t\t\t\tconfig.sync_enabled = true;\n\t\t\t\t\tif (opts.host) config.sync_host = opts.host;\n\t\t\t\t\tif (opts.port) config.sync_port = Number.parseInt(opts.port, 10);\n\t\t\t\t\tif (opts.interval) config.sync_interval_s = Number.parseInt(opts.interval, 10);\n\t\t\t\t\twriteCodememConfigFile(config);\n\n\t\t\t\t\tp.intro(\"codemem sync enable\");\n\t\t\t\t\tp.log.success(\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t`Device ID: ${deviceId}`,\n\t\t\t\t\t\t\t`Fingerprint: ${fingerprint}`,\n\t\t\t\t\t\t\t`Host: ${config.sync_host ?? \"0.0.0.0\"}`,\n\t\t\t\t\t\t\t`Port: ${config.sync_port ?? 7337}`,\n\t\t\t\t\t\t\t`Interval: ${config.sync_interval_s ?? 120}s`,\n\t\t\t\t\t\t].join(\"\\n\"),\n\t\t\t\t\t);\n\t\t\t\t\tp.outro(\"Sync enabled — restart `codemem serve` to activate\");\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\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(\"--db-path <path>\", \"database path\")\n\t\t.option(\"--json\", \"output as JSON\")\n\t\t.action((opts: { db?: string; dbPath?: string; json?: boolean }) => {\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\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 {\n\tforgetMemoryCommand,\n\tmemoryCommand,\n\trememberMemoryCommand,\n\tshowMemoryCommand,\n} 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\"forget\",\n\t\t\"memory\",\n\t\t\"import-memories\",\n\t\t\"setup\",\n\t\t\"show\",\n\t\t\"sync\",\n\t\t\"stats\",\n\t\t\"recent\",\n\t\t\"remember\",\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\nfunction hasRootFlag(flag: string): boolean {\n\tfor (const arg of process.argv.slice(2)) {\n\t\tif (arg === \"--\") return false;\n\t\tif (arg === flag) return true;\n\t\tif (!arg.startsWith(\"-\")) return false;\n\t}\n\treturn false;\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\nif (hasRootFlag(\"--setup-completion\")) {\n\tcompletion.setupShellInitFile();\n\tprocess.exit(0);\n}\n\nif (hasRootFlag(\"--cleanup-completion\")) {\n\tcompletion.cleanupShellInitFile();\n\tprocess.exit(0);\n}\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(showMemoryCommand);\nprogram.addCommand(forgetMemoryCommand);\nprogram.addCommand(rememberMemoryCommand);\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-invocation.ts","../src/commands/serve.ts","../src/commands/setup-config.ts","../src/commands/setup.ts","../src/commands/stats.ts","../src/commands/sync-helpers.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(\"--db-path <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; dbPath?: 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 ?? opts.dbPath);\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 { statSync } from \"node:fs\";\nimport * as p from \"@clack/prompts\";\nimport {\n\tconnect,\n\tgetRawEventStatus,\n\tinitDatabase,\n\tMemoryStore,\n\trawEventsGate,\n\tresolveDbPath,\n\tretryRawEventFailures,\n\tvacuumDatabase,\n} from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nfunction formatBytes(bytes: number): string {\n\tif (bytes < 1024) return `${bytes} B`;\n\tif (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n\treturn `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\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.option(\"--db-path <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t\t.action((opts: { db?: string; dbPath?: string }) => {\n\t\t\t\tconst result = initDatabase(opts.db ?? opts.dbPath);\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.option(\"--db-path <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t\t.action((opts: { db?: string; dbPath?: string }) => {\n\t\t\t\tconst result = vacuumDatabase(opts.db ?? opts.dbPath);\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(\"--db-path <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; dbPath?: string; limit: string; json?: boolean }) => {\n\t\t\t\tconst result = getRawEventStatus(\n\t\t\t\t\topts.db ?? opts.dbPath,\n\t\t\t\t\tNumber.parseInt(opts.limit, 10) || 25,\n\t\t\t\t);\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(\"--db-path <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; dbPath?: string; limit: string }) => {\n\t\t\t\tconst result = retryRawEventFailures(\n\t\t\t\t\topts.db ?? opts.dbPath,\n\t\t\t\t\tNumber.parseInt(opts.limit, 10) || 25,\n\t\t\t\t);\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(\"--db-path <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\tdbPath?: 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 ?? opts.dbPath, {\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\t.addCommand(\n\t\tnew Command(\"rename-project\")\n\t\t\t.configureHelp(helpStyle)\n\t\t\t.description(\"Rename a project across sessions and related tables\")\n\t\t\t.argument(\"<old-name>\", \"current project name\")\n\t\t\t.argument(\"<new-name>\", \"new project name\")\n\t\t\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t\t.option(\"--db-path <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t\t.option(\"--apply\", \"apply changes (default is dry-run)\")\n\t\t\t.action(\n\t\t\t\t(\n\t\t\t\t\toldName: string,\n\t\t\t\t\tnewName: string,\n\t\t\t\t\topts: { db?: string; dbPath?: string; apply?: boolean },\n\t\t\t\t) => {\n\t\t\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst dryRun = !opts.apply;\n\t\t\t\t\t\tconst escapedOld = oldName.replace(/%/g, \"\\\\%\").replace(/_/g, \"\\\\_\");\n\t\t\t\t\t\tconst suffixPattern = `%/${escapedOld}`;\n\t\t\t\t\t\tconst tables = [\"sessions\", \"raw_event_sessions\"] as const;\n\t\t\t\t\t\tconst counts: Record<string, number> = {};\n\t\t\t\t\t\tconst run = () => {\n\t\t\t\t\t\t\tfor (const table of tables) {\n\t\t\t\t\t\t\t\tconst rows = store.db\n\t\t\t\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t\t\t\t`SELECT COUNT(*) as cnt FROM ${table} WHERE project = ? OR project LIKE ? ESCAPE '\\\\'`,\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t.get(oldName, suffixPattern) as { cnt: number };\n\t\t\t\t\t\t\t\tcounts[table] = rows.cnt;\n\t\t\t\t\t\t\t\tif (!dryRun && rows.cnt > 0) {\n\t\t\t\t\t\t\t\t\tstore.db\n\t\t\t\t\t\t\t\t\t\t.prepare(`UPDATE ${table} SET project = ? WHERE project = ?`)\n\t\t\t\t\t\t\t\t\t\t.run(newName, oldName);\n\t\t\t\t\t\t\t\t\tstore.db\n\t\t\t\t\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t\t\t\t\t`UPDATE ${table} SET project = ? WHERE project LIKE ? ESCAPE '\\\\' AND project != ?`,\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t.run(newName, suffixPattern, newName);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\t\t\t\t\t\tif (dryRun) {\n\t\t\t\t\t\t\trun();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tstore.db.transaction(run)();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst action = dryRun ? \"Will rename\" : \"Renamed\";\n\t\t\t\t\t\tp.intro(\"codemem db rename-project\");\n\t\t\t\t\t\tp.log.info(`${action} ${oldName} → ${newName}`);\n\t\t\t\t\t\tp.log.info(\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t`Sessions: ${counts.sessions}`,\n\t\t\t\t\t\t\t\t`Raw event sessions: ${counts.raw_event_sessions}`,\n\t\t\t\t\t\t\t].join(\"\\n\"),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (dryRun) {\n\t\t\t\t\t\t\tp.outro(\"Pass --apply to execute\");\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tp.outro(\"done\");\n\t\t\t\t\t\t}\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tstore.close();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t),\n\t)\n\t.addCommand(\n\t\tnew Command(\"normalize-projects\")\n\t\t\t.configureHelp(helpStyle)\n\t\t\t.description(\"Normalize path-like project identifiers to their basename\")\n\t\t\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t\t.option(\"--db-path <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t\t.option(\"--apply\", \"apply changes (default is dry-run)\")\n\t\t\t.action((opts: { db?: string; dbPath?: string; apply?: boolean }) => {\n\t\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\n\t\t\t\ttry {\n\t\t\t\t\tconst dryRun = !opts.apply;\n\t\t\t\t\tconst tables = [\"sessions\", \"raw_event_sessions\"] as const;\n\t\t\t\t\tconst rewrites: Map<string, string> = new Map();\n\t\t\t\t\tconst counts: Record<string, number> = {};\n\n\t\t\t\t\tconst run = () => {\n\t\t\t\t\t\tfor (const table of tables) {\n\t\t\t\t\t\t\tconst projects = store.db\n\t\t\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t\t\t`SELECT DISTINCT project FROM ${table} WHERE project IS NOT NULL AND project LIKE '%/%'`,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t.all() as Array<{ project: string }>;\n\t\t\t\t\t\t\tlet updated = 0;\n\t\t\t\t\t\t\tfor (const row of projects) {\n\t\t\t\t\t\t\t\tconst basename = row.project.split(\"/\").pop() ?? row.project;\n\t\t\t\t\t\t\t\tif (basename !== row.project) {\n\t\t\t\t\t\t\t\t\trewrites.set(row.project, basename);\n\t\t\t\t\t\t\t\t\tif (!dryRun) {\n\t\t\t\t\t\t\t\t\t\tconst info = store.db\n\t\t\t\t\t\t\t\t\t\t\t.prepare(`UPDATE ${table} SET project = ? WHERE project = ?`)\n\t\t\t\t\t\t\t\t\t\t\t.run(basename, row.project);\n\t\t\t\t\t\t\t\t\t\tupdated += info.changes;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tconst cnt = store.db\n\t\t\t\t\t\t\t\t\t\t\t.prepare(`SELECT COUNT(*) as cnt FROM ${table} WHERE project = ?`)\n\t\t\t\t\t\t\t\t\t\t\t.get(row.project) as { cnt: number };\n\t\t\t\t\t\t\t\t\t\tupdated += cnt.cnt;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcounts[table] = updated;\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\tif (dryRun) {\n\t\t\t\t\t\trun();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstore.db.transaction(run)();\n\t\t\t\t\t}\n\n\t\t\t\t\tp.intro(\"codemem db normalize-projects\");\n\t\t\t\t\tp.log.info(`Dry run: ${dryRun}`);\n\t\t\t\t\tp.log.info(\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t`Sessions to update: ${counts.sessions}`,\n\t\t\t\t\t\t\t`Raw event sessions to update: ${counts.raw_event_sessions}`,\n\t\t\t\t\t\t].join(\"\\n\"),\n\t\t\t\t\t);\n\t\t\t\t\tif (rewrites.size > 0) {\n\t\t\t\t\t\tp.log.info(\"Rewritten paths:\");\n\t\t\t\t\t\tfor (const [from, to] of [...rewrites.entries()].sort()) {\n\t\t\t\t\t\t\tp.log.message(` ${from} → ${to}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (dryRun) {\n\t\t\t\t\t\tp.outro(\"Pass --apply to execute\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\tp.outro(\"done\");\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\tstore.close();\n\t\t\t\t}\n\t\t\t}),\n\t)\n\t.addCommand(\n\t\tnew Command(\"size-report\")\n\t\t\t.configureHelp(helpStyle)\n\t\t\t.description(\"Show SQLite file size and major storage consumers\")\n\t\t\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t\t.option(\"--db-path <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t\t.option(\"--limit <n>\", \"number of largest tables/indexes to show\", \"12\")\n\t\t\t.option(\"--json\", \"output as JSON\")\n\t\t\t.action((opts: { db?: string; dbPath?: string; limit: string; json?: boolean }) => {\n\t\t\t\tconst dbPath = resolveDbPath(opts.db ?? opts.dbPath);\n\t\t\t\tconst db = connect(dbPath);\n\t\t\t\ttry {\n\t\t\t\t\tconst limit = Math.max(1, Number.parseInt(opts.limit, 10) || 12);\n\t\t\t\t\tconst fileSizeBytes = statSync(dbPath).size;\n\t\t\t\t\tconst pageInfo = db\n\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t\"SELECT page_count * page_size as total FROM pragma_page_count, pragma_page_size\",\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.get() as { total: number } | undefined;\n\t\t\t\t\tconst freePages = db.prepare(\"SELECT freelist_count FROM pragma_freelist_count\").get() as\n\t\t\t\t\t\t| { freelist_count: number }\n\t\t\t\t\t\t| undefined;\n\t\t\t\t\tconst pageSize = db.prepare(\"PRAGMA page_size\").get() as\n\t\t\t\t\t\t| { page_size: number }\n\t\t\t\t\t\t| undefined;\n\t\t\t\t\tconst tables = db\n\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t`SELECT name, SUM(pgsize) as size_bytes\n\t\t\t\t\t\t\t FROM dbstat\n\t\t\t\t\t\t\t GROUP BY name\n\t\t\t\t\t\t\t ORDER BY size_bytes DESC\n\t\t\t\t\t\t\t LIMIT ?`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.all(limit) as Array<{ name: string; size_bytes: number }>;\n\n\t\t\t\t\tif (opts.json) {\n\t\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t\tJSON.stringify(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfile_size_bytes: fileSizeBytes,\n\t\t\t\t\t\t\t\t\tdb_size_bytes: pageInfo?.total ?? 0,\n\t\t\t\t\t\t\t\t\tfree_bytes: (freePages?.freelist_count ?? 0) * (pageSize?.page_size ?? 4096),\n\t\t\t\t\t\t\t\t\ttables: tables.map((t) => ({ name: t.name, size_bytes: t.size_bytes })),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t\t2,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tp.intro(\"codemem db size-report\");\n\t\t\t\t\tp.log.info(\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t`File size: ${formatBytes(fileSizeBytes)}`,\n\t\t\t\t\t\t\t`DB size: ${formatBytes(pageInfo?.total ?? 0)}`,\n\t\t\t\t\t\t\t`Free space: ${formatBytes((freePages?.freelist_count ?? 0) * (pageSize?.page_size ?? 4096))}`,\n\t\t\t\t\t\t].join(\"\\n\"),\n\t\t\t\t\t);\n\t\t\t\t\tif (tables.length > 0) {\n\t\t\t\t\t\tp.log.info(\"Largest objects:\");\n\t\t\t\t\t\tfor (const t of tables) {\n\t\t\t\t\t\t\tp.log.message(` ${t.name.padEnd(40)} ${formatBytes(t.size_bytes).padStart(10)}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tp.outro(\"done\");\n\t\t\t\t} finally {\n\t\t\t\t\tdb.close();\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.option(\"--db-path <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.action(async (opts: { db?: string; dbPath?: 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 ?? opts.dbPath));\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(\"--db-path <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\tdbPath?: 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 ?? opts.dbPath),\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(\"--db-path <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(\n\t\t(\n\t\t\tinputFile: string,\n\t\t\topts: { db?: string; dbPath?: string; remapProject?: string; dryRun?: boolean },\n\t\t) => {\n\t\t\tlet payload: ExportPayload;\n\t\t\ttry {\n\t\t\t\tpayload = readImportPayload(inputFile);\n\t\t\t} catch (error) {\n\t\t\t\tp.log.error(error instanceof Error ? error.message : \"Invalid import file\");\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tp.intro(\"codemem import-memories\");\n\t\t\tp.log.info(\n\t\t\t\t[\n\t\t\t\t\t`Export version: ${payload.version}`,\n\t\t\t\t\t`Exported at: ${payload.exported_at}`,\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\n\t\t\tconst result = importMemories(payload, {\n\t\t\t\tdbPath: resolveDbPath(opts.db ?? opts.dbPath),\n\t\t\t\tremapProject: opts.remapProject,\n\t\t\t\tdryRun: opts.dryRun,\n\t\t\t});\n\n\t\t\tif (result.dryRun) {\n\t\t\t\tp.outro(\"dry run complete\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.log.success(\n\t\t\t\t[\n\t\t\t\t\t`Imported sessions: ${result.sessions.toLocaleString()}`,\n\t\t\t\t\t`Imported prompts: ${result.user_prompts.toLocaleString()}`,\n\t\t\t\t\t`Imported memories: ${result.memory_items.toLocaleString()}`,\n\t\t\t\t\t`Imported summaries: ${result.session_summaries.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 { 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.option(\"--db-path <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.action(async (opts: { db?: string; dbPath?: string }) => {\n\t\tconst dbPath = opts.db ?? opts.dbPath;\n\t\tif (dbPath) process.env.CODEMEM_DB = dbPath;\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\nfunction showMemoryAction(idStr: string, opts: { db?: string; dbPath?: string }): void {\n\tconst memoryId = parseStrictPositiveId(idStr);\n\tif (memoryId === null) {\n\t\tp.log.error(`Invalid memory ID: ${idStr}`);\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\n\ttry {\n\t\tconst item = store.get(memoryId);\n\t\tif (!item) {\n\t\t\tp.log.error(`Memory ${memoryId} not found`);\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\t\tconsole.log(JSON.stringify(item, null, 2));\n\t} finally {\n\t\tstore.close();\n\t}\n}\n\nfunction forgetMemoryAction(idStr: string, opts: { db?: string; dbPath?: string }): void {\n\tconst memoryId = parseStrictPositiveId(idStr);\n\tif (memoryId === null) {\n\t\tp.log.error(`Invalid memory ID: ${idStr}`);\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\n\ttry {\n\t\tstore.forget(memoryId);\n\t\tp.log.success(`Memory ${memoryId} marked inactive`);\n\t} finally {\n\t\tstore.close();\n\t}\n}\n\ninterface RememberMemoryOptions {\n\tkind: string;\n\ttitle: string;\n\tbody: string;\n\ttags?: string[];\n\tproject?: string;\n\tdb?: string;\n\tdbPath?: string;\n}\n\nfunction rememberMemoryAction(opts: RememberMemoryOptions): void {\n\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\n\tlet sessionId: number | null = null;\n\ttry {\n\t\tconst project = resolveProject(process.cwd(), opts.project ?? null);\n\t\tsessionId = store.startSession({\n\t\t\tcwd: process.cwd(),\n\t\t\tproject,\n\t\t\tuser: process.env.USER ?? \"unknown\",\n\t\t\ttoolVersion: \"manual\",\n\t\t\tmetadata: { manual: true },\n\t\t});\n\t\tconst memId = store.remember(sessionId, opts.kind, opts.title, opts.body, 0.5, opts.tags);\n\t\tstore.endSession(sessionId, { manual: true });\n\t\tp.log.success(`Stored memory ${memId}`);\n\t} catch (err) {\n\t\tif (sessionId !== null) {\n\t\t\ttry {\n\t\t\t\tstore.endSession(sessionId, { manual: true, error: true });\n\t\t\t} catch {\n\t\t\t\t// ignore — already in error path\n\t\t\t}\n\t\t}\n\t\tthrow err;\n\t} finally {\n\t\tstore.close();\n\t}\n}\n\nfunction createShowMemoryCommand(): Command {\n\treturn new 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.option(\"--db-path <path>\", \"database path\")\n\t\t.action(showMemoryAction);\n}\n\nfunction createForgetMemoryCommand(): Command {\n\treturn new 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.option(\"--db-path <path>\", \"database path\")\n\t\t.action(forgetMemoryAction);\n}\n\nfunction createRememberMemoryCommand(): Command {\n\treturn new 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.option(\"--db-path <path>\", \"database path\")\n\t\t.action(rememberMemoryAction);\n}\n\nexport const showMemoryCommand = createShowMemoryCommand();\nexport const forgetMemoryCommand = createForgetMemoryCommand();\nexport const rememberMemoryCommand = createRememberMemoryCommand();\n\nexport const memoryCommand = new Command(\"memory\")\n\t.configureHelp(helpStyle)\n\t.description(\"Memory item management\");\n\nmemoryCommand.addCommand(createShowMemoryCommand());\nmemoryCommand.addCommand(createForgetMemoryCommand());\nmemoryCommand.addCommand(createRememberMemoryCommand());\n","import * as p from \"@clack/prompts\";\nimport { MemoryStore, resolveDbPath, resolveProject } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nfunction collectWorkingSetFile(value: string, previous: string[]): string[] {\n\treturn [...previous, value];\n}\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(\"--db-path <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(\"--token-budget <tokens>\", \"token budget\")\n\t.option(\n\t\t\"--working-set-file <path>\",\n\t\t\"recently modified file path used as ranking hint\",\n\t\tcollectWorkingSetFile,\n\t\t[],\n\t)\n\t.option(\"--project <project>\", \"project identifier (defaults to git repo root)\")\n\t.option(\"--all-projects\", \"search across all projects\")\n\t.option(\"--json\", \"output as JSON\")\n\t.action(\n\t\t(\n\t\t\tcontext: string,\n\t\t\topts: {\n\t\t\t\tdb?: string;\n\t\t\t\tdbPath?: string;\n\t\t\t\tlimit: string;\n\t\t\t\tbudget?: string;\n\t\t\t\ttokenBudget?: string;\n\t\t\t\tworkingSetFile?: string[];\n\t\t\t\tproject?: string;\n\t\t\t\tallProjects?: boolean;\n\t\t\t\tjson?: boolean;\n\t\t\t},\n\t\t) => {\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\n\t\t\ttry {\n\t\t\t\tconst limit = Number.parseInt(opts.limit, 10) || 10;\n\t\t\t\tconst budgetRaw = opts.tokenBudget ?? opts.budget;\n\t\t\t\tconst budget = budgetRaw ? Number.parseInt(budgetRaw, 10) : undefined;\n\t\t\t\tconst filters: { project?: string } = {};\n\t\t\t\tif (!opts.allProjects) {\n\t\t\t\t\tconst defaultProject = process.env.CODEMEM_PROJECT?.trim() || null;\n\t\t\t\t\tconst project = defaultProject || resolveProject(process.cwd(), opts.project ?? null);\n\t\t\t\t\tif (project) filters.project = project;\n\t\t\t\t}\n\t\t\t\tif ((opts.workingSetFile?.length ?? 0) > 0) {\n\t\t\t\t\tp.log.warn(\n\t\t\t\t\t\t\"--working-set-file is accepted for compatibility but is not yet used by the TS pack builder.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst result = store.buildMemoryPack(context, limit, budget, filters);\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, resolveProject } 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(\"--db-path <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.option(\"--limit <n>\", \"max results\", \"5\")\n\t.option(\"--project <project>\", \"project identifier (defaults to git repo root)\")\n\t.option(\"--all-projects\", \"search across all projects\")\n\t.option(\"--kind <kind>\", \"filter by memory kind\")\n\t.action(\n\t\t(opts: {\n\t\t\tdb?: string;\n\t\t\tdbPath?: string;\n\t\t\tlimit: string;\n\t\t\tproject?: string;\n\t\t\tallProjects?: boolean;\n\t\t\tkind?: string;\n\t\t}) => {\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\n\t\t\ttry {\n\t\t\t\tconst limit = Math.max(1, Number.parseInt(opts.limit, 10) || 5);\n\t\t\t\tconst filters: { kind?: string; project?: string } = {};\n\t\t\t\tif (opts.kind) filters.kind = opts.kind;\n\t\t\t\tif (!opts.allProjects) {\n\t\t\t\t\tconst defaultProject = process.env.CODEMEM_PROJECT?.trim() || null;\n\t\t\t\t\tconst project = defaultProject || resolveProject(process.cwd(), opts.project ?? null);\n\t\t\t\t\tif (project) filters.project = project;\n\t\t\t\t}\n\t\t\t\tconst items = store.recent(limit, filters);\n\t\t\t\tfor (const item of items) {\n\t\t\t\t\tconsole.log(`#${item.id} [${item.kind}] ${item.title}`);\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tstore.close();\n\t\t\t}\n\t\t},\n\t);\n","import * as p from \"@clack/prompts\";\nimport { MemoryStore, resolveDbPath, resolveProject } 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(\"--db-path <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.option(\"-n, --limit <n>\", \"max results\", \"5\")\n\t.option(\"--project <project>\", \"project identifier (defaults to git repo root)\")\n\t.option(\"--all-projects\", \"search across all projects\")\n\t.option(\"--kind <kind>\", \"filter by memory kind\")\n\t.option(\"--json\", \"output as JSON\")\n\t.action(\n\t\t(\n\t\t\tquery: string,\n\t\t\topts: {\n\t\t\t\tdb?: string;\n\t\t\t\tdbPath?: string;\n\t\t\t\tlimit: string;\n\t\t\t\tproject?: string;\n\t\t\t\tallProjects?: boolean;\n\t\t\t\tkind?: string;\n\t\t\t\tjson?: boolean;\n\t\t\t},\n\t\t) => {\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\n\t\t\ttry {\n\t\t\t\tconst limit = Math.max(1, Number.parseInt(opts.limit, 10) || 5);\n\t\t\t\tconst filters: { kind?: string; project?: string } = {};\n\t\t\t\tif (opts.kind) filters.kind = opts.kind;\n\t\t\t\tif (!opts.allProjects) {\n\t\t\t\t\tconst defaultProject = process.env.CODEMEM_PROJECT?.trim() || null;\n\t\t\t\t\tconst project = defaultProject || resolveProject(process.cwd(), opts.project ?? null);\n\t\t\t\t\tif (project) filters.project = project;\n\t\t\t\t}\n\t\t\t\tconst results = store.search(query, limit, filters);\n\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify(results, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (results.length === 0) {\n\t\t\t\t\tp.log.warn(\"No results found.\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tp.intro(`${results.length} result(s) for \"${query}\"`);\n\n\t\t\t\tfor (const item of results) {\n\t\t\t\t\tconst score = item.score.toFixed(3);\n\t\t\t\t\tconst age = timeSince(item.created_at);\n\t\t\t\t\tconst preview =\n\t\t\t\t\t\titem.body_text.length > 120 ? `${item.body_text.slice(0, 120)}…` : item.body_text;\n\n\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t[`#${item.id} ${item.kind} ${age} [${score}]`, item.title, preview].join(\"\\n\"),\n\t\t\t\t\t);\n\t\t\t\t}\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\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","export type ServeMode = \"start\" | \"stop\" | \"restart\";\n\nexport type ServeAction = ServeMode | undefined;\n\nexport interface LegacyServeOptions {\n\tdb?: string;\n\tdbPath?: string;\n\thost: string;\n\tport: string;\n\tbackground?: boolean;\n\tforeground?: boolean;\n\tstop?: boolean;\n\trestart?: boolean;\n}\n\nexport interface StartServeOptions {\n\tdb?: string;\n\tdbPath?: string;\n\thost: string;\n\tport: string;\n\tforeground?: boolean;\n}\n\nexport interface StopRestartServeOptions {\n\tdb?: string;\n\tdbPath?: string;\n\thost: string;\n\tport: string;\n}\n\nexport interface ResolvedServeInvocation {\n\tmode: ServeMode;\n\tdbPath: string | null;\n\thost: string;\n\tport: number;\n\tbackground: boolean;\n}\n\nfunction parsePort(rawPort: string): number {\n\tconst port = Number.parseInt(rawPort, 10);\n\tif (!Number.isFinite(port) || port < 1 || port > 65535) {\n\t\tthrow new Error(`Invalid port: ${rawPort}`);\n\t}\n\treturn port;\n}\n\nexport function resolveLegacyServeInvocation(opts: LegacyServeOptions): ResolvedServeInvocation {\n\tif (opts.stop && opts.restart) {\n\t\tthrow new Error(\"Use only one of --stop or --restart\");\n\t}\n\tif (opts.foreground && opts.background) {\n\t\tthrow new Error(\"Use only one of --background or --foreground\");\n\t}\n\tconst dbPath = opts.db ?? opts.dbPath ?? null;\n\treturn {\n\t\tmode: opts.stop ? \"stop\" : opts.restart ? \"restart\" : \"start\",\n\t\tdbPath,\n\t\thost: opts.host,\n\t\tport: parsePort(opts.port),\n\t\tbackground: opts.restart ? true : opts.background ? true : false,\n\t};\n}\n\nexport function resolveServeInvocation(\n\taction: ServeAction,\n\topts: LegacyServeOptions,\n): ResolvedServeInvocation {\n\tif (action === undefined) {\n\t\treturn resolveLegacyServeInvocation(opts);\n\t}\n\tif (opts.stop || opts.restart) {\n\t\tthrow new Error(\"Do not combine lifecycle flags with a serve action\");\n\t}\n\tif (action === \"start\") {\n\t\treturn resolveStartServeInvocation(opts);\n\t}\n\treturn resolveStopRestartInvocation(action, opts);\n}\n\nexport function resolveStartServeInvocation(opts: StartServeOptions): ResolvedServeInvocation {\n\tconst dbPath = opts.db ?? opts.dbPath ?? null;\n\treturn {\n\t\tmode: \"start\",\n\t\tdbPath,\n\t\thost: opts.host,\n\t\tport: parsePort(opts.port),\n\t\tbackground: !opts.foreground,\n\t};\n}\n\nexport function resolveStopRestartInvocation(\n\tmode: \"stop\" | \"restart\",\n\topts: StopRestartServeOptions,\n): ResolvedServeInvocation {\n\tconst dbPath = opts.db ?? opts.dbPath ?? null;\n\treturn {\n\t\tmode,\n\t\tdbPath,\n\t\thost: opts.host,\n\t\tport: parsePort(opts.port),\n\t\tbackground: mode === \"restart\",\n\t};\n}\n","import { spawn } from \"node:child_process\";\nimport { existsSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport net from \"node:net\";\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\";\nimport {\n\ttype LegacyServeOptions,\n\ttype ResolvedServeInvocation,\n\tresolveServeInvocation,\n\ttype ServeAction,\n} from \"./serve-invocation.js\";\n\ninterface ViewerPidRecord {\n\tpid: number;\n\thost: string;\n\tport: number;\n}\n\nfunction pidFilePath(dbPath: string): string {\n\treturn join(dirname(dbPath), \"viewer.pid\");\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\nfunction isProcessRunning(pid: number): boolean {\n\ttry {\n\t\tprocess.kill(pid, 0);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\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 isPortOpen(host: string, port: number): Promise<boolean> {\n\treturn new Promise((resolve) => {\n\t\tconst socket = net.createConnection({ host, port });\n\t\tconst done = (open: boolean) => {\n\t\t\tsocket.removeAllListeners();\n\t\t\tsocket.destroy();\n\t\t\tresolve(open);\n\t\t};\n\t\tsocket.setTimeout(300);\n\t\tsocket.once(\"connect\", () => done(true));\n\t\tsocket.once(\"timeout\", () => done(false));\n\t\tsocket.once(\"error\", () => done(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\tif (!isProcessRunning(pid)) return;\n\t\tawait new Promise((resolve) => setTimeout(resolve, 100));\n\t}\n}\n\nasync function stopExistingViewer(\n\tdbPath: string,\n): Promise<{ stopped: boolean; pid: number | null }> {\n\tconst pidPath = pidFilePath(dbPath);\n\tconst record = readViewerPidRecord(dbPath);\n\tif (!record) return { stopped: false, pid: null };\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\treturn { stopped: true, pid: record.pid };\n}\n\nexport function buildForegroundRunnerArgs(\n\tscriptPath: string,\n\tinvocation: ResolvedServeInvocation,\n\texecArgv: string[] = process.execArgv,\n): string[] {\n\tconst args = [\n\t\t...execArgv,\n\t\tscriptPath,\n\t\t\"serve\",\n\t\t\"start\",\n\t\t\"--foreground\",\n\t\t\"--host\",\n\t\tinvocation.host,\n\t\t\"--port\",\n\t\tString(invocation.port),\n\t];\n\tif (invocation.dbPath) {\n\t\targs.push(\"--db-path\", invocation.dbPath);\n\t}\n\treturn args;\n}\n\nasync function startBackgroundViewer(invocation: ResolvedServeInvocation): Promise<void> {\n\tif (await isPortOpen(invocation.host, invocation.port)) {\n\t\tp.log.warn(`Viewer already running at http://${invocation.host}:${invocation.port}`);\n\t\treturn;\n\t}\n\tconst scriptPath = process.argv[1];\n\tif (!scriptPath) throw new Error(\"Unable to resolve CLI entrypoint for background launch\");\n\tconst child = spawn(process.execPath, buildForegroundRunnerArgs(scriptPath, invocation), {\n\t\tcwd: process.cwd(),\n\t\tdetached: true,\n\t\tstdio: \"ignore\",\n\t\tenv: {\n\t\t\t...process.env,\n\t\t\t...(invocation.dbPath ? { CODEMEM_DB: invocation.dbPath } : {}),\n\t\t},\n\t});\n\tchild.unref();\n\tif (invocation.dbPath) {\n\t\twriteFileSync(\n\t\t\tpidFilePath(invocation.dbPath),\n\t\t\tJSON.stringify({ pid: child.pid, host: invocation.host, port: invocation.port }),\n\t\t\t\"utf-8\",\n\t\t);\n\t}\n\tp.intro(\"codemem viewer\");\n\tp.outro(\n\t\t`Viewer started in background (pid ${child.pid}) at http://${invocation.host}:${invocation.port}`,\n\t);\n}\n\nasync function startForegroundViewer(invocation: ResolvedServeInvocation): Promise<void> {\n\tconst { createApp, closeStore, getStore } = await import(\"@codemem/server\");\n\tconst { serve } = await import(\"@hono/node-server\");\n\n\tif (invocation.dbPath) process.env.CODEMEM_DB = invocation.dbPath;\n\tif (await isPortOpen(invocation.host, invocation.port)) {\n\t\tp.log.warn(`Viewer already running at http://${invocation.host}:${invocation.port}`);\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\n\tconst observer = new ObserverClient();\n\tconst sweeper = new RawEventSweeper(getStore(), { observer });\n\tsweeper.start();\n\n\tconst syncAbort = new AbortController();\n\tlet syncRunning = false;\n\tconst config = readCodememConfigFile();\n\tconst syncEnabled =\n\t\tconfig.sync_enabled === true ||\n\t\tprocess.env.CODEMEM_SYNC_ENABLED?.toLowerCase() === \"true\" ||\n\t\tprocess.env.CODEMEM_SYNC_ENABLED === \"1\";\n\n\tif (syncEnabled) {\n\t\tsyncRunning = true;\n\t\tconst syncIntervalS = typeof config.sync_interval_s === \"number\" ? config.sync_interval_s : 120;\n\t\trunSyncDaemon({\n\t\t\tdbPath: resolveDbPath(invocation.dbPath ?? undefined),\n\t\t\tintervalS: syncIntervalS,\n\t\t\thost: invocation.host,\n\t\t\tport: invocation.port,\n\t\t\tsignal: syncAbort.signal,\n\t\t})\n\t\t\t.catch((err: unknown) => {\n\t\t\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\t\t\tp.log.error(`Sync daemon failed: ${msg}`);\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\tsyncRunning = false;\n\t\t\t});\n\t}\n\n\tconst app = createApp({ storeFactory: getStore, sweeper });\n\tconst dbPath = resolveDbPath(invocation.dbPath ?? undefined);\n\tconst pidPath = pidFilePath(dbPath);\n\n\tconst server = serve(\n\t\t{ fetch: app.fetch, hostname: invocation.host, port: invocation.port },\n\t\t(info) => {\n\t\t\twriteFileSync(\n\t\t\t\tpidPath,\n\t\t\t\tJSON.stringify({ pid: process.pid, host: invocation.host, port: invocation.port }),\n\t\t\t\t\"utf-8\",\n\t\t\t);\n\t\t\tp.intro(\"codemem viewer\");\n\t\t\tp.log.success(`Listening on http://${info.address}:${info.port}`);\n\t\t\tp.log.info(`Database: ${dbPath}`);\n\t\t\tp.log.step(\"Raw event sweeper started\");\n\t\t\tif (syncRunning) p.log.step(\"Sync daemon started\");\n\t\t},\n\t);\n\n\tserver.on(\"error\", (err: NodeJS.ErrnoException) => {\n\t\tif (err.code === \"EADDRINUSE\") {\n\t\t\tp.log.warn(`Viewer already running at http://${invocation.host}:${invocation.port}`);\n\t\t} else {\n\t\t\tp.log.error(err.message);\n\t\t}\n\t\tprocess.exit(1);\n\t});\n\n\tconst shutdown = async () => {\n\t\tp.outro(\"shutting down\");\n\t\tsyncAbort.abort();\n\t\tawait sweeper.stop();\n\t\tserver.close(() => {\n\t\t\ttry {\n\t\t\t\trmSync(pidPath);\n\t\t\t} catch {\n\t\t\t\t// ignore\n\t\t\t}\n\t\t\tcloseStore();\n\t\t\tprocess.exit(0);\n\t\t});\n\t\tsetTimeout(() => {\n\t\t\ttry {\n\t\t\t\trmSync(pidPath);\n\t\t\t} catch {\n\t\t\t\t// ignore\n\t\t\t}\n\t\t\tcloseStore();\n\t\t\tprocess.exit(1);\n\t\t}, 5000).unref();\n\t};\n\tprocess.on(\"SIGINT\", () => {\n\t\tvoid shutdown();\n\t});\n\tprocess.on(\"SIGTERM\", () => {\n\t\tvoid shutdown();\n\t});\n}\n\nasync function runServeInvocation(invocation: ResolvedServeInvocation): Promise<void> {\n\tconst dbPath = resolveDbPath(invocation.dbPath ?? undefined);\n\tif (invocation.mode === \"stop\" || invocation.mode === \"restart\") {\n\t\tconst result = await stopExistingViewer(dbPath);\n\t\tif (result.stopped) {\n\t\t\tp.intro(\"codemem viewer\");\n\t\t\tp.log.success(`Stopped viewer${result.pid ? ` (pid ${result.pid})` : \"\"}`);\n\t\t\tif (invocation.mode === \"stop\") {\n\t\t\t\tp.outro(\"done\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else if (invocation.mode === \"stop\") {\n\t\t\tp.intro(\"codemem viewer\");\n\t\t\tp.outro(\"No background viewer found\");\n\t\t\treturn;\n\t\t}\n\t}\n\n\tif (invocation.mode === \"start\" || invocation.mode === \"restart\") {\n\t\tif (invocation.background) {\n\t\t\tawait startBackgroundViewer({ ...invocation, dbPath });\n\t\t\treturn;\n\t\t}\n\t\tawait startForegroundViewer({ ...invocation, dbPath });\n\t}\n}\n\nfunction addSharedServeOptions(command: Command): Command {\n\treturn command\n\t\t.option(\"--db <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t.option(\"--db-path <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t\t.option(\"--host <host>\", \"bind host\", \"127.0.0.1\")\n\t\t.option(\"--port <port>\", \"bind port\", \"38888\");\n}\n\nexport const serveCommand = addSharedServeOptions(\n\tnew Command(\"serve\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Run or manage the viewer\")\n\t\t.argument(\"[action]\", \"lifecycle action (start|stop|restart)\"),\n)\n\t.option(\"--background\", \"run viewer in background\")\n\t.option(\"--foreground\", \"run viewer in foreground\")\n\t.option(\"--stop\", \"stop background viewer\")\n\t.option(\"--restart\", \"restart background viewer\")\n\t.action(async (action: string | undefined, opts: LegacyServeOptions) => {\n\t\tconst normalizedAction =\n\t\t\taction === undefined\n\t\t\t\t? undefined\n\t\t\t\t: action === \"start\" || action === \"stop\" || action === \"restart\"\n\t\t\t\t\t? (action as ServeAction)\n\t\t\t\t\t: null;\n\t\tif (normalizedAction === null) {\n\t\t\tp.log.error(`Unknown serve action: ${action}`);\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\t\tawait runServeInvocation(resolveServeInvocation(normalizedAction, opts));\n\t});\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { stripJsonComments, stripTrailingCommas } from \"@codemem/core\";\n\nexport function resolveOpencodeConfigPath(configDir: string): string {\n\tconst jsonPath = join(configDir, \"opencode.json\");\n\tif (existsSync(jsonPath)) return jsonPath;\n\tconst jsoncPath = join(configDir, \"opencode.jsonc\");\n\tif (existsSync(jsoncPath)) return jsoncPath;\n\treturn jsoncPath;\n}\n\nexport function 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\nexport function 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","/**\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 } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { VERSION } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport { loadJsoncConfig, resolveOpencodeConfigPath, writeJsonConfig } from \"./setup-config.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/plugins/codemem.js in the package tree.\n */\nfunction findPluginSource(): 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\", \"plugins\", \"codemem.js\");\n\t\tif (existsSync(candidate)) return candidate;\n\t\tconst nmCandidate = join(dir, \"node_modules\", \"codemem\", \".opencode\", \"plugins\", \"codemem.js\");\n\t\tif (existsSync(nmCandidate)) return nmCandidate;\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 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(), \"plugins\");\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 = resolveOpencodeConfigPath(opencodeConfigDir());\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(\"--db-path <path>\", \"database path (default: $CODEMEM_DB or ~/.codemem/mem.sqlite)\")\n\t.option(\"--json\", \"output as JSON\")\n\t.action((opts: { db?: string; dbPath?: string; json?: boolean }) => {\n\t\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\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","export interface SyncAttemptRow {\n\tpeer_device_id: string;\n\tok: number;\n\tops_in: number;\n\tops_out: number;\n\terror: string | null;\n\tfinished_at: string | null;\n}\n\nexport function formatSyncAttempt(row: SyncAttemptRow): string {\n\tconst status = row.ok ? \"ok\" : \"error\";\n\tconst error = String(row.error || \"\");\n\tconst suffix = error ? ` | ${error}` : \"\";\n\treturn `${row.peer_device_id}|${status}|in=${row.ops_in}|out=${row.ops_out}|${row.finished_at ?? \"\"}${suffix}`;\n}\n\nexport interface SyncLifecycleOptions {\n\tdb?: string;\n\tdbPath?: string;\n\thost?: string;\n\tport?: string;\n\tuser?: boolean;\n\tsystem?: boolean;\n}\n\nexport function buildServeLifecycleArgs(\n\taction: \"start\" | \"stop\" | \"restart\",\n\topts: SyncLifecycleOptions,\n\tscriptPath: string,\n\texecArgv: string[] = [],\n): string[] {\n\tif (!scriptPath) throw new Error(\"Unable to resolve CLI entrypoint for sync lifecycle command\");\n\tconst args = [...execArgv, scriptPath, \"serve\"];\n\tif (action === \"start\") {\n\t\targs.push(\"--restart\");\n\t} else if (action === \"stop\") {\n\t\targs.push(\"--stop\");\n\t} else {\n\t\targs.push(\"--restart\");\n\t}\n\tif (opts.db ?? opts.dbPath) args.push(\"--db-path\", opts.db ?? opts.dbPath ?? \"\");\n\tif (opts.host) args.push(\"--host\", opts.host);\n\tif (opts.port) args.push(\"--port\", opts.port);\n\treturn args;\n}\n\nexport function formatSyncOnceResult(\n\tpeerDeviceId: string,\n\tresult: { ok: boolean; error?: string },\n): string {\n\tif (result.ok) return `- ${peerDeviceId}: ok`;\n\tconst suffix = result.error ? `: ${result.error}` : \"\";\n\treturn `- ${peerDeviceId}: error${suffix}`;\n}\n\nexport function parseProjectList(value: string | undefined): string[] {\n\tif (!value) return [];\n\treturn value\n\t\t.split(\",\")\n\t\t.map((item) => item.trim())\n\t\t.filter(Boolean);\n}\n\ntype InterfaceMap = Record<\n\tstring,\n\tArray<{ address: string; family?: string | number; internal?: boolean }> | undefined\n>;\n\nexport function collectAdvertiseAddresses(\n\texplicitAddress: string | null,\n\tconfiguredHost: string | null,\n\tport: number,\n\tinterfaces: InterfaceMap,\n): string[] {\n\tif (explicitAddress && ![\"auto\", \"default\"].includes(explicitAddress.toLowerCase())) {\n\t\treturn [explicitAddress];\n\t}\n\tif (configuredHost && configuredHost !== \"0.0.0.0\") {\n\t\treturn [`${configuredHost}:${port}`];\n\t}\n\tconst addresses = Object.values(interfaces)\n\t\t.flatMap((entries) => entries ?? [])\n\t\t.filter((entry) => !entry.internal)\n\t\t.map((entry) => entry.address)\n\t\t.filter((address) => address && address !== \"127.0.0.1\" && address !== \"::1\")\n\t\t.map((address) => `${address}:${port}`);\n\treturn [...new Set(addresses)];\n}\n","/**\n * Sync CLI commands — enable/disable/status/peers/connect.\n */\n\nimport { spawn } from \"node:child_process\";\nimport { readFileSync } from \"node:fs\";\nimport net from \"node:net\";\nimport { networkInterfaces } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport * as p from \"@clack/prompts\";\nimport {\n\tensureDeviceIdentity,\n\tfingerprintPublicKey,\n\tloadPublicKey,\n\tMemoryStore,\n\treadCodememConfigFile,\n\tresolveDbPath,\n\trunSyncPass,\n\tschema,\n\tsetPeerProjectFilter,\n\tsyncPassPreflight,\n\tupdatePeerAddresses,\n\twriteCodememConfigFile,\n} from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { desc, eq } from \"drizzle-orm\";\nimport { drizzle } from \"drizzle-orm/better-sqlite3\";\nimport { helpStyle } from \"../help-style.js\";\nimport {\n\tbuildServeLifecycleArgs,\n\tcollectAdvertiseAddresses,\n\tformatSyncAttempt,\n\tformatSyncOnceResult,\n\tparseProjectList,\n\ttype SyncLifecycleOptions,\n} from \"./sync-helpers.js\";\n\nfunction parseAttemptsLimit(value: string): number {\n\tif (!/^\\d+$/.test(value.trim())) {\n\t\tthrow new Error(`Invalid --limit: ${value}`);\n\t}\n\treturn Number.parseInt(value, 10);\n}\n\ninterface SyncOnceOptions {\n\tdb?: string;\n\tdbPath?: string;\n\tpeer?: string;\n}\n\ninterface SyncPairOptions {\n\taccept?: string;\n\tacceptFile?: string;\n\tpayloadOnly?: boolean;\n\tname?: string;\n\taddress?: string;\n\tinclude?: string;\n\texclude?: string;\n\tall?: boolean;\n\tdefault?: boolean;\n\tdbPath?: string;\n}\n\nasync function portOpen(host: string, port: number): Promise<boolean> {\n\treturn new Promise((resolve) => {\n\t\tconst socket = net.createConnection({ host, port });\n\t\tconst done = (ok: boolean) => {\n\t\t\tsocket.removeAllListeners();\n\t\t\tsocket.destroy();\n\t\t\tresolve(ok);\n\t\t};\n\t\tsocket.setTimeout(300);\n\t\tsocket.once(\"connect\", () => done(true));\n\t\tsocket.once(\"timeout\", () => done(false));\n\t\tsocket.once(\"error\", () => done(false));\n\t});\n}\n\nfunction readViewerBinding(dbPath: string): { host: string; port: number } | null {\n\ttry {\n\t\tconst raw = readFileSync(join(dirname(dbPath), \"viewer.pid\"), \"utf8\");\n\t\tconst parsed = JSON.parse(raw) as Partial<{ host: string; port: number }>;\n\t\tif (typeof parsed.host === \"string\" && typeof parsed.port === \"number\") {\n\t\t\treturn { host: parsed.host, port: parsed.port };\n\t\t}\n\t} catch {\n\t\t// ignore malformed or missing pidfile\n\t}\n\treturn null;\n}\n\nfunction parseStoredAddressEndpoint(value: string): { host: string; port: number } | null {\n\ttry {\n\t\tconst normalized = value.includes(\"://\") ? value : `http://${value}`;\n\t\tconst url = new URL(normalized);\n\t\tconst port = url.port ? Number.parseInt(url.port, 10) : url.protocol === \"https:\" ? 443 : 80;\n\t\tif (!url.hostname || !Number.isFinite(port)) return null;\n\t\treturn { host: url.hostname, port };\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nasync function runServeLifecycle(\n\taction: \"start\" | \"stop\" | \"restart\",\n\topts: SyncLifecycleOptions,\n): Promise<void> {\n\tif (opts.user === false || opts.system === true) {\n\t\tp.log.warn(\n\t\t\t\"TS sync lifecycle currently manages the local viewer process, not separate user/system services.\",\n\t\t);\n\t}\n\tif (action === \"start\") {\n\t\tconst config = readCodememConfigFile();\n\t\tif (config.sync_enabled !== true) {\n\t\t\tp.log.error(\"Sync is disabled. Run `codemem sync enable` first.\");\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\t\tconst configuredHost = typeof config.sync_host === \"string\" ? config.sync_host : \"0.0.0.0\";\n\t\tconst configuredPort = typeof config.sync_port === \"number\" ? String(config.sync_port) : \"7337\";\n\t\topts.host ??= configuredHost;\n\t\topts.port ??= configuredPort;\n\t} else if (action === \"restart\") {\n\t\tconst config = readCodememConfigFile();\n\t\tconst configuredHost = typeof config.sync_host === \"string\" ? config.sync_host : \"0.0.0.0\";\n\t\tconst configuredPort = typeof config.sync_port === \"number\" ? String(config.sync_port) : \"7337\";\n\t\topts.host ??= configuredHost;\n\t\topts.port ??= configuredPort;\n\t}\n\tconst args = buildServeLifecycleArgs(action, opts, process.argv[1] ?? \"\", process.execArgv);\n\tawait new Promise<void>((resolve, reject) => {\n\t\tconst child = spawn(process.execPath, args, {\n\t\t\tcwd: process.cwd(),\n\t\t\tstdio: \"inherit\",\n\t\t\tenv: {\n\t\t\t\t...process.env,\n\t\t\t\t...((opts.db ?? opts.dbPath) ? { CODEMEM_DB: opts.db ?? opts.dbPath } : {}),\n\t\t\t},\n\t\t});\n\t\tchild.once(\"error\", reject);\n\t\tchild.once(\"exit\", (code) => {\n\t\t\tif (code && code !== 0) {\n\t\t\t\tprocess.exitCode = code;\n\t\t\t}\n\t\t\tresolve();\n\t\t});\n\t});\n}\n\nexport const syncCommand = new Command(\"sync\")\n\t.configureHelp(helpStyle)\n\t.description(\"Sync configuration and peer management\");\n\n// codemem sync attempts\nsyncCommand.addCommand(\n\tnew Command(\"attempts\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Show recent sync attempts\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.option(\"--db-path <path>\", \"database path\")\n\t\t.option(\"--limit <n>\", \"max attempts\", \"10\")\n\t\t.option(\"--json\", \"output as JSON\")\n\t\t.action((opts: { db?: string; dbPath?: string; limit: string; json?: boolean }) => {\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\n\t\t\ttry {\n\t\t\t\tconst d = drizzle(store.db, { schema });\n\t\t\t\tconst limit = parseAttemptsLimit(opts.limit);\n\t\t\t\tconst rows = d\n\t\t\t\t\t.select({\n\t\t\t\t\t\tpeer_device_id: schema.syncAttempts.peer_device_id,\n\t\t\t\t\t\tok: schema.syncAttempts.ok,\n\t\t\t\t\t\tops_in: schema.syncAttempts.ops_in,\n\t\t\t\t\t\tops_out: schema.syncAttempts.ops_out,\n\t\t\t\t\t\terror: schema.syncAttempts.error,\n\t\t\t\t\t\tfinished_at: schema.syncAttempts.finished_at,\n\t\t\t\t\t})\n\t\t\t\t\t.from(schema.syncAttempts)\n\t\t\t\t\t.orderBy(desc(schema.syncAttempts.finished_at))\n\t\t\t\t\t.limit(limit)\n\t\t\t\t\t.all();\n\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify(rows, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tfor (const row of rows) {\n\t\t\t\t\tconsole.log(formatSyncAttempt(row));\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tstore.close();\n\t\t\t}\n\t\t}),\n);\n\nsyncCommand.addCommand(\n\tnew Command(\"start\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Start sync daemon\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.option(\"--db-path <path>\", \"database path\")\n\t\t.option(\"--host <host>\", \"viewer host\")\n\t\t.option(\"--port <port>\", \"viewer port\")\n\t\t.option(\"--user\", \"accepted for compatibility\", true)\n\t\t.option(\"--system\", \"accepted for compatibility\")\n\t\t.action(async (opts: SyncLifecycleOptions) => {\n\t\t\tawait runServeLifecycle(\"start\", opts);\n\t\t}),\n);\n\nsyncCommand.addCommand(\n\tnew Command(\"stop\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Stop sync daemon\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.option(\"--db-path <path>\", \"database path\")\n\t\t.option(\"--host <host>\", \"viewer host\")\n\t\t.option(\"--port <port>\", \"viewer port\")\n\t\t.option(\"--user\", \"accepted for compatibility\", true)\n\t\t.option(\"--system\", \"accepted for compatibility\")\n\t\t.action(async (opts: SyncLifecycleOptions) => {\n\t\t\tawait runServeLifecycle(\"stop\", opts);\n\t\t}),\n);\n\nsyncCommand.addCommand(\n\tnew Command(\"restart\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Restart sync daemon\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.option(\"--db-path <path>\", \"database path\")\n\t\t.option(\"--host <host>\", \"viewer host\")\n\t\t.option(\"--port <port>\", \"viewer port\")\n\t\t.option(\"--user\", \"accepted for compatibility\", true)\n\t\t.option(\"--system\", \"accepted for compatibility\")\n\t\t.action(async (opts: SyncLifecycleOptions) => {\n\t\t\tawait runServeLifecycle(\"restart\", opts);\n\t\t}),\n);\n\nsyncCommand.addCommand(\n\tnew Command(\"once\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Run a single sync pass\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.option(\"--db-path <path>\", \"database path\")\n\t\t.option(\"--peer <peer>\", \"peer device id or name\")\n\t\t.action(async (opts: SyncOnceOptions) => {\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\n\t\t\ttry {\n\t\t\t\tsyncPassPreflight(store.db);\n\t\t\t\tconst d = drizzle(store.db, { schema });\n\t\t\t\tconst rows = opts.peer\n\t\t\t\t\t? (() => {\n\t\t\t\t\t\t\tconst deviceMatches = d\n\t\t\t\t\t\t\t\t.select({ peer_device_id: schema.syncPeers.peer_device_id })\n\t\t\t\t\t\t\t\t.from(schema.syncPeers)\n\t\t\t\t\t\t\t\t.where(eq(schema.syncPeers.peer_device_id, opts.peer))\n\t\t\t\t\t\t\t\t.all();\n\t\t\t\t\t\t\tif (deviceMatches.length > 0) return deviceMatches;\n\t\t\t\t\t\t\tconst nameMatches = d\n\t\t\t\t\t\t\t\t.select({ peer_device_id: schema.syncPeers.peer_device_id })\n\t\t\t\t\t\t\t\t.from(schema.syncPeers)\n\t\t\t\t\t\t\t\t.where(eq(schema.syncPeers.name, opts.peer))\n\t\t\t\t\t\t\t\t.all();\n\t\t\t\t\t\t\tif (nameMatches.length > 1) {\n\t\t\t\t\t\t\t\tp.log.error(`Peer name is ambiguous: ${opts.peer}`);\n\t\t\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\t\t\treturn [];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn nameMatches;\n\t\t\t\t\t\t})()\n\t\t\t\t\t: d\n\t\t\t\t\t\t\t.select({ peer_device_id: schema.syncPeers.peer_device_id })\n\t\t\t\t\t\t\t.from(schema.syncPeers)\n\t\t\t\t\t\t\t.all();\n\n\t\t\t\tif (rows.length === 0) {\n\t\t\t\t\tp.log.warn(\"No peers available for sync\");\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tlet hadFailure = false;\n\t\t\t\tfor (const row of rows) {\n\t\t\t\t\tconst result = await runSyncPass(store.db, row.peer_device_id);\n\t\t\t\t\tif (!result.ok) hadFailure = true;\n\t\t\t\t\tconsole.log(formatSyncOnceResult(row.peer_device_id, result));\n\t\t\t\t}\n\t\t\t\tif (hadFailure) {\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tstore.close();\n\t\t\t}\n\t\t}),\n);\n\nsyncCommand.addCommand(\n\tnew Command(\"pair\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Print pairing payload or accept a peer payload\")\n\t\t.option(\"--accept <json>\", \"accept pairing payload JSON from another device\")\n\t\t.option(\"--accept-file <path>\", \"accept pairing payload from file path, or '-' for stdin\")\n\t\t.option(\"--payload-only\", \"when generating pairing payload, print JSON only\")\n\t\t.option(\"--name <name>\", \"label for the peer\")\n\t\t.option(\"--address <host:port>\", \"override peer address (host:port)\")\n\t\t.option(\"--include <projects>\", \"outbound-only allowlist for accepted peer\")\n\t\t.option(\"--exclude <projects>\", \"outbound-only blocklist for accepted peer\")\n\t\t.option(\"--all\", \"with --accept, push all projects to that peer\")\n\t\t.option(\"--default\", \"with --accept, use default/global push filters\")\n\t\t.option(\"--db-path <path>\", \"database path\")\n\t\t.action(async (opts: SyncPairOptions) => {\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.dbPath));\n\t\t\ttry {\n\t\t\t\tconst acceptModeRequested = opts.accept != null || opts.acceptFile != null;\n\t\t\t\tif (opts.payloadOnly && acceptModeRequested) {\n\t\t\t\t\tp.log.error(\"--payload-only cannot be combined with --accept or --accept-file\");\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (opts.accept && opts.acceptFile) {\n\t\t\t\t\tp.log.error(\"Use only one of --accept or --accept-file\");\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tlet acceptText = opts.accept;\n\t\t\t\tif (opts.acceptFile) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tacceptText =\n\t\t\t\t\t\t\topts.acceptFile === \"-\"\n\t\t\t\t\t\t\t\t? await new Promise<string>((resolve, reject) => {\n\t\t\t\t\t\t\t\t\t\tlet text = \"\";\n\t\t\t\t\t\t\t\t\t\tprocess.stdin.setEncoding(\"utf8\");\n\t\t\t\t\t\t\t\t\t\tprocess.stdin.on(\"data\", (chunk) => {\n\t\t\t\t\t\t\t\t\t\t\ttext += chunk;\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\tprocess.stdin.on(\"end\", () => resolve(text));\n\t\t\t\t\t\t\t\t\t\tprocess.stdin.on(\"error\", reject);\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t: readFileSync(opts.acceptFile, \"utf8\");\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tp.log.error(\n\t\t\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t\t\t? `Failed to read pairing payload from ${opts.acceptFile}: ${error.message}`\n\t\t\t\t\t\t\t\t: `Failed to read pairing payload from ${opts.acceptFile}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (acceptModeRequested && !(acceptText ?? \"\").trim()) {\n\t\t\t\t\tp.log.error(\"Empty pairing payload; provide JSON via --accept or --accept-file\");\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (!acceptText && (opts.include || opts.exclude || opts.all || opts.default)) {\n\t\t\t\t\tp.log.error(\n\t\t\t\t\t\t\"Project filters are outbound-only and must be set on the device running --accept\",\n\t\t\t\t\t);\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (acceptText?.trim()) {\n\t\t\t\t\tif (opts.all && opts.default) {\n\t\t\t\t\t\tp.log.error(\"Use only one of --all or --default\");\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif ((opts.all || opts.default) && (opts.include || opts.exclude)) {\n\t\t\t\t\t\tp.log.error(\"--include/--exclude cannot be combined with --all/--default\");\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tlet payload: Record<string, unknown>;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tpayload = JSON.parse(acceptText) as Record<string, unknown>;\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tp.log.error(\n\t\t\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t\t\t? `Invalid pairing payload: ${error.message}`\n\t\t\t\t\t\t\t\t: \"Invalid pairing payload\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst deviceId = String(payload.device_id || \"\").trim();\n\t\t\t\t\tconst fingerprint = String(payload.fingerprint || \"\").trim();\n\t\t\t\t\tconst publicKey = String(payload.public_key || \"\").trim();\n\t\t\t\t\tconst resolvedAddresses = opts.address?.trim()\n\t\t\t\t\t\t? [opts.address.trim()]\n\t\t\t\t\t\t: Array.isArray(payload.addresses)\n\t\t\t\t\t\t\t? (payload.addresses as unknown[])\n\t\t\t\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t\t\t\t(item): item is string => typeof item === \"string\" && item.trim().length > 0,\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t.map((item) => item.trim())\n\t\t\t\t\t\t\t: [];\n\t\t\t\t\tif (!deviceId || !fingerprint || !publicKey || resolvedAddresses.length === 0) {\n\t\t\t\t\t\tp.log.error(\"Pairing payload missing device_id, fingerprint, public_key, or addresses\");\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (fingerprintPublicKey(publicKey) !== fingerprint) {\n\t\t\t\t\t\tp.log.error(\"Pairing payload fingerprint mismatch\");\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tupdatePeerAddresses(store.db, deviceId, resolvedAddresses, {\n\t\t\t\t\t\tname: opts.name,\n\t\t\t\t\t\tpinnedFingerprint: fingerprint,\n\t\t\t\t\t\tpublicKey,\n\t\t\t\t\t});\n\n\t\t\t\t\tif (opts.default) {\n\t\t\t\t\t\tsetPeerProjectFilter(store.db, deviceId, { include: null, exclude: null });\n\t\t\t\t\t} else if (opts.all || opts.include || opts.exclude) {\n\t\t\t\t\t\tsetPeerProjectFilter(store.db, deviceId, {\n\t\t\t\t\t\t\tinclude: opts.all ? [] : parseProjectList(opts.include),\n\t\t\t\t\t\t\texclude: opts.all ? [] : parseProjectList(opts.exclude),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tp.log.success(`Paired with ${deviceId}`);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst keysDir = process.env.CODEMEM_KEYS_DIR?.trim() || undefined;\n\t\t\t\tconst [deviceId, fingerprint] = ensureDeviceIdentity(store.db, { keysDir });\n\t\t\t\tconst publicKey = loadPublicKey(keysDir);\n\t\t\t\tif (!publicKey) {\n\t\t\t\t\tp.log.error(\"Public key missing\");\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst config = readCodememConfigFile();\n\t\t\t\tconst explicitAddress = opts.address?.trim();\n\t\t\t\tconst configuredHost = typeof config.sync_host === \"string\" ? config.sync_host : null;\n\t\t\t\tconst configuredPort = typeof config.sync_port === \"number\" ? config.sync_port : 7337;\n\t\t\t\tconst addresses = collectAdvertiseAddresses(\n\t\t\t\t\texplicitAddress ?? null,\n\t\t\t\t\tconfiguredHost,\n\t\t\t\t\tconfiguredPort,\n\t\t\t\t\tnetworkInterfaces(),\n\t\t\t\t);\n\t\t\t\tconst payload = {\n\t\t\t\t\tdevice_id: deviceId,\n\t\t\t\t\tfingerprint,\n\t\t\t\t\tpublic_key: publicKey,\n\t\t\t\t\taddress: addresses[0] ?? \"\",\n\t\t\t\t\taddresses,\n\t\t\t\t};\n\t\t\t\tconst payloadText = JSON.stringify(payload);\n\n\t\t\t\tif (opts.payloadOnly) {\n\t\t\t\t\tprocess.stdout.write(`${payloadText}\\n`);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst escaped = payloadText.replaceAll(\"'\", \"'\\\\''\");\n\t\t\t\tconsole.log(\"Pairing payload\");\n\t\t\t\tconsole.log(payloadText);\n\t\t\t\tconsole.log(\"On the other device, save this JSON to pairing.json, then run:\");\n\t\t\t\tconsole.log(\" codemem sync pair --accept-file pairing.json\");\n\t\t\t\tconsole.log(\"If you prefer inline JSON, run:\");\n\t\t\t\tconsole.log(` codemem sync pair --accept '${escaped}'`);\n\t\t\t\tconsole.log(\"For machine-friendly output next time, run:\");\n\t\t\t\tconsole.log(\" codemem sync pair --payload-only\");\n\t\t\t\tconsole.log(\n\t\t\t\t\t\"On the accepting device, --include/--exclude only control what it sends to peers.\",\n\t\t\t\t);\n\t\t\t\tconsole.log(\"This device does not yet enforce incoming project filters.\");\n\t\t\t} finally {\n\t\t\t\tstore.close();\n\t\t\t}\n\t\t}),\n);\n\nsyncCommand.addCommand(\n\tnew Command(\"doctor\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Diagnose common sync setup and connectivity issues\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.option(\"--db-path <path>\", \"database path\")\n\t\t.action(async (opts: { db?: string; dbPath?: string }) => {\n\t\t\tconst config = readCodememConfigFile();\n\t\t\tconst dbPath = resolveDbPath(opts.db ?? opts.dbPath);\n\t\t\tconst store = new MemoryStore(dbPath);\n\t\t\ttry {\n\t\t\t\tconst d = drizzle(store.db, { schema });\n\t\t\t\tconst device = d\n\t\t\t\t\t.select({ device_id: schema.syncDevice.device_id })\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 daemonState = d\n\t\t\t\t\t.select()\n\t\t\t\t\t.from(schema.syncDaemonState)\n\t\t\t\t\t.where(eq(schema.syncDaemonState.id, 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\taddresses_json: schema.syncPeers.addresses_json,\n\t\t\t\t\t\tpinned_fingerprint: schema.syncPeers.pinned_fingerprint,\n\t\t\t\t\t\tpublic_key: schema.syncPeers.public_key,\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\tconst issues: string[] = [];\n\t\t\t\tconst syncHost = typeof config.sync_host === \"string\" ? config.sync_host : \"0.0.0.0\";\n\t\t\t\tconst syncPort = typeof config.sync_port === \"number\" ? config.sync_port : 7337;\n\t\t\t\tconst viewerBinding = readViewerBinding(dbPath);\n\n\t\t\t\tconsole.log(\"Sync doctor\");\n\t\t\t\tconsole.log(`- Enabled: ${config.sync_enabled === true}`);\n\t\t\t\tconsole.log(`- Listen: ${syncHost}:${syncPort}`);\n\t\t\t\tconsole.log(`- mDNS: ${process.env.CODEMEM_SYNC_MDNS ? \"env-configured\" : \"default/off\"}`);\n\n\t\t\t\tconst reachable = viewerBinding\n\t\t\t\t\t? await portOpen(viewerBinding.host, viewerBinding.port)\n\t\t\t\t\t: false;\n\t\t\t\tconsole.log(`- Daemon: ${reachable ? \"running\" : \"not running\"}`);\n\t\t\t\tif (!reachable) issues.push(\"daemon not running\");\n\n\t\t\t\tif (!device) {\n\t\t\t\t\tconsole.log(\"- Identity: missing (run `codemem sync enable`)\");\n\t\t\t\t\tissues.push(\"identity missing\");\n\t\t\t\t} else {\n\t\t\t\t\tconsole.log(`- Identity: ${device.device_id}`);\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\tdaemonState?.last_error &&\n\t\t\t\t\t(!daemonState.last_ok_at || daemonState.last_ok_at < (daemonState.last_error_at ?? \"\"))\n\t\t\t\t) {\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t`- Daemon error: ${daemonState.last_error} (at ${daemonState.last_error_at ?? \"unknown\"})`,\n\t\t\t\t\t);\n\t\t\t\t\tissues.push(\"daemon error\");\n\t\t\t\t}\n\n\t\t\t\tif (peers.length === 0) {\n\t\t\t\t\tconsole.log(\"- Peers: none (pair a device first)\");\n\t\t\t\t\tissues.push(\"no peers\");\n\t\t\t\t} else {\n\t\t\t\t\tconsole.log(`- Peers: ${peers.length}`);\n\t\t\t\t\tfor (const peer of peers) {\n\t\t\t\t\t\tconst addresses = peer.addresses_json\n\t\t\t\t\t\t\t? (JSON.parse(peer.addresses_json) as string[])\n\t\t\t\t\t\t\t: [];\n\t\t\t\t\t\tconst endpoint = parseStoredAddressEndpoint(addresses[0] ?? \"\");\n\t\t\t\t\t\tconst reach = endpoint\n\t\t\t\t\t\t\t? (await portOpen(endpoint.host, endpoint.port))\n\t\t\t\t\t\t\t\t? \"ok\"\n\t\t\t\t\t\t\t\t: \"unreachable\"\n\t\t\t\t\t\t\t: \"unknown\";\n\t\t\t\t\t\tconst pinned = Boolean(peer.pinned_fingerprint);\n\t\t\t\t\t\tconst hasKey = Boolean(peer.public_key);\n\t\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t\t` - ${peer.peer_device_id}: addresses=${addresses.length} reach=${reach} pinned=${pinned} public_key=${hasKey}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (reach !== \"ok\") issues.push(`peer ${peer.peer_device_id} unreachable`);\n\t\t\t\t\t\tif (!pinned || !hasKey) issues.push(`peer ${peer.peer_device_id} not pinned`);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!config.sync_enabled) issues.push(\"sync is disabled\");\n\n\t\t\t\tif (issues.length > 0) {\n\t\t\t\t\tconsole.log(`WARN: ${[...new Set(issues)].slice(0, 3).join(\", \")}`);\n\t\t\t\t} else {\n\t\t\t\t\tconsole.log(\"OK: sync looks healthy\");\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tstore.close();\n\t\t\t}\n\t\t}),\n);\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(\"--db-path <path>\", \"database path\")\n\t\t.option(\"--json\", \"output as JSON\")\n\t\t.action((opts: { db?: string; dbPath?: string; json?: boolean }) => {\n\t\t\tconst config = readCodememConfigFile();\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\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(\"--db-path <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(\n\t\t\t(opts: { db?: string; dbPath?: string; host?: string; port?: string; interval?: string }) => {\n\t\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\n\t\t\t\ttry {\n\t\t\t\t\tconst [deviceId, fingerprint] = ensureDeviceIdentity(store.db);\n\t\t\t\t\tconst config = readCodememConfigFile();\n\t\t\t\t\tconfig.sync_enabled = true;\n\t\t\t\t\tif (opts.host) config.sync_host = opts.host;\n\t\t\t\t\tif (opts.port) config.sync_port = Number.parseInt(opts.port, 10);\n\t\t\t\t\tif (opts.interval) config.sync_interval_s = Number.parseInt(opts.interval, 10);\n\t\t\t\t\twriteCodememConfigFile(config);\n\n\t\t\t\t\tp.intro(\"codemem sync enable\");\n\t\t\t\t\tp.log.success(\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t`Device ID: ${deviceId}`,\n\t\t\t\t\t\t\t`Fingerprint: ${fingerprint}`,\n\t\t\t\t\t\t\t`Host: ${config.sync_host ?? \"0.0.0.0\"}`,\n\t\t\t\t\t\t\t`Port: ${config.sync_port ?? 7337}`,\n\t\t\t\t\t\t\t`Interval: ${config.sync_interval_s ?? 120}s`,\n\t\t\t\t\t\t].join(\"\\n\"),\n\t\t\t\t\t);\n\t\t\t\t\tp.outro(\"Sync enabled — restart `codemem serve` to activate\");\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\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(\"--db-path <path>\", \"database path\")\n\t\t.option(\"--json\", \"output as JSON\")\n\t\t.action((opts: { db?: string; dbPath?: string; json?: boolean }) => {\n\t\t\tconst store = new MemoryStore(resolveDbPath(opts.db ?? opts.dbPath));\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 {\n\tforgetMemoryCommand,\n\tmemoryCommand,\n\trememberMemoryCommand,\n\tshowMemoryCommand,\n} 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\"forget\",\n\t\t\"memory\",\n\t\t\"import-memories\",\n\t\t\"setup\",\n\t\t\"show\",\n\t\t\"sync\",\n\t\t\"stats\",\n\t\t\"recent\",\n\t\t\"remember\",\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\nfunction hasRootFlag(flag: string): boolean {\n\tfor (const arg of process.argv.slice(2)) {\n\t\tif (arg === \"--\") return false;\n\t\tif (arg === flag) return true;\n\t\tif (!arg.startsWith(\"-\")) return false;\n\t}\n\treturn false;\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\nif (hasRootFlag(\"--setup-completion\")) {\n\tcompletion.setupShellInitFile();\n\tprocess.exit(0);\n}\n\nif (hasRootFlag(\"--cleanup-completion\")) {\n\tcompletion.cleanupShellInitFile();\n\tprocess.exit(0);\n}\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(showMemoryCommand);\nprogram.addCommand(forgetMemoryCommand);\nprogram.addCommand(rememberMemoryCommand);\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,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codemem",
|
|
3
|
-
"version": "0.20.0-alpha.
|
|
3
|
+
"version": "0.20.0-alpha.4",
|
|
4
4
|
"description": "Memory layer for AI coding agents — search, recall, and sync context across sessions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"dist/",
|
|
11
|
-
".opencode/
|
|
11
|
+
".opencode/plugins/",
|
|
12
12
|
".opencode/lib/",
|
|
13
13
|
"README.md",
|
|
14
14
|
"LICENSE"
|
|
@@ -19,17 +19,17 @@
|
|
|
19
19
|
"commander": "^14.0.3",
|
|
20
20
|
"drizzle-orm": "^0.45.1",
|
|
21
21
|
"omelette": "^0.4.17",
|
|
22
|
-
"@codemem/core": "^0.20.0-alpha.
|
|
23
|
-
"@codemem/
|
|
24
|
-
"@codemem/
|
|
22
|
+
"@codemem/core": "^0.20.0-alpha.4",
|
|
23
|
+
"@codemem/mcp": "^0.20.0-alpha.4",
|
|
24
|
+
"@codemem/server": "^0.20.0-alpha.4"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/node": "^25.5.0",
|
|
28
28
|
"@types/omelette": "^0.4.5",
|
|
29
29
|
"tsx": "^4.21.0",
|
|
30
30
|
"typescript": "^5.8.2",
|
|
31
|
-
"vite": "
|
|
32
|
-
"vitest": "
|
|
31
|
+
"vite": "8.0.1",
|
|
32
|
+
"vitest": "4.0.17"
|
|
33
33
|
},
|
|
34
34
|
"engines": {
|
|
35
35
|
"node": ">=22"
|