@h-rig/cli 0.0.6-alpha.36 → 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.
package/dist/bin/rig.js CHANGED
@@ -531,7 +531,8 @@ import { loadPolicy as loadPolicy3 } from "@rig/runtime/control-plane/runtime/gu
531
531
  // packages/cli/src/commands.ts
532
532
  init_runner();
533
533
  import {
534
- existsSync as existsSync16
534
+ existsSync as existsSync16,
535
+ readFileSync as readFileSync12
535
536
  } from "fs";
536
537
  import { resolve as resolve25 } from "path";
537
538
  import { readBuildConfig } from "@rig/runtime/build-time-config";
@@ -6305,6 +6306,7 @@ ${acceptance}` : null,
6305
6306
  ${sourceContractLines.join(`
6306
6307
  `)}` : null,
6307
6308
  scopeText || renderSourceScopeValidation(sourceTask, sourceValidation) || null,
6309
+ readPriorPrProgressForPrompt(input.projectRoot, input.taskId),
6308
6310
  initialPrompt ? `Additional operator guidance:
6309
6311
  ${initialPrompt}` : null,
6310
6312
  providerLines.length > 0 ? `Provider-specific runtime tooling:
@@ -6314,6 +6316,26 @@ ${providerLines.join(" ")}` : null,
6314
6316
 
6315
6317
  `);
6316
6318
  }
6319
+ function readPriorPrProgressForPrompt(projectRoot, taskId) {
6320
+ for (const candidate of [
6321
+ resolve20(projectRoot, ".worktrees", taskId, "artifacts", taskId, "pr-state.json"),
6322
+ resolve20(projectRoot, "artifacts", taskId, "pr-state.json")
6323
+ ]) {
6324
+ try {
6325
+ const raw = JSON.parse(readFileSync8(candidate, "utf8"));
6326
+ const entries = Array.isArray(raw) ? raw : [raw];
6327
+ const first = entries.find((entry) => entry && typeof entry === "object" && typeof entry.url === "string");
6328
+ if (!first)
6329
+ continue;
6330
+ return [
6331
+ `Prior progress exists for this task: PR ${first.url}${first.branch ? ` (branch ${first.branch})` : ""} was opened by an earlier run.`,
6332
+ "Check its current state first (diff, checks, review). If the work is already complete and checks are green,",
6333
+ "run `rig-agent completion-verification` to merge and close instead of re-implementing anything."
6334
+ ].join(" ");
6335
+ } catch {}
6336
+ }
6337
+ return null;
6338
+ }
6317
6339
  function firstPromptString(...values) {
6318
6340
  for (const value of values) {
6319
6341
  const trimmed = typeof value === "string" ? value.trim() : "";
@@ -8715,52 +8737,50 @@ import { intro as intro3, log as log4, note as note4, outro as outro3 } from "@c
8715
8737
  import pc4 from "picocolors";
8716
8738
  var TOP_LEVEL_SECTIONS = [
8717
8739
  {
8718
- title: "Server",
8719
- subtitle: "choose the local or remote Rig server that owns this repo",
8740
+ title: "Start here",
8741
+ subtitle: "one-time setup for a repo",
8720
8742
  commands: [
8721
- { command: "rig server status", description: "Show the selected local/remote server for this repo." },
8722
- { command: "rig server use local", description: "Switch this repo back to the local Rig server." },
8723
- { command: "rig server add <alias> <url>", description: "Save a remote Rig server alias." },
8724
- { command: "rig server use <alias>", description: "Switch this repo to a saved remote server." },
8725
- { command: "rig server list", description: "Show saved server aliases, including local." }
8743
+ { command: "rig init", description: "Wizard: config, GitHub auth, task source, server, Pi wiring." },
8744
+ { command: "rig doctor", description: "Check every part of the wiring \u2014 run this when anything feels off." },
8745
+ { command: "rig server use <alias|local>", description: "Pick which Rig server owns this repo (`rig server list` to see them)." }
8726
8746
  ]
8727
8747
  },
8728
8748
  {
8729
- title: "Tasks",
8730
- subtitle: "find work, inspect it, and submit Pi-backed workers",
8749
+ title: "Work",
8750
+ subtitle: "find a task and put an agent on it",
8731
8751
  commands: [
8732
- { command: "rig task list", description: "List tasks from the selected task source/server." },
8733
- { command: "rig task next", description: "Show the next matching task as a selected-task card." },
8734
- { command: "rig task show <id>", description: "Show a human task summary; add --raw or --json for the full payload." },
8735
- { command: "rig task run <id|--next> [--detach]", description: "Submit a task run; interactive mode follows with bundled Pi." }
8752
+ { command: "rig task list", description: "What's on the board (from the selected source/server)." },
8753
+ { command: "rig task next", description: "The next ready task, as a card." },
8754
+ { command: "rig task run --next", description: "Dispatch an agent; interactive mode opens the native Pi session." },
8755
+ { command: "rig task run <id> --detach", description: "Fire-and-forget a specific task." }
8736
8756
  ]
8737
8757
  },
8738
8758
  {
8739
- title: "Runs",
8740
- subtitle: "observe, attach to, and stop live or recent runs",
8759
+ title: "Watch & steer",
8760
+ subtitle: "live runs are observable and steerable, attached or not",
8741
8761
  commands: [
8742
- { command: "rig run list", description: "List recent runs from the selected server or local state." },
8743
- { command: "rig run show <id>", description: "Show a human run summary; add --raw or --json for the full payload." },
8744
- { command: "rig run attach <id> --follow", description: "Open the native bundled Pi live view for a worker run." },
8745
- { command: "rig run stop <id>", description: "Request cancellation for a running worker." }
8762
+ { command: "rig run status", description: "Active and recent runs at a glance." },
8763
+ { command: "rig run attach <id> --follow", description: "Join the live Pi session (worker keeps running if you /detach)." },
8764
+ { command: "rig run steer <id> -m <text>", description: "Drop a message into a live worker without attaching." },
8765
+ { command: "rig run stop <id>", description: "Cancel a running worker." }
8746
8766
  ]
8747
8767
  },
8748
8768
  {
8749
- title: "Review / inbox",
8750
- subtitle: "clear blocked runs and configure completion review",
8769
+ title: "Unblock & gate",
8770
+ subtitle: "answer what workers ask; control what merges",
8751
8771
  commands: [
8752
- { command: "rig inbox approvals", description: "List pending approval requests from local/server run state." },
8753
- { command: "rig inbox inputs", description: "List pending user-input requests from local/server run state." },
8754
- { command: "rig review show|set", description: "Inspect or change the review gate policy." }
8772
+ { command: "rig inbox approvals", description: "Approvals workers are waiting on (then `rig inbox approve \u2026`)." },
8773
+ { command: "rig inbox inputs", description: "Questions workers asked (then `rig inbox respond \u2026`)." },
8774
+ { command: "rig review show|set", description: "The completion review gate (Greptile is mandatory on merges)." }
8755
8775
  ]
8756
8776
  },
8757
8777
  {
8758
- title: "Health / setup",
8759
- subtitle: "bootstrap and diagnose the repo/server/GitHub/Pi path",
8778
+ title: "Extend",
8779
+ subtitle: "more Pi, more plugins",
8760
8780
  commands: [
8761
- { command: "rig init", description: "Interactive setup: config, GitHub auth, task source, server, checkout, Pi." },
8762
- { command: "rig doctor", description: "Diagnose project/server/GitHub/task/Pi wiring." },
8763
- { command: "rig github auth status", description: "Show GitHub auth state on the selected Rig server." }
8781
+ { command: "rig pi search <term>", description: "Discover community Pi extensions on npm." },
8782
+ { command: "rig pi add <pkg>", description: "Add a Pi extension to this project (workers pick it up too)." },
8783
+ { command: "rig plugin list", description: "What the rig.config.ts plugins contribute." }
8764
8784
  ]
8765
8785
  }
8766
8786
  ];
@@ -8968,6 +8988,25 @@ var ALL_GROUPS = [...PRIMARY_GROUPS, ...ADVANCED_GROUPS];
8968
8988
  function heading(title) {
8969
8989
  return pc4.bold(pc4.cyan(title));
8970
8990
  }
8991
+ function renderRigBanner(version) {
8992
+ const m = (s) => pc4.bold(pc4.magenta(s));
8993
+ const c = (s) => pc4.bold(pc4.cyan(s));
8994
+ const y = (s) => pc4.yellow(s);
8995
+ const d = (s) => pc4.dim(s);
8996
+ const lines = [
8997
+ m(" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ") + d(" \u2591\u2592\u2593\u2588 "),
8998
+ m(" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D ") + d("\u2593\u2592\u2591"),
8999
+ c(" \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2557") + d(" \u2591\u2592"),
9000
+ c(" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551") + d(" \u2588\u2593\u2591"),
9001
+ y(" \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D") + d(" \u2592\u2591"),
9002
+ y(" \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D "),
9003
+ "",
9004
+ ` ${c("\u25E2\u25E4")} ${pc4.bold("the control rig for autonomous coding agents")} ${m("//")} ${d("you are the operator")}`,
9005
+ version ? ` ${d(`v${version} \xB7 jack in: rig task run --next`)}` : ` ${d("jack in: rig task run --next")}`
9006
+ ];
9007
+ return lines.join(`
9008
+ `);
9009
+ }
8971
9010
  function commandLine(command, description) {
8972
9011
  const commandColumn = command.length >= 38 ? `${command} ` : command.padEnd(38);
8973
9012
  return `${pc4.dim("\u2502")} ${pc4.bold(commandColumn)} ${description}`;
@@ -9041,12 +9080,25 @@ function renderGroupHelp(groupName) {
9041
9080
  function shouldUseClackOutput2() {
9042
9081
  return Boolean(process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1";
9043
9082
  }
9044
- function printTopLevelHelp() {
9083
+ function printTopLevelHelp(state = {}) {
9045
9084
  if (!shouldUseClackOutput2()) {
9046
9085
  console.log(renderTopLevelHelp());
9047
9086
  return;
9048
9087
  }
9049
- intro3("rig");
9088
+ console.log(renderRigBanner(state.version));
9089
+ console.log("");
9090
+ if (state.projectInitialized === false) {
9091
+ intro3("no rig project in this directory");
9092
+ note4([
9093
+ commandLine("rig init", "Set this repo up: config, GitHub auth, task source, server, Pi."),
9094
+ commandLine("rig init --yes", "Same, non-interactive, sensible defaults."),
9095
+ commandLine("rig doctor", "Already initialized somewhere else? Check the wiring.")
9096
+ ].join(`
9097
+ `), "Get started");
9098
+ outro3("After init: rig task run --next puts an agent on your next task.");
9099
+ return;
9100
+ }
9101
+ intro3(state.selectedServer ? `server: ${state.selectedServer}` : "rig");
9050
9102
  for (const section of TOP_LEVEL_SECTIONS) {
9051
9103
  note4(renderCommandBlock(section.commands), `${section.title} \u2014 ${section.subtitle}`);
9052
9104
  }
@@ -9057,7 +9109,7 @@ function printTopLevelHelp() {
9057
9109
  commandLine("--dry-run", "Print the command plan without mutating state.")
9058
9110
  ].join(`
9059
9111
  `), "Global options");
9060
- outro3("Server \u2192 task \u2192 run \u2192 inbox/review.");
9112
+ outro3("init \u2192 task run \u2192 watch/steer \u2192 inbox/review \u2192 merged.");
9061
9113
  }
9062
9114
  function printAdvancedHelp() {
9063
9115
  if (!shouldUseClackOutput2()) {
@@ -11923,9 +11975,23 @@ function isHelpArg(arg) {
11923
11975
  function helpText() {
11924
11976
  return renderTopLevelHelp();
11925
11977
  }
11978
+ function resolveTopLevelLaunchState(context) {
11979
+ const projectInitialized = hasInitializedRigProject(context.projectRoot);
11980
+ let selectedServer = null;
11981
+ if (projectInitialized) {
11982
+ try {
11983
+ const statePath = resolve25(context.projectRoot, ".rig", "state", "connection.json");
11984
+ if (existsSync16(statePath)) {
11985
+ const parsed = JSON.parse(readFileSync12(statePath, "utf-8"));
11986
+ selectedServer = parsed.remoteUrl || parsed.url || parsed.selected || null;
11987
+ }
11988
+ } catch {}
11989
+ }
11990
+ return { projectInitialized, selectedServer, version: process.env.RIG_CLI_VERSION || readBuildConfig().RIG_CLI_VERSION || undefined };
11991
+ }
11926
11992
  async function execute(context, args) {
11927
11993
  if (args.length === 0) {
11928
- printTopLevelHelp();
11994
+ printTopLevelHelp(resolveTopLevelLaunchState(context));
11929
11995
  return { ok: true, group: "help", command: "show" };
11930
11996
  }
11931
11997
  const [first, ...rest] = args;
@@ -4,52 +4,50 @@ import { intro, log, note, outro } from "@clack/prompts";
4
4
  import pc from "picocolors";
5
5
  var TOP_LEVEL_SECTIONS = [
6
6
  {
7
- title: "Server",
8
- subtitle: "choose the local or remote Rig server that owns this repo",
7
+ title: "Start here",
8
+ subtitle: "one-time setup for a repo",
9
9
  commands: [
10
- { command: "rig server status", description: "Show the selected local/remote server for this repo." },
11
- { command: "rig server use local", description: "Switch this repo back to the local Rig server." },
12
- { command: "rig server add <alias> <url>", description: "Save a remote Rig server alias." },
13
- { command: "rig server use <alias>", description: "Switch this repo to a saved remote server." },
14
- { command: "rig server list", description: "Show saved server aliases, including local." }
10
+ { command: "rig init", description: "Wizard: config, GitHub auth, task source, server, Pi wiring." },
11
+ { command: "rig doctor", description: "Check every part of the wiring \u2014 run this when anything feels off." },
12
+ { command: "rig server use <alias|local>", description: "Pick which Rig server owns this repo (`rig server list` to see them)." }
15
13
  ]
16
14
  },
17
15
  {
18
- title: "Tasks",
19
- subtitle: "find work, inspect it, and submit Pi-backed workers",
16
+ title: "Work",
17
+ subtitle: "find a task and put an agent on it",
20
18
  commands: [
21
- { command: "rig task list", description: "List tasks from the selected task source/server." },
22
- { command: "rig task next", description: "Show the next matching task as a selected-task card." },
23
- { command: "rig task show <id>", description: "Show a human task summary; add --raw or --json for the full payload." },
24
- { command: "rig task run <id|--next> [--detach]", description: "Submit a task run; interactive mode follows with bundled Pi." }
19
+ { command: "rig task list", description: "What's on the board (from the selected source/server)." },
20
+ { command: "rig task next", description: "The next ready task, as a card." },
21
+ { command: "rig task run --next", description: "Dispatch an agent; interactive mode opens the native Pi session." },
22
+ { command: "rig task run <id> --detach", description: "Fire-and-forget a specific task." }
25
23
  ]
26
24
  },
27
25
  {
28
- title: "Runs",
29
- subtitle: "observe, attach to, and stop live or recent runs",
26
+ title: "Watch & steer",
27
+ subtitle: "live runs are observable and steerable, attached or not",
30
28
  commands: [
31
- { command: "rig run list", description: "List recent runs from the selected server or local state." },
32
- { command: "rig run show <id>", description: "Show a human run summary; add --raw or --json for the full payload." },
33
- { command: "rig run attach <id> --follow", description: "Open the native bundled Pi live view for a worker run." },
34
- { command: "rig run stop <id>", description: "Request cancellation for a running worker." }
29
+ { command: "rig run status", description: "Active and recent runs at a glance." },
30
+ { command: "rig run attach <id> --follow", description: "Join the live Pi session (worker keeps running if you /detach)." },
31
+ { command: "rig run steer <id> -m <text>", description: "Drop a message into a live worker without attaching." },
32
+ { command: "rig run stop <id>", description: "Cancel a running worker." }
35
33
  ]
36
34
  },
37
35
  {
38
- title: "Review / inbox",
39
- subtitle: "clear blocked runs and configure completion review",
36
+ title: "Unblock & gate",
37
+ subtitle: "answer what workers ask; control what merges",
40
38
  commands: [
41
- { command: "rig inbox approvals", description: "List pending approval requests from local/server run state." },
42
- { command: "rig inbox inputs", description: "List pending user-input requests from local/server run state." },
43
- { command: "rig review show|set", description: "Inspect or change the review gate policy." }
39
+ { command: "rig inbox approvals", description: "Approvals workers are waiting on (then `rig inbox approve \u2026`)." },
40
+ { command: "rig inbox inputs", description: "Questions workers asked (then `rig inbox respond \u2026`)." },
41
+ { command: "rig review show|set", description: "The completion review gate (Greptile is mandatory on merges)." }
44
42
  ]
45
43
  },
46
44
  {
47
- title: "Health / setup",
48
- subtitle: "bootstrap and diagnose the repo/server/GitHub/Pi path",
45
+ title: "Extend",
46
+ subtitle: "more Pi, more plugins",
49
47
  commands: [
50
- { command: "rig init", description: "Interactive setup: config, GitHub auth, task source, server, checkout, Pi." },
51
- { command: "rig doctor", description: "Diagnose project/server/GitHub/task/Pi wiring." },
52
- { command: "rig github auth status", description: "Show GitHub auth state on the selected Rig server." }
48
+ { command: "rig pi search <term>", description: "Discover community Pi extensions on npm." },
49
+ { command: "rig pi add <pkg>", description: "Add a Pi extension to this project (workers pick it up too)." },
50
+ { command: "rig plugin list", description: "What the rig.config.ts plugins contribute." }
53
51
  ]
54
52
  }
55
53
  ];
@@ -257,6 +255,25 @@ var ALL_GROUPS = [...PRIMARY_GROUPS, ...ADVANCED_GROUPS];
257
255
  function heading(title) {
258
256
  return pc.bold(pc.cyan(title));
259
257
  }
258
+ function renderRigBanner(version) {
259
+ const m = (s) => pc.bold(pc.magenta(s));
260
+ const c = (s) => pc.bold(pc.cyan(s));
261
+ const y = (s) => pc.yellow(s);
262
+ const d = (s) => pc.dim(s);
263
+ const lines = [
264
+ m(" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ") + d(" \u2591\u2592\u2593\u2588 "),
265
+ m(" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D ") + d("\u2593\u2592\u2591"),
266
+ c(" \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2557") + d(" \u2591\u2592"),
267
+ c(" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551") + d(" \u2588\u2593\u2591"),
268
+ y(" \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D") + d(" \u2592\u2591"),
269
+ y(" \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D "),
270
+ "",
271
+ ` ${c("\u25E2\u25E4")} ${pc.bold("the control rig for autonomous coding agents")} ${m("//")} ${d("you are the operator")}`,
272
+ version ? ` ${d(`v${version} \xB7 jack in: rig task run --next`)}` : ` ${d("jack in: rig task run --next")}`
273
+ ];
274
+ return lines.join(`
275
+ `);
276
+ }
260
277
  function commandLine(command, description) {
261
278
  const commandColumn = command.length >= 38 ? `${command} ` : command.padEnd(38);
262
279
  return `${pc.dim("\u2502")} ${pc.bold(commandColumn)} ${description}`;
@@ -333,12 +350,25 @@ function listHelpGroups() {
333
350
  function shouldUseClackOutput() {
334
351
  return Boolean(process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1";
335
352
  }
336
- function printTopLevelHelp() {
353
+ function printTopLevelHelp(state = {}) {
337
354
  if (!shouldUseClackOutput()) {
338
355
  console.log(renderTopLevelHelp());
339
356
  return;
340
357
  }
341
- intro("rig");
358
+ console.log(renderRigBanner(state.version));
359
+ console.log("");
360
+ if (state.projectInitialized === false) {
361
+ intro("no rig project in this directory");
362
+ note([
363
+ commandLine("rig init", "Set this repo up: config, GitHub auth, task source, server, Pi."),
364
+ commandLine("rig init --yes", "Same, non-interactive, sensible defaults."),
365
+ commandLine("rig doctor", "Already initialized somewhere else? Check the wiring.")
366
+ ].join(`
367
+ `), "Get started");
368
+ outro("After init: rig task run --next puts an agent on your next task.");
369
+ return;
370
+ }
371
+ intro(state.selectedServer ? `server: ${state.selectedServer}` : "rig");
342
372
  for (const section of TOP_LEVEL_SECTIONS) {
343
373
  note(renderCommandBlock(section.commands), `${section.title} \u2014 ${section.subtitle}`);
344
374
  }
@@ -349,7 +379,7 @@ function printTopLevelHelp() {
349
379
  commandLine("--dry-run", "Print the command plan without mutating state.")
350
380
  ].join(`
351
381
  `), "Global options");
352
- outro("Server \u2192 task \u2192 run \u2192 inbox/review.");
382
+ outro("init \u2192 task run \u2192 watch/steer \u2192 inbox/review \u2192 merged.");
353
383
  }
354
384
  function printAdvancedHelp() {
355
385
  if (!shouldUseClackOutput()) {
@@ -393,6 +423,7 @@ function printGroupHelpDocument(groupName) {
393
423
  }
394
424
  export {
395
425
  renderTopLevelHelp,
426
+ renderRigBanner,
396
427
  renderGroupHelp,
397
428
  renderAdvancedHelp,
398
429
  printTopLevelHelp,
@@ -205,6 +205,7 @@ ${acceptance}` : null,
205
205
  ${sourceContractLines.join(`
206
206
  `)}` : null,
207
207
  scopeText || renderSourceScopeValidation(sourceTask, sourceValidation) || null,
208
+ readPriorPrProgressForPrompt(input.projectRoot, input.taskId),
208
209
  initialPrompt ? `Additional operator guidance:
209
210
  ${initialPrompt}` : null,
210
211
  providerLines.length > 0 ? `Provider-specific runtime tooling:
@@ -214,6 +215,26 @@ ${providerLines.join(" ")}` : null,
214
215
 
215
216
  `);
216
217
  }
218
+ function readPriorPrProgressForPrompt(projectRoot, taskId) {
219
+ for (const candidate of [
220
+ resolve3(projectRoot, ".worktrees", taskId, "artifacts", taskId, "pr-state.json"),
221
+ resolve3(projectRoot, "artifacts", taskId, "pr-state.json")
222
+ ]) {
223
+ try {
224
+ const raw = JSON.parse(readFileSync(candidate, "utf8"));
225
+ const entries = Array.isArray(raw) ? raw : [raw];
226
+ const first = entries.find((entry) => entry && typeof entry === "object" && typeof entry.url === "string");
227
+ if (!first)
228
+ continue;
229
+ return [
230
+ `Prior progress exists for this task: PR ${first.url}${first.branch ? ` (branch ${first.branch})` : ""} was opened by an earlier run.`,
231
+ "Check its current state first (diff, checks, review). If the work is already complete and checks are green,",
232
+ "run `rig-agent completion-verification` to merge and close instead of re-implementing anything."
233
+ ].join(" ");
234
+ } catch {}
235
+ }
236
+ return null;
237
+ }
217
238
  function firstPromptString(...values) {
218
239
  for (const value of values) {
219
240
  const trimmed = typeof value === "string" ? value.trim() : "";
@@ -314,6 +314,7 @@ ${acceptance}` : null,
314
314
  ${sourceContractLines.join(`
315
315
  `)}` : null,
316
316
  scopeText || renderSourceScopeValidation(sourceTask, sourceValidation) || null,
317
+ readPriorPrProgressForPrompt(input.projectRoot, input.taskId),
317
318
  initialPrompt ? `Additional operator guidance:
318
319
  ${initialPrompt}` : null,
319
320
  providerLines.length > 0 ? `Provider-specific runtime tooling:
@@ -323,6 +324,26 @@ ${providerLines.join(" ")}` : null,
323
324
 
324
325
  `);
325
326
  }
327
+ function readPriorPrProgressForPrompt(projectRoot, taskId) {
328
+ for (const candidate of [
329
+ resolve3(projectRoot, ".worktrees", taskId, "artifacts", taskId, "pr-state.json"),
330
+ resolve3(projectRoot, "artifacts", taskId, "pr-state.json")
331
+ ]) {
332
+ try {
333
+ const raw = JSON.parse(readFileSync(candidate, "utf8"));
334
+ const entries = Array.isArray(raw) ? raw : [raw];
335
+ const first = entries.find((entry) => entry && typeof entry === "object" && typeof entry.url === "string");
336
+ if (!first)
337
+ continue;
338
+ return [
339
+ `Prior progress exists for this task: PR ${first.url}${first.branch ? ` (branch ${first.branch})` : ""} was opened by an earlier run.`,
340
+ "Check its current state first (diff, checks, review). If the work is already complete and checks are green,",
341
+ "run `rig-agent completion-verification` to merge and close instead of re-implementing anything."
342
+ ].join(" ");
343
+ } catch {}
344
+ }
345
+ return null;
346
+ }
326
347
  function firstPromptString(...values) {
327
348
  for (const value of values) {
328
349
  const trimmed = typeof value === "string" ? value.trim() : "";
@@ -1874,52 +1874,50 @@ import { intro, log as log2, note as note2, outro } from "@clack/prompts";
1874
1874
  import pc2 from "picocolors";
1875
1875
  var TOP_LEVEL_SECTIONS = [
1876
1876
  {
1877
- title: "Server",
1878
- subtitle: "choose the local or remote Rig server that owns this repo",
1877
+ title: "Start here",
1878
+ subtitle: "one-time setup for a repo",
1879
1879
  commands: [
1880
- { command: "rig server status", description: "Show the selected local/remote server for this repo." },
1881
- { command: "rig server use local", description: "Switch this repo back to the local Rig server." },
1882
- { command: "rig server add <alias> <url>", description: "Save a remote Rig server alias." },
1883
- { command: "rig server use <alias>", description: "Switch this repo to a saved remote server." },
1884
- { 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)." }
1885
1883
  ]
1886
1884
  },
1887
1885
  {
1888
- title: "Tasks",
1889
- subtitle: "find work, inspect it, and submit Pi-backed workers",
1886
+ title: "Work",
1887
+ subtitle: "find a task and put an agent on it",
1890
1888
  commands: [
1891
- { command: "rig task list", description: "List tasks from the selected task source/server." },
1892
- { command: "rig task next", description: "Show the next matching task as a selected-task card." },
1893
- { command: "rig task show <id>", description: "Show a human task summary; add --raw or --json for the full payload." },
1894
- { 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." }
1895
1893
  ]
1896
1894
  },
1897
1895
  {
1898
- title: "Runs",
1899
- 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",
1900
1898
  commands: [
1901
- { command: "rig run list", description: "List recent runs from the selected server or local state." },
1902
- { command: "rig run show <id>", description: "Show a human run summary; add --raw or --json for the full payload." },
1903
- { command: "rig run attach <id> --follow", description: "Open the native bundled Pi live view for a worker run." },
1904
- { 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." }
1905
1903
  ]
1906
1904
  },
1907
1905
  {
1908
- title: "Review / inbox",
1909
- subtitle: "clear blocked runs and configure completion review",
1906
+ title: "Unblock & gate",
1907
+ subtitle: "answer what workers ask; control what merges",
1910
1908
  commands: [
1911
- { command: "rig inbox approvals", description: "List pending approval requests from local/server run state." },
1912
- { command: "rig inbox inputs", description: "List pending user-input requests from local/server run state." },
1913
- { 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)." }
1914
1912
  ]
1915
1913
  },
1916
1914
  {
1917
- title: "Health / setup",
1918
- subtitle: "bootstrap and diagnose the repo/server/GitHub/Pi path",
1915
+ title: "Extend",
1916
+ subtitle: "more Pi, more plugins",
1919
1917
  commands: [
1920
- { command: "rig init", description: "Interactive setup: config, GitHub auth, task source, server, checkout, Pi." },
1921
- { command: "rig doctor", description: "Diagnose project/server/GitHub/task/Pi wiring." },
1922
- { 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." }
1923
1921
  ]
1924
1922
  }
1925
1923
  ];
@@ -2121,6 +2119,25 @@ var ALL_GROUPS = [...PRIMARY_GROUPS, ...ADVANCED_GROUPS];
2121
2119
  function heading(title) {
2122
2120
  return pc2.bold(pc2.cyan(title));
2123
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
+ }
2124
2141
  function commandLine(command, description) {
2125
2142
  const commandColumn = command.length >= 38 ? `${command} ` : command.padEnd(38);
2126
2143
  return `${pc2.dim("\u2502")} ${pc2.bold(commandColumn)} ${description}`;
@@ -2177,12 +2194,25 @@ function renderGroupHelp(groupName) {
2177
2194
  function shouldUseClackOutput2() {
2178
2195
  return Boolean(process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1";
2179
2196
  }
2180
- function printTopLevelHelp() {
2197
+ function printTopLevelHelp(state = {}) {
2181
2198
  if (!shouldUseClackOutput2()) {
2182
2199
  console.log(renderTopLevelHelp());
2183
2200
  return;
2184
2201
  }
2185
- 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");
2186
2216
  for (const section of TOP_LEVEL_SECTIONS) {
2187
2217
  note2(renderCommandBlock(section.commands), `${section.title} \u2014 ${section.subtitle}`);
2188
2218
  }
@@ -2193,7 +2223,7 @@ function printTopLevelHelp() {
2193
2223
  commandLine("--dry-run", "Print the command plan without mutating state.")
2194
2224
  ].join(`
2195
2225
  `), "Global options");
2196
- outro("Server \u2192 task \u2192 run \u2192 inbox/review.");
2226
+ outro("init \u2192 task run \u2192 watch/steer \u2192 inbox/review \u2192 merged.");
2197
2227
  }
2198
2228
  function printGroupHelpDocument(groupName) {
2199
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() : "";
@@ -8521,52 +8543,50 @@ import { intro as intro3, log as log4, note as note4, outro as outro3 } from "@c
8521
8543
  import pc4 from "picocolors";
8522
8544
  var TOP_LEVEL_SECTIONS = [
8523
8545
  {
8524
- title: "Server",
8525
- subtitle: "choose the local or remote Rig server that owns this repo",
8546
+ title: "Start here",
8547
+ subtitle: "one-time setup for a repo",
8526
8548
  commands: [
8527
- { command: "rig server status", description: "Show the selected local/remote server for this repo." },
8528
- { command: "rig server use local", description: "Switch this repo back to the local Rig server." },
8529
- { command: "rig server add <alias> <url>", description: "Save a remote Rig server alias." },
8530
- { command: "rig server use <alias>", description: "Switch this repo to a saved remote server." },
8531
- { 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)." }
8532
8552
  ]
8533
8553
  },
8534
8554
  {
8535
- title: "Tasks",
8536
- subtitle: "find work, inspect it, and submit Pi-backed workers",
8555
+ title: "Work",
8556
+ subtitle: "find a task and put an agent on it",
8537
8557
  commands: [
8538
- { command: "rig task list", description: "List tasks from the selected task source/server." },
8539
- { command: "rig task next", description: "Show the next matching task as a selected-task card." },
8540
- { command: "rig task show <id>", description: "Show a human task summary; add --raw or --json for the full payload." },
8541
- { 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." }
8542
8562
  ]
8543
8563
  },
8544
8564
  {
8545
- title: "Runs",
8546
- 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",
8547
8567
  commands: [
8548
- { command: "rig run list", description: "List recent runs from the selected server or local state." },
8549
- { command: "rig run show <id>", description: "Show a human run summary; add --raw or --json for the full payload." },
8550
- { command: "rig run attach <id> --follow", description: "Open the native bundled Pi live view for a worker run." },
8551
- { 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." }
8552
8572
  ]
8553
8573
  },
8554
8574
  {
8555
- title: "Review / inbox",
8556
- subtitle: "clear blocked runs and configure completion review",
8575
+ title: "Unblock & gate",
8576
+ subtitle: "answer what workers ask; control what merges",
8557
8577
  commands: [
8558
- { command: "rig inbox approvals", description: "List pending approval requests from local/server run state." },
8559
- { command: "rig inbox inputs", description: "List pending user-input requests from local/server run state." },
8560
- { 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)." }
8561
8581
  ]
8562
8582
  },
8563
8583
  {
8564
- title: "Health / setup",
8565
- subtitle: "bootstrap and diagnose the repo/server/GitHub/Pi path",
8584
+ title: "Extend",
8585
+ subtitle: "more Pi, more plugins",
8566
8586
  commands: [
8567
- { command: "rig init", description: "Interactive setup: config, GitHub auth, task source, server, checkout, Pi." },
8568
- { command: "rig doctor", description: "Diagnose project/server/GitHub/task/Pi wiring." },
8569
- { 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." }
8570
8590
  ]
8571
8591
  }
8572
8592
  ];
@@ -8774,6 +8794,25 @@ var ALL_GROUPS = [...PRIMARY_GROUPS, ...ADVANCED_GROUPS];
8774
8794
  function heading(title) {
8775
8795
  return pc4.bold(pc4.cyan(title));
8776
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
+ }
8777
8816
  function commandLine(command, description) {
8778
8817
  const commandColumn = command.length >= 38 ? `${command} ` : command.padEnd(38);
8779
8818
  return `${pc4.dim("\u2502")} ${pc4.bold(commandColumn)} ${description}`;
@@ -8847,12 +8886,25 @@ function renderGroupHelp(groupName) {
8847
8886
  function shouldUseClackOutput2() {
8848
8887
  return Boolean(process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1";
8849
8888
  }
8850
- function printTopLevelHelp() {
8889
+ function printTopLevelHelp(state = {}) {
8851
8890
  if (!shouldUseClackOutput2()) {
8852
8891
  console.log(renderTopLevelHelp());
8853
8892
  return;
8854
8893
  }
8855
- 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");
8856
8908
  for (const section of TOP_LEVEL_SECTIONS) {
8857
8909
  note4(renderCommandBlock(section.commands), `${section.title} \u2014 ${section.subtitle}`);
8858
8910
  }
@@ -8863,7 +8915,7 @@ function printTopLevelHelp() {
8863
8915
  commandLine("--dry-run", "Print the command plan without mutating state.")
8864
8916
  ].join(`
8865
8917
  `), "Global options");
8866
- outro3("Server \u2192 task \u2192 run \u2192 inbox/review.");
8918
+ outro3("init \u2192 task run \u2192 watch/steer \u2192 inbox/review \u2192 merged.");
8867
8919
  }
8868
8920
  function printAdvancedHelp() {
8869
8921
  if (!shouldUseClackOutput2()) {
@@ -11729,9 +11781,23 @@ function isHelpArg(arg) {
11729
11781
  function helpText() {
11730
11782
  return renderTopLevelHelp();
11731
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
+ }
11732
11798
  async function execute(context, args) {
11733
11799
  if (args.length === 0) {
11734
- printTopLevelHelp();
11800
+ printTopLevelHelp(resolveTopLevelLaunchState(context));
11735
11801
  return { ok: true, group: "help", command: "show" };
11736
11802
  }
11737
11803
  const [first, ...rest] = args;
package/dist/src/index.js CHANGED
@@ -527,7 +527,8 @@ var init_plugin = __esm(() => {
527
527
  // packages/cli/src/commands.ts
528
528
  init_runner();
529
529
  import {
530
- existsSync as existsSync16
530
+ existsSync as existsSync16,
531
+ readFileSync as readFileSync12
531
532
  } from "fs";
532
533
  import { resolve as resolve25 } from "path";
533
534
  import { readBuildConfig } from "@rig/runtime/build-time-config";
@@ -6301,6 +6302,7 @@ ${acceptance}` : null,
6301
6302
  ${sourceContractLines.join(`
6302
6303
  `)}` : null,
6303
6304
  scopeText || renderSourceScopeValidation(sourceTask, sourceValidation) || null,
6305
+ readPriorPrProgressForPrompt(input.projectRoot, input.taskId),
6304
6306
  initialPrompt ? `Additional operator guidance:
6305
6307
  ${initialPrompt}` : null,
6306
6308
  providerLines.length > 0 ? `Provider-specific runtime tooling:
@@ -6310,6 +6312,26 @@ ${providerLines.join(" ")}` : null,
6310
6312
 
6311
6313
  `);
6312
6314
  }
6315
+ function readPriorPrProgressForPrompt(projectRoot, taskId) {
6316
+ for (const candidate of [
6317
+ resolve20(projectRoot, ".worktrees", taskId, "artifacts", taskId, "pr-state.json"),
6318
+ resolve20(projectRoot, "artifacts", taskId, "pr-state.json")
6319
+ ]) {
6320
+ try {
6321
+ const raw = JSON.parse(readFileSync8(candidate, "utf8"));
6322
+ const entries = Array.isArray(raw) ? raw : [raw];
6323
+ const first = entries.find((entry) => entry && typeof entry === "object" && typeof entry.url === "string");
6324
+ if (!first)
6325
+ continue;
6326
+ return [
6327
+ `Prior progress exists for this task: PR ${first.url}${first.branch ? ` (branch ${first.branch})` : ""} was opened by an earlier run.`,
6328
+ "Check its current state first (diff, checks, review). If the work is already complete and checks are green,",
6329
+ "run `rig-agent completion-verification` to merge and close instead of re-implementing anything."
6330
+ ].join(" ");
6331
+ } catch {}
6332
+ }
6333
+ return null;
6334
+ }
6313
6335
  function firstPromptString(...values) {
6314
6336
  for (const value of values) {
6315
6337
  const trimmed = typeof value === "string" ? value.trim() : "";
@@ -8711,52 +8733,50 @@ import { intro as intro3, log as log4, note as note4, outro as outro3 } from "@c
8711
8733
  import pc4 from "picocolors";
8712
8734
  var TOP_LEVEL_SECTIONS = [
8713
8735
  {
8714
- title: "Server",
8715
- subtitle: "choose the local or remote Rig server that owns this repo",
8736
+ title: "Start here",
8737
+ subtitle: "one-time setup for a repo",
8716
8738
  commands: [
8717
- { command: "rig server status", description: "Show the selected local/remote server for this repo." },
8718
- { command: "rig server use local", description: "Switch this repo back to the local Rig server." },
8719
- { command: "rig server add <alias> <url>", description: "Save a remote Rig server alias." },
8720
- { command: "rig server use <alias>", description: "Switch this repo to a saved remote server." },
8721
- { command: "rig server list", description: "Show saved server aliases, including local." }
8739
+ { command: "rig init", description: "Wizard: config, GitHub auth, task source, server, Pi wiring." },
8740
+ { command: "rig doctor", description: "Check every part of the wiring \u2014 run this when anything feels off." },
8741
+ { command: "rig server use <alias|local>", description: "Pick which Rig server owns this repo (`rig server list` to see them)." }
8722
8742
  ]
8723
8743
  },
8724
8744
  {
8725
- title: "Tasks",
8726
- subtitle: "find work, inspect it, and submit Pi-backed workers",
8745
+ title: "Work",
8746
+ subtitle: "find a task and put an agent on it",
8727
8747
  commands: [
8728
- { command: "rig task list", description: "List tasks from the selected task source/server." },
8729
- { command: "rig task next", description: "Show the next matching task as a selected-task card." },
8730
- { command: "rig task show <id>", description: "Show a human task summary; add --raw or --json for the full payload." },
8731
- { command: "rig task run <id|--next> [--detach]", description: "Submit a task run; interactive mode follows with bundled Pi." }
8748
+ { command: "rig task list", description: "What's on the board (from the selected source/server)." },
8749
+ { command: "rig task next", description: "The next ready task, as a card." },
8750
+ { command: "rig task run --next", description: "Dispatch an agent; interactive mode opens the native Pi session." },
8751
+ { command: "rig task run <id> --detach", description: "Fire-and-forget a specific task." }
8732
8752
  ]
8733
8753
  },
8734
8754
  {
8735
- title: "Runs",
8736
- subtitle: "observe, attach to, and stop live or recent runs",
8755
+ title: "Watch & steer",
8756
+ subtitle: "live runs are observable and steerable, attached or not",
8737
8757
  commands: [
8738
- { command: "rig run list", description: "List recent runs from the selected server or local state." },
8739
- { command: "rig run show <id>", description: "Show a human run summary; add --raw or --json for the full payload." },
8740
- { command: "rig run attach <id> --follow", description: "Open the native bundled Pi live view for a worker run." },
8741
- { command: "rig run stop <id>", description: "Request cancellation for a running worker." }
8758
+ { command: "rig run status", description: "Active and recent runs at a glance." },
8759
+ { command: "rig run attach <id> --follow", description: "Join the live Pi session (worker keeps running if you /detach)." },
8760
+ { command: "rig run steer <id> -m <text>", description: "Drop a message into a live worker without attaching." },
8761
+ { command: "rig run stop <id>", description: "Cancel a running worker." }
8742
8762
  ]
8743
8763
  },
8744
8764
  {
8745
- title: "Review / inbox",
8746
- subtitle: "clear blocked runs and configure completion review",
8765
+ title: "Unblock & gate",
8766
+ subtitle: "answer what workers ask; control what merges",
8747
8767
  commands: [
8748
- { command: "rig inbox approvals", description: "List pending approval requests from local/server run state." },
8749
- { command: "rig inbox inputs", description: "List pending user-input requests from local/server run state." },
8750
- { command: "rig review show|set", description: "Inspect or change the review gate policy." }
8768
+ { command: "rig inbox approvals", description: "Approvals workers are waiting on (then `rig inbox approve \u2026`)." },
8769
+ { command: "rig inbox inputs", description: "Questions workers asked (then `rig inbox respond \u2026`)." },
8770
+ { command: "rig review show|set", description: "The completion review gate (Greptile is mandatory on merges)." }
8751
8771
  ]
8752
8772
  },
8753
8773
  {
8754
- title: "Health / setup",
8755
- subtitle: "bootstrap and diagnose the repo/server/GitHub/Pi path",
8774
+ title: "Extend",
8775
+ subtitle: "more Pi, more plugins",
8756
8776
  commands: [
8757
- { command: "rig init", description: "Interactive setup: config, GitHub auth, task source, server, checkout, Pi." },
8758
- { command: "rig doctor", description: "Diagnose project/server/GitHub/task/Pi wiring." },
8759
- { command: "rig github auth status", description: "Show GitHub auth state on the selected Rig server." }
8777
+ { command: "rig pi search <term>", description: "Discover community Pi extensions on npm." },
8778
+ { command: "rig pi add <pkg>", description: "Add a Pi extension to this project (workers pick it up too)." },
8779
+ { command: "rig plugin list", description: "What the rig.config.ts plugins contribute." }
8760
8780
  ]
8761
8781
  }
8762
8782
  ];
@@ -8964,6 +8984,25 @@ var ALL_GROUPS = [...PRIMARY_GROUPS, ...ADVANCED_GROUPS];
8964
8984
  function heading(title) {
8965
8985
  return pc4.bold(pc4.cyan(title));
8966
8986
  }
8987
+ function renderRigBanner(version) {
8988
+ const m = (s) => pc4.bold(pc4.magenta(s));
8989
+ const c = (s) => pc4.bold(pc4.cyan(s));
8990
+ const y = (s) => pc4.yellow(s);
8991
+ const d = (s) => pc4.dim(s);
8992
+ const lines = [
8993
+ m(" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ") + d(" \u2591\u2592\u2593\u2588 "),
8994
+ m(" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D ") + d("\u2593\u2592\u2591"),
8995
+ c(" \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2557") + d(" \u2591\u2592"),
8996
+ c(" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551") + d(" \u2588\u2593\u2591"),
8997
+ y(" \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D") + d(" \u2592\u2591"),
8998
+ y(" \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D "),
8999
+ "",
9000
+ ` ${c("\u25E2\u25E4")} ${pc4.bold("the control rig for autonomous coding agents")} ${m("//")} ${d("you are the operator")}`,
9001
+ version ? ` ${d(`v${version} \xB7 jack in: rig task run --next`)}` : ` ${d("jack in: rig task run --next")}`
9002
+ ];
9003
+ return lines.join(`
9004
+ `);
9005
+ }
8967
9006
  function commandLine(command, description) {
8968
9007
  const commandColumn = command.length >= 38 ? `${command} ` : command.padEnd(38);
8969
9008
  return `${pc4.dim("\u2502")} ${pc4.bold(commandColumn)} ${description}`;
@@ -9037,12 +9076,25 @@ function renderGroupHelp(groupName) {
9037
9076
  function shouldUseClackOutput2() {
9038
9077
  return Boolean(process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1";
9039
9078
  }
9040
- function printTopLevelHelp() {
9079
+ function printTopLevelHelp(state = {}) {
9041
9080
  if (!shouldUseClackOutput2()) {
9042
9081
  console.log(renderTopLevelHelp());
9043
9082
  return;
9044
9083
  }
9045
- intro3("rig");
9084
+ console.log(renderRigBanner(state.version));
9085
+ console.log("");
9086
+ if (state.projectInitialized === false) {
9087
+ intro3("no rig project in this directory");
9088
+ note4([
9089
+ commandLine("rig init", "Set this repo up: config, GitHub auth, task source, server, Pi."),
9090
+ commandLine("rig init --yes", "Same, non-interactive, sensible defaults."),
9091
+ commandLine("rig doctor", "Already initialized somewhere else? Check the wiring.")
9092
+ ].join(`
9093
+ `), "Get started");
9094
+ outro3("After init: rig task run --next puts an agent on your next task.");
9095
+ return;
9096
+ }
9097
+ intro3(state.selectedServer ? `server: ${state.selectedServer}` : "rig");
9046
9098
  for (const section of TOP_LEVEL_SECTIONS) {
9047
9099
  note4(renderCommandBlock(section.commands), `${section.title} \u2014 ${section.subtitle}`);
9048
9100
  }
@@ -9053,7 +9105,7 @@ function printTopLevelHelp() {
9053
9105
  commandLine("--dry-run", "Print the command plan without mutating state.")
9054
9106
  ].join(`
9055
9107
  `), "Global options");
9056
- outro3("Server \u2192 task \u2192 run \u2192 inbox/review.");
9108
+ outro3("init \u2192 task run \u2192 watch/steer \u2192 inbox/review \u2192 merged.");
9057
9109
  }
9058
9110
  function printAdvancedHelp() {
9059
9111
  if (!shouldUseClackOutput2()) {
@@ -11919,9 +11971,23 @@ function isHelpArg(arg) {
11919
11971
  function helpText() {
11920
11972
  return renderTopLevelHelp();
11921
11973
  }
11974
+ function resolveTopLevelLaunchState(context) {
11975
+ const projectInitialized = hasInitializedRigProject(context.projectRoot);
11976
+ let selectedServer = null;
11977
+ if (projectInitialized) {
11978
+ try {
11979
+ const statePath = resolve25(context.projectRoot, ".rig", "state", "connection.json");
11980
+ if (existsSync16(statePath)) {
11981
+ const parsed = JSON.parse(readFileSync12(statePath, "utf-8"));
11982
+ selectedServer = parsed.remoteUrl || parsed.url || parsed.selected || null;
11983
+ }
11984
+ } catch {}
11985
+ }
11986
+ return { projectInitialized, selectedServer, version: process.env.RIG_CLI_VERSION || readBuildConfig().RIG_CLI_VERSION || undefined };
11987
+ }
11922
11988
  async function execute(context, args) {
11923
11989
  if (args.length === 0) {
11924
- printTopLevelHelp();
11990
+ printTopLevelHelp(resolveTopLevelLaunchState(context));
11925
11991
  return { ok: true, group: "help", command: "show" };
11926
11992
  }
11927
11993
  const [first, ...rest] = args;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@h-rig/cli",
3
- "version": "0.0.6-alpha.36",
3
+ "version": "0.0.6-alpha.37",
4
4
  "type": "module",
5
5
  "description": "Rig package",
6
6
  "license": "UNLICENSED",
@@ -23,11 +23,11 @@
23
23
  },
24
24
  "dependencies": {
25
25
  "@clack/prompts": "^1.2.0",
26
- "@earendil-works/pi-coding-agent": "npm:@h-rig/pi-coding-agent@0.0.6-alpha.36",
27
- "@rig/core": "npm:@h-rig/core@0.0.6-alpha.36",
28
- "@rig/runtime": "npm:@h-rig/runtime@0.0.6-alpha.36",
29
- "@rig/client": "npm:@h-rig/client@0.0.6-alpha.36",
30
- "@rig/server": "npm:@h-rig/server@0.0.6-alpha.36",
26
+ "@earendil-works/pi-coding-agent": "npm:@h-rig/pi-coding-agent@0.0.6-alpha.37",
27
+ "@rig/core": "npm:@h-rig/core@0.0.6-alpha.37",
28
+ "@rig/runtime": "npm:@h-rig/runtime@0.0.6-alpha.37",
29
+ "@rig/client": "npm:@h-rig/client@0.0.6-alpha.37",
30
+ "@rig/server": "npm:@h-rig/server@0.0.6-alpha.37",
31
31
  "picocolors": "^1.1.1"
32
32
  }
33
33
  }