@sideboard-ai/cli 0.1.103 → 0.1.107

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/README.md CHANGED
@@ -8,6 +8,7 @@ npm i -g @sideboard-ai/cli
8
8
  sideboard ls
9
9
  sideboard send <thread> "…"
10
10
  sideboard mcp # MCP stdio server
11
+ sideboard schedule ls # local jobs that trigger orchestration chats
11
12
  ```
12
13
 
13
14
  Also installs `side` as a short alias. The MCP server is available as `sideboard mcp`, or via `@sideboard-ai/core`'s `sideboard-mcp` bin.
@@ -20,3 +21,5 @@ sideboard slack listen
20
21
  ```
21
22
 
22
23
  How to connect and address Personal / Work Macs: [README — Slack](../../README.md#slack).
24
+
25
+ Schedules (Settings, CLI, or MCP `create_schedule`) fire only while Sideboard.app is running. Overnight: Settings → Advanced → Caffeinate while schedules are enabled. Details: [README — Scheduled orchestration](../../README.md#scheduled-orchestration).
package/dist/index.js CHANGED
@@ -30,7 +30,15 @@ import {
30
30
  disconnectLinear,
31
31
  runSlackListen,
32
32
  SLACK_OAUTH_REDIRECT,
33
- LINEAR_OAUTH_REDIRECT
33
+ LINEAR_OAUTH_REDIRECT,
34
+ createSchedule,
35
+ deleteSchedule,
36
+ fireSchedule,
37
+ formatScheduleWhen,
38
+ getSchedule,
39
+ listSchedules,
40
+ resolveScheduleThreadId,
41
+ updateSchedule
34
42
  } from "@sideboard-ai/core";
35
43
  var VERSION = "0.1.0";
36
44
  async function printUpgradeHint() {
@@ -504,6 +512,96 @@ ${preview.diffStat}`);
504
512
  program.command("mcp").description("Run the Sideboard MCP stdio server").action(async () => {
505
513
  await startMcpServer();
506
514
  });
515
+ const scheduleCmd = program.command("schedule").description(
516
+ "Local jobs that trigger orchestration chats (Sideboard.app must be running to fire)"
517
+ );
518
+ scheduleCmd.command("ls").description("List schedules").action(() => {
519
+ const rows = listSchedules();
520
+ if (rows.length === 0) {
521
+ console.log(chalk.dim("No schedules"));
522
+ return;
523
+ }
524
+ for (const row of rows) {
525
+ const target = row.threadId ? row.threadId.slice(0, 8) : "new chat";
526
+ const on = row.enabled ? chalk.green("on ") : chalk.dim("off");
527
+ console.log(
528
+ `${row.id.slice(0, 8)} ${on} ${formatScheduleWhen(row.when)} next ${row.nextRunAt} ${target} ${row.name}`
529
+ );
530
+ if (row.lastError) console.log(chalk.red(` ${row.lastError}`));
531
+ }
532
+ });
533
+ scheduleCmd.command("add").requiredOption("--prompt <text>", "prompt / goal queued when the job fires").option("--name <name>", "short label").option("--at <iso>", "one-shot ISO datetime").option("--every <duration>", "interval (15m, 1h, 6h, 1d)").option("--cron <expr>", "5-field cron").option("--tz <iana>", "timezone for cron").option(
534
+ "--thread <id>",
535
+ "existing orchestration chat (or self). Omit to create a new Global chat each run"
536
+ ).option("--agent <agent>", "claude|cursor|codex|opencode (new chats only)").action((opts) => {
537
+ const cadence = [opts.at, opts.every, opts.cron].filter(Boolean);
538
+ if (cadence.length !== 1) {
539
+ throw new Error("Pass exactly one of --at, --every, or --cron");
540
+ }
541
+ const when = opts.at ? { kind: "once", at: String(opts.at) } : opts.every ? { kind: "every", every: String(opts.every) } : {
542
+ kind: "cron",
543
+ expr: String(opts.cron),
544
+ tz: opts.tz ? String(opts.tz) : void 0
545
+ };
546
+ const threadId = resolveScheduleThreadId(
547
+ opts.thread ? String(opts.thread) : void 0
548
+ );
549
+ if (String(opts.thread ?? "").trim().toLowerCase() === "self" && !threadId) {
550
+ throw new Error("--thread self needs SIDEBOARD_ORCHESTRATOR_THREAD_ID");
551
+ }
552
+ const agent = opts.agent ? parseAgent(String(opts.agent)) : void 0;
553
+ if (agent === "brightsy") {
554
+ throw new Error("schedules cannot use brightsy \u2014 pick claude, cursor, codex, or opencode");
555
+ }
556
+ const row = createSchedule({
557
+ name: opts.name,
558
+ prompt: String(opts.prompt),
559
+ when,
560
+ threadId,
561
+ agent,
562
+ createdBy: "cli"
563
+ });
564
+ if (!row.threadId && row.when.kind !== "once") {
565
+ console.log(
566
+ chalk.yellow(
567
+ "Recurring schedule has no --thread: each run opens a new orchestration chat."
568
+ )
569
+ );
570
+ }
571
+ console.log(
572
+ chalk.green(
573
+ `Scheduled ${row.id.slice(0, 8)} ${formatScheduleWhen(row.when)} next ${row.nextRunAt}`
574
+ )
575
+ );
576
+ console.log(chalk.dim("Fires while Sideboard.app is running on this Mac."));
577
+ });
578
+ scheduleCmd.command("enable").argument("<id>", "schedule id").action((id) => {
579
+ const row = updateSchedule(id, { enabled: true });
580
+ console.log(chalk.green(`Enabled ${row.id.slice(0, 8)}`));
581
+ });
582
+ scheduleCmd.command("disable").argument("<id>", "schedule id").action((id) => {
583
+ const row = updateSchedule(id, { enabled: false });
584
+ console.log(chalk.yellow(`Disabled ${row.id.slice(0, 8)}`));
585
+ });
586
+ scheduleCmd.command("rm").argument("<id>", "schedule id").action((id) => {
587
+ const row = getSchedule(id);
588
+ if (!row) throw new Error(`Schedule not found: ${id}`);
589
+ deleteSchedule(row.id);
590
+ console.log(chalk.yellow(`Removed ${row.id.slice(0, 8)}`));
591
+ });
592
+ scheduleCmd.command("run").argument("<id>", "schedule id").description("Fire now").action(async (id) => {
593
+ const row = await fireSchedule(id);
594
+ if (row.lastError) {
595
+ console.error(chalk.red(row.lastError));
596
+ process.exitCode = 1;
597
+ return;
598
+ }
599
+ console.log(
600
+ chalk.green(
601
+ `Fired ${row.id.slice(0, 8)} \u2192 ${row.lastThreadId?.slice(0, 8) ?? "thread"}`
602
+ )
603
+ );
604
+ });
507
605
  const brightsyCmd = program.command("brightsy").description(
508
606
  "Brightsy team helpers (wraps `brightsy teams` + Sideboard multi-team MCP state)"
509
607
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sideboard-ai/cli",
3
- "version": "0.1.103",
3
+ "version": "0.1.107",
4
4
  "description": "Sideboard CLI — agent-agnostic worktree orchestration (includes `sideboard mcp`)",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -16,7 +16,7 @@
16
16
  "chalk": "^5.4.1",
17
17
  "commander": "^13.1.0",
18
18
  "ora": "^8.2.0",
19
- "@sideboard-ai/core": "0.1.103"
19
+ "@sideboard-ai/core": "0.1.107"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@types/node": "^22.13.10",