@onebrain-ai/cli 2.1.5 → 2.1.6

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 +46 -50
  2. package/package.json +1 -1
package/dist/onebrain CHANGED
@@ -9364,17 +9364,16 @@ async function checkSettingsHooks(vaultRoot, config) {
9364
9364
  confirmedHooks.push("PostToolUse \u2713");
9365
9365
  }
9366
9366
  }
9367
- const precompactGroups = settings.hooks?.["PreCompact"] ?? [];
9368
- const hasStalePreCompact = precompactGroups.some((g) => g.hooks?.some((h) => (h.command ?? "").includes(PRECOMPACT_ONEBRAIN_SUBSTRING)));
9369
- if (hasStalePreCompact) {
9370
- warnings.push("stale PreCompact hook found");
9371
- }
9372
9367
  for (const event of Object.keys(settings.hooks ?? {})) {
9373
9368
  const groups = settings.hooks?.[event] ?? [];
9374
9369
  for (const g of groups) {
9375
9370
  for (const h of g.hooks ?? []) {
9371
+ const cmd = h.command ?? "";
9372
+ if (!ALLOWED_HOOK_EVENTS.has(event) && cmd.includes(ONEBRAIN_COMMAND_SUBSTRING)) {
9373
+ warnings.push(`stale ${event} hook found (onebrain CLI only registers Stop + PostToolUse)`);
9374
+ }
9376
9375
  for (const sub of STALE_HOOK_SUBSTRINGS) {
9377
- if ((h.command ?? "").includes(sub)) {
9376
+ if (cmd.includes(sub)) {
9378
9377
  warnings.push(`stale bash hook reference: ${sub}`);
9379
9378
  }
9380
9379
  }
@@ -9408,7 +9407,7 @@ async function checkSettingsHooks(vaultRoot, config) {
9408
9407
  ...okDetails.length > 0 ? { details: okDetails } : {}
9409
9408
  };
9410
9409
  }
9411
- var import_yaml2, STANDARD_FOLDER_KEYS, REQUIRED_PLUGIN_FILES, REQUIRED_PLUGIN_DIRS, STALE_BASH_FILES, REQUIRED_VAULT_YML_KEYS, REQUIRED_FOLDER_KEYS, REQUIRED_HOOKS, QMD_HOOK_SUBSTRING = "onebrain qmd-reindex", PRECOMPACT_ONEBRAIN_SUBSTRING = "onebrain", REQUIRED_PERMISSION = "Bash(onebrain *)", STALE_HOOK_SUBSTRINGS;
9410
+ var import_yaml2, STANDARD_FOLDER_KEYS, REQUIRED_PLUGIN_FILES, REQUIRED_PLUGIN_DIRS, STALE_BASH_FILES, REQUIRED_VAULT_YML_KEYS, REQUIRED_FOLDER_KEYS, REQUIRED_HOOKS, ALLOWED_HOOK_EVENTS, QMD_HOOK_SUBSTRING = "onebrain qmd-reindex", ONEBRAIN_COMMAND_SUBSTRING = "onebrain", REQUIRED_PERMISSION = "Bash(onebrain *)", STALE_HOOK_SUBSTRINGS;
9412
9411
  var init_validator = __esm(() => {
9413
9412
  import_yaml2 = __toESM(require_dist(), 1);
9414
9413
  STANDARD_FOLDER_KEYS = [
@@ -9444,9 +9443,9 @@ var init_validator = __esm(() => {
9444
9443
  "logs"
9445
9444
  ];
9446
9445
  REQUIRED_HOOKS = [
9447
- { event: "Stop", cmdSubstring: "onebrain checkpoint stop" },
9448
- { event: "PostCompact", cmdSubstring: "onebrain checkpoint postcompact" }
9446
+ { event: "Stop", cmdSubstring: "onebrain checkpoint stop" }
9449
9447
  ];
9448
+ ALLOWED_HOOK_EVENTS = new Set(["Stop", "PostToolUse"]);
9450
9449
  STALE_HOOK_SUBSTRINGS = ["checkpoint-hook.sh", "session-init.sh"];
9451
9450
  });
9452
9451
 
@@ -9460,7 +9459,7 @@ var init_lib = __esm(() => {
9460
9459
  var require_package = __commonJS((exports, module) => {
9461
9460
  module.exports = {
9462
9461
  name: "@onebrain-ai/cli",
9463
- version: "2.1.5",
9462
+ version: "2.1.6",
9464
9463
  description: "CLI for OneBrain \u2014 personal AI OS for Obsidian with persistent memory, 24+ skills, and Claude Code integration",
9465
9464
  keywords: [
9466
9465
  "onebrain",
@@ -9978,12 +9977,22 @@ function applyHooks(settings) {
9978
9977
  settings.hooks = {};
9979
9978
  const hooks = settings.hooks;
9980
9979
  const result = {};
9981
- for (const [event, staleCmd] of Object.entries(STALE_HOOK_COMMANDS)) {
9982
- if (!hooks[event])
9980
+ for (const event of Object.keys(hooks)) {
9981
+ if (ALLOWED_HOOK_EVENTS2.has(event))
9983
9982
  continue;
9984
- hooks[event] = hooks[event].filter((group) => !group.hooks?.some((entry) => entry.command === staleCmd));
9985
- if (hooks[event].length === 0)
9983
+ const groups = hooks[event] ?? [];
9984
+ const filtered = groups.map((group) => ({
9985
+ ...group,
9986
+ hooks: (group.hooks ?? []).filter((entry) => {
9987
+ const cmd = entry.command ?? "";
9988
+ return !cmd.includes("onebrain");
9989
+ })
9990
+ })).filter((group) => (group.hooks?.length ?? 0) > 0);
9991
+ if (filtered.length === 0) {
9986
9992
  delete hooks[event];
9993
+ } else {
9994
+ hooks[event] = filtered;
9995
+ }
9987
9996
  }
9988
9997
  for (const event of HOOK_EVENTS) {
9989
9998
  const cmd = HOOK_COMMANDS[event];
@@ -10172,20 +10181,16 @@ async function registerHooksCommand(vaultDir) {
10172
10181
  process.exit(1);
10173
10182
  }
10174
10183
  }
10175
- var import_picocolors4, HOOK_COMMANDS, HOOK_EVENTS, STALE_HOOK_COMMANDS, 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";
10184
+ var import_picocolors4, HOOK_COMMANDS, HOOK_EVENTS, PERMISSIONS_TO_ADD, ONEBRAIN_MARKER = "# onebrain", PATH_EXPORT = 'export PATH="$HOME/.bun/bin:$HOME/.npm-global/bin:$PATH"', ALLOWED_HOOK_EVENTS2, QMD_CMD = "onebrain qmd-reindex", QMD_MATCHER = "Write|Edit";
10176
10185
  var init_register_hooks = __esm(() => {
10177
10186
  init_dist2();
10178
10187
  init_lib();
10179
10188
  init_harness();
10180
10189
  import_picocolors4 = __toESM(require_picocolors(), 1);
10181
10190
  HOOK_COMMANDS = {
10182
- Stop: "onebrain checkpoint stop",
10183
- PostCompact: "onebrain checkpoint postcompact"
10184
- };
10185
- HOOK_EVENTS = ["Stop", "PostCompact"];
10186
- STALE_HOOK_COMMANDS = {
10187
- PreCompact: "onebrain checkpoint precompact"
10191
+ Stop: "onebrain checkpoint stop"
10188
10192
  };
10193
+ HOOK_EVENTS = ["Stop"];
10189
10194
  PERMISSIONS_TO_ADD = [
10190
10195
  "Read",
10191
10196
  "Write",
@@ -10202,6 +10207,7 @@ var init_register_hooks = __esm(() => {
10202
10207
  "WebFetch",
10203
10208
  "WebSearch"
10204
10209
  ];
10210
+ ALLOWED_HOOK_EVENTS2 = new Set(["Stop", "PostToolUse"]);
10205
10211
  });
10206
10212
 
10207
10213
  // src/commands/internal/vault-sync.ts
@@ -10755,7 +10761,7 @@ var import_picocolors5 = __toESM(require_picocolors(), 1);
10755
10761
  var import_picocolors = __toESM(require_picocolors(), 1);
10756
10762
  function resolveBinaryVersion() {
10757
10763
  if (true)
10758
- return "2.1.5";
10764
+ return "2.1.6";
10759
10765
  try {
10760
10766
  const pkg = require_package();
10761
10767
  return pkg.version ?? "dev";
@@ -11944,7 +11950,7 @@ async function runInit(opts = {}) {
11944
11950
  }
11945
11951
  if (sp6) {
11946
11952
  await randDelay();
11947
- sp6.stop(hooksOk ? undefined : "not registered \u2014 run onebrain update", hooksOk ? ["Stop \u2713 PostCompact \u2713", "Bash(onebrain *) \u2713"] : undefined);
11953
+ sp6.stop(hooksOk ? undefined : "not registered \u2014 run onebrain update", hooksOk ? ["Stop \u2713", "Bash(onebrain *) \u2713"] : undefined);
11948
11954
  } else {
11949
11955
  writeLine(`hooks: ${hooksOk ? "ok" : "warning \u2014 hooks not registered; run onebrain update"}`);
11950
11956
  }
@@ -11971,24 +11977,24 @@ async function initCommand(opts = {}) {
11971
11977
  }
11972
11978
 
11973
11979
  // src/commands/internal/checkpoint.ts
11974
- import { readFileSync, readdirSync, writeFileSync } from "fs";
11980
+ import { readFileSync, readdirSync, renameSync, unlinkSync, writeFileSync } from "fs";
11975
11981
  import { tmpdir as osTmpdir } from "os";
11976
11982
  import { join as join7 } from "path";
11977
11983
  var SKIP_WINDOW = 60;
11978
11984
  var MIN_ACTIVITY = 2;
11979
- var PRECOMPACT_RECENCY = 300;
11980
11985
  var DEFAULT_MESSAGES_THRESHOLD = 15;
11981
11986
  var DEFAULT_MINUTES_THRESHOLD = 30;
11982
11987
  function stateFilePath(token, tmpDir) {
11983
11988
  return join7(tmpDir, `onebrain-${token}.state`);
11984
11989
  }
11990
+ var FRESH_STATE_DISK = "0:0:00";
11985
11991
  function readState(token, tmpDir = osTmpdir()) {
11986
11992
  const path = stateFilePath(token, tmpDir);
11987
11993
  try {
11988
11994
  const raw = readFileSync(path, "utf8").trim();
11989
11995
  const parts = raw.split(":");
11990
- if (parts.length < 3) {
11991
- throw new Error("v1 state format");
11996
+ if (parts.length !== 3) {
11997
+ throw new Error("state file must be exactly 3 fields");
11992
11998
  }
11993
11999
  const count = Number(parts[0]);
11994
12000
  const last_ts = Number(parts[1]);
@@ -11999,7 +12005,7 @@ function readState(token, tmpDir = osTmpdir()) {
11999
12005
  return { count, last_ts, last_stop_nn };
12000
12006
  } catch {
12001
12007
  try {
12002
- writeFileSync(stateFilePath(token, tmpDir), "0:0:00", "utf8");
12008
+ writeFileSync(stateFilePath(token, tmpDir), FRESH_STATE_DISK, "utf8");
12003
12009
  } catch (writeErr) {
12004
12010
  process.stderr.write(`checkpoint: failed to rewrite state file for token ${token}: ${writeErr}
12005
12011
  `);
@@ -12013,12 +12019,17 @@ function readState(token, tmpDir = osTmpdir()) {
12013
12019
  }
12014
12020
  function writeState(token, state, tmpDir = osTmpdir()) {
12015
12021
  const path = stateFilePath(token, tmpDir);
12022
+ const tmpPath = `${path}.tmp.${process.pid}`;
12016
12023
  const content = `${state.count}:${state.last_ts}:${state.last_stop_nn}`;
12017
12024
  try {
12018
- writeFileSync(path, content, "utf8");
12025
+ writeFileSync(tmpPath, content, "utf8");
12026
+ renameSync(tmpPath, path);
12019
12027
  } catch (err) {
12020
12028
  process.stderr.write(`checkpoint: failed to write state file ${path}: ${err}
12021
12029
  `);
12030
+ try {
12031
+ unlinkSync(tmpPath);
12032
+ } catch {}
12022
12033
  }
12023
12034
  }
12024
12035
  var DEFAULT_LOGS_FOLDER = "07-logs";
@@ -12098,11 +12109,11 @@ function handleStop(token, vaultRoot, now = Math.floor(Date.now() / 1000), tmpDi
12098
12109
  const elapsed = state.last_ts === 0 ? 0 : now - state.last_ts;
12099
12110
  const thresholdMet = state.count >= messagesThreshold || elapsed >= timeThreshold;
12100
12111
  if (!thresholdMet) {
12101
- writeState(token, { count: state.count, last_ts: state.last_ts, last_stop_nn: state.last_stop_nn }, tmpDir);
12112
+ writeState(token, { ...state }, tmpDir);
12102
12113
  return;
12103
12114
  }
12104
12115
  if (state.count < MIN_ACTIVITY) {
12105
- writeState(token, { count: state.count, last_ts: state.last_ts, last_stop_nn: state.last_stop_nn }, tmpDir);
12116
+ writeState(token, { ...state }, tmpDir);
12106
12117
  return;
12107
12118
  }
12108
12119
  const date = formatDate(now);
@@ -12112,27 +12123,12 @@ function handleStop(token, vaultRoot, now = Math.floor(Date.now() / 1000), tmpDi
12112
12123
  emitBlock(`${nextNn}${since}`);
12113
12124
  writeState(token, { count: 0, last_ts: now, last_stop_nn: nextNn }, tmpDir);
12114
12125
  }
12115
- function handlePostcompact(token, _vaultRoot, now = Math.floor(Date.now() / 1000), tmpDir = osTmpdir()) {
12116
- const state = readState(token, tmpDir);
12117
- if (state.last_ts > 0 && now - state.last_ts < PRECOMPACT_RECENCY) {
12118
- writeState(token, { count: 0, last_ts: state.last_ts, last_stop_nn: state.last_stop_nn }, tmpDir);
12119
- return;
12120
- }
12121
- emitBlock("auto-wrapup");
12122
- writeState(token, { count: 0, last_ts: now, last_stop_nn: state.last_stop_nn }, tmpDir);
12123
- }
12124
- function postcompactFallback(token, vaultRoot, now = Math.floor(Date.now() / 1000), tmpDir = osTmpdir()) {
12125
- handlePostcompact(token, vaultRoot, now, tmpDir);
12126
- }
12127
12126
  async function checkpointCommand(mode, token, vaultRoot) {
12128
12127
  try {
12129
12128
  switch (mode) {
12130
12129
  case "stop":
12131
12130
  handleStop(token, vaultRoot);
12132
12131
  break;
12133
- case "postcompact":
12134
- postcompactFallback(token, vaultRoot);
12135
- break;
12136
12132
  case "reset":
12137
12133
  handleReset(token);
12138
12134
  break;
@@ -12797,8 +12793,8 @@ function patchUtf8(stream) {
12797
12793
  }
12798
12794
 
12799
12795
  // src/index.ts
12800
- var VERSION = "2.1.5";
12801
- var RELEASE_DATE = "2026-04-29";
12796
+ var VERSION = "2.1.6";
12797
+ var RELEASE_DATE = "2026-04-30";
12802
12798
  patchUtf8(process.stdout);
12803
12799
  patchUtf8(process.stderr);
12804
12800
  var VERSION_STRING = `OneBrain v${VERSION} \u2014 released ${RELEASE_DATE}`;
@@ -12850,9 +12846,9 @@ program2.command("session-init", { hidden: true }).description("Emit session tok
12850
12846
  program2.command("orphan-scan", { hidden: true }).description("Scan for orphaned checkpoint files in logs folder").argument("<logs_folder>", "path to logs folder").argument("<session_token>", "current session token to exclude").action(async (logsFolder, sessionToken) => {
12851
12847
  await orphanScanCommand(logsFolder, sessionToken);
12852
12848
  });
12853
- program2.command("checkpoint", { hidden: true }).description("Handle checkpoint lifecycle (stop/postcompact/reset)").argument("<mode>", "stop | postcompact | reset").option("--vault-dir <path>", "vault root directory (default: auto-detect from cwd)").action(async (mode, opts) => {
12849
+ program2.command("checkpoint", { hidden: true }).description("Handle checkpoint lifecycle (stop/reset)").argument("<mode>", "stop | reset").option("--vault-dir <path>", "vault root directory (default: auto-detect from cwd)").action(async (mode, opts) => {
12854
12850
  const token = await resolveSessionToken();
12855
- const vaultRoot = opts.vaultDir ?? findVaultRoot(process.cwd());
12851
+ const vaultRoot = mode === "stop" ? opts.vaultDir ?? findVaultRoot(process.cwd()) : "";
12856
12852
  await checkpointCommand(mode, token, vaultRoot);
12857
12853
  });
12858
12854
  program2.command("qmd-reindex", { hidden: true }).description("Trigger qmd index rebuild").action(async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onebrain-ai/cli",
3
- "version": "2.1.5",
3
+ "version": "2.1.6",
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",