@h-rig/cli 0.0.6-alpha.35 → 0.0.6-alpha.37

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.
@@ -1283,7 +1283,38 @@ function parseWsPayload(message2) {
1283
1283
  return JSON.parse(message2.data);
1284
1284
  return JSON.parse(Buffer.from(message2.data).toString("utf8"));
1285
1285
  }
1286
- async function connectWorkerStream(options, ctx, state) {
1286
+ var BRIDGE_LOCAL_COMMANDS = new Set(["detach", "quit", "q", "stop"]);
1287
+ function registerDaemonCommandsNatively(pi, options, ctx, state, commands, registered) {
1288
+ for (const command of commands) {
1289
+ const record = recordOf(command);
1290
+ const name = typeof record?.name === "string" ? record.name : "";
1291
+ if (!name || registered.has(name) || BRIDGE_LOCAL_COMMANDS.has(name))
1292
+ continue;
1293
+ registered.add(name);
1294
+ const description = typeof record?.description === "string" ? record.description : undefined;
1295
+ const source = typeof record?.source === "string" ? record.source : "worker";
1296
+ try {
1297
+ pi.registerCommand(name, {
1298
+ description: `[worker ${source}] ${description ?? ""}`.trim(),
1299
+ handler: async (args) => {
1300
+ const text = `/${name}${args ? ` ${args}` : ""}`;
1301
+ appendTranscript(state, "You", text);
1302
+ try {
1303
+ const result = await runRunPiCommandViaServer(options.context, options.runId, text);
1304
+ const message2 = typeof result.message === "string" ? result.message : "worker command accepted";
1305
+ appendTranscript(state, "System", message2);
1306
+ if (state.nativeStream)
1307
+ ctx.ui.notify(message2, "info");
1308
+ } catch (error) {
1309
+ reportBridgeError(ctx, state, error instanceof Error ? error.message : String(error));
1310
+ }
1311
+ updatePiUi(ctx, state);
1312
+ }
1313
+ });
1314
+ } catch {}
1315
+ }
1316
+ }
1317
+ async function connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands) {
1287
1318
  const ready = await waitForWorkerReady(options, ctx, state);
1288
1319
  if (!ready)
1289
1320
  return;
@@ -1338,6 +1369,7 @@ async function connectWorkerStream(options, ctx, state) {
1338
1369
  const record = recordOf(command);
1339
1370
  return typeof record?.name === "string" ? [`/${record.name}`] : [];
1340
1371
  });
1372
+ registerDaemonCommandsNatively(pi, options, ctx, state, commands, registeredDaemonCommands);
1341
1373
  catchupDone = true;
1342
1374
  for (const payload of buffered.splice(0))
1343
1375
  applyEnvelope(ctx, state, payload);
@@ -1465,6 +1497,7 @@ function createRigWorkerPiBridgeExtension(options) {
1465
1497
  };
1466
1498
  if (options.initialMessageSent)
1467
1499
  appendTranscript(state, "System", "Initial message sent to worker Pi daemon.");
1500
+ const registeredDaemonCommands = new Set;
1468
1501
  let nativePiUiContextAvailable = false;
1469
1502
  pi.on("user_bash", (event) => {
1470
1503
  state.nativeStream = Boolean(state.nativeStream || nativePiUiContextAvailable);
@@ -1497,7 +1530,7 @@ function createRigWorkerPiBridgeExtension(options) {
1497
1530
  });
1498
1531
  return { consume: true };
1499
1532
  });
1500
- connectWorkerStream(options, ctx, state).catch((error) => {
1533
+ connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands).catch((error) => {
1501
1534
  appendTranscript(state, "Error", error instanceof Error ? error.message : String(error));
1502
1535
  updatePiUi(ctx, state);
1503
1536
  });
@@ -1544,8 +1577,6 @@ async function attachRunBundledPiFrontend(context, input) {
1544
1577
  "--no-tools",
1545
1578
  "--no-builtin-tools",
1546
1579
  "--no-skills",
1547
- "--no-prompt-templates",
1548
- "--no-themes",
1549
1580
  "--no-context-files",
1550
1581
  "--no-approve"
1551
1582
  ], {
@@ -1843,52 +1874,50 @@ import { intro, log as log2, note as note2, outro } from "@clack/prompts";
1843
1874
  import pc2 from "picocolors";
1844
1875
  var TOP_LEVEL_SECTIONS = [
1845
1876
  {
1846
- title: "Server",
1847
- subtitle: "choose the local or remote Rig server that owns this repo",
1877
+ title: "Start here",
1878
+ subtitle: "one-time setup for a repo",
1848
1879
  commands: [
1849
- { command: "rig server status", description: "Show the selected local/remote server for this repo." },
1850
- { command: "rig server use local", description: "Switch this repo back to the local Rig server." },
1851
- { command: "rig server add <alias> <url>", description: "Save a remote Rig server alias." },
1852
- { command: "rig server use <alias>", description: "Switch this repo to a saved remote server." },
1853
- { command: "rig server list", description: "Show saved server aliases, including local." }
1880
+ { command: "rig init", description: "Wizard: config, GitHub auth, task source, server, Pi wiring." },
1881
+ { command: "rig doctor", description: "Check every part of the wiring \u2014 run this when anything feels off." },
1882
+ { command: "rig server use <alias|local>", description: "Pick which Rig server owns this repo (`rig server list` to see them)." }
1854
1883
  ]
1855
1884
  },
1856
1885
  {
1857
- title: "Tasks",
1858
- subtitle: "find work, inspect it, and submit Pi-backed workers",
1886
+ title: "Work",
1887
+ subtitle: "find a task and put an agent on it",
1859
1888
  commands: [
1860
- { command: "rig task list", description: "List tasks from the selected task source/server." },
1861
- { command: "rig task next", description: "Show the next matching task as a selected-task card." },
1862
- { command: "rig task show <id>", description: "Show a human task summary; add --raw or --json for the full payload." },
1863
- { command: "rig task run <id|--next> [--detach]", description: "Submit a task run; interactive mode follows with bundled Pi." }
1889
+ { command: "rig task list", description: "What's on the board (from the selected source/server)." },
1890
+ { command: "rig task next", description: "The next ready task, as a card." },
1891
+ { command: "rig task run --next", description: "Dispatch an agent; interactive mode opens the native Pi session." },
1892
+ { command: "rig task run <id> --detach", description: "Fire-and-forget a specific task." }
1864
1893
  ]
1865
1894
  },
1866
1895
  {
1867
- title: "Runs",
1868
- subtitle: "observe, attach to, and stop live or recent runs",
1896
+ title: "Watch & steer",
1897
+ subtitle: "live runs are observable and steerable, attached or not",
1869
1898
  commands: [
1870
- { command: "rig run list", description: "List recent runs from the selected server or local state." },
1871
- { command: "rig run show <id>", description: "Show a human run summary; add --raw or --json for the full payload." },
1872
- { command: "rig run attach <id> --follow", description: "Open the native bundled Pi live view for a worker run." },
1873
- { command: "rig run stop <id>", description: "Request cancellation for a running worker." }
1899
+ { command: "rig run status", description: "Active and recent runs at a glance." },
1900
+ { command: "rig run attach <id> --follow", description: "Join the live Pi session (worker keeps running if you /detach)." },
1901
+ { command: "rig run steer <id> -m <text>", description: "Drop a message into a live worker without attaching." },
1902
+ { command: "rig run stop <id>", description: "Cancel a running worker." }
1874
1903
  ]
1875
1904
  },
1876
1905
  {
1877
- title: "Review / inbox",
1878
- subtitle: "clear blocked runs and configure completion review",
1906
+ title: "Unblock & gate",
1907
+ subtitle: "answer what workers ask; control what merges",
1879
1908
  commands: [
1880
- { command: "rig inbox approvals", description: "List pending approval requests from local/server run state." },
1881
- { command: "rig inbox inputs", description: "List pending user-input requests from local/server run state." },
1882
- { command: "rig review show|set", description: "Inspect or change the review gate policy." }
1909
+ { command: "rig inbox approvals", description: "Approvals workers are waiting on (then `rig inbox approve \u2026`)." },
1910
+ { command: "rig inbox inputs", description: "Questions workers asked (then `rig inbox respond \u2026`)." },
1911
+ { command: "rig review show|set", description: "The completion review gate (Greptile is mandatory on merges)." }
1883
1912
  ]
1884
1913
  },
1885
1914
  {
1886
- title: "Health / setup",
1887
- subtitle: "bootstrap and diagnose the repo/server/GitHub/Pi path",
1915
+ title: "Extend",
1916
+ subtitle: "more Pi, more plugins",
1888
1917
  commands: [
1889
- { command: "rig init", description: "Interactive setup: config, GitHub auth, task source, server, checkout, Pi." },
1890
- { command: "rig doctor", description: "Diagnose project/server/GitHub/task/Pi wiring." },
1891
- { command: "rig github auth status", description: "Show GitHub auth state on the selected Rig server." }
1918
+ { command: "rig pi search <term>", description: "Discover community Pi extensions on npm." },
1919
+ { command: "rig pi add <pkg>", description: "Add a Pi extension to this project (workers pick it up too)." },
1920
+ { command: "rig plugin list", description: "What the rig.config.ts plugins contribute." }
1892
1921
  ]
1893
1922
  }
1894
1923
  ];
@@ -2090,6 +2119,25 @@ var ALL_GROUPS = [...PRIMARY_GROUPS, ...ADVANCED_GROUPS];
2090
2119
  function heading(title) {
2091
2120
  return pc2.bold(pc2.cyan(title));
2092
2121
  }
2122
+ function renderRigBanner(version) {
2123
+ const m = (s) => pc2.bold(pc2.magenta(s));
2124
+ const c = (s) => pc2.bold(pc2.cyan(s));
2125
+ const y = (s) => pc2.yellow(s);
2126
+ const d = (s) => pc2.dim(s);
2127
+ const lines = [
2128
+ m(" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ") + d(" \u2591\u2592\u2593\u2588 "),
2129
+ m(" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D ") + d("\u2593\u2592\u2591"),
2130
+ c(" \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2557") + d(" \u2591\u2592"),
2131
+ c(" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551") + d(" \u2588\u2593\u2591"),
2132
+ y(" \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D") + d(" \u2592\u2591"),
2133
+ y(" \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D "),
2134
+ "",
2135
+ ` ${c("\u25E2\u25E4")} ${pc2.bold("the control rig for autonomous coding agents")} ${m("//")} ${d("you are the operator")}`,
2136
+ version ? ` ${d(`v${version} \xB7 jack in: rig task run --next`)}` : ` ${d("jack in: rig task run --next")}`
2137
+ ];
2138
+ return lines.join(`
2139
+ `);
2140
+ }
2093
2141
  function commandLine(command, description) {
2094
2142
  const commandColumn = command.length >= 38 ? `${command} ` : command.padEnd(38);
2095
2143
  return `${pc2.dim("\u2502")} ${pc2.bold(commandColumn)} ${description}`;
@@ -2146,12 +2194,25 @@ function renderGroupHelp(groupName) {
2146
2194
  function shouldUseClackOutput2() {
2147
2195
  return Boolean(process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1";
2148
2196
  }
2149
- function printTopLevelHelp() {
2197
+ function printTopLevelHelp(state = {}) {
2150
2198
  if (!shouldUseClackOutput2()) {
2151
2199
  console.log(renderTopLevelHelp());
2152
2200
  return;
2153
2201
  }
2154
- intro("rig");
2202
+ console.log(renderRigBanner(state.version));
2203
+ console.log("");
2204
+ if (state.projectInitialized === false) {
2205
+ intro("no rig project in this directory");
2206
+ note2([
2207
+ commandLine("rig init", "Set this repo up: config, GitHub auth, task source, server, Pi."),
2208
+ commandLine("rig init --yes", "Same, non-interactive, sensible defaults."),
2209
+ commandLine("rig doctor", "Already initialized somewhere else? Check the wiring.")
2210
+ ].join(`
2211
+ `), "Get started");
2212
+ outro("After init: rig task run --next puts an agent on your next task.");
2213
+ return;
2214
+ }
2215
+ intro(state.selectedServer ? `server: ${state.selectedServer}` : "rig");
2155
2216
  for (const section of TOP_LEVEL_SECTIONS) {
2156
2217
  note2(renderCommandBlock(section.commands), `${section.title} \u2014 ${section.subtitle}`);
2157
2218
  }
@@ -2162,7 +2223,7 @@ function printTopLevelHelp() {
2162
2223
  commandLine("--dry-run", "Print the command plan without mutating state.")
2163
2224
  ].join(`
2164
2225
  `), "Global options");
2165
- outro("Server \u2192 task \u2192 run \u2192 inbox/review.");
2226
+ outro("init \u2192 task run \u2192 watch/steer \u2192 inbox/review \u2192 merged.");
2166
2227
  }
2167
2228
  function printGroupHelpDocument(groupName) {
2168
2229
  const rendered = renderGroupHelp(groupName) ?? renderTopLevelHelp();
@@ -337,7 +337,8 @@ var init_plugin = __esm(() => {
337
337
  // packages/cli/src/commands.ts
338
338
  init_runner();
339
339
  import {
340
- existsSync as existsSync15
340
+ existsSync as existsSync15,
341
+ readFileSync as readFileSync12
341
342
  } from "fs";
342
343
  import { resolve as resolve24 } from "path";
343
344
  import { readBuildConfig } from "@rig/runtime/build-time-config";
@@ -6111,6 +6112,7 @@ ${acceptance}` : null,
6111
6112
  ${sourceContractLines.join(`
6112
6113
  `)}` : null,
6113
6114
  scopeText || renderSourceScopeValidation(sourceTask, sourceValidation) || null,
6115
+ readPriorPrProgressForPrompt(input.projectRoot, input.taskId),
6114
6116
  initialPrompt ? `Additional operator guidance:
6115
6117
  ${initialPrompt}` : null,
6116
6118
  providerLines.length > 0 ? `Provider-specific runtime tooling:
@@ -6120,6 +6122,26 @@ ${providerLines.join(" ")}` : null,
6120
6122
 
6121
6123
  `);
6122
6124
  }
6125
+ function readPriorPrProgressForPrompt(projectRoot, taskId) {
6126
+ for (const candidate of [
6127
+ resolve19(projectRoot, ".worktrees", taskId, "artifacts", taskId, "pr-state.json"),
6128
+ resolve19(projectRoot, "artifacts", taskId, "pr-state.json")
6129
+ ]) {
6130
+ try {
6131
+ const raw = JSON.parse(readFileSync8(candidate, "utf8"));
6132
+ const entries = Array.isArray(raw) ? raw : [raw];
6133
+ const first = entries.find((entry) => entry && typeof entry === "object" && typeof entry.url === "string");
6134
+ if (!first)
6135
+ continue;
6136
+ return [
6137
+ `Prior progress exists for this task: PR ${first.url}${first.branch ? ` (branch ${first.branch})` : ""} was opened by an earlier run.`,
6138
+ "Check its current state first (diff, checks, review). If the work is already complete and checks are green,",
6139
+ "run `rig-agent completion-verification` to merge and close instead of re-implementing anything."
6140
+ ].join(" ");
6141
+ } catch {}
6142
+ }
6143
+ return null;
6144
+ }
6123
6145
  function firstPromptString(...values) {
6124
6146
  for (const value of values) {
6125
6147
  const trimmed = typeof value === "string" ? value.trim() : "";
@@ -6204,7 +6226,24 @@ async function executeInspect(context, args) {
6204
6226
  const requiredTask = requireTask(task, "rig inspect logs --task <task-id>");
6205
6227
  const latestRun = listAuthorityRuns2(context.projectRoot).map((entry) => readAuthorityRun3(context.projectRoot, entry.runId)).filter((run) => Boolean(run)).filter((run) => run.taskId === requiredTask).sort((left, right) => String(right.updatedAt ?? "").localeCompare(String(left.updatedAt ?? "")))[0];
6206
6228
  if (!latestRun) {
6207
- throw new CliError2(`No runs found for ${requiredTask}.`);
6229
+ const serverRuns = await listRunsViaServer(context, { limit: 200 }).catch(() => []);
6230
+ const serverRun = serverRuns.filter((run) => String(run.taskId ?? "") === requiredTask).sort((left, right) => String(right.updatedAt ?? "").localeCompare(String(left.updatedAt ?? "")))[0];
6231
+ if (!serverRun || typeof serverRun.runId !== "string") {
6232
+ throw new CliError2(`No runs found for ${requiredTask} (local or on the selected server).`);
6233
+ }
6234
+ const page = await getRunLogsViaServer(context, serverRun.runId, { limit: 500 });
6235
+ const entries = Array.isArray(page.entries) ? page.entries : [];
6236
+ if (context.outputMode === "text") {
6237
+ for (const entry of entries) {
6238
+ const record = entry && typeof entry === "object" ? entry : {};
6239
+ const title = String(record.title ?? "");
6240
+ const detail = String(record.detail ?? "");
6241
+ console.log([title, detail].filter(Boolean).join(" \u2014 "));
6242
+ }
6243
+ if (entries.length === 0)
6244
+ console.log(`(no log entries for run ${serverRun.runId})`);
6245
+ }
6246
+ return { ok: true, group: "inspect", command, details: { task: requiredTask, runId: serverRun.runId, source: "server", entries } };
6208
6247
  }
6209
6248
  const logsPath = resolve20(resolveAuthorityRunDir4(context.projectRoot, latestRun.runId), "logs.jsonl");
6210
6249
  if (!existsSync12(logsPath)) {
@@ -7489,7 +7528,38 @@ function parseWsPayload(message2) {
7489
7528
  return JSON.parse(message2.data);
7490
7529
  return JSON.parse(Buffer.from(message2.data).toString("utf8"));
7491
7530
  }
7492
- async function connectWorkerStream(options, ctx, state) {
7531
+ var BRIDGE_LOCAL_COMMANDS = new Set(["detach", "quit", "q", "stop"]);
7532
+ function registerDaemonCommandsNatively(pi, options, ctx, state, commands, registered) {
7533
+ for (const command of commands) {
7534
+ const record = recordOf(command);
7535
+ const name = typeof record?.name === "string" ? record.name : "";
7536
+ if (!name || registered.has(name) || BRIDGE_LOCAL_COMMANDS.has(name))
7537
+ continue;
7538
+ registered.add(name);
7539
+ const description = typeof record?.description === "string" ? record.description : undefined;
7540
+ const source = typeof record?.source === "string" ? record.source : "worker";
7541
+ try {
7542
+ pi.registerCommand(name, {
7543
+ description: `[worker ${source}] ${description ?? ""}`.trim(),
7544
+ handler: async (args) => {
7545
+ const text2 = `/${name}${args ? ` ${args}` : ""}`;
7546
+ appendTranscript(state, "You", text2);
7547
+ try {
7548
+ const result = await runRunPiCommandViaServer(options.context, options.runId, text2);
7549
+ const message2 = typeof result.message === "string" ? result.message : "worker command accepted";
7550
+ appendTranscript(state, "System", message2);
7551
+ if (state.nativeStream)
7552
+ ctx.ui.notify(message2, "info");
7553
+ } catch (error) {
7554
+ reportBridgeError(ctx, state, error instanceof Error ? error.message : String(error));
7555
+ }
7556
+ updatePiUi(ctx, state);
7557
+ }
7558
+ });
7559
+ } catch {}
7560
+ }
7561
+ }
7562
+ async function connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands) {
7493
7563
  const ready = await waitForWorkerReady(options, ctx, state);
7494
7564
  if (!ready)
7495
7565
  return;
@@ -7544,6 +7614,7 @@ async function connectWorkerStream(options, ctx, state) {
7544
7614
  const record = recordOf(command);
7545
7615
  return typeof record?.name === "string" ? [`/${record.name}`] : [];
7546
7616
  });
7617
+ registerDaemonCommandsNatively(pi, options, ctx, state, commands, registeredDaemonCommands);
7547
7618
  catchupDone = true;
7548
7619
  for (const payload of buffered.splice(0))
7549
7620
  applyEnvelope(ctx, state, payload);
@@ -7671,6 +7742,7 @@ function createRigWorkerPiBridgeExtension(options) {
7671
7742
  };
7672
7743
  if (options.initialMessageSent)
7673
7744
  appendTranscript(state, "System", "Initial message sent to worker Pi daemon.");
7745
+ const registeredDaemonCommands = new Set;
7674
7746
  let nativePiUiContextAvailable = false;
7675
7747
  pi.on("user_bash", (event) => {
7676
7748
  state.nativeStream = Boolean(state.nativeStream || nativePiUiContextAvailable);
@@ -7703,7 +7775,7 @@ function createRigWorkerPiBridgeExtension(options) {
7703
7775
  });
7704
7776
  return { consume: true };
7705
7777
  });
7706
- connectWorkerStream(options, ctx, state).catch((error) => {
7778
+ connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands).catch((error) => {
7707
7779
  appendTranscript(state, "Error", error instanceof Error ? error.message : String(error));
7708
7780
  updatePiUi(ctx, state);
7709
7781
  });
@@ -7750,8 +7822,6 @@ async function attachRunBundledPiFrontend(context, input) {
7750
7822
  "--no-tools",
7751
7823
  "--no-builtin-tools",
7752
7824
  "--no-skills",
7753
- "--no-prompt-templates",
7754
- "--no-themes",
7755
7825
  "--no-context-files",
7756
7826
  "--no-approve"
7757
7827
  ], {
@@ -8296,6 +8366,7 @@ async function executeRun(context, args) {
8296
8366
 
8297
8367
  // packages/cli/src/commands/server.ts
8298
8368
  init_runner();
8369
+ import { resolveRigServerCommand } from "@rig/runtime/local-server";
8299
8370
  async function executeServer(context, args, options) {
8300
8371
  const [command = "status", ...rest] = args;
8301
8372
  if (["status", "list", "add", "use"].includes(command)) {
@@ -8313,7 +8384,8 @@ async function executeServer(context, args, options) {
8313
8384
  const authTokenResult = takeOption(pending, "--auth-token");
8314
8385
  pending = authTokenResult.rest;
8315
8386
  requireNoExtraArgs(pending, "rig server start [--host <host>] [--port <n>] [--poll-ms <n>] [--auth-token <token>]");
8316
- const commandParts = ["rig-server", "start"];
8387
+ const serverCommand = resolveRigServerCommand(context.projectRoot);
8388
+ const commandParts = [serverCommand.command, ...serverCommand.commandArgs, "start"];
8317
8389
  if (hostResult.value) {
8318
8390
  commandParts.push("--host", hostResult.value);
8319
8391
  }
@@ -8336,7 +8408,8 @@ async function executeServer(context, args, options) {
8336
8408
  const eventResult = takeOption(pending, "--event");
8337
8409
  pending = eventResult.rest;
8338
8410
  requireNoExtraArgs(pending, "rig server notify-test [--event <type>]");
8339
- const commandParts = ["rig-server", "notify-test"];
8411
+ const serverCommand = resolveRigServerCommand(context.projectRoot);
8412
+ const commandParts = [serverCommand.command, ...serverCommand.commandArgs, "notify-test"];
8340
8413
  if (eventResult.value) {
8341
8414
  commandParts.push("--event", eventResult.value);
8342
8415
  }
@@ -8470,52 +8543,50 @@ import { intro as intro3, log as log4, note as note4, outro as outro3 } from "@c
8470
8543
  import pc4 from "picocolors";
8471
8544
  var TOP_LEVEL_SECTIONS = [
8472
8545
  {
8473
- title: "Server",
8474
- subtitle: "choose the local or remote Rig server that owns this repo",
8546
+ title: "Start here",
8547
+ subtitle: "one-time setup for a repo",
8475
8548
  commands: [
8476
- { command: "rig server status", description: "Show the selected local/remote server for this repo." },
8477
- { command: "rig server use local", description: "Switch this repo back to the local Rig server." },
8478
- { command: "rig server add <alias> <url>", description: "Save a remote Rig server alias." },
8479
- { command: "rig server use <alias>", description: "Switch this repo to a saved remote server." },
8480
- { command: "rig server list", description: "Show saved server aliases, including local." }
8549
+ { command: "rig init", description: "Wizard: config, GitHub auth, task source, server, Pi wiring." },
8550
+ { command: "rig doctor", description: "Check every part of the wiring \u2014 run this when anything feels off." },
8551
+ { command: "rig server use <alias|local>", description: "Pick which Rig server owns this repo (`rig server list` to see them)." }
8481
8552
  ]
8482
8553
  },
8483
8554
  {
8484
- title: "Tasks",
8485
- subtitle: "find work, inspect it, and submit Pi-backed workers",
8555
+ title: "Work",
8556
+ subtitle: "find a task and put an agent on it",
8486
8557
  commands: [
8487
- { command: "rig task list", description: "List tasks from the selected task source/server." },
8488
- { command: "rig task next", description: "Show the next matching task as a selected-task card." },
8489
- { command: "rig task show <id>", description: "Show a human task summary; add --raw or --json for the full payload." },
8490
- { command: "rig task run <id|--next> [--detach]", description: "Submit a task run; interactive mode follows with bundled Pi." }
8558
+ { command: "rig task list", description: "What's on the board (from the selected source/server)." },
8559
+ { command: "rig task next", description: "The next ready task, as a card." },
8560
+ { command: "rig task run --next", description: "Dispatch an agent; interactive mode opens the native Pi session." },
8561
+ { command: "rig task run <id> --detach", description: "Fire-and-forget a specific task." }
8491
8562
  ]
8492
8563
  },
8493
8564
  {
8494
- title: "Runs",
8495
- subtitle: "observe, attach to, and stop live or recent runs",
8565
+ title: "Watch & steer",
8566
+ subtitle: "live runs are observable and steerable, attached or not",
8496
8567
  commands: [
8497
- { command: "rig run list", description: "List recent runs from the selected server or local state." },
8498
- { command: "rig run show <id>", description: "Show a human run summary; add --raw or --json for the full payload." },
8499
- { command: "rig run attach <id> --follow", description: "Open the native bundled Pi live view for a worker run." },
8500
- { command: "rig run stop <id>", description: "Request cancellation for a running worker." }
8568
+ { command: "rig run status", description: "Active and recent runs at a glance." },
8569
+ { command: "rig run attach <id> --follow", description: "Join the live Pi session (worker keeps running if you /detach)." },
8570
+ { command: "rig run steer <id> -m <text>", description: "Drop a message into a live worker without attaching." },
8571
+ { command: "rig run stop <id>", description: "Cancel a running worker." }
8501
8572
  ]
8502
8573
  },
8503
8574
  {
8504
- title: "Review / inbox",
8505
- subtitle: "clear blocked runs and configure completion review",
8575
+ title: "Unblock & gate",
8576
+ subtitle: "answer what workers ask; control what merges",
8506
8577
  commands: [
8507
- { command: "rig inbox approvals", description: "List pending approval requests from local/server run state." },
8508
- { command: "rig inbox inputs", description: "List pending user-input requests from local/server run state." },
8509
- { command: "rig review show|set", description: "Inspect or change the review gate policy." }
8578
+ { command: "rig inbox approvals", description: "Approvals workers are waiting on (then `rig inbox approve \u2026`)." },
8579
+ { command: "rig inbox inputs", description: "Questions workers asked (then `rig inbox respond \u2026`)." },
8580
+ { command: "rig review show|set", description: "The completion review gate (Greptile is mandatory on merges)." }
8510
8581
  ]
8511
8582
  },
8512
8583
  {
8513
- title: "Health / setup",
8514
- subtitle: "bootstrap and diagnose the repo/server/GitHub/Pi path",
8584
+ title: "Extend",
8585
+ subtitle: "more Pi, more plugins",
8515
8586
  commands: [
8516
- { command: "rig init", description: "Interactive setup: config, GitHub auth, task source, server, checkout, Pi." },
8517
- { command: "rig doctor", description: "Diagnose project/server/GitHub/task/Pi wiring." },
8518
- { command: "rig github auth status", description: "Show GitHub auth state on the selected Rig server." }
8587
+ { command: "rig pi search <term>", description: "Discover community Pi extensions on npm." },
8588
+ { command: "rig pi add <pkg>", description: "Add a Pi extension to this project (workers pick it up too)." },
8589
+ { command: "rig plugin list", description: "What the rig.config.ts plugins contribute." }
8519
8590
  ]
8520
8591
  }
8521
8592
  ];
@@ -8723,6 +8794,25 @@ var ALL_GROUPS = [...PRIMARY_GROUPS, ...ADVANCED_GROUPS];
8723
8794
  function heading(title) {
8724
8795
  return pc4.bold(pc4.cyan(title));
8725
8796
  }
8797
+ function renderRigBanner(version) {
8798
+ const m = (s) => pc4.bold(pc4.magenta(s));
8799
+ const c = (s) => pc4.bold(pc4.cyan(s));
8800
+ const y = (s) => pc4.yellow(s);
8801
+ const d = (s) => pc4.dim(s);
8802
+ const lines = [
8803
+ m(" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ") + d(" \u2591\u2592\u2593\u2588 "),
8804
+ m(" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D ") + d("\u2593\u2592\u2591"),
8805
+ c(" \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2557") + d(" \u2591\u2592"),
8806
+ c(" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551") + d(" \u2588\u2593\u2591"),
8807
+ y(" \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D") + d(" \u2592\u2591"),
8808
+ y(" \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D "),
8809
+ "",
8810
+ ` ${c("\u25E2\u25E4")} ${pc4.bold("the control rig for autonomous coding agents")} ${m("//")} ${d("you are the operator")}`,
8811
+ version ? ` ${d(`v${version} \xB7 jack in: rig task run --next`)}` : ` ${d("jack in: rig task run --next")}`
8812
+ ];
8813
+ return lines.join(`
8814
+ `);
8815
+ }
8726
8816
  function commandLine(command, description) {
8727
8817
  const commandColumn = command.length >= 38 ? `${command} ` : command.padEnd(38);
8728
8818
  return `${pc4.dim("\u2502")} ${pc4.bold(commandColumn)} ${description}`;
@@ -8796,12 +8886,25 @@ function renderGroupHelp(groupName) {
8796
8886
  function shouldUseClackOutput2() {
8797
8887
  return Boolean(process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1";
8798
8888
  }
8799
- function printTopLevelHelp() {
8889
+ function printTopLevelHelp(state = {}) {
8800
8890
  if (!shouldUseClackOutput2()) {
8801
8891
  console.log(renderTopLevelHelp());
8802
8892
  return;
8803
8893
  }
8804
- intro3("rig");
8894
+ console.log(renderRigBanner(state.version));
8895
+ console.log("");
8896
+ if (state.projectInitialized === false) {
8897
+ intro3("no rig project in this directory");
8898
+ note4([
8899
+ commandLine("rig init", "Set this repo up: config, GitHub auth, task source, server, Pi."),
8900
+ commandLine("rig init --yes", "Same, non-interactive, sensible defaults."),
8901
+ commandLine("rig doctor", "Already initialized somewhere else? Check the wiring.")
8902
+ ].join(`
8903
+ `), "Get started");
8904
+ outro3("After init: rig task run --next puts an agent on your next task.");
8905
+ return;
8906
+ }
8907
+ intro3(state.selectedServer ? `server: ${state.selectedServer}` : "rig");
8805
8908
  for (const section of TOP_LEVEL_SECTIONS) {
8806
8909
  note4(renderCommandBlock(section.commands), `${section.title} \u2014 ${section.subtitle}`);
8807
8910
  }
@@ -8812,7 +8915,7 @@ function printTopLevelHelp() {
8812
8915
  commandLine("--dry-run", "Print the command plan without mutating state.")
8813
8916
  ].join(`
8814
8917
  `), "Global options");
8815
- outro3("Server \u2192 task \u2192 run \u2192 inbox/review.");
8918
+ outro3("init \u2192 task run \u2192 watch/steer \u2192 inbox/review \u2192 merged.");
8816
8919
  }
8817
8920
  function printAdvancedHelp() {
8818
8921
  if (!shouldUseClackOutput2()) {
@@ -11678,9 +11781,23 @@ function isHelpArg(arg) {
11678
11781
  function helpText() {
11679
11782
  return renderTopLevelHelp();
11680
11783
  }
11784
+ function resolveTopLevelLaunchState(context) {
11785
+ const projectInitialized = hasInitializedRigProject(context.projectRoot);
11786
+ let selectedServer = null;
11787
+ if (projectInitialized) {
11788
+ try {
11789
+ const statePath = resolve24(context.projectRoot, ".rig", "state", "connection.json");
11790
+ if (existsSync15(statePath)) {
11791
+ const parsed = JSON.parse(readFileSync12(statePath, "utf-8"));
11792
+ selectedServer = parsed.remoteUrl || parsed.url || parsed.selected || null;
11793
+ }
11794
+ } catch {}
11795
+ }
11796
+ return { projectInitialized, selectedServer, version: process.env.RIG_CLI_VERSION || readBuildConfig().RIG_CLI_VERSION || undefined };
11797
+ }
11681
11798
  async function execute(context, args) {
11682
11799
  if (args.length === 0) {
11683
- printTopLevelHelp();
11800
+ printTopLevelHelp(resolveTopLevelLaunchState(context));
11684
11801
  return { ok: true, group: "help", command: "show" };
11685
11802
  }
11686
11803
  const [first, ...rest] = args;