@onebrain-ai/cli 2.1.14 → 2.1.15

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 +74 -27
  2. package/package.json +1 -1
package/dist/onebrain CHANGED
@@ -9510,18 +9510,55 @@ async function atomicWrite(dest, contents, label) {
9510
9510
  }
9511
9511
  var init_fs_atomic = () => {};
9512
9512
 
9513
+ // src/lib/fs-mkdir-safe.ts
9514
+ import { mkdir, stat as stat2 } from "fs/promises";
9515
+ async function mkdirIdempotent(path) {
9516
+ try {
9517
+ await mkdir(path, { recursive: true });
9518
+ } catch (err) {
9519
+ const code = err?.code;
9520
+ if (code !== "EEXIST")
9521
+ throw err;
9522
+ let info;
9523
+ try {
9524
+ info = await stat2(path);
9525
+ } catch (statErr) {
9526
+ const statCode = statErr?.code;
9527
+ throw statCode ? statErr : err;
9528
+ }
9529
+ if (!info.isDirectory())
9530
+ throw err;
9531
+ }
9532
+ }
9533
+ var init_fs_mkdir_safe = () => {};
9534
+
9513
9535
  // src/lib/index.ts
9536
+ var exports_lib = {};
9537
+ __export(exports_lib, {
9538
+ mkdirIdempotent: () => mkdirIdempotent,
9539
+ loadVaultConfig: () => loadVaultConfig,
9540
+ checkVaultYmlKeys: () => checkVaultYmlKeys,
9541
+ checkVaultYml: () => checkVaultYml,
9542
+ checkSettingsHooks: () => checkSettingsHooks,
9543
+ checkQmdEmbeddings: () => checkQmdEmbeddings,
9544
+ checkPluginFiles: () => checkPluginFiles,
9545
+ checkOrphanCheckpoints: () => checkOrphanCheckpoints,
9546
+ checkFolders: () => checkFolders,
9547
+ checkClaudeSettings: () => checkClaudeSettings,
9548
+ atomicWrite: () => atomicWrite
9549
+ });
9514
9550
  var init_lib = __esm(() => {
9515
9551
  init_parser();
9516
9552
  init_validator();
9517
9553
  init_fs_atomic();
9554
+ init_fs_mkdir_safe();
9518
9555
  });
9519
9556
 
9520
9557
  // package.json
9521
9558
  var require_package = __commonJS((exports, module) => {
9522
9559
  module.exports = {
9523
9560
  name: "@onebrain-ai/cli",
9524
- version: "2.1.14",
9561
+ version: "2.1.15",
9525
9562
  description: "CLI for OneBrain \u2014 personal AI OS for Obsidian with persistent memory, 24+ skills, and Claude Code integration",
9526
9563
  keywords: [
9527
9564
  "onebrain",
@@ -9966,11 +10003,11 @@ var init_dist2 = __esm(() => {
9966
10003
  });
9967
10004
 
9968
10005
  // src/commands/internal/harness.ts
9969
- import { stat as stat2 } from "fs/promises";
10006
+ import { stat as stat3 } from "fs/promises";
9970
10007
  import { join as join3 } from "path";
9971
10008
  async function pathExists(p2) {
9972
10009
  try {
9973
- await stat2(p2);
10010
+ await stat3(p2);
9974
10011
  return true;
9975
10012
  } catch {
9976
10013
  return false;
@@ -10002,7 +10039,7 @@ __export(exports_register_hooks, {
10002
10039
  runRegisterHooks: () => runRegisterHooks,
10003
10040
  registerHooksCommand: () => registerHooksCommand
10004
10041
  });
10005
- import { mkdir, readFile, rename as rename2, writeFile as writeFile2 } from "fs/promises";
10042
+ import { readFile, rename as rename2, writeFile as writeFile2 } from "fs/promises";
10006
10043
  import { homedir } from "os";
10007
10044
  import { dirname, join as join4 } from "path";
10008
10045
  async function readSettings(settingsPath) {
@@ -10016,7 +10053,7 @@ async function readSettings(settingsPath) {
10016
10053
  }
10017
10054
  }
10018
10055
  async function writeSettings(settingsPath, settings) {
10019
- await mkdir(dirname(settingsPath), { recursive: true });
10056
+ await mkdirIdempotent(dirname(settingsPath));
10020
10057
  const tmpPath = `${settingsPath}.tmp`;
10021
10058
  await writeFile2(tmpPath, JSON.stringify(settings, null, 4), "utf8");
10022
10059
  await rename2(tmpPath, settingsPath);
@@ -10340,9 +10377,10 @@ var init_register_hooks = __esm(() => {
10340
10377
  var exports_vault_sync = {};
10341
10378
  __export(exports_vault_sync, {
10342
10379
  vaultSyncCommand: () => vaultSyncCommand,
10343
- runVaultSync: () => runVaultSync
10380
+ runVaultSync: () => runVaultSync,
10381
+ buildTarSpawnOverrides: () => buildTarSpawnOverrides
10344
10382
  });
10345
- import { mkdir as mkdir2, mkdtemp, readFile as readFile2, readdir, rm, stat as stat3, unlink as unlink2, writeFile as writeFile3 } from "fs/promises";
10383
+ import { mkdtemp, readFile as readFile2, readdir, rm, stat as stat4, unlink as unlink2, writeFile as writeFile3 } from "fs/promises";
10346
10384
  import { homedir as homedir2, tmpdir } from "os";
10347
10385
  import { dirname as dirname2, join as join5, sep as pathSep, relative, resolve as resolvePath } from "path";
10348
10386
  function normalizePath(p2) {
@@ -10368,17 +10406,25 @@ async function downloadTarball(branch, fetchFn) {
10368
10406
  const tmpDir = await mkdtemp(join5(tmpdir(), "onebrain-sync-"));
10369
10407
  return { tarball, tmpDir };
10370
10408
  }
10409
+ function buildTarSpawnOverrides(platform = process.platform, parentEnv = process.env) {
10410
+ if (platform !== "win32")
10411
+ return {};
10412
+ return { env: { ...parentEnv, TAR_OPTIONS: "--force-local" } };
10413
+ }
10371
10414
  async function extractTarball(tarball, destDir) {
10372
10415
  const tarPath = join5(destDir, "bundle.tar.gz");
10373
10416
  await writeFile3(tarPath, Buffer.from(tarball));
10417
+ const tarOverrides = buildTarSpawnOverrides();
10374
10418
  const proc = Bun.spawn(["tar", "-xzf", tarPath, "-C", destDir], {
10375
10419
  stdout: "pipe",
10376
- stderr: "pipe"
10420
+ stderr: "pipe",
10421
+ ...tarOverrides
10377
10422
  });
10378
10423
  const exitCode = await proc.exited;
10379
10424
  if (exitCode !== 0) {
10380
10425
  const errText = await new Response(proc.stderr).text();
10381
- throw new Error(`tar extraction failed (exit ${exitCode}): ${errText.trim()}`);
10426
+ const envHint = tarOverrides.env ? ", TAR_OPTIONS=--force-local" : "";
10427
+ throw new Error(`tar extraction failed (exit ${exitCode}${envHint}): ${errText.trim()}`);
10382
10428
  }
10383
10429
  await unlink2(tarPath);
10384
10430
  const entries = await readdir(destDir);
@@ -10403,7 +10449,7 @@ async function listFilesRecursive(dir) {
10403
10449
  const fullPath = join5(current, entry);
10404
10450
  let s;
10405
10451
  try {
10406
- s = await stat3(fullPath);
10452
+ s = await stat4(fullPath);
10407
10453
  } catch {
10408
10454
  continue;
10409
10455
  }
@@ -10419,7 +10465,7 @@ async function listFilesRecursive(dir) {
10419
10465
  async function syncPluginFiles(extractedDir, vaultRoot, unlinkFn = unlink2) {
10420
10466
  const sourcePlugin = join5(extractedDir, ".claude", "plugins", "onebrain");
10421
10467
  const destPlugin = join5(vaultRoot, ".claude", "plugins", "onebrain");
10422
- await mkdir2(destPlugin, { recursive: true });
10468
+ await mkdirIdempotent(destPlugin);
10423
10469
  const sourceFiles = await listFilesRecursive(sourcePlugin);
10424
10470
  const sourceRelSet = new Set(sourceFiles.map((f2) => relative(sourcePlugin, f2)));
10425
10471
  const destFiles = await listFilesRecursive(destPlugin);
@@ -10434,7 +10480,7 @@ async function syncPluginFiles(extractedDir, vaultRoot, unlinkFn = unlink2) {
10434
10480
  for (const srcPath of sourceFiles) {
10435
10481
  const rel = relative(sourcePlugin, srcPath);
10436
10482
  const destPath = join5(destPlugin, rel);
10437
- await mkdir2(dirname2(destPath), { recursive: true });
10483
+ await mkdirIdempotent(dirname2(destPath));
10438
10484
  const content = await readFile2(srcPath);
10439
10485
  await writeFile3(destPath, content);
10440
10486
  filesAdded++;
@@ -10577,7 +10623,7 @@ async function pinToVault(vaultRoot, installedPluginsPath, installedPluginsCache
10577
10623
  continue;
10578
10624
  }
10579
10625
  try {
10580
- await stat3(projectPath);
10626
+ await stat4(projectPath);
10581
10627
  keep.push(entry);
10582
10628
  } catch (err) {
10583
10629
  const code = err?.code;
@@ -10635,7 +10681,7 @@ async function pinToVault(vaultRoot, installedPluginsPath, installedPluginsCache
10635
10681
  async function cleanPluginCache(installedPluginsPath, installedPluginsCacheDir) {
10636
10682
  const cacheDir = installedPluginsCacheDir ?? join5(dirname2(installedPluginsPath), "cache");
10637
10683
  try {
10638
- await stat3(cacheDir);
10684
+ await stat4(cacheDir);
10639
10685
  } catch {
10640
10686
  return 0;
10641
10687
  }
@@ -10651,7 +10697,7 @@ async function cleanPluginCache(installedPluginsPath, installedPluginsCacheDir)
10651
10697
  const marketplace = key.split("@")[1];
10652
10698
  const candidate = join5(cacheDir, marketplace, "onebrain");
10653
10699
  try {
10654
- await stat3(candidate);
10700
+ await stat4(candidate);
10655
10701
  onebrainDirs.push(candidate);
10656
10702
  } catch {}
10657
10703
  }
@@ -10663,7 +10709,7 @@ async function cleanPluginCache(installedPluginsPath, installedPluginsCacheDir)
10663
10709
  for (const mp of marketplaceDirs) {
10664
10710
  const candidate = join5(cacheDir, mp, "onebrain");
10665
10711
  try {
10666
- await stat3(candidate);
10712
+ await stat4(candidate);
10667
10713
  onebrainDirs.push(candidate);
10668
10714
  } catch {}
10669
10715
  }
@@ -10682,7 +10728,7 @@ async function cleanPluginCache(installedPluginsPath, installedPluginsCacheDir)
10682
10728
  for (const versionDir of versionDirs) {
10683
10729
  const fullPath = join5(pluginDir, versionDir);
10684
10730
  try {
10685
- const s = await stat3(fullPath);
10731
+ const s = await stat4(fullPath);
10686
10732
  if (s.isDirectory()) {
10687
10733
  await rm(fullPath, { recursive: true, force: true });
10688
10734
  removed++;
@@ -10795,7 +10841,7 @@ async function runVaultSync(vaultRoot, opts = {}) {
10795
10841
  for (const srcPath of obsidianFiles) {
10796
10842
  const rel = relative(sourceObsidian, srcPath);
10797
10843
  const destPath = join5(destObsidian, rel);
10798
- await mkdir2(dirname2(destPath), { recursive: true });
10844
+ await mkdirIdempotent(dirname2(destPath));
10799
10845
  const content = await readFile2(srcPath);
10800
10846
  await writeFile3(destPath, content);
10801
10847
  }
@@ -10922,7 +10968,7 @@ var import_picocolors5 = __toESM(require_picocolors(), 1);
10922
10968
  var import_picocolors = __toESM(require_picocolors(), 1);
10923
10969
  function resolveBinaryVersion() {
10924
10970
  if (true)
10925
- return "2.1.14";
10971
+ return "2.1.15";
10926
10972
  try {
10927
10973
  const pkg = require_package();
10928
10974
  return pkg.version ?? "dev";
@@ -11682,11 +11728,11 @@ function getFix(r2) {
11682
11728
  const missingStr = r2.hint.replace("Missing: ", "");
11683
11729
  return {
11684
11730
  fn: async (vaultDir) => {
11685
- const { mkdir: mkdir2 } = await import("fs/promises");
11731
+ const { mkdirIdempotent: mkdirIdempotent2 } = await Promise.resolve().then(() => (init_lib(), exports_lib));
11686
11732
  const { join: join5 } = await import("path");
11687
11733
  const missing = missingStr.split(", ").map((f2) => f2.trim()).filter(Boolean);
11688
11734
  for (const folder of missing) {
11689
- await mkdir2(join5(vaultDir, folder), { recursive: true });
11735
+ await mkdirIdempotent2(join5(vaultDir, folder));
11690
11736
  }
11691
11737
  },
11692
11738
  description: `Create missing folders: ${missingStr}`
@@ -11778,9 +11824,10 @@ async function applyFixes(vaultDir, results, isTTY, registerHooksFn) {
11778
11824
  }
11779
11825
 
11780
11826
  // src/commands/init.ts
11827
+ init_lib();
11781
11828
  var import_picocolors7 = __toESM(require_picocolors(), 1);
11782
11829
  var import_yaml4 = __toESM(require_dist(), 1);
11783
- import { mkdir as mkdir3, readFile as readFile3, readdir as readdir2, rename as rename3, stat as stat4, writeFile as writeFile4 } from "fs/promises";
11830
+ import { readFile as readFile3, readdir as readdir2, rename as rename3, stat as stat5, writeFile as writeFile4 } from "fs/promises";
11784
11831
  import { homedir as homedir3 } from "os";
11785
11832
  import { dirname as dirname3, join as join6 } from "path";
11786
11833
  init_cli_ui();
@@ -11798,7 +11845,7 @@ var STANDARD_FOLDERS = [
11798
11845
  var INBOX_IMPORTS = join6("00-inbox", "imports");
11799
11846
  async function pathExists2(p2) {
11800
11847
  try {
11801
- await stat4(p2);
11848
+ await stat5(p2);
11802
11849
  return true;
11803
11850
  } catch {
11804
11851
  return false;
@@ -11810,7 +11857,7 @@ async function createFolders(vaultDir) {
11810
11857
  for (const rel of allPaths) {
11811
11858
  const full = join6(vaultDir, rel);
11812
11859
  if (!await pathExists2(full)) {
11813
- await mkdir3(full, { recursive: true });
11860
+ await mkdirIdempotent(full);
11814
11861
  created++;
11815
11862
  }
11816
11863
  }
@@ -11923,7 +11970,7 @@ async function registerPlugin(vaultDir, installedPluginsPath) {
11923
11970
  }
11924
11971
  const tmpPath = `${installedPluginsPath}.tmp`;
11925
11972
  try {
11926
- await mkdir3(dirname3(installedPluginsPath), { recursive: true });
11973
+ await mkdirIdempotent(dirname3(installedPluginsPath));
11927
11974
  await writeFile4(tmpPath, JSON.stringify(data, null, 4), "utf8");
11928
11975
  await rename3(tmpPath, installedPluginsPath);
11929
11976
  } catch (err) {
@@ -12010,7 +12057,7 @@ async function installObsidianPlugins(vaultDir, opts) {
12010
12057
  });
12011
12058
  continue;
12012
12059
  }
12013
- await mkdir3(pluginDir, { recursive: true });
12060
+ await mkdirIdempotent(pluginDir);
12014
12061
  let pluginFailed = false;
12015
12062
  for (const assetName of ["main.js", "manifest.json", "styles.css"]) {
12016
12063
  const asset = assets.find((a2) => a2.name === assetName);
@@ -13152,7 +13199,7 @@ function patchUtf8(stream) {
13152
13199
  }
13153
13200
 
13154
13201
  // src/index.ts
13155
- var VERSION = "2.1.14";
13202
+ var VERSION = "2.1.15";
13156
13203
  var RELEASE_DATE = "2026-05-06";
13157
13204
  patchUtf8(process.stdout);
13158
13205
  patchUtf8(process.stderr);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onebrain-ai/cli",
3
- "version": "2.1.14",
3
+ "version": "2.1.15",
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",