@onebrain-ai/cli 2.1.0 → 2.1.2
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.
- package/dist/onebrain +311 -265
- package/package.json +2 -2
package/dist/onebrain
CHANGED
|
@@ -9015,7 +9015,7 @@ async function checkVaultYml(vaultRoot) {
|
|
|
9015
9015
|
check: "vault.yml",
|
|
9016
9016
|
status: "ok",
|
|
9017
9017
|
message: "valid",
|
|
9018
|
-
details
|
|
9018
|
+
...details.length > 0 ? { details } : {}
|
|
9019
9019
|
};
|
|
9020
9020
|
}
|
|
9021
9021
|
async function checkFolders(vaultRoot, config) {
|
|
@@ -9338,7 +9338,7 @@ async function checkVaultYmlKeys(vaultRoot) {
|
|
|
9338
9338
|
check: "vault.yml-keys",
|
|
9339
9339
|
status: "error",
|
|
9340
9340
|
message: `${errors.length} error(s)`,
|
|
9341
|
-
hint,
|
|
9341
|
+
...hint !== undefined ? { hint } : {},
|
|
9342
9342
|
details: hint ? [...errors, hint] : errors
|
|
9343
9343
|
};
|
|
9344
9344
|
}
|
|
@@ -9349,7 +9349,7 @@ async function checkVaultYmlKeys(vaultRoot) {
|
|
|
9349
9349
|
check: "vault.yml-keys",
|
|
9350
9350
|
status: "warn",
|
|
9351
9351
|
message: `${warnings.length} issue(s)`,
|
|
9352
|
-
hint,
|
|
9352
|
+
...hint !== undefined ? { hint } : {},
|
|
9353
9353
|
details: hint ? [...warnings, hint] : warnings
|
|
9354
9354
|
};
|
|
9355
9355
|
}
|
|
@@ -9443,7 +9443,7 @@ async function checkSettingsHooks(vaultRoot, config) {
|
|
|
9443
9443
|
check: "settings-hooks",
|
|
9444
9444
|
status: "ok",
|
|
9445
9445
|
message: "hooks ok",
|
|
9446
|
-
|
|
9446
|
+
...okDetails.length > 0 ? { details: okDetails } : {}
|
|
9447
9447
|
};
|
|
9448
9448
|
}
|
|
9449
9449
|
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;
|
|
@@ -9498,7 +9498,7 @@ var init_lib = __esm(() => {
|
|
|
9498
9498
|
var require_package = __commonJS((exports, module) => {
|
|
9499
9499
|
module.exports = {
|
|
9500
9500
|
name: "@onebrain-ai/cli",
|
|
9501
|
-
version: "2.1.
|
|
9501
|
+
version: "2.1.2",
|
|
9502
9502
|
description: "CLI for OneBrain — personal AI OS for Obsidian with persistent memory, 24+ skills, and Claude Code integration",
|
|
9503
9503
|
keywords: [
|
|
9504
9504
|
"onebrain",
|
|
@@ -9526,7 +9526,7 @@ var require_package = __commonJS((exports, module) => {
|
|
|
9526
9526
|
},
|
|
9527
9527
|
files: ["dist/onebrain"],
|
|
9528
9528
|
scripts: {
|
|
9529
|
-
build: "bun build src/index.ts --outfile dist/onebrain --target
|
|
9529
|
+
build: "bun build src/index.ts --outfile dist/onebrain --target bun",
|
|
9530
9530
|
test: "bun test --pass-with-no-tests src/",
|
|
9531
9531
|
typecheck: "tsc --noEmit"
|
|
9532
9532
|
},
|
|
@@ -9545,6 +9545,129 @@ var require_package = __commonJS((exports, module) => {
|
|
|
9545
9545
|
};
|
|
9546
9546
|
});
|
|
9547
9547
|
|
|
9548
|
+
// src/commands/internal/cli-ui.ts
|
|
9549
|
+
function out(str) {
|
|
9550
|
+
process.stdout.write(Buffer.from(str, "utf8"));
|
|
9551
|
+
}
|
|
9552
|
+
function writeLine(msg) {
|
|
9553
|
+
out(`${msg}
|
|
9554
|
+
`);
|
|
9555
|
+
}
|
|
9556
|
+
function barLine(msg) {
|
|
9557
|
+
out(`${bar} ${msg}
|
|
9558
|
+
`);
|
|
9559
|
+
}
|
|
9560
|
+
function barBlank() {
|
|
9561
|
+
out(`${bar}
|
|
9562
|
+
`);
|
|
9563
|
+
}
|
|
9564
|
+
function close(msg, isError = false, isWarning = false) {
|
|
9565
|
+
if (isError) {
|
|
9566
|
+
out(`${import_picocolors2.default.cyan("└")} ${import_picocolors2.default.bold(import_picocolors2.default.red(msg))}
|
|
9567
|
+
`);
|
|
9568
|
+
} else if (isWarning) {
|
|
9569
|
+
out(`${import_picocolors2.default.cyan("└")} ${import_picocolors2.default.yellow(msg)}
|
|
9570
|
+
`);
|
|
9571
|
+
} else {
|
|
9572
|
+
out(`${import_picocolors2.default.cyan("└")} ${msg}
|
|
9573
|
+
`);
|
|
9574
|
+
}
|
|
9575
|
+
}
|
|
9576
|
+
function dotLine(emoji, label) {
|
|
9577
|
+
out(`${dot} ${emoji} ${label}
|
|
9578
|
+
`);
|
|
9579
|
+
}
|
|
9580
|
+
function makeStepFn(isTTY) {
|
|
9581
|
+
return function createStep(emoji, label) {
|
|
9582
|
+
if (!isTTY)
|
|
9583
|
+
return null;
|
|
9584
|
+
const frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
9585
|
+
let i = 0;
|
|
9586
|
+
out(`${import_picocolors2.default.green(frames[0])} ${emoji} ${label}…
|
|
9587
|
+
`);
|
|
9588
|
+
const timer = setInterval(() => {
|
|
9589
|
+
i = (i + 1) % frames.length;
|
|
9590
|
+
out(`\x1B[1A\x1B[2K${import_picocolors2.default.green(frames[i])} ${emoji} ${label}…
|
|
9591
|
+
`);
|
|
9592
|
+
}, 80);
|
|
9593
|
+
return {
|
|
9594
|
+
stop(result, details) {
|
|
9595
|
+
clearInterval(timer);
|
|
9596
|
+
process.stdout.write(Buffer.from("\x1B[1A\x1B[2K", "utf8"));
|
|
9597
|
+
out(`${dot} ${emoji} ${label}
|
|
9598
|
+
`);
|
|
9599
|
+
if (result !== undefined)
|
|
9600
|
+
barLine(result);
|
|
9601
|
+
if (details)
|
|
9602
|
+
for (const d of details)
|
|
9603
|
+
barLine(` · ${d}`);
|
|
9604
|
+
barBlank();
|
|
9605
|
+
}
|
|
9606
|
+
};
|
|
9607
|
+
};
|
|
9608
|
+
}
|
|
9609
|
+
async function askYesNo(question) {
|
|
9610
|
+
out(`${import_picocolors2.default.cyan("◆")} ${question}
|
|
9611
|
+
`);
|
|
9612
|
+
process.stdout.write(Buffer.from("\x1B[?25l", "utf8"));
|
|
9613
|
+
function renderOptions(yes) {
|
|
9614
|
+
const yesLabel = yes ? `${import_picocolors2.default.bold(import_picocolors2.default.green("●"))} Yes` : `${import_picocolors2.default.dim("○")} Yes`;
|
|
9615
|
+
const noLabel = yes ? `${import_picocolors2.default.dim("○")} No` : `${import_picocolors2.default.bold(import_picocolors2.default.green("●"))} No`;
|
|
9616
|
+
out(`\x1B[2K${bar} ${yesLabel} / ${noLabel}\r`);
|
|
9617
|
+
}
|
|
9618
|
+
const answer = await new Promise((resolve) => {
|
|
9619
|
+
let selected = true;
|
|
9620
|
+
renderOptions(selected);
|
|
9621
|
+
const { stdin } = process;
|
|
9622
|
+
const wasRaw = stdin.isTTY ? stdin.isRaw : false;
|
|
9623
|
+
if (stdin.isTTY)
|
|
9624
|
+
stdin.setRawMode(true);
|
|
9625
|
+
stdin.resume();
|
|
9626
|
+
function onData(buf) {
|
|
9627
|
+
const key = buf.toString();
|
|
9628
|
+
if (key === "\x03") {
|
|
9629
|
+
stdin.removeListener("data", onData);
|
|
9630
|
+
if (stdin.isTTY)
|
|
9631
|
+
stdin.setRawMode(wasRaw);
|
|
9632
|
+
stdin.pause();
|
|
9633
|
+
resolve(null);
|
|
9634
|
+
} else if (key === "\r" || key === `
|
|
9635
|
+
`) {
|
|
9636
|
+
stdin.removeListener("data", onData);
|
|
9637
|
+
if (stdin.isTTY)
|
|
9638
|
+
stdin.setRawMode(wasRaw);
|
|
9639
|
+
stdin.pause();
|
|
9640
|
+
resolve(selected);
|
|
9641
|
+
} else if (key === "y" || key === "Y") {
|
|
9642
|
+
stdin.removeListener("data", onData);
|
|
9643
|
+
if (stdin.isTTY)
|
|
9644
|
+
stdin.setRawMode(wasRaw);
|
|
9645
|
+
stdin.pause();
|
|
9646
|
+
resolve(true);
|
|
9647
|
+
} else if (key === "n" || key === "N") {
|
|
9648
|
+
stdin.removeListener("data", onData);
|
|
9649
|
+
if (stdin.isTTY)
|
|
9650
|
+
stdin.setRawMode(wasRaw);
|
|
9651
|
+
stdin.pause();
|
|
9652
|
+
resolve(false);
|
|
9653
|
+
} else if (key === "\x1B[C" || key === "\x1B[D" || key === "\t") {
|
|
9654
|
+
selected = !selected;
|
|
9655
|
+
renderOptions(selected);
|
|
9656
|
+
}
|
|
9657
|
+
}
|
|
9658
|
+
stdin.on("data", onData);
|
|
9659
|
+
});
|
|
9660
|
+
process.stdout.write(Buffer.from(`
|
|
9661
|
+
\x1B[?25h\x1B[1A\x1B[2K`, "utf8"));
|
|
9662
|
+
return answer;
|
|
9663
|
+
}
|
|
9664
|
+
var import_picocolors2, bar, dot;
|
|
9665
|
+
var init_cli_ui = __esm(() => {
|
|
9666
|
+
import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
9667
|
+
bar = import_picocolors2.default.cyan("│");
|
|
9668
|
+
dot = import_picocolors2.default.green("●");
|
|
9669
|
+
});
|
|
9670
|
+
|
|
9548
9671
|
// node_modules/sisteransi/src/index.js
|
|
9549
9672
|
var require_src = __commonJS((exports, module) => {
|
|
9550
9673
|
var ESC = "\x1B";
|
|
@@ -10461,35 +10584,47 @@ async function runVaultSync(vaultRoot, opts = {}) {
|
|
|
10461
10584
|
pinSkipped: true,
|
|
10462
10585
|
cacheRemoved: 0
|
|
10463
10586
|
};
|
|
10587
|
+
const embedded = opts.embedded ?? false;
|
|
10588
|
+
const createEmbeddedStep = embedded ? makeStepFn(true) : null;
|
|
10464
10589
|
let s = null;
|
|
10465
|
-
|
|
10590
|
+
let currentStep = null;
|
|
10591
|
+
function startSpinner(emoji, label) {
|
|
10466
10592
|
if (isTTY) {
|
|
10467
|
-
|
|
10468
|
-
|
|
10593
|
+
if (embedded) {
|
|
10594
|
+
currentStep = createEmbeddedStep(emoji, label);
|
|
10595
|
+
} else {
|
|
10596
|
+
s = L2();
|
|
10597
|
+
s.start(label);
|
|
10598
|
+
}
|
|
10469
10599
|
} else {
|
|
10470
|
-
process.stdout.write(`vault-sync: ${
|
|
10600
|
+
process.stdout.write(`vault-sync: ${label}
|
|
10471
10601
|
`);
|
|
10472
10602
|
}
|
|
10473
10603
|
}
|
|
10474
|
-
function stopSpinner(
|
|
10475
|
-
if (isTTY
|
|
10476
|
-
|
|
10477
|
-
|
|
10604
|
+
function stopSpinner(result2, details) {
|
|
10605
|
+
if (isTTY) {
|
|
10606
|
+
if (embedded) {
|
|
10607
|
+
currentStep?.stop(import_picocolors6.default.dim(result2), details);
|
|
10608
|
+
currentStep = null;
|
|
10609
|
+
} else if (s) {
|
|
10610
|
+
s.stop(result2);
|
|
10611
|
+
s = null;
|
|
10612
|
+
}
|
|
10478
10613
|
}
|
|
10479
10614
|
}
|
|
10480
|
-
if (isTTY) {
|
|
10615
|
+
if (isTTY && !embedded) {
|
|
10481
10616
|
we("OneBrain Vault Sync");
|
|
10482
10617
|
}
|
|
10483
10618
|
let tmpDir = null;
|
|
10484
10619
|
try {
|
|
10485
|
-
startSpinner("
|
|
10620
|
+
startSpinner("\uD83D\uDCE5", "Downloading");
|
|
10486
10621
|
let extractedDir;
|
|
10487
10622
|
try {
|
|
10488
10623
|
const dl = await downloadTarball(branch, fetchFn);
|
|
10489
10624
|
tmpDir = dl.tmpDir;
|
|
10490
10625
|
extractedDir = await extractTarball(dl.tarball, tmpDir);
|
|
10491
10626
|
} catch (err) {
|
|
10492
|
-
stopSpinner("
|
|
10627
|
+
stopSpinner("download failed");
|
|
10493
10628
|
const msg = err instanceof Error ? err.message : String(err);
|
|
10494
10629
|
result.error = msg;
|
|
10495
10630
|
process.stderr.write(`vault-sync: download failed: ${msg}
|
|
@@ -10504,13 +10639,13 @@ async function runVaultSync(vaultRoot, opts = {}) {
|
|
|
10504
10639
|
}
|
|
10505
10640
|
} catch {}
|
|
10506
10641
|
stopSpinner(`kengio/onebrain@${branch} (v${result.version})`);
|
|
10507
|
-
startSpinner("Syncing
|
|
10642
|
+
startSpinner("\uD83D\uDCC2", "Syncing files");
|
|
10508
10643
|
try {
|
|
10509
10644
|
const { filesAdded, filesRemoved } = await syncPluginFiles(extractedDir, vaultRoot, unlinkFn);
|
|
10510
10645
|
result.filesAdded = filesAdded;
|
|
10511
10646
|
result.filesRemoved = filesRemoved;
|
|
10512
10647
|
} catch (err) {
|
|
10513
|
-
stopSpinner("
|
|
10648
|
+
stopSpinner("plugin sync failed");
|
|
10514
10649
|
const msg = err instanceof Error ? err.message : String(err);
|
|
10515
10650
|
result.error = msg;
|
|
10516
10651
|
process.stderr.write(`vault-sync: plugin sync failed: ${msg}
|
|
@@ -10533,13 +10668,13 @@ async function runVaultSync(vaultRoot, opts = {}) {
|
|
|
10533
10668
|
} catch {}
|
|
10534
10669
|
}
|
|
10535
10670
|
await copyRootDocs(extractedDir, vaultRoot);
|
|
10536
|
-
startSpinner("Updating harness
|
|
10671
|
+
startSpinner("\uD83D\uDD27", "Updating harness");
|
|
10537
10672
|
let importsAdded = 0;
|
|
10538
10673
|
try {
|
|
10539
10674
|
importsAdded = await mergeHarnessFiles(extractedDir, vaultRoot);
|
|
10540
10675
|
result.importsAdded = importsAdded;
|
|
10541
10676
|
} catch (err) {
|
|
10542
|
-
stopSpinner("
|
|
10677
|
+
stopSpinner("harness merge failed");
|
|
10543
10678
|
const msg = err instanceof Error ? err.message : String(err);
|
|
10544
10679
|
result.error = msg;
|
|
10545
10680
|
process.stderr.write(`vault-sync: harness merge failed: ${msg}
|
|
@@ -10561,7 +10696,7 @@ async function runVaultSync(vaultRoot, opts = {}) {
|
|
|
10561
10696
|
return result;
|
|
10562
10697
|
}
|
|
10563
10698
|
if (harness === "claude") {
|
|
10564
|
-
startSpinner("Pinning to vault
|
|
10699
|
+
startSpinner("\uD83D\uDCCC", "Pinning to vault");
|
|
10565
10700
|
try {
|
|
10566
10701
|
const pinResult = await pinToVault(vaultRoot, installedPluginsPath, installedPluginsCacheDir);
|
|
10567
10702
|
result.pinSkipped = pinResult.skipped;
|
|
@@ -10577,7 +10712,7 @@ async function runVaultSync(vaultRoot, opts = {}) {
|
|
|
10577
10712
|
result.pinSkipped = true;
|
|
10578
10713
|
stopSpinner("pin skipped (error — non-fatal)");
|
|
10579
10714
|
}
|
|
10580
|
-
startSpinner("Cleaning cache
|
|
10715
|
+
startSpinner("\uD83E\uDDF9", "Cleaning cache");
|
|
10581
10716
|
try {
|
|
10582
10717
|
const cacheRemoved = await cleanPluginCache(installedPluginsPath, installedPluginsCacheDir);
|
|
10583
10718
|
result.cacheRemoved = cacheRemoved;
|
|
@@ -10595,7 +10730,9 @@ async function runVaultSync(vaultRoot, opts = {}) {
|
|
|
10595
10730
|
}
|
|
10596
10731
|
result.ok = true;
|
|
10597
10732
|
if (isTTY) {
|
|
10598
|
-
|
|
10733
|
+
if (!embedded) {
|
|
10734
|
+
fe(`Done — v${result.version} synced`);
|
|
10735
|
+
}
|
|
10599
10736
|
} else {
|
|
10600
10737
|
process.stdout.write(`vault-sync: done
|
|
10601
10738
|
`);
|
|
@@ -10613,16 +10750,18 @@ async function vaultSyncCommand(vaultRoot, opts = {}) {
|
|
|
10613
10750
|
process.exit(1);
|
|
10614
10751
|
}
|
|
10615
10752
|
}
|
|
10616
|
-
var import_yaml3;
|
|
10753
|
+
var import_picocolors6, import_yaml3;
|
|
10617
10754
|
var init_vault_sync = __esm(() => {
|
|
10618
10755
|
init_dist2();
|
|
10756
|
+
init_cli_ui();
|
|
10619
10757
|
init_harness();
|
|
10758
|
+
import_picocolors6 = __toESM(require_picocolors(), 1);
|
|
10620
10759
|
import_yaml3 = __toESM(require_dist(), 1);
|
|
10621
10760
|
});
|
|
10622
10761
|
|
|
10623
10762
|
// src/index.ts
|
|
10624
10763
|
import { existsSync } from "fs";
|
|
10625
|
-
import { dirname as dirname6, join as
|
|
10764
|
+
import { dirname as dirname6, join as join13 } from "path";
|
|
10626
10765
|
|
|
10627
10766
|
// node_modules/commander/esm.mjs
|
|
10628
10767
|
var import__ = __toESM(require_commander(), 1);
|
|
@@ -10648,7 +10787,7 @@ var import_picocolors5 = __toESM(require_picocolors(), 1);
|
|
|
10648
10787
|
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
10649
10788
|
function resolveBinaryVersion() {
|
|
10650
10789
|
if (true)
|
|
10651
|
-
return "2.1.
|
|
10790
|
+
return "2.1.2";
|
|
10652
10791
|
try {
|
|
10653
10792
|
const pkg = require_package();
|
|
10654
10793
|
return pkg.version ?? "dev";
|
|
@@ -10713,39 +10852,42 @@ function scanLine(line) {
|
|
|
10713
10852
|
function dimLine(line) {
|
|
10714
10853
|
return line.split("").map((ch) => ch === " " ? ch : `\x1B[2;38;2;50;50;70m${ch}\x1B[0m`).join("");
|
|
10715
10854
|
}
|
|
10855
|
+
function outb(str) {
|
|
10856
|
+
process.stdout.write(Buffer.from(str, "utf8"));
|
|
10857
|
+
}
|
|
10716
10858
|
function printFrame(artLines, tagline) {
|
|
10717
|
-
|
|
10859
|
+
outb(`
|
|
10718
10860
|
`);
|
|
10719
10861
|
for (const l of artLines)
|
|
10720
|
-
|
|
10862
|
+
outb(`${l}
|
|
10721
10863
|
`);
|
|
10722
|
-
|
|
10864
|
+
outb(`
|
|
10723
10865
|
`);
|
|
10724
|
-
|
|
10866
|
+
outb(`${tagline}
|
|
10725
10867
|
`);
|
|
10726
|
-
|
|
10868
|
+
outb(`
|
|
10727
10869
|
`);
|
|
10728
10870
|
}
|
|
10729
10871
|
async function printBanner() {
|
|
10730
10872
|
if (!process.stdout.isTTY)
|
|
10731
10873
|
return;
|
|
10732
10874
|
const delay = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
10733
|
-
const up = (n) =>
|
|
10875
|
+
const up = (n) => outb(`\x1B[${n}F`);
|
|
10734
10876
|
if (!supportsRgb()) {
|
|
10735
|
-
|
|
10877
|
+
outb(`
|
|
10736
10878
|
`);
|
|
10737
10879
|
for (const l of ART_LINES)
|
|
10738
|
-
|
|
10880
|
+
outb(`${import_picocolors.default.bold(import_picocolors.default.cyan(l))}
|
|
10739
10881
|
`);
|
|
10740
|
-
|
|
10882
|
+
outb(`
|
|
10741
10883
|
`);
|
|
10742
|
-
|
|
10884
|
+
outb(` ${import_picocolors.default.bold(import_picocolors.default.magenta(TAGLINE))}
|
|
10743
10885
|
`);
|
|
10744
|
-
|
|
10886
|
+
outb(`
|
|
10745
10887
|
`);
|
|
10746
10888
|
return;
|
|
10747
10889
|
}
|
|
10748
|
-
|
|
10890
|
+
outb("\x1B[?25l");
|
|
10749
10891
|
try {
|
|
10750
10892
|
let diagFrame = function(highlight) {
|
|
10751
10893
|
return ART_LINES.map((line, row) => line.split("").map((ch, col) => {
|
|
@@ -10818,126 +10960,12 @@ async function printBanner() {
|
|
|
10818
10960
|
up(BANNER_LINE_COUNT);
|
|
10819
10961
|
printFrame(ART_LINES.map((l, i) => neonLine(l, i)), ` ${import_picocolors.default.bold(import_picocolors.default.magenta(TAGLINE))}\x1B[K`);
|
|
10820
10962
|
} finally {
|
|
10821
|
-
|
|
10963
|
+
outb("\x1B[?25h");
|
|
10822
10964
|
}
|
|
10823
10965
|
}
|
|
10824
10966
|
|
|
10825
|
-
// src/commands/internal/cli-ui.ts
|
|
10826
|
-
var import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
10827
|
-
var bar = import_picocolors2.default.cyan("│");
|
|
10828
|
-
var dot = import_picocolors2.default.green("●");
|
|
10829
|
-
function writeLine(msg) {
|
|
10830
|
-
process.stdout.write(`${msg}
|
|
10831
|
-
`);
|
|
10832
|
-
}
|
|
10833
|
-
function barLine(msg) {
|
|
10834
|
-
process.stdout.write(`${bar} ${msg}
|
|
10835
|
-
`);
|
|
10836
|
-
}
|
|
10837
|
-
function barBlank() {
|
|
10838
|
-
process.stdout.write(`${bar}
|
|
10839
|
-
`);
|
|
10840
|
-
}
|
|
10841
|
-
function close(msg, isError = false, isWarning = false) {
|
|
10842
|
-
if (isError) {
|
|
10843
|
-
process.stdout.write(`${import_picocolors2.default.cyan("└")} ${import_picocolors2.default.bold(import_picocolors2.default.red(msg))}
|
|
10844
|
-
`);
|
|
10845
|
-
} else if (isWarning) {
|
|
10846
|
-
process.stdout.write(`${import_picocolors2.default.cyan("└")} ${import_picocolors2.default.yellow(msg)}
|
|
10847
|
-
`);
|
|
10848
|
-
} else {
|
|
10849
|
-
process.stdout.write(`${import_picocolors2.default.cyan("└")} ${msg}
|
|
10850
|
-
`);
|
|
10851
|
-
}
|
|
10852
|
-
}
|
|
10853
|
-
function makeStepFn(isTTY) {
|
|
10854
|
-
return function createStep(emoji, label) {
|
|
10855
|
-
if (!isTTY)
|
|
10856
|
-
return null;
|
|
10857
|
-
const frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
10858
|
-
let i = 0;
|
|
10859
|
-
process.stdout.write(`${import_picocolors2.default.green(frames[0])} ${emoji} ${label}…
|
|
10860
|
-
`);
|
|
10861
|
-
const timer = setInterval(() => {
|
|
10862
|
-
i = (i + 1) % frames.length;
|
|
10863
|
-
process.stdout.write(`\x1B[1A\x1B[2K${import_picocolors2.default.green(frames[i])} ${emoji} ${label}…
|
|
10864
|
-
`);
|
|
10865
|
-
}, 80);
|
|
10866
|
-
return {
|
|
10867
|
-
stop(result, details) {
|
|
10868
|
-
clearInterval(timer);
|
|
10869
|
-
process.stdout.write("\x1B[1A\x1B[2K");
|
|
10870
|
-
process.stdout.write(`${dot} ${emoji} ${label}
|
|
10871
|
-
`);
|
|
10872
|
-
if (result !== undefined)
|
|
10873
|
-
barLine(result);
|
|
10874
|
-
if (details)
|
|
10875
|
-
for (const d of details)
|
|
10876
|
-
barLine(` · ${d}`);
|
|
10877
|
-
barBlank();
|
|
10878
|
-
}
|
|
10879
|
-
};
|
|
10880
|
-
};
|
|
10881
|
-
}
|
|
10882
|
-
async function askYesNo(question) {
|
|
10883
|
-
process.stdout.write(`${import_picocolors2.default.cyan("◆")} ${question}
|
|
10884
|
-
`);
|
|
10885
|
-
process.stdout.write("\x1B[?25l");
|
|
10886
|
-
function renderOptions(yes) {
|
|
10887
|
-
const yesLabel = yes ? `${import_picocolors2.default.bold(import_picocolors2.default.green("●"))} Yes` : `${import_picocolors2.default.dim("○")} Yes`;
|
|
10888
|
-
const noLabel = yes ? `${import_picocolors2.default.dim("○")} No` : `${import_picocolors2.default.bold(import_picocolors2.default.green("●"))} No`;
|
|
10889
|
-
process.stdout.write(`\x1B[2K${bar} ${yesLabel} / ${noLabel}\r`);
|
|
10890
|
-
}
|
|
10891
|
-
const answer = await new Promise((resolve) => {
|
|
10892
|
-
let selected = true;
|
|
10893
|
-
renderOptions(selected);
|
|
10894
|
-
const { stdin } = process;
|
|
10895
|
-
const wasRaw = stdin.isTTY ? stdin.isRaw : false;
|
|
10896
|
-
if (stdin.isTTY)
|
|
10897
|
-
stdin.setRawMode(true);
|
|
10898
|
-
stdin.resume();
|
|
10899
|
-
function onData(buf) {
|
|
10900
|
-
const key = buf.toString();
|
|
10901
|
-
if (key === "\x03") {
|
|
10902
|
-
stdin.removeListener("data", onData);
|
|
10903
|
-
if (stdin.isTTY)
|
|
10904
|
-
stdin.setRawMode(wasRaw);
|
|
10905
|
-
stdin.pause();
|
|
10906
|
-
resolve(null);
|
|
10907
|
-
} else if (key === "\r" || key === `
|
|
10908
|
-
`) {
|
|
10909
|
-
stdin.removeListener("data", onData);
|
|
10910
|
-
if (stdin.isTTY)
|
|
10911
|
-
stdin.setRawMode(wasRaw);
|
|
10912
|
-
stdin.pause();
|
|
10913
|
-
resolve(selected);
|
|
10914
|
-
} else if (key === "y" || key === "Y") {
|
|
10915
|
-
stdin.removeListener("data", onData);
|
|
10916
|
-
if (stdin.isTTY)
|
|
10917
|
-
stdin.setRawMode(wasRaw);
|
|
10918
|
-
stdin.pause();
|
|
10919
|
-
resolve(true);
|
|
10920
|
-
} else if (key === "n" || key === "N") {
|
|
10921
|
-
stdin.removeListener("data", onData);
|
|
10922
|
-
if (stdin.isTTY)
|
|
10923
|
-
stdin.setRawMode(wasRaw);
|
|
10924
|
-
stdin.pause();
|
|
10925
|
-
resolve(false);
|
|
10926
|
-
} else if (key === "\x1B[C" || key === "\x1B[D" || key === "\t") {
|
|
10927
|
-
selected = !selected;
|
|
10928
|
-
renderOptions(selected);
|
|
10929
|
-
}
|
|
10930
|
-
}
|
|
10931
|
-
stdin.on("data", onData);
|
|
10932
|
-
});
|
|
10933
|
-
process.stdout.write(`
|
|
10934
|
-
`);
|
|
10935
|
-
process.stdout.write("\x1B[?25h");
|
|
10936
|
-
process.stdout.write("\x1B[1A\x1B[2K");
|
|
10937
|
-
return answer;
|
|
10938
|
-
}
|
|
10939
|
-
|
|
10940
10967
|
// src/commands/doctor.ts
|
|
10968
|
+
init_cli_ui();
|
|
10941
10969
|
async function runDoctor(opts = {}) {
|
|
10942
10970
|
const vaultDir = opts.vaultDir ?? process.cwd();
|
|
10943
10971
|
const isTTY = opts.isTTY ?? process.stdout.isTTY ?? false;
|
|
@@ -11274,11 +11302,12 @@ async function applyFixes(vaultDir, results, isTTY, registerHooksFn) {
|
|
|
11274
11302
|
}
|
|
11275
11303
|
|
|
11276
11304
|
// src/commands/init.ts
|
|
11277
|
-
var
|
|
11305
|
+
var import_picocolors7 = __toESM(require_picocolors(), 1);
|
|
11278
11306
|
var import_yaml4 = __toESM(require_dist(), 1);
|
|
11279
11307
|
import { mkdir as mkdir3, readFile as readFile3, readdir as readdir2, rename as rename3, stat as stat4, writeFile as writeFile3 } from "node:fs/promises";
|
|
11280
11308
|
import { homedir as homedir3 } from "node:os";
|
|
11281
11309
|
import { dirname as dirname3, join as join6 } from "node:path";
|
|
11310
|
+
init_cli_ui();
|
|
11282
11311
|
var binaryVersion = resolveBinaryVersion();
|
|
11283
11312
|
var STANDARD_FOLDERS = [
|
|
11284
11313
|
"00-inbox",
|
|
@@ -11348,7 +11377,7 @@ async function downloadPluginFiles(vaultDir, vaultSyncFn) {
|
|
|
11348
11377
|
return driftWarning !== undefined ? { skipped: true, driftWarning } : { skipped: true };
|
|
11349
11378
|
}
|
|
11350
11379
|
try {
|
|
11351
|
-
await vaultSyncFn(vaultDir, { includeObsidian: true });
|
|
11380
|
+
await vaultSyncFn(vaultDir, { includeObsidian: true, embedded: true });
|
|
11352
11381
|
} catch (err) {
|
|
11353
11382
|
const msg = err instanceof Error ? err.message : String(err);
|
|
11354
11383
|
process.stderr.write(`init: vault-sync warning: ${msg}
|
|
@@ -11578,22 +11607,17 @@ async function runInit(opts = {}) {
|
|
|
11578
11607
|
const createStep = makeStepFn(isTTY);
|
|
11579
11608
|
const delay = opts.delayFn ?? ((ms) => new Promise((r2) => setTimeout(r2, ms)));
|
|
11580
11609
|
const randDelay = () => isTTY ? delay(Math.floor(Math.random() * 1000) + 1000) : Promise.resolve();
|
|
11610
|
+
const _confirmFn = opts.confirmFn ?? askYesNo;
|
|
11581
11611
|
const vaultYmlPath = join6(vaultDir, "vault.yml");
|
|
11582
11612
|
const vaultYmlExists = await pathExists2(vaultYmlPath);
|
|
11583
|
-
if (
|
|
11584
|
-
|
|
11585
|
-
|
|
11586
|
-
|
|
11587
|
-
|
|
11588
|
-
|
|
11589
|
-
|
|
11590
|
-
|
|
11591
|
-
}
|
|
11592
|
-
if (isTTY) {
|
|
11593
|
-
await printBanner();
|
|
11594
|
-
const answer = await askYesNo("vault.yml already exists. Overwrite?");
|
|
11595
|
-
if (answer === null || answer === false) {
|
|
11596
|
-
barLine(import_picocolors6.default.dim("No"));
|
|
11613
|
+
if (isTTY) {
|
|
11614
|
+
await printBanner();
|
|
11615
|
+
if (!force) {
|
|
11616
|
+
barLine(`${import_picocolors7.default.dim("vault root")} ${import_picocolors7.default.cyan(vaultDir)}`);
|
|
11617
|
+
barBlank();
|
|
11618
|
+
const proceed = await _confirmFn("Initialize OneBrain vault here?");
|
|
11619
|
+
if (proceed === null || proceed === false) {
|
|
11620
|
+
barLine(import_picocolors7.default.dim("No"));
|
|
11597
11621
|
barBlank();
|
|
11598
11622
|
close("Aborted");
|
|
11599
11623
|
result.ok = true;
|
|
@@ -11602,18 +11626,36 @@ async function runInit(opts = {}) {
|
|
|
11602
11626
|
}
|
|
11603
11627
|
barLine("Yes");
|
|
11604
11628
|
barBlank();
|
|
11629
|
+
if (vaultYmlExists) {
|
|
11630
|
+
const overwrite = await _confirmFn("vault.yml already exists. Overwrite?");
|
|
11631
|
+
if (overwrite === null || overwrite === false) {
|
|
11632
|
+
barLine(import_picocolors7.default.dim("No"));
|
|
11633
|
+
barBlank();
|
|
11634
|
+
close("Aborted");
|
|
11635
|
+
result.ok = true;
|
|
11636
|
+
result.exitCode = 0;
|
|
11637
|
+
return result;
|
|
11638
|
+
}
|
|
11639
|
+
barLine("Yes");
|
|
11640
|
+
barBlank();
|
|
11641
|
+
}
|
|
11642
|
+
}
|
|
11643
|
+
} else {
|
|
11644
|
+
if (vaultYmlExists && !force) {
|
|
11645
|
+
const msg = "vault.yml exists. Re-run with --force to overwrite.";
|
|
11646
|
+
process.stdout.write(`${msg}
|
|
11647
|
+
`);
|
|
11648
|
+
result.message = msg;
|
|
11649
|
+
result.exitCode = 1;
|
|
11650
|
+
return result;
|
|
11605
11651
|
}
|
|
11606
|
-
} else if (isTTY) {
|
|
11607
|
-
await printBanner();
|
|
11608
|
-
}
|
|
11609
|
-
if (!isTTY) {
|
|
11610
11652
|
writeLine("OneBrain Init");
|
|
11611
11653
|
}
|
|
11612
11654
|
const sp2 = createStep("\uD83D\uDCCB", "vault.yml");
|
|
11613
11655
|
await writeVaultYml(vaultDir);
|
|
11614
11656
|
if (sp2) {
|
|
11615
11657
|
await randDelay();
|
|
11616
|
-
sp2.stop(
|
|
11658
|
+
sp2.stop(import_picocolors7.default.dim("written"), ["update_channel: stable", "checkpoint: 15 msgs · 30 min"]);
|
|
11617
11659
|
} else {
|
|
11618
11660
|
writeLine("vault.yml: written");
|
|
11619
11661
|
}
|
|
@@ -11626,7 +11668,9 @@ async function runInit(opts = {}) {
|
|
|
11626
11668
|
} else {
|
|
11627
11669
|
writeLine(`folders: ${foldersCreated} created`);
|
|
11628
11670
|
}
|
|
11629
|
-
const
|
|
11671
|
+
const pluginJsonPath = join6(vaultDir, ".claude", "plugins", "onebrain", ".claude-plugin", "plugin.json");
|
|
11672
|
+
const pluginFilesExist = await pathExists2(pluginJsonPath);
|
|
11673
|
+
const sp4 = pluginFilesExist ? createStep("\uD83D\uDCE6", "Plugin files") : null;
|
|
11630
11674
|
const {
|
|
11631
11675
|
skipped: pluginSkipped,
|
|
11632
11676
|
failed: pluginDownloadFailed
|
|
@@ -11637,7 +11681,15 @@ async function runInit(opts = {}) {
|
|
|
11637
11681
|
sp4.stop("download failed");
|
|
11638
11682
|
} else {
|
|
11639
11683
|
const { skills, agents } = await countPluginContents(vaultDir);
|
|
11640
|
-
sp4.stop(
|
|
11684
|
+
sp4.stop(import_picocolors7.default.dim("already installed"), [`${skills} skills · ${agents} agents`]);
|
|
11685
|
+
}
|
|
11686
|
+
} else if (isTTY) {
|
|
11687
|
+
if (!pluginDownloadFailed) {
|
|
11688
|
+
const { skills, agents } = await countPluginContents(vaultDir);
|
|
11689
|
+
dotLine("\uD83D\uDCE6", "Plugin files");
|
|
11690
|
+
barLine(import_picocolors7.default.dim("downloaded"));
|
|
11691
|
+
barLine(` · ${skills} skills · ${agents} agents`);
|
|
11692
|
+
barBlank();
|
|
11641
11693
|
}
|
|
11642
11694
|
} else {
|
|
11643
11695
|
if (pluginSkipped)
|
|
@@ -11669,7 +11721,7 @@ async function runInit(opts = {}) {
|
|
|
11669
11721
|
...pluginResult.installed,
|
|
11670
11722
|
...pluginResult.failed.map((f2) => `${f2.id} (skipped)`)
|
|
11671
11723
|
];
|
|
11672
|
-
sp4b.stop(
|
|
11724
|
+
sp4b.stop(import_picocolors7.default.dim(n > 0 ? `${n} installed` : "none"), details.length > 0 ? details : undefined);
|
|
11673
11725
|
} else {
|
|
11674
11726
|
if (pluginResult.installed.length > 0)
|
|
11675
11727
|
writeLine(`plugins: ${pluginResult.installed.join(", ")} installed`);
|
|
@@ -11681,7 +11733,7 @@ async function runInit(opts = {}) {
|
|
|
11681
11733
|
result.pluginRegistrationSkipped = pluginRegistrationSkipped;
|
|
11682
11734
|
if (sp5) {
|
|
11683
11735
|
await randDelay();
|
|
11684
|
-
sp5.stop(
|
|
11736
|
+
sp5.stop(import_picocolors7.default.dim(pluginRegistrationSkipped ? "skipped" : "registered"), [`source: ${pluginRegistrationSkipped ? "marketplace" : "local"}`]);
|
|
11685
11737
|
} else {
|
|
11686
11738
|
writeLine(`plugin: ${pluginRegistrationSkipped ? "skipped (marketplace)" : "registered"}`);
|
|
11687
11739
|
}
|
|
@@ -11704,13 +11756,13 @@ async function runInit(opts = {}) {
|
|
|
11704
11756
|
result.ok = true;
|
|
11705
11757
|
result.exitCode = 0;
|
|
11706
11758
|
if (isTTY) {
|
|
11707
|
-
barLine(
|
|
11759
|
+
barLine(import_picocolors7.default.dim(`─── Next steps ${"─".repeat(25)}`));
|
|
11708
11760
|
barBlank();
|
|
11709
|
-
barLine(` ${
|
|
11710
|
-
barLine(` ${
|
|
11711
|
-
barLine(` ${
|
|
11761
|
+
barLine(` ${import_picocolors7.default.bold(import_picocolors7.default.cyan("1"))} \uD83D\uDCC1 Open Obsidian → open this folder as vault`);
|
|
11762
|
+
barLine(` ${import_picocolors7.default.bold(import_picocolors7.default.cyan("2"))} \uD83E\uDD16 Run ${import_picocolors7.default.cyan("claude")}`);
|
|
11763
|
+
barLine(` ${import_picocolors7.default.bold(import_picocolors7.default.cyan("3"))} \uD83E\uDDE0 Type ${import_picocolors7.default.cyan("/onboarding")} to personalize`);
|
|
11712
11764
|
barBlank();
|
|
11713
|
-
close(`✨ ${
|
|
11765
|
+
close(`✨ ${import_picocolors7.default.bold("Ready")} — ${import_picocolors7.default.cyan("/onboarding")}`);
|
|
11714
11766
|
} else {
|
|
11715
11767
|
writeLine("done: run /onboarding in Claude to finish setup");
|
|
11716
11768
|
}
|
|
@@ -12158,7 +12210,7 @@ async function qmdReindexCommand(vaultRoot) {
|
|
|
12158
12210
|
init_dist2();
|
|
12159
12211
|
init_lib();
|
|
12160
12212
|
init_harness();
|
|
12161
|
-
var
|
|
12213
|
+
var import_picocolors8 = __toESM(require_picocolors(), 1);
|
|
12162
12214
|
import { mkdir as mkdir4, readFile as readFile6, rename as rename4, writeFile as writeFile5 } from "node:fs/promises";
|
|
12163
12215
|
import { homedir as homedir4 } from "node:os";
|
|
12164
12216
|
import { dirname as dirname4, join as join10 } from "node:path";
|
|
@@ -12366,11 +12418,11 @@ async function runRegisterHooks2(opts = {}) {
|
|
|
12366
12418
|
if (isTTY) {
|
|
12367
12419
|
const parts = HOOK_EVENTS2.map((e2) => {
|
|
12368
12420
|
const status = result.hooks[e2];
|
|
12369
|
-
const icon =
|
|
12370
|
-
return `${
|
|
12421
|
+
const icon = import_picocolors8.default.green(status === "ok" ? "✓" : status === "migrated" ? "↑" : "+");
|
|
12422
|
+
return `${import_picocolors8.default.dim(e2)} ${icon}`;
|
|
12371
12423
|
});
|
|
12372
12424
|
if (qmdStatus)
|
|
12373
|
-
parts.push(`${
|
|
12425
|
+
parts.push(`${import_picocolors8.default.dim("PostToolUse")} ${import_picocolors8.default.green(qmdStatus === "ok" ? "✓" : "+")}`);
|
|
12374
12426
|
hooksSpinner?.stop(`Hooks ${parts.join(" ")}`);
|
|
12375
12427
|
} else {
|
|
12376
12428
|
const hookLine = HOOK_EVENTS2.map((e2) => {
|
|
@@ -12509,10 +12561,10 @@ async function resolveSessionToken(tmpDir = osTmpdir2()) {
|
|
|
12509
12561
|
if (timerId !== undefined)
|
|
12510
12562
|
clearTimeout(timerId);
|
|
12511
12563
|
if (race !== "timeout") {
|
|
12512
|
-
const
|
|
12513
|
-
if (
|
|
12514
|
-
await Bun.write(cacheFile,
|
|
12515
|
-
return
|
|
12564
|
+
const out2 = (await new Response(ps.stdout).text()).replace(/\D/g, "").trim();
|
|
12565
|
+
if (out2 && Number(out2) > 1) {
|
|
12566
|
+
await Bun.write(cacheFile, out2);
|
|
12567
|
+
return out2;
|
|
12516
12568
|
}
|
|
12517
12569
|
} else {
|
|
12518
12570
|
ps.kill();
|
|
@@ -12592,7 +12644,9 @@ async function sessionInitCommand(vaultRoot) {
|
|
|
12592
12644
|
|
|
12593
12645
|
// src/commands/internal/vault-sync.ts
|
|
12594
12646
|
init_dist2();
|
|
12647
|
+
init_cli_ui();
|
|
12595
12648
|
init_harness();
|
|
12649
|
+
var import_picocolors9 = __toESM(require_picocolors(), 1);
|
|
12596
12650
|
var import_yaml7 = __toESM(require_dist(), 1);
|
|
12597
12651
|
import {
|
|
12598
12652
|
mkdir as mkdir5,
|
|
@@ -12936,35 +12990,47 @@ async function runVaultSync2(vaultRoot, opts = {}) {
|
|
|
12936
12990
|
pinSkipped: true,
|
|
12937
12991
|
cacheRemoved: 0
|
|
12938
12992
|
};
|
|
12993
|
+
const embedded = opts.embedded ?? false;
|
|
12994
|
+
const createEmbeddedStep = embedded ? makeStepFn(true) : null;
|
|
12939
12995
|
let s = null;
|
|
12940
|
-
|
|
12996
|
+
let currentStep = null;
|
|
12997
|
+
function startSpinner(emoji, label) {
|
|
12941
12998
|
if (isTTY) {
|
|
12942
|
-
|
|
12943
|
-
|
|
12999
|
+
if (embedded) {
|
|
13000
|
+
currentStep = createEmbeddedStep(emoji, label);
|
|
13001
|
+
} else {
|
|
13002
|
+
s = L2();
|
|
13003
|
+
s.start(label);
|
|
13004
|
+
}
|
|
12944
13005
|
} else {
|
|
12945
|
-
process.stdout.write(`vault-sync: ${
|
|
13006
|
+
process.stdout.write(`vault-sync: ${label}
|
|
12946
13007
|
`);
|
|
12947
13008
|
}
|
|
12948
13009
|
}
|
|
12949
|
-
function stopSpinner(
|
|
12950
|
-
if (isTTY
|
|
12951
|
-
|
|
12952
|
-
|
|
13010
|
+
function stopSpinner(result2, details) {
|
|
13011
|
+
if (isTTY) {
|
|
13012
|
+
if (embedded) {
|
|
13013
|
+
currentStep?.stop(import_picocolors9.default.dim(result2), details);
|
|
13014
|
+
currentStep = null;
|
|
13015
|
+
} else if (s) {
|
|
13016
|
+
s.stop(result2);
|
|
13017
|
+
s = null;
|
|
13018
|
+
}
|
|
12953
13019
|
}
|
|
12954
13020
|
}
|
|
12955
|
-
if (isTTY) {
|
|
13021
|
+
if (isTTY && !embedded) {
|
|
12956
13022
|
we("OneBrain Vault Sync");
|
|
12957
13023
|
}
|
|
12958
13024
|
let tmpDir = null;
|
|
12959
13025
|
try {
|
|
12960
|
-
startSpinner("
|
|
13026
|
+
startSpinner("\uD83D\uDCE5", "Downloading");
|
|
12961
13027
|
let extractedDir;
|
|
12962
13028
|
try {
|
|
12963
13029
|
const dl = await downloadTarball2(branch, fetchFn);
|
|
12964
13030
|
tmpDir = dl.tmpDir;
|
|
12965
13031
|
extractedDir = await extractTarball2(dl.tarball, tmpDir);
|
|
12966
13032
|
} catch (err) {
|
|
12967
|
-
stopSpinner("
|
|
13033
|
+
stopSpinner("download failed");
|
|
12968
13034
|
const msg = err instanceof Error ? err.message : String(err);
|
|
12969
13035
|
result.error = msg;
|
|
12970
13036
|
process.stderr.write(`vault-sync: download failed: ${msg}
|
|
@@ -12979,13 +13045,13 @@ async function runVaultSync2(vaultRoot, opts = {}) {
|
|
|
12979
13045
|
}
|
|
12980
13046
|
} catch {}
|
|
12981
13047
|
stopSpinner(`kengio/onebrain@${branch} (v${result.version})`);
|
|
12982
|
-
startSpinner("Syncing
|
|
13048
|
+
startSpinner("\uD83D\uDCC2", "Syncing files");
|
|
12983
13049
|
try {
|
|
12984
13050
|
const { filesAdded, filesRemoved } = await syncPluginFiles2(extractedDir, vaultRoot, unlinkFn);
|
|
12985
13051
|
result.filesAdded = filesAdded;
|
|
12986
13052
|
result.filesRemoved = filesRemoved;
|
|
12987
13053
|
} catch (err) {
|
|
12988
|
-
stopSpinner("
|
|
13054
|
+
stopSpinner("plugin sync failed");
|
|
12989
13055
|
const msg = err instanceof Error ? err.message : String(err);
|
|
12990
13056
|
result.error = msg;
|
|
12991
13057
|
process.stderr.write(`vault-sync: plugin sync failed: ${msg}
|
|
@@ -13008,13 +13074,13 @@ async function runVaultSync2(vaultRoot, opts = {}) {
|
|
|
13008
13074
|
} catch {}
|
|
13009
13075
|
}
|
|
13010
13076
|
await copyRootDocs2(extractedDir, vaultRoot);
|
|
13011
|
-
startSpinner("Updating harness
|
|
13077
|
+
startSpinner("\uD83D\uDD27", "Updating harness");
|
|
13012
13078
|
let importsAdded = 0;
|
|
13013
13079
|
try {
|
|
13014
13080
|
importsAdded = await mergeHarnessFiles2(extractedDir, vaultRoot);
|
|
13015
13081
|
result.importsAdded = importsAdded;
|
|
13016
13082
|
} catch (err) {
|
|
13017
|
-
stopSpinner("
|
|
13083
|
+
stopSpinner("harness merge failed");
|
|
13018
13084
|
const msg = err instanceof Error ? err.message : String(err);
|
|
13019
13085
|
result.error = msg;
|
|
13020
13086
|
process.stderr.write(`vault-sync: harness merge failed: ${msg}
|
|
@@ -13036,7 +13102,7 @@ async function runVaultSync2(vaultRoot, opts = {}) {
|
|
|
13036
13102
|
return result;
|
|
13037
13103
|
}
|
|
13038
13104
|
if (harness === "claude") {
|
|
13039
|
-
startSpinner("Pinning to vault
|
|
13105
|
+
startSpinner("\uD83D\uDCCC", "Pinning to vault");
|
|
13040
13106
|
try {
|
|
13041
13107
|
const pinResult = await pinToVault2(vaultRoot, installedPluginsPath, installedPluginsCacheDir);
|
|
13042
13108
|
result.pinSkipped = pinResult.skipped;
|
|
@@ -13052,7 +13118,7 @@ async function runVaultSync2(vaultRoot, opts = {}) {
|
|
|
13052
13118
|
result.pinSkipped = true;
|
|
13053
13119
|
stopSpinner("pin skipped (error — non-fatal)");
|
|
13054
13120
|
}
|
|
13055
|
-
startSpinner("Cleaning cache
|
|
13121
|
+
startSpinner("\uD83E\uDDF9", "Cleaning cache");
|
|
13056
13122
|
try {
|
|
13057
13123
|
const cacheRemoved = await cleanPluginCache2(installedPluginsPath, installedPluginsCacheDir);
|
|
13058
13124
|
result.cacheRemoved = cacheRemoved;
|
|
@@ -13070,7 +13136,9 @@ async function runVaultSync2(vaultRoot, opts = {}) {
|
|
|
13070
13136
|
}
|
|
13071
13137
|
result.ok = true;
|
|
13072
13138
|
if (isTTY) {
|
|
13073
|
-
|
|
13139
|
+
if (!embedded) {
|
|
13140
|
+
fe(`Done — v${result.version} synced`);
|
|
13141
|
+
}
|
|
13074
13142
|
} else {
|
|
13075
13143
|
process.stdout.write(`vault-sync: done
|
|
13076
13144
|
`);
|
|
@@ -13090,9 +13158,8 @@ async function vaultSyncCommand2(vaultRoot, opts = {}) {
|
|
|
13090
13158
|
}
|
|
13091
13159
|
|
|
13092
13160
|
// src/commands/update.ts
|
|
13093
|
-
var
|
|
13094
|
-
|
|
13095
|
-
import { join as join13 } from "node:path";
|
|
13161
|
+
var import_picocolors10 = __toESM(require_picocolors(), 1);
|
|
13162
|
+
init_cli_ui();
|
|
13096
13163
|
var GITHUB_REPO = "https://api.github.com/repos/kengio/onebrain";
|
|
13097
13164
|
var GITHUB_RELEASES_URL = `${GITHUB_REPO}/releases/latest`;
|
|
13098
13165
|
async function fetchLatestRelease(fetchFn) {
|
|
@@ -13113,14 +13180,6 @@ async function fetchLatestRelease(fetchFn) {
|
|
|
13113
13180
|
function formatReleaseDate(date) {
|
|
13114
13181
|
return date.toLocaleDateString("en-GB", { day: "numeric", month: "short", year: "numeric" });
|
|
13115
13182
|
}
|
|
13116
|
-
function daysBehind(date) {
|
|
13117
|
-
const days = Math.floor((Date.now() - date.getTime()) / (1000 * 60 * 60 * 24));
|
|
13118
|
-
if (days <= 0)
|
|
13119
|
-
return "just released";
|
|
13120
|
-
if (days === 1)
|
|
13121
|
-
return "1 day behind";
|
|
13122
|
-
return `${days} days behind`;
|
|
13123
|
-
}
|
|
13124
13183
|
var _windowsShell;
|
|
13125
13184
|
function windowsShell() {
|
|
13126
13185
|
if (_windowsShell !== undefined)
|
|
@@ -13178,7 +13237,6 @@ async function defaultCurrentVersion() {
|
|
|
13178
13237
|
}
|
|
13179
13238
|
}
|
|
13180
13239
|
async function runUpdate(opts = {}) {
|
|
13181
|
-
const vaultDir = opts.vaultDir ?? process.cwd();
|
|
13182
13240
|
const isTTY = opts.isTTY ?? process.stdout.isTTY ?? false;
|
|
13183
13241
|
const check = opts.check ?? false;
|
|
13184
13242
|
const fetchFn = opts.fetchFn ?? globalThis.fetch;
|
|
@@ -13187,35 +13245,19 @@ async function runUpdate(opts = {}) {
|
|
|
13187
13245
|
const currentVersionFn = opts.currentVersionFn ?? defaultCurrentVersion;
|
|
13188
13246
|
const result = { ok: false, exitCode: 0 };
|
|
13189
13247
|
const createStep = makeStepFn(isTTY);
|
|
13190
|
-
const delay = opts.delayFn ?? ((ms) => new Promise((r2) => setTimeout(r2, ms)));
|
|
13191
|
-
const randDelay = () => isTTY ? delay(Math.floor(Math.random() * 1000) + 1000) : Promise.resolve();
|
|
13192
13248
|
if (isTTY) {
|
|
13193
13249
|
await printBanner();
|
|
13194
13250
|
} else {
|
|
13195
13251
|
writeLine("OneBrain Update");
|
|
13196
13252
|
}
|
|
13197
|
-
try {
|
|
13198
|
-
await access(join13(vaultDir, "vault.yml"));
|
|
13199
|
-
} catch {
|
|
13200
|
-
const msg = `vault.yml not found in ${vaultDir}. Run 'onebrain update' from inside an OneBrain vault.`;
|
|
13201
|
-
if (isTTY) {
|
|
13202
|
-
close(msg, true);
|
|
13203
|
-
} else {
|
|
13204
|
-
writeLine(`error: ${msg}`);
|
|
13205
|
-
}
|
|
13206
|
-
result.error = msg;
|
|
13207
|
-
result.exitCode = 1;
|
|
13208
|
-
return result;
|
|
13209
|
-
}
|
|
13210
13253
|
const sp1 = createStep("\uD83D\uDD0D", "Local version");
|
|
13211
13254
|
const { version: currentVersion, publishedAt: localPublishedAt } = await currentVersionFn();
|
|
13212
13255
|
result.currentVersion = currentVersion;
|
|
13213
|
-
|
|
13214
|
-
const localVersionLabel = localPublishedAt ? `${import_picocolors8.default.dim(currentVersion)} ${import_picocolors8.default.dim("·")} ${import_picocolors8.default.dim(formatReleaseDate(localPublishedAt))}` : import_picocolors8.default.dim(currentVersion);
|
|
13256
|
+
const localVersionLabel = localPublishedAt ? `${import_picocolors10.default.dim(currentVersion)} ${import_picocolors10.default.dim("·")} ${import_picocolors10.default.dim(formatReleaseDate(localPublishedAt))}` : import_picocolors10.default.dim(currentVersion);
|
|
13215
13257
|
if (sp1)
|
|
13216
13258
|
sp1.stop(localVersionLabel);
|
|
13217
13259
|
else
|
|
13218
|
-
writeLine(`current: ${currentVersion}
|
|
13260
|
+
writeLine(`current: ${currentVersion}`);
|
|
13219
13261
|
const sp2 = createStep("\uD83C\uDF10", "Remote version");
|
|
13220
13262
|
let latestVersion;
|
|
13221
13263
|
let publishedAt = null;
|
|
@@ -13223,14 +13265,11 @@ async function runUpdate(opts = {}) {
|
|
|
13223
13265
|
const release = await fetchLatestRelease(fetchFn);
|
|
13224
13266
|
latestVersion = release.version;
|
|
13225
13267
|
publishedAt = release.publishedAt;
|
|
13226
|
-
|
|
13227
|
-
const isOutdated = latestVersion !== currentVersion;
|
|
13228
|
-
const behindSuffix = isOutdated && publishedAt ? ` ${import_picocolors8.default.dim("·")} ${import_picocolors8.default.dim(daysBehind(publishedAt))}` : "";
|
|
13229
|
-
const dateSuffix = publishedAt ? ` ${import_picocolors8.default.dim("·")} ${import_picocolors8.default.dim(formatReleaseDate(publishedAt))}${behindSuffix}` : "";
|
|
13268
|
+
const dateSuffix = publishedAt ? ` ${import_picocolors10.default.dim("·")} ${import_picocolors10.default.dim(formatReleaseDate(publishedAt))}` : "";
|
|
13230
13269
|
if (sp2)
|
|
13231
|
-
sp2.stop(`${
|
|
13270
|
+
sp2.stop(`${import_picocolors10.default.green(latestVersion)}${dateSuffix}`);
|
|
13232
13271
|
else
|
|
13233
|
-
writeLine(`latest: ${latestVersion}
|
|
13272
|
+
writeLine(`latest: ${latestVersion}`);
|
|
13234
13273
|
} catch (err) {
|
|
13235
13274
|
const msg = err instanceof Error ? err.message : String(err);
|
|
13236
13275
|
if (sp2)
|
|
@@ -13249,7 +13288,7 @@ async function runUpdate(opts = {}) {
|
|
|
13249
13288
|
if (check) {
|
|
13250
13289
|
if (isTTY) {
|
|
13251
13290
|
if (currentVersion !== latestVersion) {
|
|
13252
|
-
barLine(`⬆️ ${
|
|
13291
|
+
barLine(`⬆️ ${import_picocolors10.default.dim(currentVersion)} → ${import_picocolors10.default.green(latestVersion)} · binary would upgrade`);
|
|
13253
13292
|
barBlank();
|
|
13254
13293
|
}
|
|
13255
13294
|
close("Dry run complete — no changes made");
|
|
@@ -13262,11 +13301,9 @@ async function runUpdate(opts = {}) {
|
|
|
13262
13301
|
}
|
|
13263
13302
|
if (latestVersion === currentVersion) {
|
|
13264
13303
|
if (isTTY) {
|
|
13265
|
-
|
|
13266
|
-
close(`Already up to date — @onebrain-ai/cli ${import_picocolors8.default.dim(latestVersion)}${import_picocolors8.default.dim(dateSuffix)}`);
|
|
13304
|
+
close(`Already up to date — @onebrain-ai/cli ${import_picocolors10.default.dim(latestVersion)}`);
|
|
13267
13305
|
} else {
|
|
13268
|
-
|
|
13269
|
-
writeLine(`already up to date: @onebrain-ai/cli ${latestVersion}${dateSuffix}`);
|
|
13306
|
+
writeLine(`already up to date: @onebrain-ai/cli ${latestVersion}`);
|
|
13270
13307
|
writeLine("done: nothing to do");
|
|
13271
13308
|
}
|
|
13272
13309
|
result.ok = true;
|
|
@@ -13274,15 +13311,14 @@ async function runUpdate(opts = {}) {
|
|
|
13274
13311
|
return result;
|
|
13275
13312
|
}
|
|
13276
13313
|
if (isTTY) {
|
|
13277
|
-
barLine(`⬆️ ${
|
|
13314
|
+
barLine(`⬆️ ${import_picocolors10.default.dim(currentVersion)} → ${import_picocolors10.default.green(latestVersion)}`);
|
|
13278
13315
|
barBlank();
|
|
13279
13316
|
}
|
|
13280
13317
|
const sp3 = createStep("\uD83D\uDCE6", "Installing @onebrain-ai/cli");
|
|
13281
13318
|
try {
|
|
13282
13319
|
await installBinaryFn(latestVersion);
|
|
13283
|
-
await randDelay();
|
|
13284
13320
|
if (sp3)
|
|
13285
|
-
sp3.stop(
|
|
13321
|
+
sp3.stop(import_picocolors10.default.green(latestVersion));
|
|
13286
13322
|
else
|
|
13287
13323
|
writeLine(`upgrading: @onebrain-ai/cli ${latestVersion} installed`);
|
|
13288
13324
|
} catch (err) {
|
|
@@ -13301,7 +13337,6 @@ async function runUpdate(opts = {}) {
|
|
|
13301
13337
|
}
|
|
13302
13338
|
const sp4 = createStep("✅", "Validating binary");
|
|
13303
13339
|
const binaryValid = await validateBinaryFn();
|
|
13304
|
-
await randDelay();
|
|
13305
13340
|
if (!binaryValid) {
|
|
13306
13341
|
if (sp4)
|
|
13307
13342
|
sp4.stop("failed");
|
|
@@ -13320,7 +13355,7 @@ async function runUpdate(opts = {}) {
|
|
|
13320
13355
|
result.ok = true;
|
|
13321
13356
|
result.exitCode = 0;
|
|
13322
13357
|
if (isTTY) {
|
|
13323
|
-
close(`Done — run ${
|
|
13358
|
+
close(`Done — run ${import_picocolors10.default.cyan("/update")} in Claude to sync vault files`);
|
|
13324
13359
|
} else {
|
|
13325
13360
|
writeLine("done: run /update in Claude to sync vault files");
|
|
13326
13361
|
}
|
|
@@ -13333,11 +13368,24 @@ async function updateCommand(opts = {}) {
|
|
|
13333
13368
|
}
|
|
13334
13369
|
}
|
|
13335
13370
|
|
|
13371
|
+
// src/lib/patch-utf8.ts
|
|
13372
|
+
function patchUtf8(stream) {
|
|
13373
|
+
const orig = stream.write.bind(stream);
|
|
13374
|
+
stream.write = (chunk, encodingOrCb, cb) => {
|
|
13375
|
+
const buf = typeof chunk === "string" ? Buffer.from(chunk, "utf8") : chunk;
|
|
13376
|
+
if (typeof encodingOrCb === "function")
|
|
13377
|
+
return orig(buf, encodingOrCb);
|
|
13378
|
+
if (cb !== undefined)
|
|
13379
|
+
return orig(buf, cb);
|
|
13380
|
+
return orig(buf);
|
|
13381
|
+
};
|
|
13382
|
+
}
|
|
13383
|
+
|
|
13336
13384
|
// src/index.ts
|
|
13337
|
-
var VERSION = "2.1.
|
|
13385
|
+
var VERSION = "2.1.2";
|
|
13338
13386
|
var RELEASE_DATE = "2026-04-28";
|
|
13339
|
-
process.stdout
|
|
13340
|
-
process.stderr
|
|
13387
|
+
patchUtf8(process.stdout);
|
|
13388
|
+
patchUtf8(process.stderr);
|
|
13341
13389
|
var VERSION_STRING = `OneBrain v${VERSION} \u2014 released ${RELEASE_DATE}`;
|
|
13342
13390
|
if (process.argv.slice(2).length === 0) {
|
|
13343
13391
|
console.log(VERSION_STRING);
|
|
@@ -13349,7 +13397,7 @@ function findVaultRoot(startDir) {
|
|
|
13349
13397
|
return process.cwd();
|
|
13350
13398
|
let dir = startDir;
|
|
13351
13399
|
while (true) {
|
|
13352
|
-
if (existsSync(
|
|
13400
|
+
if (existsSync(join13(dir, "vault.yml")))
|
|
13353
13401
|
return dir;
|
|
13354
13402
|
const parent = dirname6(dir);
|
|
13355
13403
|
if (parent === dir)
|
|
@@ -13365,11 +13413,9 @@ program2.command("init").description("Initialize a new OneBrain vault").option("
|
|
|
13365
13413
|
...opts.force !== undefined ? { force: opts.force } : {}
|
|
13366
13414
|
});
|
|
13367
13415
|
});
|
|
13368
|
-
program2.command("update").description("Update
|
|
13416
|
+
program2.command("update").description("Update @onebrain-ai/cli to the latest version").option("--check", "show what would change and exit without making changes").action(async (opts) => {
|
|
13369
13417
|
await updateCommand({
|
|
13370
|
-
|
|
13371
|
-
...opts.check !== undefined ? { check: opts.check } : {},
|
|
13372
|
-
...opts.channel !== undefined ? { channel: opts.channel } : {}
|
|
13418
|
+
...opts.check !== undefined ? { check: opts.check } : {}
|
|
13373
13419
|
});
|
|
13374
13420
|
});
|
|
13375
13421
|
program2.command("doctor").description("Run vault health checks and report issues").option("--fix", "auto-fix detected issues").action(async (opts) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onebrain-ai/cli",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.2",
|
|
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",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
"files": ["dist/onebrain"],
|
|
30
30
|
"scripts": {
|
|
31
|
-
"build": "bun build src/index.ts --outfile dist/onebrain --target
|
|
31
|
+
"build": "bun build src/index.ts --outfile dist/onebrain --target bun",
|
|
32
32
|
"test": "bun test --pass-with-no-tests src/",
|
|
33
33
|
"typecheck": "tsc --noEmit"
|
|
34
34
|
},
|