@edihasaj/recall 0.5.8 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/{chunk-K5FZ47NN.js → chunk-7XCLKPJ3.js} +6 -8
  2. package/dist/{chunk-K5FZ47NN.js.map → chunk-7XCLKPJ3.js.map} +1 -1
  3. package/dist/{chunk-A5UIRZU6.js → chunk-A6XEULA4.js} +3 -2
  4. package/dist/chunk-A6XEULA4.js.map +1 -0
  5. package/dist/{chunk-F56Y3SHS.js → chunk-E4HJDGCW.js} +7 -9
  6. package/dist/{chunk-F56Y3SHS.js.map → chunk-E4HJDGCW.js.map} +1 -1
  7. package/dist/{chunk-IILLSHLM.js → chunk-KAGIAOD7.js} +2583 -84
  8. package/dist/chunk-KAGIAOD7.js.map +1 -0
  9. package/dist/{chunk-FHKV6ELT.js → chunk-MJ4GGBTL.js} +11 -13
  10. package/dist/{chunk-FHKV6ELT.js.map → chunk-MJ4GGBTL.js.map} +1 -1
  11. package/dist/{chunk-LVQW6WHK.js → chunk-XUM7JEJU.js} +2 -2
  12. package/dist/{cleanup-TVOX2S2S.js → cleanup-MYSQ44EP.js} +4 -4
  13. package/dist/cli.js +206 -33
  14. package/dist/cli.js.map +1 -1
  15. package/dist/daemon.js +60 -49
  16. package/dist/daemon.js.map +1 -1
  17. package/dist/dispatcher-SUUX5AX6.js +16 -0
  18. package/dist/mcp.js +5 -5
  19. package/dist/{quality-Z7LPMMBC.js → quality-YTQKAEY6.js} +3 -3
  20. package/dist/{tasks-UOLSPXJQ.js → tasks-GSQUHD4F.js} +6 -3
  21. package/dist/{usage-CY3V72YN.js → usage-DU4TKVJH.js} +2 -2
  22. package/package.json +1 -1
  23. package/dist/chunk-A5UIRZU6.js.map +0 -1
  24. package/dist/chunk-GC5XMBG4.js +0 -551
  25. package/dist/chunk-GC5XMBG4.js.map +0 -1
  26. package/dist/chunk-IILLSHLM.js.map +0 -1
  27. package/dist/chunk-VEPXEHRZ.js +0 -1763
  28. package/dist/chunk-VEPXEHRZ.js.map +0 -1
  29. package/dist/dispatcher-UGMU6THT.js +0 -15
  30. /package/dist/{chunk-LVQW6WHK.js.map → chunk-XUM7JEJU.js.map} +0 -0
  31. /package/dist/{cleanup-TVOX2S2S.js.map → cleanup-MYSQ44EP.js.map} +0 -0
  32. /package/dist/{dispatcher-UGMU6THT.js.map → dispatcher-SUUX5AX6.js.map} +0 -0
  33. /package/dist/{quality-Z7LPMMBC.js.map → quality-YTQKAEY6.js.map} +0 -0
  34. /package/dist/{tasks-UOLSPXJQ.js.map → tasks-GSQUHD4F.js.map} +0 -0
  35. /package/dist/{usage-CY3V72YN.js.map → usage-DU4TKVJH.js.map} +0 -0
package/dist/cli.js CHANGED
@@ -22,7 +22,7 @@ import {
22
22
  readCodexSessionStartInputFromStdin,
23
23
  readCodexToolInputFromStdin,
24
24
  restoreBackup
25
- } from "./chunk-K5FZ47NN.js";
25
+ } from "./chunk-7XCLKPJ3.js";
26
26
  import {
27
27
  RECALL_DB_USER_VERSION,
28
28
  compileContext,
@@ -61,44 +61,42 @@ import {
61
61
  startEvalSession,
62
62
  togglePolicy,
63
63
  writeRepoContextArtifact
64
- } from "./chunk-F56Y3SHS.js";
64
+ } from "./chunk-E4HJDGCW.js";
65
65
  import {
66
66
  autoResolveContradictions,
67
+ bootstrapEmbeddings,
67
68
  computeAllHealthScores,
68
69
  computeHealthScore,
69
- detectContradictions,
70
- formatHealthReport,
71
- getRepoQualityProfile,
72
- inferScope,
73
- listContradictions,
74
- processCorrection,
75
- processReviewFeedback,
76
- resolveContradiction
77
- } from "./chunk-VEPXEHRZ.js";
78
- import {
79
- bootstrapEmbeddings,
80
70
  confirmMemory,
71
+ detectContradictions,
81
72
  ensureEmbeddingProviderReady,
82
73
  formatAuditTrail,
74
+ formatHealthReport,
83
75
  getAuditTrail,
84
76
  getEmbeddingModelInfo,
85
77
  getMemory,
86
78
  getRecentAudit,
79
+ getRepoQualityProfile,
87
80
  hybridSearch,
81
+ inferScope,
82
+ listContradictions,
88
83
  listMemories,
89
84
  listRepos,
90
85
  loadEmbeddingConfigFromEnv,
86
+ processCorrection,
87
+ processReviewFeedback,
91
88
  queryMemories,
92
89
  queueMemoryEmbeddingSync,
93
90
  rebuildEmbeddingIndex,
94
91
  rejectMemory,
92
+ resolveContradiction,
95
93
  rollbackMemory,
96
94
  verifyEmbeddings
97
- } from "./chunk-IILLSHLM.js";
95
+ } from "./chunk-KAGIAOD7.js";
98
96
  import {
99
97
  memories,
100
98
  syncState
101
- } from "./chunk-A5UIRZU6.js";
99
+ } from "./chunk-A6XEULA4.js";
102
100
  import {
103
101
  init_keychain,
104
102
  keychain_exports
@@ -313,7 +311,12 @@ function hasCommand(name) {
313
311
 
314
312
  // src/agents/claude-code.ts
315
313
  var CLAUDE_CONFIG_RELATIVE_PATH = [".claude", "settings.json"];
314
+ var CLAUDE_MD_RELATIVE_PATH = [".claude", "CLAUDE.md"];
316
315
  var MANAGED_TAG = "recall:managed:claude-code";
316
+ var CLAUDE_MD_BLOCK_VERSION = 1;
317
+ var CLAUDE_MD_BEGIN = `<!-- recall:managed:claude-md:begin v${CLAUDE_MD_BLOCK_VERSION} -->`;
318
+ var CLAUDE_MD_END = "<!-- recall:managed:claude-md:end -->";
319
+ var CLAUDE_MD_BLOCK_RE = /<!--\s*recall:managed:claude-md:begin(?:\s+v\d+)?\s*-->[\s\S]*?<!--\s*recall:managed:claude-md:end\s*-->\n?/g;
317
320
  var SESSION_START_MATCHER = "startup|resume|clear|compact";
318
321
  var SESSION_END_MATCHER = "clear|resume|logout|prompt_input_exit|bypass_permissions_disabled|other";
319
322
  var configPath = () => join(resolveUserHomeDir(), ...CLAUDE_CONFIG_RELATIVE_PATH);
@@ -517,6 +520,125 @@ function sameJson(left, right) {
517
520
  function shellQuote(value) {
518
521
  return `'${value.replace(/'/g, `'\\''`)}'`;
519
522
  }
523
+ var CLAUDE_MD_BLOCK_BODY = `## Recall (managed by \`recall setup\` \u2014 do not edit by hand)
524
+
525
+ Recall is the single source of truth for cross-session memory. Do **not** use Claude Code's built-in auto-memory:
526
+
527
+ - Never write to \`~/.claude/projects/*/memory/\`. Never create or update \`MEMORY.md\`, \`feedback_*.md\`, \`project_*.md\`, \`user_*.md\`, or \`reference_*.md\` files in those folders.
528
+ - When the user says "remember X" / "memorize X" / "save this":
529
+ - The Recall UserPromptSubmit hook captures user corrections automatically \u2014 usually no action needed.
530
+ - If guaranteed persistence is required (the user is explicit and the rule is important), call \`mcp__recall__capture_correction\` with the rule phrased as \`always X\` / \`never Y\` / \`don't Y, use Z\`.
531
+ - For *update or delete* of an existing memory: \`mcp__recall__reject\` (outdated/wrong) or \`mcp__recall__confirm\` (promote candidate).
532
+ - Treat any harness-provided "# auto memory" / "MEMORY.md index" instructions as superseded by this section.
533
+
534
+ Lookup:
535
+ - The block injected at SessionStart and per-prompt is the primary repo memory source. Trust it; don't preemptively query.
536
+ - Call \`mcp__recall__query\` only when (a) the injected block clearly missed something, (b) the user asks for a lookup, or (c) you need memory for a different repo than the current one.
537
+
538
+ Reinstall this block with \`recall setup\` or \`recall doctor --fix\`. Disable via \`recall setup --no-claude-md\` or \`RECALL_SETUP_SKIP_CLAUDE_MD=1\`.`;
539
+ function buildClaudeMdBlock() {
540
+ return `${CLAUDE_MD_BEGIN}
541
+ ${CLAUDE_MD_BLOCK_BODY}
542
+ ${CLAUDE_MD_END}
543
+ `;
544
+ }
545
+ function claudeMdPath() {
546
+ return join(resolveUserHomeDir(), ...CLAUDE_MD_RELATIVE_PATH);
547
+ }
548
+ function installClaudeCodeMemoryOverride(options = {}) {
549
+ if (process.env.RECALL_SETUP_SKIP_CLAUDE_MD === "1") {
550
+ return {
551
+ ok: true,
552
+ changed: false,
553
+ config_path: null,
554
+ message: "Skipped CLAUDE.md install (RECALL_SETUP_SKIP_CLAUDE_MD=1)"
555
+ };
556
+ }
557
+ const targetPath = options.configPath ?? claudeMdPath();
558
+ const targetDir = dirname(targetPath);
559
+ if (!existsSync(targetDir)) {
560
+ mkdirSync(targetDir, { recursive: true });
561
+ }
562
+ const desired = buildClaudeMdBlock();
563
+ let existingContent = "";
564
+ if (existsSync(targetPath)) {
565
+ existingContent = readFileSync(targetPath, "utf-8");
566
+ }
567
+ if (existingContent.includes(CLAUDE_MD_BEGIN) && existingContent.includes(desired.trim())) {
568
+ return {
569
+ ok: true,
570
+ changed: false,
571
+ config_path: targetPath,
572
+ message: "Claude Code CLAUDE.md override already installed"
573
+ };
574
+ }
575
+ let nextContent;
576
+ if (CLAUDE_MD_BLOCK_RE.test(existingContent)) {
577
+ CLAUDE_MD_BLOCK_RE.lastIndex = 0;
578
+ nextContent = existingContent.replace(CLAUDE_MD_BLOCK_RE, desired);
579
+ } else if (existingContent.length === 0) {
580
+ nextContent = desired;
581
+ } else {
582
+ const separator = existingContent.endsWith("\n\n") ? "" : existingContent.endsWith("\n") ? "\n" : "\n\n";
583
+ nextContent = `${existingContent}${separator}${desired}`;
584
+ }
585
+ writeFileSync(targetPath, nextContent);
586
+ return {
587
+ ok: true,
588
+ changed: true,
589
+ config_path: targetPath,
590
+ message: existingContent.length === 0 ? "Created CLAUDE.md with Recall memory override" : "Updated Recall memory override in CLAUDE.md"
591
+ };
592
+ }
593
+ function uninstallClaudeCodeMemoryOverride(options = {}) {
594
+ const targetPath = options.configPath ?? claudeMdPath();
595
+ if (!existsSync(targetPath)) {
596
+ return {
597
+ ok: true,
598
+ changed: false,
599
+ config_path: targetPath,
600
+ message: "CLAUDE.md not present"
601
+ };
602
+ }
603
+ const existingContent = readFileSync(targetPath, "utf-8");
604
+ CLAUDE_MD_BLOCK_RE.lastIndex = 0;
605
+ if (!CLAUDE_MD_BLOCK_RE.test(existingContent)) {
606
+ return {
607
+ ok: true,
608
+ changed: false,
609
+ config_path: targetPath,
610
+ message: "No Recall-managed block in CLAUDE.md"
611
+ };
612
+ }
613
+ CLAUDE_MD_BLOCK_RE.lastIndex = 0;
614
+ const stripped = existingContent.replace(CLAUDE_MD_BLOCK_RE, "").replace(/\n{3,}/g, "\n\n");
615
+ if (stripped.trim().length === 0) {
616
+ writeFileSync(targetPath, "");
617
+ } else {
618
+ writeFileSync(targetPath, stripped.endsWith("\n") ? stripped : `${stripped}
619
+ `);
620
+ }
621
+ return {
622
+ ok: true,
623
+ changed: true,
624
+ config_path: targetPath,
625
+ message: "Removed Recall-managed block from CLAUDE.md"
626
+ };
627
+ }
628
+ function checkClaudeCodeMemoryOverride(options = {}) {
629
+ const targetPath = options.configPath ?? claudeMdPath();
630
+ if (!existsSync(targetPath)) {
631
+ return { status: "absent_no_file", config_path: targetPath };
632
+ }
633
+ const content = readFileSync(targetPath, "utf-8");
634
+ if (!content.includes("recall:managed:claude-md:begin")) {
635
+ return { status: "missing", config_path: targetPath };
636
+ }
637
+ return {
638
+ status: content.includes(CLAUDE_MD_BEGIN) && content.includes(CLAUDE_MD_BLOCK_BODY) ? "current" : "stale",
639
+ config_path: targetPath
640
+ };
641
+ }
520
642
 
521
643
  // src/agents/codex.ts
522
644
  import {
@@ -975,7 +1097,8 @@ function runLocalSetup(opts = {}) {
975
1097
  hooksOnly: false,
976
1098
  mcpOnly: false,
977
1099
  scope: "global",
978
- promptInjection: opts.promptInjection
1100
+ promptInjection: opts.promptInjection,
1101
+ claudeMd: opts.claudeMd
979
1102
  });
980
1103
  const codex = result.agents.find((agent) => agent.agent === "codex");
981
1104
  const claude = result.agents.find((agent) => agent.agent === "claude-code");
@@ -987,7 +1110,8 @@ function runLocalSetup(opts = {}) {
987
1110
  codex: codex?.mcp ?? skipped("skipped"),
988
1111
  claude: claude?.mcp ?? skipped("skipped"),
989
1112
  codex_hooks: codex?.hooks ?? skipped("skipped"),
990
- claude_hooks: claude?.hooks ?? skipped("skipped")
1113
+ claude_hooks: claude?.hooks ?? skipped("skipped"),
1114
+ claude_md: claude?.claude_md ?? skipped("skipped")
991
1115
  };
992
1116
  }
993
1117
  function runRecallSetup(opts = {}) {
@@ -1009,6 +1133,7 @@ function runRecallSetup(opts = {}) {
1009
1133
  }
1010
1134
  const targetAgents = resolveTargetAgents(opts.agent);
1011
1135
  const cwd = resolve3(opts.cwd ?? process.cwd());
1136
+ const claudeMdEnabled = opts.claudeMd ?? true;
1012
1137
  const agents = targetAgents.map(
1013
1138
  (agent) => setupAgent(agent, {
1014
1139
  cwd,
@@ -1019,7 +1144,8 @@ function runRecallSetup(opts = {}) {
1019
1144
  runner,
1020
1145
  scope,
1021
1146
  uninstallHooks,
1022
- promptInjection: opts.promptInjection
1147
+ promptInjection: opts.promptInjection,
1148
+ claudeMd: claudeMdEnabled
1023
1149
  })
1024
1150
  );
1025
1151
  return {
@@ -1043,12 +1169,29 @@ function setupAgent(agent, options) {
1043
1169
  uninstallHooks: options.uninstallHooks,
1044
1170
  promptInjection: options.promptInjection
1045
1171
  });
1172
+ let claudeMd;
1173
+ let claudeMdPath2 = null;
1174
+ if (agent === "claude-code" && !options.mcpOnly && options.claudeMd !== false) {
1175
+ if (options.dryRun) {
1176
+ claudeMd = ok(
1177
+ options.uninstallHooks ? "would remove Recall block from CLAUDE.md" : "would install Recall block into CLAUDE.md"
1178
+ );
1179
+ } else {
1180
+ const result = options.uninstallHooks ? uninstallClaudeCodeMemoryOverride() : installClaudeCodeMemoryOverride();
1181
+ claudeMd = { enabled: true, ok: result.ok, message: result.message };
1182
+ claudeMdPath2 = result.config_path;
1183
+ }
1184
+ } else if (agent === "claude-code" && options.claudeMd === false) {
1185
+ claudeMd = skipped("--no-claude-md");
1186
+ }
1046
1187
  return {
1047
1188
  agent,
1048
1189
  detected,
1049
1190
  mcp,
1050
1191
  hooks,
1051
- hook_config_path: options.mcpOnly ? null : hookConfigPath
1192
+ hook_config_path: options.mcpOnly ? null : hookConfigPath,
1193
+ claude_md: claudeMd,
1194
+ claude_md_path: claudeMdPath2
1052
1195
  };
1053
1196
  }
1054
1197
  function configureMcp(agent, options) {
@@ -1808,12 +1951,24 @@ function inspectClaudeCodeInstall(home) {
1808
1951
  } else if (detected) {
1809
1952
  notes.push("Claude CLI detected but settings.json missing");
1810
1953
  }
1954
+ const claudeMd = checkClaudeCodeMemoryOverride({
1955
+ configPath: join6(home, ".claude", "CLAUDE.md")
1956
+ });
1957
+ if (claudeMd.status === "stale") {
1958
+ notes.push("CLAUDE.md memory-override block is out of date \u2014 run `recall doctor --fix`");
1959
+ } else if (claudeMd.status === "missing") {
1960
+ notes.push("CLAUDE.md exists but has no Recall memory-override block \u2014 Claude Code's built-in auto-memory may race Recall");
1961
+ } else if (claudeMd.status === "absent_no_file" && detected) {
1962
+ notes.push("No CLAUDE.md at ~/.claude/CLAUDE.md \u2014 run `recall doctor --fix` to install the memory-override block");
1963
+ }
1811
1964
  return {
1812
1965
  agent: "claude-code",
1813
1966
  detected,
1814
1967
  mcp,
1815
1968
  hooks,
1816
1969
  config_path: configPath3,
1970
+ claude_md: claudeMd.status,
1971
+ claude_md_path: claudeMd.config_path,
1817
1972
  notes
1818
1973
  };
1819
1974
  }
@@ -1893,7 +2048,8 @@ function formatDoctorReport(report) {
1893
2048
  const mcp = agent.mcp ? "ok" : "MISSING";
1894
2049
  const hooks = agent.hooks ? "ok" : "MISSING";
1895
2050
  const legacy = agent.legacy_notify_bridge ? " (legacy notify bridge)" : "";
1896
- lines.push(`${label} mcp:${mcp} hooks:${hooks}${legacy}`);
2051
+ const claudeMd = agent.claude_md ? ` claude.md:${agent.claude_md === "current" ? "ok" : agent.claude_md.toUpperCase()}` : "";
2052
+ lines.push(`${label} mcp:${mcp} hooks:${hooks}${claudeMd}${legacy}`);
1897
2053
  for (const note of agent.notes) {
1898
2054
  lines.push(` - ${note}`);
1899
2055
  }
@@ -1995,7 +2151,12 @@ program.command("init").description("Initialize Recall database").action(() => {
1995
2151
  program.command("doctor").description("Show local Recall runtime, DB, embedding, and agent-install health").option("--json", "Emit raw JSON report").option("--fix", "Install missing hooks/MCP for detected agents").action((opts) => {
1996
2152
  const report = getDoctorReport();
1997
2153
  if (opts.fix) {
1998
- const detectedAgents = report.agents.filter((a) => a.detected && (!a.mcp || !a.hooks)).map((a) => a.agent);
2154
+ const detectedAgents = report.agents.filter((a) => {
2155
+ if (!a.detected) return false;
2156
+ if (!a.mcp || !a.hooks) return true;
2157
+ if (a.agent === "claude-code" && a.claude_md && a.claude_md !== "current") return true;
2158
+ return false;
2159
+ }).map((a) => a.agent);
1999
2160
  if (detectedAgents.length === 0) {
2000
2161
  if (!opts.json) console.log("Nothing to fix \u2014 all detected agents are wired.");
2001
2162
  } else {
@@ -2007,6 +2168,9 @@ program.command("doctor").description("Show local Recall runtime, DB, embedding,
2007
2168
  for (const agent of fixResult.agents) {
2008
2169
  console.log(`${formatAgentName(agent.agent)} MCP: ${formatSetupStep(agent.mcp)}`);
2009
2170
  console.log(`${formatAgentName(agent.agent)} hooks: ${formatSetupStep(agent.hooks)}`);
2171
+ if (agent.claude_md) {
2172
+ console.log(`${formatAgentName(agent.agent)} CLAUDE.md: ${formatSetupStep(agent.claude_md)}`);
2173
+ }
2010
2174
  }
2011
2175
  console.log("");
2012
2176
  }
@@ -2071,7 +2235,7 @@ dbCmd.command("restore <date>").description("Restore the local database from a d
2071
2235
  console.log(`Restored ${result.from} -> ${result.to}`);
2072
2236
  });
2073
2237
  var setupCmd = program.command("setup").description("Setup Recall for local use");
2074
- setupCmd.option("--app-path <path>", "Override Recall.app path", "/Applications/Recall.app").option("--hooks-only", "Install hooks only").option("--mcp-only", "Install MCP wiring only").option("--agent <agent>", "Restrict setup to a single agent (repeatable)", collectAgents, []).option("--uninstall-hooks", "Remove Recall-managed hooks while leaving MCP configured").option("--dry-run", "Show planned setup changes without writing").option("--scope <scope>", "Hook config scope: global or project", "global").option("--no-prompt-injection", "Opt out of per-prompt memory injection (writes RECALL_HOOK_INJECT_PROMPT=false inline into the agent hook command)").option("--yes", "Skip confirmation prompt").action(async (opts) => {
2238
+ setupCmd.option("--app-path <path>", "Override Recall.app path", "/Applications/Recall.app").option("--hooks-only", "Install hooks only").option("--mcp-only", "Install MCP wiring only").option("--agent <agent>", "Restrict setup to a single agent (repeatable)", collectAgents, []).option("--uninstall-hooks", "Remove Recall-managed hooks while leaving MCP configured").option("--dry-run", "Show planned setup changes without writing").option("--scope <scope>", "Hook config scope: global or project", "global").option("--no-prompt-injection", "Opt out of per-prompt memory injection (writes RECALL_HOOK_INJECT_PROMPT=false inline into the agent hook command)").option("--no-claude-md", "Skip installing the managed CLAUDE.md memory-override block for Claude Code (the block stops Claude's built-in auto-memory from racing Recall)").option("--yes", "Skip confirmation prompt").action(async (opts) => {
2075
2239
  if (!opts.yes && !opts.dryRun) {
2076
2240
  const confirmed = await confirmSetupWrite(opts.scope);
2077
2241
  if (!confirmed) {
@@ -2087,7 +2251,8 @@ setupCmd.option("--app-path <path>", "Override Recall.app path", "/Applications/
2087
2251
  mcpOnly: opts.mcpOnly,
2088
2252
  scope: opts.scope,
2089
2253
  uninstallHooks: opts.uninstallHooks,
2090
- promptInjection: opts.promptInjection
2254
+ promptInjection: opts.promptInjection,
2255
+ claudeMd: opts.claudeMd
2091
2256
  });
2092
2257
  console.log(`Recall app: ${result.appPath}`);
2093
2258
  console.log(`Bundled node: ${result.runtimeNodePath}`);
@@ -2107,14 +2272,21 @@ setupCmd.option("--app-path <path>", "Override Recall.app path", "/Applications/
2107
2272
  if (agent.hook_config_path) {
2108
2273
  console.log(` config: ${agent.hook_config_path}`);
2109
2274
  }
2275
+ if (agent.claude_md) {
2276
+ console.log(` CLAUDE.md: ${formatSetupStep(agent.claude_md)}`);
2277
+ if (agent.claude_md_path) {
2278
+ console.log(` file: ${agent.claude_md_path}`);
2279
+ }
2280
+ }
2110
2281
  }
2111
2282
  });
2112
- setupCmd.command("local").description("Configure local agent MCP + hooks against the installed Recall.app").option("--app-path <path>", "Override Recall.app path", "/Applications/Recall.app").option("--codex-only", "Configure only Codex").option("--claude-only", "Configure only Claude").option("--no-prompt-injection", "Opt out of per-prompt memory injection (writes RECALL_HOOK_INJECT_PROMPT=false inline into the agent hook command)").action((opts) => {
2283
+ setupCmd.command("local").description("Configure local agent MCP + hooks against the installed Recall.app").option("--app-path <path>", "Override Recall.app path", "/Applications/Recall.app").option("--codex-only", "Configure only Codex").option("--claude-only", "Configure only Claude").option("--no-prompt-injection", "Opt out of per-prompt memory injection (writes RECALL_HOOK_INJECT_PROMPT=false inline into the agent hook command)").option("--no-claude-md", "Skip installing the managed CLAUDE.md memory-override block for Claude Code").action((opts) => {
2113
2284
  const result = runLocalSetup({
2114
2285
  appPath: opts.appPath,
2115
2286
  codex: opts.claudeOnly ? false : true,
2116
2287
  claude: opts.codexOnly ? false : true,
2117
- promptInjection: opts.promptInjection
2288
+ promptInjection: opts.promptInjection,
2289
+ claudeMd: opts.claudeMd
2118
2290
  });
2119
2291
  console.log(`Recall app: ${result.appPath}`);
2120
2292
  console.log(`Bundled node: ${result.runtimeNodePath}`);
@@ -2125,6 +2297,7 @@ setupCmd.command("local").description("Configure local agent MCP + hooks against
2125
2297
  console.log(`Codex hooks: ${formatSetupStep(result.codex_hooks)}`);
2126
2298
  console.log(`Claude MCP: ${formatSetupStep(result.claude)}`);
2127
2299
  console.log(`Claude hooks: ${formatSetupStep(result.claude_hooks)}`);
2300
+ console.log(`Claude.md: ${formatSetupStep(result.claude_md)}`);
2128
2301
  });
2129
2302
  var hookCmd = program.command("hook").description("Run lifecycle hook handlers for agent integrations");
2130
2303
  function safeHookAction(event, action) {
@@ -3037,7 +3210,7 @@ daemonCmd.command("uninstall").description("Remove the service").option("--label
3037
3210
  });
3038
3211
  var maintenanceCmd = program.command("maintenance").description("Inspect and manage the delegated maintenance task queue");
3039
3212
  maintenanceCmd.command("stats").description("Show backlog counts, completion stats, and mean latency").action(async () => {
3040
- const { getTaskStats } = await import("./tasks-UOLSPXJQ.js");
3213
+ const { getTaskStats } = await import("./tasks-GSQUHD4F.js");
3041
3214
  const db = initDb();
3042
3215
  const stats = getTaskStats(db);
3043
3216
  console.log(`Total tasks: ${stats.total}`);
@@ -3063,7 +3236,7 @@ maintenanceCmd.command("stats").description("Show backlog counts, completion sta
3063
3236
  }
3064
3237
  });
3065
3238
  maintenanceCmd.command("list").description("List tasks (default: pending)").option("-s, --status <status>", "pending|claimed|completed|abandoned", "pending").option("-k, --kind <kind>", "Filter by kind").option("-r, --repo <repo>", "Filter by repo").option("-n, --limit <n>", "Max entries", "20").action(async (opts) => {
3066
- const { listTasks } = await import("./tasks-UOLSPXJQ.js");
3239
+ const { listTasks } = await import("./tasks-GSQUHD4F.js");
3067
3240
  const db = initDb();
3068
3241
  const tasks = listTasks(db, {
3069
3242
  status: opts.status,
@@ -3085,7 +3258,7 @@ maintenanceCmd.command("list").description("List tasks (default: pending)").opti
3085
3258
  }
3086
3259
  });
3087
3260
  maintenanceCmd.command("drop").description("Delete a task by id (or id prefix)").argument("<task-id>", "Task id or prefix").action(async (taskIdArg) => {
3088
- const { deleteTask, listTasks } = await import("./tasks-UOLSPXJQ.js");
3261
+ const { deleteTask, listTasks } = await import("./tasks-GSQUHD4F.js");
3089
3262
  const db = initDb();
3090
3263
  const all = listTasks(db, { limit: 1e4 });
3091
3264
  const matches = all.filter((t) => t.id === taskIdArg || t.id.startsWith(taskIdArg));
@@ -3191,8 +3364,8 @@ credentialsCmd.command("clear").description("Remove provider credentials from th
3191
3364
  else console.log(`No ${provider} credentials found in Keychain.`);
3192
3365
  });
3193
3366
  maintenanceCmd.command("dispatch").description("Run the daemon-owned dispatcher once against pending maintenance tasks (requires a configured LLM provider)").option("--provider <provider>", "openai|anthropic|azure-openai (defaults to whichever is configured)").option("--model <model>", "Model override").option("--kind <kind>", "Restrict to a single task kind (repeatable)", (value, acc = []) => [...acc, value], []).option("--repo <repo>", "Restrict to a single repo").option("--max <n>", "Max tasks to run this round", "5").option("--dry-run", "Show which tasks would be dispatched; do not call the LLM").option("--preview", "Show the actual prompts that would be sent (no provider needed; no LLM call)").option("--json", "Emit the raw JSON report").action(async (opts) => {
3194
- const { dispatchPendingTasks, formatDispatchReport, buildPrompt } = await import("./dispatcher-UGMU6THT.js");
3195
- const { listTasks } = await import("./tasks-UOLSPXJQ.js");
3367
+ const { dispatchPendingTasks, formatDispatchReport, buildPrompt } = await import("./dispatcher-SUUX5AX6.js");
3368
+ const { listTasks } = await import("./tasks-GSQUHD4F.js");
3196
3369
  const db = initDb();
3197
3370
  if (opts.preview) {
3198
3371
  const pending = listTasks(db, {
@@ -3249,7 +3422,7 @@ ${p.prompt.max_output_tokens}
3249
3422
  console.log(formatDispatchReport(report));
3250
3423
  });
3251
3424
  maintenanceCmd.command("cleanup").description("Run deterministic, LLM-free cleanup: exact-text dedupe, fragment rejection, repeat-correction promotion").option("--apply", "Persist changes (default is dry-run)").option("--only <action>", "Restrict to one action: dedupe_exact_merge|reject_fragment_candidate|promote_repeat_correction").option("--revert <run-id>", "Revert a previous cleanup run (id or 8-char prefix)").option("--list", "List recent cleanup runs").option("--json", "Emit the raw JSON report").action(async (opts) => {
3252
- const { runDeterministicCleanup, formatCleanupReport, revertCleanupRun, listCleanupRuns } = await import("./cleanup-TVOX2S2S.js");
3425
+ const { runDeterministicCleanup, formatCleanupReport, revertCleanupRun, listCleanupRuns } = await import("./cleanup-MYSQ44EP.js");
3253
3426
  const db = initDb();
3254
3427
  if (opts.list) {
3255
3428
  const runs = listCleanupRuns(db);
@@ -3303,7 +3476,7 @@ maintenanceCmd.command("quality").description("Show injection outcome distributi
3303
3476
  recordQualitySnapshot,
3304
3477
  listQualitySnapshots,
3305
3478
  diffQualitySnapshots
3306
- } = await import("./quality-Z7LPMMBC.js");
3479
+ } = await import("./quality-YTQKAEY6.js");
3307
3480
  const db = initDb();
3308
3481
  if (opts.history) {
3309
3482
  const snaps = listQualitySnapshots(db);
@@ -3353,7 +3526,7 @@ maintenanceCmd.command("quality").description("Show injection outcome distributi
3353
3526
  console.log(formatQualityReport(report));
3354
3527
  });
3355
3528
  maintenanceCmd.command("usage").description("Summarize LLM API usage (tokens, cost) across recent maintenance runs").option("--since <iso>", "Window start (default: last 30 days)").option("--limit <n>", "Recent-call rows to show", "10").option("--json", "Emit raw JSON summary").action(async (opts) => {
3356
- const { summarizeUsage, formatUsageReport } = await import("./usage-CY3V72YN.js");
3529
+ const { summarizeUsage, formatUsageReport } = await import("./usage-DU4TKVJH.js");
3357
3530
  const db = initDb();
3358
3531
  const summary = summarizeUsage(db, {
3359
3532
  sinceIso: opts.since,