@onebrain-ai/cli 2.0.8 → 2.0.10

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 (2) hide show
  1. package/dist/onebrain +116 -115
  2. package/package.json +1 -1
package/dist/onebrain CHANGED
@@ -9571,7 +9571,7 @@ async function syncPluginFiles(extractedDir, vaultRoot, unlinkFn = unlink) {
9571
9571
  return { filesAdded, filesRemoved };
9572
9572
  }
9573
9573
  async function copyRootDocs(extractedDir, vaultRoot) {
9574
- const docs = ["README.md", "CONTRIBUTING.md", "CHANGELOG.md"];
9574
+ const docs = ["README.md", "CONTRIBUTING.md", "CHANGELOG.md", "PLUGIN-CHANGELOG.md"];
9575
9575
  for (const doc of docs) {
9576
9576
  const srcPath = join3(extractedDir, doc);
9577
9577
  const destPath = join3(vaultRoot, doc);
@@ -10002,53 +10002,52 @@ function applyHooks(settings) {
10002
10002
  result[event] = "ok";
10003
10003
  } else if (presence === "migrate") {
10004
10004
  for (const group of groups) {
10005
+ if (group.matcher === undefined)
10006
+ group.matcher = "";
10005
10007
  for (const entry of group.hooks ?? []) {
10006
10008
  if ((entry.command ?? "").includes("checkpoint-hook.sh")) {
10007
10009
  entry.command = cmd;
10010
+ if (!entry.type)
10011
+ entry.type = "command";
10008
10012
  }
10009
10013
  }
10010
10014
  }
10011
10015
  result[event] = "migrated";
10012
10016
  } else {
10013
- groups.push({ hooks: [{ command: cmd }] });
10017
+ groups.push({ matcher: "", hooks: [{ type: "command", command: cmd }] });
10014
10018
  result[event] = "added";
10015
10019
  }
10016
10020
  }
10017
10021
  return result;
10018
10022
  }
10019
- function applyPath(settings) {
10020
- if (!settings.env)
10021
- settings.env = {};
10022
- const existing = settings.env.PATH ?? "";
10023
- const parts = existing ? existing.split(":") : [];
10024
- const bunForms = [BUN_BIN, "$HOME/.bun/bin", "${HOME}/.bun/bin", "~/.bun/bin"];
10025
- const npmForms = [
10026
- NPM_GLOBAL_BIN,
10027
- "$HOME/.npm-global/bin",
10028
- "${HOME}/.npm-global/bin",
10029
- "~/.npm-global/bin"
10030
- ];
10031
- const missing = [];
10032
- if (!bunForms.some((f2) => parts.includes(f2)))
10033
- missing.push(BUN_BIN);
10034
- if (!npmForms.some((f2) => parts.includes(f2)))
10035
- missing.push(NPM_GLOBAL_BIN);
10036
- if (missing.length === 0)
10023
+ function applyQmdHook(settings) {
10024
+ if (!settings.hooks)
10025
+ settings.hooks = {};
10026
+ if (!settings.hooks["PostToolUse"])
10027
+ settings.hooks["PostToolUse"] = [];
10028
+ const groups = settings.hooks["PostToolUse"];
10029
+ const already = groups.some((g) => g.hooks?.some((h2) => h2.command === QMD_CMD));
10030
+ if (already)
10037
10031
  return "ok";
10038
- const base = existing || "${PATH}";
10039
- const hasPlaceholder = base.includes("${PATH}");
10040
- if (hasPlaceholder) {
10041
- const withoutPlaceholder = base.replace("${PATH}", "").replace(/:+$/, "").replace(/^:+/, "");
10042
- const allParts = [
10043
- ...missing,
10044
- ...withoutPlaceholder ? withoutPlaceholder.split(":").filter(Boolean) : [],
10045
- "${PATH}"
10046
- ];
10047
- settings.env.PATH = allParts.join(":");
10032
+ groups.push({ matcher: QMD_MATCHER, hooks: [{ type: "command", command: QMD_CMD }] });
10033
+ return "added";
10034
+ }
10035
+ function removeQmdHook(settings) {
10036
+ if (!settings.hooks?.["PostToolUse"])
10037
+ return "ok";
10038
+ const before = settings.hooks["PostToolUse"].length;
10039
+ const filtered = settings.hooks["PostToolUse"].filter((g) => !g.hooks?.some((h2) => (h2.command ?? "").includes("qmd-reindex")));
10040
+ if (filtered.length === 0) {
10041
+ const remaining = {};
10042
+ for (const [key, val] of Object.entries(settings.hooks)) {
10043
+ if (key !== "PostToolUse")
10044
+ remaining[key] = val;
10045
+ }
10046
+ settings.hooks = remaining;
10048
10047
  } else {
10049
- settings.env.PATH = [...missing, base].join(":");
10048
+ settings.hooks["PostToolUse"] = filtered;
10050
10049
  }
10051
- return "updated";
10050
+ return before !== filtered.length ? "removed" : "ok";
10052
10051
  }
10053
10052
  function applyPermissions(settings) {
10054
10053
  if (!settings.permissions)
@@ -10118,7 +10117,6 @@ async function runRegisterHooks(opts = {}) {
10118
10117
  const result = {
10119
10118
  ok: false,
10120
10119
  hooks: {},
10121
- pathStatus: "ok",
10122
10120
  permissionsAdded: []
10123
10121
  };
10124
10122
  const settingsPath = join4(vaultRoot, ".claude", "settings.json");
@@ -10148,19 +10146,17 @@ async function runRegisterHooks(opts = {}) {
10148
10146
  } else {
10149
10147
  const hookLine = HOOK_EVENTS.map((e2) => {
10150
10148
  const status = result.hooks[e2];
10151
- const label = status === "ok" || status === "added" || status === "migrated" || status === "found" ? "ok" : status ?? "ok";
10149
+ const label = status === "ok" || status === "added" || status === "migrated" ? "ok" : status ?? "ok";
10152
10150
  return `${e2} ${label}`;
10153
10151
  }).join(" ");
10154
10152
  note(hookLine);
10155
10153
  }
10156
- const pathSpinner = isTTY ? L2() : null;
10157
- pathSpinner?.start("Registering PATH...");
10158
- result.pathStatus = applyPath(settings);
10159
- pathSpinner?.stop("PATH registered");
10160
- if (isTTY) {
10161
- note("env.PATH in .claude/settings.json: ");
10162
- } else {
10163
- note("PATH ok");
10154
+ if (opts.removeQmd) {
10155
+ const status = removeQmdHook(settings);
10156
+ note(status === "removed" ? "PostToolUse qmd hook removed" : "PostToolUse qmd hook not found");
10157
+ } else if (opts.qmd) {
10158
+ const status = applyQmdHook(settings);
10159
+ note(status === "added" ? "PostToolUse qmd: added" : "PostToolUse qmd: already registered");
10164
10160
  }
10165
10161
  const permSpinner = isTTY ? L2() : null;
10166
10162
  permSpinner?.start("Updating permissions...");
@@ -10194,30 +10190,30 @@ async function runRegisterHooks(opts = {}) {
10194
10190
  }
10195
10191
  return result;
10196
10192
  }
10197
- async function registerHooksCommand(vaultDir) {
10198
- const result = await runRegisterHooks(vaultDir !== undefined ? { vaultDir } : {});
10193
+ async function registerHooksCommand(vaultDir, flags) {
10194
+ const result = await runRegisterHooks({
10195
+ ...vaultDir !== undefined ? { vaultDir } : {},
10196
+ ...flags
10197
+ });
10199
10198
  if (!result.ok) {
10200
10199
  process.exit(1);
10201
10200
  }
10202
10201
  }
10203
- var HOOK_COMMANDS, HOOK_EVENTS, PERMISSIONS_TO_ADD, BUN_BIN, NPM_GLOBAL_BIN, ONEBRAIN_MARKER = "# onebrain", PATH_EXPORT = 'export PATH="$HOME/.bun/bin:$HOME/.npm-global/bin:$PATH"';
10202
+ var HOOK_COMMANDS, HOOK_EVENTS, PERMISSIONS_TO_ADD, ONEBRAIN_MARKER = "# onebrain", PATH_EXPORT = 'export PATH="$HOME/.bun/bin:$HOME/.npm-global/bin:$PATH"', QMD_CMD = "onebrain qmd-reindex", QMD_MATCHER = "Write|Edit";
10204
10203
  var init_register_hooks = __esm(() => {
10205
10204
  init_dist2();
10206
10205
  init_dist3();
10207
10206
  HOOK_COMMANDS = {
10208
10207
  Stop: "onebrain checkpoint stop",
10209
10208
  PreCompact: "onebrain checkpoint precompact",
10210
- PostCompact: "onebrain checkpoint postcompact",
10211
- SessionStart: "onebrain session-init"
10209
+ PostCompact: "onebrain checkpoint postcompact"
10212
10210
  };
10213
- HOOK_EVENTS = ["Stop", "PreCompact", "PostCompact", "SessionStart"];
10211
+ HOOK_EVENTS = ["Stop", "PreCompact", "PostCompact"];
10214
10212
  PERMISSIONS_TO_ADD = [
10215
10213
  "Bash(onebrain *)",
10216
10214
  "Bash(bun install -g @onebrain-ai/cli*)",
10217
10215
  "Bash(npm install -g @onebrain-ai/cli*)"
10218
10216
  ];
10219
- BUN_BIN = join4(homedir2(), ".bun", "bin");
10220
- NPM_GLOBAL_BIN = join4(homedir2(), ".npm-global", "bin");
10221
10217
  });
10222
10218
 
10223
10219
  // src/index.ts
@@ -10494,11 +10490,11 @@ async function checkQmdEmbeddings(config) {
10494
10490
  };
10495
10491
  }
10496
10492
  }
10497
- async function checkVersionDrift(vaultRoot, config, binaryVersion) {
10493
+ async function checkVersionDrift(vaultRoot, config) {
10498
10494
  const pluginJsonPath = join2(vaultRoot, ".claude", "plugins", "onebrain", ".claude-plugin", "plugin.json");
10499
10495
  const pluginFile = Bun.file(pluginJsonPath);
10500
10496
  const exists = await pluginFile.exists();
10501
- const compareVersion = binaryVersion ?? config.onebrain_version;
10497
+ const compareVersion = config.onebrain_version;
10502
10498
  if (!compareVersion || !exists) {
10503
10499
  return {
10504
10500
  check: "version-drift",
@@ -10532,11 +10528,10 @@ async function checkVersionDrift(vaultRoot, config, binaryVersion) {
10532
10528
  message: `v${compareVersion}`
10533
10529
  };
10534
10530
  }
10535
- const driftMessage = binaryVersion ? `binary v${binaryVersion}, plugin files v${pluginVersion}` : `vault v${compareVersion}, plugin files v${pluginVersion}`;
10536
10531
  return {
10537
10532
  check: "version-drift",
10538
10533
  status: "warn",
10539
- message: driftMessage,
10534
+ message: `vault v${compareVersion}, plugin files v${pluginVersion}`,
10540
10535
  hint: "Run onebrain update to sync"
10541
10536
  };
10542
10537
  }
@@ -10629,7 +10624,6 @@ function checkSandbox(config) {
10629
10624
  async function runDoctor(opts = {}) {
10630
10625
  const vaultDir = opts.vaultDir ?? process.cwd();
10631
10626
  const isTTY = opts.isTTY ?? process.stdout.isTTY ?? false;
10632
- const binaryVersion = opts.binaryVersion;
10633
10627
  const checkVaultYmlFn = opts.checkVaultYmlFn ?? checkVaultYml;
10634
10628
  const loadVaultConfigFn = opts.loadVaultConfigFn ?? loadVaultConfig;
10635
10629
  const checkFoldersFn = opts.checkFoldersFn ?? checkFolders;
@@ -10676,7 +10670,7 @@ async function runDoctor(opts = {}) {
10676
10670
  checkFoldersFn(vaultDir, config),
10677
10671
  checkHarnessBinaryFn(config),
10678
10672
  checkQmdEmbeddingsFn(config),
10679
- checkVersionDriftFn(vaultDir, config, binaryVersion),
10673
+ checkVersionDriftFn(vaultDir, config),
10680
10674
  checkOrphanCheckpointsFn(vaultDir, config),
10681
10675
  checkSandboxFn(config)
10682
10676
  ]);
@@ -10788,7 +10782,7 @@ init_dist3();
10788
10782
  import { mkdir as mkdir3, readFile as readFile3, rename as rename3, stat as stat3, writeFile as writeFile3 } from "node:fs/promises";
10789
10783
  import { homedir as homedir3 } from "node:os";
10790
10784
  import { dirname as dirname3, join as join5 } from "node:path";
10791
- var binaryVersion = "2.0.8";
10785
+ var binaryVersion = "2.0.10";
10792
10786
  var STANDARD_FOLDERS = [
10793
10787
  "00-inbox",
10794
10788
  "01-projects",
@@ -11292,7 +11286,7 @@ async function listMdFiles(dir) {
11292
11286
  return [];
11293
11287
  }
11294
11288
  }
11295
- async function runBackfillRecapped(logsFolder) {
11289
+ async function runBackfillRecapped(logsFolder, cutoffDate) {
11296
11290
  const today = new Date().toISOString().slice(0, 10);
11297
11291
  let backfilled = 0;
11298
11292
  let skipped = 0;
@@ -11318,6 +11312,12 @@ async function runBackfillRecapped(logsFolder) {
11318
11312
  if (fname.includes("-checkpoint-")) {
11319
11313
  continue;
11320
11314
  }
11315
+ if (cutoffDate) {
11316
+ const dateMatch = fname.match(/^(\d{4}-\d{2}-\d{2})/);
11317
+ if (dateMatch?.[1] !== undefined && dateMatch[1] > cutoffDate) {
11318
+ continue;
11319
+ }
11320
+ }
11321
11321
  try {
11322
11322
  const content = await readFile4(fpath, "utf8");
11323
11323
  const parsed = parseFrontmatterWithRest(content);
@@ -11348,13 +11348,13 @@ ${rest}`;
11348
11348
  }
11349
11349
  return { backfilled, skipped };
11350
11350
  }
11351
- async function migrateCommand(migrationName) {
11351
+ async function migrateCommand(migrationName, cutoffDate) {
11352
11352
  try {
11353
11353
  const vaultRoot = process.cwd();
11354
11354
  const config = await loadVaultConfig(vaultRoot);
11355
11355
  const logsFolder = join7(vaultRoot, config.folders.logs);
11356
11356
  if (migrationName === "backfill-recapped") {
11357
- const result = await runBackfillRecapped(logsFolder);
11357
+ const result = await runBackfillRecapped(logsFolder, cutoffDate);
11358
11358
  process.stdout.write(`backfilled: ${result.backfilled} files, skipped: ${result.skipped}
11359
11359
  `);
11360
11360
  } else {
@@ -11512,17 +11512,14 @@ import { dirname as dirname4, join as join9 } from "node:path";
11512
11512
  var HOOK_COMMANDS2 = {
11513
11513
  Stop: "onebrain checkpoint stop",
11514
11514
  PreCompact: "onebrain checkpoint precompact",
11515
- PostCompact: "onebrain checkpoint postcompact",
11516
- SessionStart: "onebrain session-init"
11515
+ PostCompact: "onebrain checkpoint postcompact"
11517
11516
  };
11518
- var HOOK_EVENTS2 = ["Stop", "PreCompact", "PostCompact", "SessionStart"];
11517
+ var HOOK_EVENTS2 = ["Stop", "PreCompact", "PostCompact"];
11519
11518
  var PERMISSIONS_TO_ADD2 = [
11520
11519
  "Bash(onebrain *)",
11521
11520
  "Bash(bun install -g @onebrain-ai/cli*)",
11522
11521
  "Bash(npm install -g @onebrain-ai/cli*)"
11523
11522
  ];
11524
- var BUN_BIN2 = join9(homedir4(), ".bun", "bin");
11525
- var NPM_GLOBAL_BIN2 = join9(homedir4(), ".npm-global", "bin");
11526
11523
  var ONEBRAIN_MARKER2 = "# onebrain";
11527
11524
  var PATH_EXPORT2 = 'export PATH="$HOME/.bun/bin:$HOME/.npm-global/bin:$PATH"';
11528
11525
  async function readSettings2(settingsPath) {
@@ -11571,53 +11568,54 @@ function applyHooks2(settings) {
11571
11568
  result[event] = "ok";
11572
11569
  } else if (presence === "migrate") {
11573
11570
  for (const group of groups) {
11571
+ if (group.matcher === undefined)
11572
+ group.matcher = "";
11574
11573
  for (const entry of group.hooks ?? []) {
11575
11574
  if ((entry.command ?? "").includes("checkpoint-hook.sh")) {
11576
11575
  entry.command = cmd;
11576
+ if (!entry.type)
11577
+ entry.type = "command";
11577
11578
  }
11578
11579
  }
11579
11580
  }
11580
11581
  result[event] = "migrated";
11581
11582
  } else {
11582
- groups.push({ hooks: [{ command: cmd }] });
11583
+ groups.push({ matcher: "", hooks: [{ type: "command", command: cmd }] });
11583
11584
  result[event] = "added";
11584
11585
  }
11585
11586
  }
11586
11587
  return result;
11587
11588
  }
11588
- function applyPath2(settings) {
11589
- if (!settings.env)
11590
- settings.env = {};
11591
- const existing = settings.env.PATH ?? "";
11592
- const parts = existing ? existing.split(":") : [];
11593
- const bunForms = [BUN_BIN2, "$HOME/.bun/bin", "${HOME}/.bun/bin", "~/.bun/bin"];
11594
- const npmForms = [
11595
- NPM_GLOBAL_BIN2,
11596
- "$HOME/.npm-global/bin",
11597
- "${HOME}/.npm-global/bin",
11598
- "~/.npm-global/bin"
11599
- ];
11600
- const missing = [];
11601
- if (!bunForms.some((f2) => parts.includes(f2)))
11602
- missing.push(BUN_BIN2);
11603
- if (!npmForms.some((f2) => parts.includes(f2)))
11604
- missing.push(NPM_GLOBAL_BIN2);
11605
- if (missing.length === 0)
11589
+ var QMD_CMD2 = "onebrain qmd-reindex";
11590
+ var QMD_MATCHER2 = "Write|Edit";
11591
+ function applyQmdHook2(settings) {
11592
+ if (!settings.hooks)
11593
+ settings.hooks = {};
11594
+ if (!settings.hooks["PostToolUse"])
11595
+ settings.hooks["PostToolUse"] = [];
11596
+ const groups = settings.hooks["PostToolUse"];
11597
+ const already = groups.some((g) => g.hooks?.some((h2) => h2.command === QMD_CMD2));
11598
+ if (already)
11606
11599
  return "ok";
11607
- const base = existing || "${PATH}";
11608
- const hasPlaceholder = base.includes("${PATH}");
11609
- if (hasPlaceholder) {
11610
- const withoutPlaceholder = base.replace("${PATH}", "").replace(/:+$/, "").replace(/^:+/, "");
11611
- const allParts = [
11612
- ...missing,
11613
- ...withoutPlaceholder ? withoutPlaceholder.split(":").filter(Boolean) : [],
11614
- "${PATH}"
11615
- ];
11616
- settings.env.PATH = allParts.join(":");
11600
+ groups.push({ matcher: QMD_MATCHER2, hooks: [{ type: "command", command: QMD_CMD2 }] });
11601
+ return "added";
11602
+ }
11603
+ function removeQmdHook2(settings) {
11604
+ if (!settings.hooks?.["PostToolUse"])
11605
+ return "ok";
11606
+ const before = settings.hooks["PostToolUse"].length;
11607
+ const filtered = settings.hooks["PostToolUse"].filter((g) => !g.hooks?.some((h2) => (h2.command ?? "").includes("qmd-reindex")));
11608
+ if (filtered.length === 0) {
11609
+ const remaining = {};
11610
+ for (const [key, val] of Object.entries(settings.hooks)) {
11611
+ if (key !== "PostToolUse")
11612
+ remaining[key] = val;
11613
+ }
11614
+ settings.hooks = remaining;
11617
11615
  } else {
11618
- settings.env.PATH = [...missing, base].join(":");
11616
+ settings.hooks["PostToolUse"] = filtered;
11619
11617
  }
11620
- return "updated";
11618
+ return before !== filtered.length ? "removed" : "ok";
11621
11619
  }
11622
11620
  function applyPermissions2(settings) {
11623
11621
  if (!settings.permissions)
@@ -11687,7 +11685,6 @@ async function runRegisterHooks2(opts = {}) {
11687
11685
  const result = {
11688
11686
  ok: false,
11689
11687
  hooks: {},
11690
- pathStatus: "ok",
11691
11688
  permissionsAdded: []
11692
11689
  };
11693
11690
  const settingsPath = join9(vaultRoot, ".claude", "settings.json");
@@ -11717,19 +11714,17 @@ async function runRegisterHooks2(opts = {}) {
11717
11714
  } else {
11718
11715
  const hookLine = HOOK_EVENTS2.map((e2) => {
11719
11716
  const status = result.hooks[e2];
11720
- const label = status === "ok" || status === "added" || status === "migrated" || status === "found" ? "ok" : status ?? "ok";
11717
+ const label = status === "ok" || status === "added" || status === "migrated" ? "ok" : status ?? "ok";
11721
11718
  return `${e2} ${label}`;
11722
11719
  }).join(" ");
11723
11720
  note(hookLine);
11724
11721
  }
11725
- const pathSpinner = isTTY ? L2() : null;
11726
- pathSpinner?.start("Registering PATH...");
11727
- result.pathStatus = applyPath2(settings);
11728
- pathSpinner?.stop("PATH registered");
11729
- if (isTTY) {
11730
- note("env.PATH in .claude/settings.json: ");
11731
- } else {
11732
- note("PATH ok");
11722
+ if (opts.removeQmd) {
11723
+ const status = removeQmdHook2(settings);
11724
+ note(status === "removed" ? "PostToolUse qmd hook removed" : "PostToolUse qmd hook not found");
11725
+ } else if (opts.qmd) {
11726
+ const status = applyQmdHook2(settings);
11727
+ note(status === "added" ? "PostToolUse qmd: added" : "PostToolUse qmd: already registered");
11733
11728
  }
11734
11729
  const permSpinner = isTTY ? L2() : null;
11735
11730
  permSpinner?.start("Updating permissions...");
@@ -11763,8 +11758,11 @@ async function runRegisterHooks2(opts = {}) {
11763
11758
  }
11764
11759
  return result;
11765
11760
  }
11766
- async function registerHooksCommand2(vaultDir) {
11767
- const result = await runRegisterHooks2(vaultDir !== undefined ? { vaultDir } : {});
11761
+ async function registerHooksCommand2(vaultDir, flags) {
11762
+ const result = await runRegisterHooks2({
11763
+ ...vaultDir !== undefined ? { vaultDir } : {},
11764
+ ...flags
11765
+ });
11768
11766
  if (!result.ok) {
11769
11767
  process.exit(1);
11770
11768
  }
@@ -12041,7 +12039,7 @@ async function syncPluginFiles2(extractedDir, vaultRoot, unlinkFn = unlink3) {
12041
12039
  return { filesAdded, filesRemoved };
12042
12040
  }
12043
12041
  async function copyRootDocs2(extractedDir, vaultRoot) {
12044
- const docs = ["README.md", "CONTRIBUTING.md", "CHANGELOG.md"];
12042
+ const docs = ["README.md", "CONTRIBUTING.md", "CHANGELOG.md", "PLUGIN-CHANGELOG.md"];
12045
12043
  for (const doc of docs) {
12046
12044
  const srcPath = join11(extractedDir, doc);
12047
12045
  const destPath = join11(vaultRoot, doc);
@@ -12666,7 +12664,7 @@ async function updateCommand(opts = {}) {
12666
12664
  }
12667
12665
 
12668
12666
  // src/index.ts
12669
- var VERSION = "2.0.8";
12667
+ var VERSION = "2.0.10";
12670
12668
  var RELEASE_DATE = "2026-04-26";
12671
12669
  process.stdout.setDefaultEncoding("utf8");
12672
12670
  process.stderr.setDefaultEncoding("utf8");
@@ -12707,7 +12705,7 @@ program2.command("update").description("Update OneBrain plugin files from GitHub
12707
12705
  });
12708
12706
  program2.command("doctor").description("Run vault health checks and report issues").action(async () => {
12709
12707
  const vaultRoot = findVaultRoot(process.cwd());
12710
- await doctorCommand({ vaultDir: vaultRoot, binaryVersion: VERSION });
12708
+ await doctorCommand({ vaultDir: vaultRoot });
12711
12709
  });
12712
12710
  program2.command("help").description("Show this help message").action(() => {
12713
12711
  program2.help();
@@ -12732,10 +12730,13 @@ program2.command("vault-sync", { hidden: true }).description("Sync plugin files
12732
12730
  const root = vaultRoot ?? process.cwd();
12733
12731
  await vaultSyncCommand2(root, opts.branch !== undefined ? { branch: opts.branch } : {});
12734
12732
  });
12735
- program2.command("register-hooks", { hidden: true }).description("Install Claude Code hooks into settings.json").option("--vault-dir <path>", "vault root directory (default: cwd)").action(async (opts) => {
12736
- await registerHooksCommand2(opts.vaultDir);
12733
+ program2.command("register-hooks", { hidden: true }).description("Install Claude Code hooks into settings.json").option("--vault-dir <path>", "vault root directory (default: cwd)").option("--qmd", "also register PostToolUse qmd-reindex hook").option("--remove-qmd", "remove PostToolUse qmd-reindex hook").action(async (opts) => {
12734
+ await registerHooksCommand2(opts.vaultDir, {
12735
+ ...opts.qmd !== undefined ? { qmd: opts.qmd } : {},
12736
+ ...opts.removeQmd !== undefined ? { removeQmd: opts.removeQmd } : {}
12737
+ });
12737
12738
  });
12738
- program2.command("migrate", { hidden: true }).description("Run one-time migration scripts").argument("<name>", "migration name: backfill-recapped").action(async (name) => {
12739
- await migrateCommand(name);
12739
+ program2.command("migrate", { hidden: true }).description("Run one-time migration scripts").argument("<name>", "migration name: backfill-recapped").argument("[cutoff_date]", "ISO date cutoff (YYYY-MM-DD) \u2014 skip logs newer than this date").action(async (name, cutoffDate) => {
12740
+ await migrateCommand(name, cutoffDate);
12740
12741
  });
12741
12742
  program2.parse(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onebrain-ai/cli",
3
- "version": "2.0.8",
3
+ "version": "2.0.10",
4
4
  "description": "CLI for OneBrain — personal AI OS for Obsidian with persistent memory, 24+ skills, and Claude Code integration",
5
5
  "keywords": [
6
6
  "onebrain",