@onebrain-ai/cli 2.3.2 → 2.3.3
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 +194 -59
- package/package.json +1 -1
package/dist/onebrain
CHANGED
|
@@ -9590,7 +9590,7 @@ var init_lib = __esm(() => {
|
|
|
9590
9590
|
var require_package = __commonJS((exports, module) => {
|
|
9591
9591
|
module.exports = {
|
|
9592
9592
|
name: "@onebrain-ai/cli",
|
|
9593
|
-
version: "2.3.
|
|
9593
|
+
version: "2.3.3",
|
|
9594
9594
|
description: "CLI for OneBrain \u2014 personal AI OS for Obsidian with persistent memory, 24+ skills, and Claude Code integration",
|
|
9595
9595
|
keywords: [
|
|
9596
9596
|
"onebrain",
|
|
@@ -11050,9 +11050,90 @@ var init_vault_sync = __esm(() => {
|
|
|
11050
11050
|
import_yaml3 = __toESM(require_dist(), 1);
|
|
11051
11051
|
});
|
|
11052
11052
|
|
|
11053
|
+
// src/commands/run-skill.ts
|
|
11054
|
+
var exports_run_skill = {};
|
|
11055
|
+
__export(exports_run_skill, {
|
|
11056
|
+
runSkillCommand: () => runSkillCommand,
|
|
11057
|
+
buildPrompt: () => buildPrompt
|
|
11058
|
+
});
|
|
11059
|
+
import { spawn } from "child_process";
|
|
11060
|
+
import { existsSync } from "fs";
|
|
11061
|
+
import { constants as osConstants } from "os";
|
|
11062
|
+
import { join as join11 } from "path";
|
|
11063
|
+
function resolveClaudeBin(override) {
|
|
11064
|
+
if (override)
|
|
11065
|
+
return override;
|
|
11066
|
+
const fromEnv = process.env["CLAUDE_BIN"];
|
|
11067
|
+
if (fromEnv) {
|
|
11068
|
+
if (existsSync(fromEnv))
|
|
11069
|
+
return fromEnv;
|
|
11070
|
+
console.error(import_picocolors8.default.yellow(`CLAUDE_BIN points to a missing file: ${fromEnv} \u2014 ignoring and probing defaults`));
|
|
11071
|
+
}
|
|
11072
|
+
for (const candidate of CLAUDE_FALLBACK_PATHS) {
|
|
11073
|
+
if (existsSync(candidate))
|
|
11074
|
+
return candidate;
|
|
11075
|
+
}
|
|
11076
|
+
return "claude";
|
|
11077
|
+
}
|
|
11078
|
+
function buildPrompt(skill, args) {
|
|
11079
|
+
const bare = skill.replace(/^\//, "");
|
|
11080
|
+
if (!bare) {
|
|
11081
|
+
throw new Error('skill name must not be empty (got "/" or "")');
|
|
11082
|
+
}
|
|
11083
|
+
const namespaced = bare.includes(":") ? bare : `onebrain:${bare}`;
|
|
11084
|
+
const slash = `/${namespaced}`;
|
|
11085
|
+
if (!args)
|
|
11086
|
+
return slash;
|
|
11087
|
+
const tokens = Object.entries(args).map(([k2, v2]) => `${k2}=${v2}`);
|
|
11088
|
+
return tokens.length ? `${slash} ${tokens.join(" ")}` : slash;
|
|
11089
|
+
}
|
|
11090
|
+
async function runSkillCommand(opts) {
|
|
11091
|
+
const vault = opts.vault;
|
|
11092
|
+
if (!existsSync(join11(vault, "vault.yml"))) {
|
|
11093
|
+
console.error(import_picocolors8.default.red(`Vault not found at ${vault} (no vault.yml present)`));
|
|
11094
|
+
return 78;
|
|
11095
|
+
}
|
|
11096
|
+
const claudeBin = resolveClaudeBin(opts.claudeBin);
|
|
11097
|
+
const prompt = buildPrompt(opts.skill, opts.args);
|
|
11098
|
+
const spawnFn = opts.spawnFn ?? spawn;
|
|
11099
|
+
const spawnOpts = {
|
|
11100
|
+
cwd: vault,
|
|
11101
|
+
stdio: "inherit"
|
|
11102
|
+
};
|
|
11103
|
+
const child = spawnFn(claudeBin, ["-p", prompt, "--add-dir", vault], spawnOpts);
|
|
11104
|
+
return await new Promise((resolve) => {
|
|
11105
|
+
child.on("exit", (code, signal) => {
|
|
11106
|
+
if (signal) {
|
|
11107
|
+
console.error(import_picocolors8.default.red(`claude terminated by signal: ${signal}`));
|
|
11108
|
+
resolve(128 + signalNumber(signal));
|
|
11109
|
+
return;
|
|
11110
|
+
}
|
|
11111
|
+
resolve(code ?? 1);
|
|
11112
|
+
});
|
|
11113
|
+
child.on("error", (err) => {
|
|
11114
|
+
console.error(import_picocolors8.default.red(`Failed to spawn claude (${claudeBin}): ${err.message}`));
|
|
11115
|
+
resolve(127);
|
|
11116
|
+
});
|
|
11117
|
+
});
|
|
11118
|
+
}
|
|
11119
|
+
function signalNumber(signal) {
|
|
11120
|
+
const sigs = osConstants.signals;
|
|
11121
|
+
return sigs[signal] ?? 0;
|
|
11122
|
+
}
|
|
11123
|
+
var import_picocolors8, HOME, CLAUDE_FALLBACK_PATHS;
|
|
11124
|
+
var init_run_skill = __esm(() => {
|
|
11125
|
+
import_picocolors8 = __toESM(require_picocolors(), 1);
|
|
11126
|
+
HOME = process.env["HOME"] ?? "";
|
|
11127
|
+
CLAUDE_FALLBACK_PATHS = [
|
|
11128
|
+
...HOME ? [join11(HOME, ".local/bin/claude")] : [],
|
|
11129
|
+
"/opt/homebrew/bin/claude",
|
|
11130
|
+
"/usr/local/bin/claude"
|
|
11131
|
+
];
|
|
11132
|
+
});
|
|
11133
|
+
|
|
11053
11134
|
// src/index.ts
|
|
11054
|
-
import { existsSync as
|
|
11055
|
-
import { dirname as dirname4, join as
|
|
11135
|
+
import { existsSync as existsSync3 } from "fs";
|
|
11136
|
+
import { dirname as dirname4, join as join13 } from "path";
|
|
11056
11137
|
|
|
11057
11138
|
// node_modules/commander/esm.mjs
|
|
11058
11139
|
var import__ = __toESM(require_commander(), 1);
|
|
@@ -11078,7 +11159,7 @@ var import_picocolors5 = __toESM(require_picocolors(), 1);
|
|
|
11078
11159
|
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
11079
11160
|
function resolveBinaryVersion() {
|
|
11080
11161
|
if (true)
|
|
11081
|
-
return "2.3.
|
|
11162
|
+
return "2.3.3";
|
|
11082
11163
|
try {
|
|
11083
11164
|
const pkg = require_package();
|
|
11084
11165
|
return pkg.version ?? "dev";
|
|
@@ -13152,12 +13233,13 @@ async function sessionInitCommand(vaultRoot) {
|
|
|
13152
13233
|
init_vault_sync();
|
|
13153
13234
|
|
|
13154
13235
|
// src/commands/register-schedule.ts
|
|
13155
|
-
var
|
|
13236
|
+
var import_picocolors9 = __toESM(require_picocolors(), 1);
|
|
13156
13237
|
var import_yaml7 = __toESM(require_dist(), 1);
|
|
13157
|
-
import {
|
|
13238
|
+
import { execFileSync } from "child_process";
|
|
13239
|
+
import { existsSync as existsSync2 } from "fs";
|
|
13158
13240
|
import { readFile as readFile6, unlink as unlink4, writeFile as writeFile6 } from "fs/promises";
|
|
13159
13241
|
import { homedir as homedir4 } from "os";
|
|
13160
|
-
import { join as
|
|
13242
|
+
import { isAbsolute, join as join12, resolve as pathResolve } from "path";
|
|
13161
13243
|
|
|
13162
13244
|
// src/lib/scheduler/cron-parse.ts
|
|
13163
13245
|
var CRON_FIELD_RE = /^(\*|\d+)$/;
|
|
@@ -13276,9 +13358,10 @@ function validateEntry(entry) {
|
|
|
13276
13358
|
}
|
|
13277
13359
|
|
|
13278
13360
|
// src/lib/scheduler/launchd.ts
|
|
13361
|
+
import { basename } from "path";
|
|
13279
13362
|
var xmlEscape = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
13280
13363
|
function labelForEntry(entry) {
|
|
13281
|
-
const raw = isCommandMode(entry) ? entry.command : (entry.skill ?? "").replace(/^\//, "");
|
|
13364
|
+
const raw = isCommandMode(entry) ? basename(entry.command) : (entry.skill ?? "").replace(/^\//, "");
|
|
13282
13365
|
return raw.replace(/[^a-zA-Z0-9-]/g, "-");
|
|
13283
13366
|
}
|
|
13284
13367
|
function generatePlist(entry, ctx) {
|
|
@@ -13300,9 +13383,9 @@ function generatePlist(entry, ctx) {
|
|
|
13300
13383
|
<string>-c</string>
|
|
13301
13384
|
<string>${shellLine}</string>`;
|
|
13302
13385
|
} else {
|
|
13303
|
-
const plistFilePath =
|
|
13304
|
-
const argsFlags = entry.args ? ` ${Object.entries(entry.args).map(([k2, v2]) =>
|
|
13305
|
-
const shellLine = xmlEscape(`"${ctx.skillCliPath}" --vault="${ctx.vaultPath}" --skill="${entry.skill}"
|
|
13386
|
+
const plistFilePath = `${ctx.homedir}/Library/LaunchAgents/${label}.plist`;
|
|
13387
|
+
const argsFlags = entry.args ? ` ${Object.entries(entry.args).map(([k2, v2]) => `--arg="${k2}=${v2}"`).join(" ")}` : "";
|
|
13388
|
+
const shellLine = xmlEscape(`"${ctx.skillCliPath}" run-skill --vault="${ctx.vaultPath}" --skill="${entry.skill}"${argsFlags}; launchctl bootout gui/${ctx.uid}/${label}; rm -f "${plistFilePath}"`);
|
|
13306
13389
|
programArgumentsBlock = ` <string>/bin/sh</string>
|
|
13307
13390
|
<string>-c</string>
|
|
13308
13391
|
<string>${shellLine}</string>`;
|
|
@@ -13316,14 +13399,17 @@ function generatePlist(entry, ctx) {
|
|
|
13316
13399
|
`);
|
|
13317
13400
|
} else {
|
|
13318
13401
|
const argsBlock = entry.args ? `
|
|
13319
|
-
${Object.entries(entry.args).
|
|
13402
|
+
${Object.entries(entry.args).flatMap(([k2, v2]) => [
|
|
13403
|
+
" <string>--arg</string>",
|
|
13404
|
+
` <string>${xmlEscape(`${k2}=${v2}`)}</string>`
|
|
13405
|
+
]).join(`
|
|
13320
13406
|
`)}` : "";
|
|
13321
13407
|
programArgumentsBlock = ` <string>${xmlEscape(ctx.skillCliPath)}</string>
|
|
13408
|
+
<string>run-skill</string>
|
|
13322
13409
|
<string>--vault</string>
|
|
13323
13410
|
<string>${xmlEscape(ctx.vaultPath)}</string>
|
|
13324
13411
|
<string>--skill</string>
|
|
13325
|
-
<string>${xmlEscape(entry.skill ?? "")}</string
|
|
13326
|
-
<string>--headless</string>${argsBlock}`;
|
|
13412
|
+
<string>${xmlEscape(entry.skill ?? "")}</string>${argsBlock}`;
|
|
13327
13413
|
}
|
|
13328
13414
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
13329
13415
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
@@ -13364,12 +13450,12 @@ async function registerSchedule(opts) {
|
|
|
13364
13450
|
if (opts.resume)
|
|
13365
13451
|
return await resumeSkill(opts.vault, opts.resume);
|
|
13366
13452
|
if (opts.refresh) {
|
|
13367
|
-
console.log(
|
|
13453
|
+
console.log(import_picocolors9.default.dim("(--refresh: re-emitting plists with current vault path)"));
|
|
13368
13454
|
}
|
|
13369
13455
|
const config = await readVaultConfig(opts.vault);
|
|
13370
13456
|
const entries = config.schedule ?? [];
|
|
13371
13457
|
if (entries.length === 0) {
|
|
13372
|
-
console.log(
|
|
13458
|
+
console.log(import_picocolors9.default.yellow("No schedule entries in vault.yml. Nothing to register."));
|
|
13373
13459
|
return;
|
|
13374
13460
|
}
|
|
13375
13461
|
for (const entry of entries) {
|
|
@@ -13390,16 +13476,17 @@ async function registerSchedule(opts) {
|
|
|
13390
13476
|
await validateSchedulable(opts.vault, entry);
|
|
13391
13477
|
}
|
|
13392
13478
|
}
|
|
13479
|
+
const resolvedEntries = entries.map((entry) => isCommandMode(entry) ? { ...entry, command: resolveCommandBinary(entry.command, opts.vault) } : entry);
|
|
13393
13480
|
const skillCliPath = process.argv[1] ?? "onebrain";
|
|
13394
13481
|
const ctx = {
|
|
13395
13482
|
vaultPath: opts.vault,
|
|
13396
13483
|
skillCliPath,
|
|
13397
|
-
logBasePath:
|
|
13484
|
+
logBasePath: join12(opts.vault, "07-logs/scheduler"),
|
|
13398
13485
|
uid: process.getuid?.() ?? 501,
|
|
13399
13486
|
homedir: homedir4()
|
|
13400
13487
|
};
|
|
13401
13488
|
const seen = new Map;
|
|
13402
|
-
for (const entry of
|
|
13489
|
+
for (const entry of resolvedEntries) {
|
|
13403
13490
|
const target = plistPath(labelForEntry(entry), ctx.homedir);
|
|
13404
13491
|
if (seen.has(target)) {
|
|
13405
13492
|
const existing = seen.get(target);
|
|
@@ -13411,28 +13498,28 @@ async function registerSchedule(opts) {
|
|
|
13411
13498
|
}
|
|
13412
13499
|
seen.set(target, entry);
|
|
13413
13500
|
}
|
|
13414
|
-
for (const entry of
|
|
13501
|
+
for (const entry of resolvedEntries) {
|
|
13415
13502
|
const plistContent = generatePlist(entry, ctx);
|
|
13416
13503
|
const targetPath = plistPath(labelForEntry(entry), ctx.homedir);
|
|
13417
13504
|
if (opts.dryRun) {
|
|
13418
|
-
console.log(
|
|
13505
|
+
console.log(import_picocolors9.default.cyan(`--- ${targetPath} ---`));
|
|
13419
13506
|
console.log(plistContent);
|
|
13420
13507
|
continue;
|
|
13421
13508
|
}
|
|
13422
13509
|
await writeFile6(targetPath, plistContent, "utf8");
|
|
13423
|
-
console.log(
|
|
13510
|
+
console.log(import_picocolors9.default.green(`\u2713 Wrote ${targetPath}`));
|
|
13424
13511
|
}
|
|
13425
|
-
console.log(
|
|
13512
|
+
console.log(import_picocolors9.default.green(`
|
|
13426
13513
|
Registered ${entries.length} schedule entries.`));
|
|
13427
|
-
console.log(
|
|
13428
|
-
for (const entry of
|
|
13514
|
+
console.log(import_picocolors9.default.dim("Use launchctl to load (or restart launchd):"));
|
|
13515
|
+
for (const entry of resolvedEntries) {
|
|
13429
13516
|
const target = plistPath(labelForEntry(entry), ctx.homedir);
|
|
13430
|
-
console.log(
|
|
13517
|
+
console.log(import_picocolors9.default.dim(` launchctl load ${target}`));
|
|
13431
13518
|
}
|
|
13432
13519
|
}
|
|
13433
13520
|
async function readVaultConfig(vault) {
|
|
13434
|
-
const yamlPath =
|
|
13435
|
-
if (!
|
|
13521
|
+
const yamlPath = join12(vault, "vault.yml");
|
|
13522
|
+
if (!existsSync2(yamlPath))
|
|
13436
13523
|
return {};
|
|
13437
13524
|
const raw = await readFile6(yamlPath, "utf8");
|
|
13438
13525
|
return import_yaml7.parse(raw) ?? {};
|
|
@@ -13450,8 +13537,8 @@ async function validateSchedulable(vault, entry) {
|
|
|
13450
13537
|
throw new Error("validateSchedulable invoked on non-skill entry \u2014 caller bug");
|
|
13451
13538
|
}
|
|
13452
13539
|
const skillName = entry.skill.replace(/^\//, "");
|
|
13453
|
-
const skillPath =
|
|
13454
|
-
if (!
|
|
13540
|
+
const skillPath = join12(vault, ".claude/plugins/onebrain/skills", skillName, "SKILL.md");
|
|
13541
|
+
if (!existsSync2(skillPath)) {
|
|
13455
13542
|
throw new Error(`Skill ${entry.skill} not found at ${skillPath}`);
|
|
13456
13543
|
}
|
|
13457
13544
|
const raw = await readFile6(skillPath, "utf8");
|
|
@@ -13486,55 +13573,85 @@ async function removeAll(vault) {
|
|
|
13486
13573
|
const entries = config.schedule ?? [];
|
|
13487
13574
|
for (const entry of entries) {
|
|
13488
13575
|
const target = plistPath(labelForEntry(entry), homedir4());
|
|
13489
|
-
if (
|
|
13576
|
+
if (existsSync2(target)) {
|
|
13490
13577
|
await unlink4(target);
|
|
13491
|
-
console.log(
|
|
13578
|
+
console.log(import_picocolors9.default.green(`\u2713 Removed ${target}`));
|
|
13492
13579
|
}
|
|
13493
13580
|
}
|
|
13494
13581
|
}
|
|
13495
13582
|
async function printStatus(vault) {
|
|
13496
13583
|
const config = await readVaultConfig(vault);
|
|
13497
13584
|
const entries = config.schedule ?? [];
|
|
13498
|
-
console.log(
|
|
13585
|
+
console.log(import_picocolors9.default.cyan(`Registered schedules: ${entries.length}`));
|
|
13499
13586
|
for (const entry of entries) {
|
|
13500
13587
|
const target = plistPath(labelForEntry(entry), homedir4());
|
|
13501
|
-
const installed =
|
|
13588
|
+
const installed = existsSync2(target) ? "\u2713" : "\u2717";
|
|
13502
13589
|
const when = entry.at ?? entry.cron ?? "?";
|
|
13503
|
-
const tag = entry.at ?
|
|
13590
|
+
const tag = entry.at ? import_picocolors9.default.magenta("[once]") : import_picocolors9.default.dim("[cron]");
|
|
13504
13591
|
let targetLabel;
|
|
13505
13592
|
if (isCommandMode(entry)) {
|
|
13506
13593
|
const argv = entry.args ?? [];
|
|
13507
13594
|
const argStr = argv.length ? ` ${argv.join(" ")}` : "";
|
|
13508
|
-
targetLabel = `${
|
|
13595
|
+
targetLabel = `${import_picocolors9.default.yellow("cmd:")} ${entry.command}${argStr}`;
|
|
13509
13596
|
} else {
|
|
13510
13597
|
const argsMap = entry.args ?? {};
|
|
13511
13598
|
const argStr = Object.keys(argsMap).length ? ` (${Object.entries(argsMap).map(([k2, v2]) => `${k2}=${v2}`).join(", ")})` : "";
|
|
13512
|
-
targetLabel = `${
|
|
13599
|
+
targetLabel = `${import_picocolors9.default.green("skill:")} ${entry.skill}${argStr}`;
|
|
13513
13600
|
}
|
|
13514
13601
|
console.log(` ${installed} ${tag} ${when} ${targetLabel}`);
|
|
13515
13602
|
}
|
|
13516
13603
|
}
|
|
13517
13604
|
async function testRun(vault, skill) {
|
|
13518
|
-
console.log(
|
|
13519
|
-
console.log(
|
|
13520
|
-
const {
|
|
13521
|
-
const
|
|
13522
|
-
|
|
13523
|
-
|
|
13524
|
-
|
|
13605
|
+
console.log(import_picocolors9.default.cyan(`Testing scheduled invocation of ${skill}...`));
|
|
13606
|
+
console.log(import_picocolors9.default.dim("(Spawns `onebrain run-skill` which shells out to Claude Code.)"));
|
|
13607
|
+
const { runSkillCommand: runSkillCommand2 } = await Promise.resolve().then(() => (init_run_skill(), exports_run_skill));
|
|
13608
|
+
const code = await runSkillCommand2({ vault, skill });
|
|
13609
|
+
if (code !== 0) {
|
|
13610
|
+
console.error(import_picocolors9.default.red(`Test run exited with code ${code}`));
|
|
13611
|
+
process.exit(code);
|
|
13612
|
+
}
|
|
13613
|
+
}
|
|
13614
|
+
var WHICH_BIN = "/usr/bin/which";
|
|
13615
|
+
function resolveCommandBinary(name, vaultRoot) {
|
|
13616
|
+
if (isAbsolute(name)) {
|
|
13617
|
+
if (!existsSync2(name)) {
|
|
13618
|
+
throw new Error(`Command not found at absolute path: ${name}. Check the path in vault.yml \u2014 launchd will silently fail at run time if the binary is missing.`);
|
|
13619
|
+
}
|
|
13620
|
+
return name;
|
|
13621
|
+
}
|
|
13622
|
+
if (name.startsWith("./") || name.startsWith("../")) {
|
|
13623
|
+
const base = vaultRoot ?? process.cwd();
|
|
13624
|
+
const resolved = pathResolve(base, name);
|
|
13625
|
+
if (!existsSync2(resolved)) {
|
|
13626
|
+
throw new Error(`Command not found at relative path: ${name} (resolved: ${resolved})`);
|
|
13627
|
+
}
|
|
13628
|
+
return resolved;
|
|
13629
|
+
}
|
|
13630
|
+
try {
|
|
13631
|
+
const out2 = execFileSync(WHICH_BIN, [name], {
|
|
13632
|
+
encoding: "utf8",
|
|
13633
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
13634
|
+
}).trim();
|
|
13635
|
+
if (out2 && existsSync2(out2))
|
|
13636
|
+
return out2;
|
|
13637
|
+
} catch {}
|
|
13638
|
+
throw new Error(`Command "${name}" not found in PATH. Use an absolute path in vault.yml (launchd's PATH is restricted to /usr/bin:/bin:/usr/sbin:/sbin and won't find ${name}).`);
|
|
13525
13639
|
}
|
|
13526
13640
|
async function resumeSkill(vault, skill) {
|
|
13527
|
-
const marker =
|
|
13528
|
-
if (
|
|
13641
|
+
const marker = join12(vault, "07-logs/scheduler/.paused", `${skill.replace(/^\//, "")}.txt`);
|
|
13642
|
+
if (existsSync2(marker)) {
|
|
13529
13643
|
await unlink4(marker);
|
|
13530
|
-
console.log(
|
|
13644
|
+
console.log(import_picocolors9.default.green(`\u2713 Resumed ${skill}`));
|
|
13531
13645
|
} else {
|
|
13532
|
-
console.log(
|
|
13646
|
+
console.log(import_picocolors9.default.yellow(`${skill} is not paused.`));
|
|
13533
13647
|
}
|
|
13534
13648
|
}
|
|
13535
13649
|
|
|
13650
|
+
// src/index.ts
|
|
13651
|
+
init_run_skill();
|
|
13652
|
+
|
|
13536
13653
|
// src/commands/update.ts
|
|
13537
|
-
var
|
|
13654
|
+
var import_picocolors10 = __toESM(require_picocolors(), 1);
|
|
13538
13655
|
init_cli_ui();
|
|
13539
13656
|
var GITHUB_REPO = "https://api.github.com/repos/onebrain-ai/onebrain";
|
|
13540
13657
|
var GITHUB_RELEASES_URL = `${GITHUB_REPO}/releases/latest`;
|
|
@@ -13629,7 +13746,7 @@ async function runUpdate(opts = {}) {
|
|
|
13629
13746
|
const sp1 = createStep("\uD83D\uDD0D", "Local version");
|
|
13630
13747
|
const { version: currentVersion, publishedAt: localPublishedAt } = await currentVersionFn();
|
|
13631
13748
|
result.currentVersion = currentVersion;
|
|
13632
|
-
const localVersionLabel = localPublishedAt ? `${
|
|
13749
|
+
const localVersionLabel = localPublishedAt ? `${import_picocolors10.default.dim(currentVersion)} ${import_picocolors10.default.dim("\xB7")} ${import_picocolors10.default.dim(formatReleaseDate(localPublishedAt))}` : import_picocolors10.default.dim(currentVersion);
|
|
13633
13750
|
if (sp1)
|
|
13634
13751
|
sp1.stop(localVersionLabel);
|
|
13635
13752
|
else
|
|
@@ -13641,9 +13758,9 @@ async function runUpdate(opts = {}) {
|
|
|
13641
13758
|
const release = await fetchLatestRelease(fetchFn);
|
|
13642
13759
|
latestVersion = release.version;
|
|
13643
13760
|
publishedAt = release.publishedAt;
|
|
13644
|
-
const dateSuffix = publishedAt ? ` ${
|
|
13761
|
+
const dateSuffix = publishedAt ? ` ${import_picocolors10.default.dim("\xB7")} ${import_picocolors10.default.dim(formatReleaseDate(publishedAt))}` : "";
|
|
13645
13762
|
if (sp2)
|
|
13646
|
-
sp2.stop(`${
|
|
13763
|
+
sp2.stop(`${import_picocolors10.default.green(latestVersion)}${dateSuffix}`);
|
|
13647
13764
|
else
|
|
13648
13765
|
writeLine(`latest: ${latestVersion}`);
|
|
13649
13766
|
} catch (err) {
|
|
@@ -13664,7 +13781,7 @@ async function runUpdate(opts = {}) {
|
|
|
13664
13781
|
if (check) {
|
|
13665
13782
|
if (isTTY) {
|
|
13666
13783
|
if (currentVersion !== latestVersion) {
|
|
13667
|
-
barLine(`\u2B06\uFE0F ${
|
|
13784
|
+
barLine(`\u2B06\uFE0F ${import_picocolors10.default.dim(currentVersion)} \u2192 ${import_picocolors10.default.green(latestVersion)} \xB7 binary would upgrade`);
|
|
13668
13785
|
barBlank();
|
|
13669
13786
|
}
|
|
13670
13787
|
close("Dry run complete \u2014 no changes made");
|
|
@@ -13677,7 +13794,7 @@ async function runUpdate(opts = {}) {
|
|
|
13677
13794
|
}
|
|
13678
13795
|
if (latestVersion === currentVersion) {
|
|
13679
13796
|
if (isTTY) {
|
|
13680
|
-
close(`Already up to date \u2014 @onebrain-ai/cli ${
|
|
13797
|
+
close(`Already up to date \u2014 @onebrain-ai/cli ${import_picocolors10.default.dim(latestVersion)}`);
|
|
13681
13798
|
} else {
|
|
13682
13799
|
writeLine(`already up to date: @onebrain-ai/cli ${latestVersion}`);
|
|
13683
13800
|
writeLine("done: nothing to do");
|
|
@@ -13687,14 +13804,14 @@ async function runUpdate(opts = {}) {
|
|
|
13687
13804
|
return result;
|
|
13688
13805
|
}
|
|
13689
13806
|
if (isTTY) {
|
|
13690
|
-
barLine(`\u2B06\uFE0F ${
|
|
13807
|
+
barLine(`\u2B06\uFE0F ${import_picocolors10.default.dim(currentVersion)} \u2192 ${import_picocolors10.default.green(latestVersion)}`);
|
|
13691
13808
|
barBlank();
|
|
13692
13809
|
}
|
|
13693
13810
|
const sp3 = createStep("\uD83D\uDCE6", "Installing @onebrain-ai/cli");
|
|
13694
13811
|
try {
|
|
13695
13812
|
await installBinaryFn(latestVersion);
|
|
13696
13813
|
if (sp3)
|
|
13697
|
-
sp3.stop(
|
|
13814
|
+
sp3.stop(import_picocolors10.default.green(latestVersion));
|
|
13698
13815
|
else
|
|
13699
13816
|
writeLine(`upgrading: @onebrain-ai/cli ${latestVersion} installed`);
|
|
13700
13817
|
} catch (err) {
|
|
@@ -13731,7 +13848,7 @@ async function runUpdate(opts = {}) {
|
|
|
13731
13848
|
result.ok = true;
|
|
13732
13849
|
result.exitCode = 0;
|
|
13733
13850
|
if (isTTY) {
|
|
13734
|
-
close(`Done \u2014 run ${
|
|
13851
|
+
close(`Done \u2014 run ${import_picocolors10.default.cyan("/update")} in Claude to sync vault files`);
|
|
13735
13852
|
} else {
|
|
13736
13853
|
writeLine("done: run /update in Claude to sync vault files");
|
|
13737
13854
|
}
|
|
@@ -13758,8 +13875,8 @@ function patchUtf8(stream) {
|
|
|
13758
13875
|
}
|
|
13759
13876
|
|
|
13760
13877
|
// src/index.ts
|
|
13761
|
-
var VERSION = "2.3.
|
|
13762
|
-
var RELEASE_DATE = "2026-05-
|
|
13878
|
+
var VERSION = "2.3.3";
|
|
13879
|
+
var RELEASE_DATE = "2026-05-13";
|
|
13763
13880
|
patchUtf8(process.stdout);
|
|
13764
13881
|
patchUtf8(process.stderr);
|
|
13765
13882
|
var VERSION_STRING = `OneBrain v${VERSION} \u2014 released ${RELEASE_DATE}`;
|
|
@@ -13773,7 +13890,7 @@ function findVaultRoot(startDir) {
|
|
|
13773
13890
|
return process.cwd();
|
|
13774
13891
|
let dir = startDir;
|
|
13775
13892
|
while (true) {
|
|
13776
|
-
if (
|
|
13893
|
+
if (existsSync3(join13(dir, "vault.yml")))
|
|
13777
13894
|
return dir;
|
|
13778
13895
|
const parent = dirname4(dir);
|
|
13779
13896
|
if (parent === dir)
|
|
@@ -13830,7 +13947,25 @@ program2.command("vault-sync", { hidden: true }).description("Sync plugin files
|
|
|
13830
13947
|
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) => {
|
|
13831
13948
|
await registerHooksCommand(opts.vaultDir);
|
|
13832
13949
|
});
|
|
13950
|
+
program2.command("run-skill", { hidden: true }).description("Run a OneBrain skill headlessly via Claude Code (used by the scheduler)").requiredOption("--vault <path>", "Vault root directory").requiredOption("--skill <name>", "Skill name (e.g. /daily)").option("--arg <key=value>", "Skill argument, repeatable (e.g. --arg topic=this-week)", collectKeyValue, {}).action(async (opts) => {
|
|
13951
|
+
const exitCode = await runSkillCommand({
|
|
13952
|
+
vault: opts.vault,
|
|
13953
|
+
skill: opts.skill,
|
|
13954
|
+
...Object.keys(opts.arg).length > 0 ? { args: opts.arg } : {}
|
|
13955
|
+
});
|
|
13956
|
+
process.exit(exitCode);
|
|
13957
|
+
});
|
|
13833
13958
|
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) => {
|
|
13834
13959
|
await migrateCommand(name, cutoffDate);
|
|
13835
13960
|
});
|
|
13961
|
+
function collectKeyValue(value, prev) {
|
|
13962
|
+
const eq = value.indexOf("=");
|
|
13963
|
+
if (eq === -1) {
|
|
13964
|
+
throw new Error(`Invalid --arg format: "${value}" (expected key=value)`);
|
|
13965
|
+
}
|
|
13966
|
+
if (eq === 0) {
|
|
13967
|
+
throw new Error(`Invalid --arg: key is empty in "${value}"`);
|
|
13968
|
+
}
|
|
13969
|
+
return { ...prev, [value.slice(0, eq)]: value.slice(eq + 1) };
|
|
13970
|
+
}
|
|
13836
13971
|
program2.parse(process.argv);
|