@h-rig/cli 0.0.6-alpha.27 → 0.0.6-alpha.28

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.
Files changed (38) hide show
  1. package/dist/bin/rig.js +1038 -620
  2. package/dist/src/commands/_cli-format.js +211 -6
  3. package/dist/src/commands/_connection-state.js +1 -1
  4. package/dist/src/commands/_doctor-checks.js +3 -3
  5. package/dist/src/commands/_help-catalog.js +225 -64
  6. package/dist/src/commands/_operator-view.js +1 -1
  7. package/dist/src/commands/_pi-frontend.js +1 -1
  8. package/dist/src/commands/_pi-worker-bridge-extension.js +1 -1
  9. package/dist/src/commands/_preflight.js +2 -2
  10. package/dist/src/commands/_server-client.js +1 -1
  11. package/dist/src/commands/_snapshot-upload.js +1 -1
  12. package/dist/src/commands/agent.js +7 -7
  13. package/dist/src/commands/browser.js +4 -4
  14. package/dist/src/commands/connect.js +5 -4
  15. package/dist/src/commands/dist.js +4 -4
  16. package/dist/src/commands/doctor.js +3 -3
  17. package/dist/src/commands/github.js +1 -1
  18. package/dist/src/commands/inbox.js +351 -29
  19. package/dist/src/commands/init.js +3 -3
  20. package/dist/src/commands/inspect.js +10 -10
  21. package/dist/src/commands/inspector.js +2 -2
  22. package/dist/src/commands/plugin.js +3 -3
  23. package/dist/src/commands/profile-and-review.js +8 -8
  24. package/dist/src/commands/queue.js +1 -1
  25. package/dist/src/commands/remote.js +18 -18
  26. package/dist/src/commands/repo-git-harness.js +4 -4
  27. package/dist/src/commands/run.js +157 -37
  28. package/dist/src/commands/server.js +6 -5
  29. package/dist/src/commands/setup.js +8 -8
  30. package/dist/src/commands/task-report-bug.js +5 -5
  31. package/dist/src/commands/task-run-driver.js +1 -1
  32. package/dist/src/commands/task.js +451 -45
  33. package/dist/src/commands/test.js +3 -3
  34. package/dist/src/commands/workspace.js +4 -4
  35. package/dist/src/commands.js +1038 -620
  36. package/dist/src/index.js +1038 -620
  37. package/dist/src/report-bug.js +3 -3
  38. package/package.json +6 -6
package/dist/bin/rig.js CHANGED
@@ -495,15 +495,15 @@ function buildBugReportMarkdown(input, browser, screenshots, assets) {
495
495
  ...input.issueId ? [
496
496
  `- Canonical task assets live under \`artifacts/${input.issueId}/bug-report/\`.`,
497
497
  `- Start with \`artifacts/${input.issueId}/bug-report/task.md\` and the files in \`artifacts/${input.issueId}/bug-report/assets/\`.`,
498
- browserRequired ? `- Run \`bun run rig task info --task ${input.issueId}\` to confirm browser wiring before debugging.` : `- Run \`bun run rig task info --task ${input.issueId}\` to confirm scope and artifact links before debugging.`
498
+ browserRequired ? `- Run \`rig task info --task ${input.issueId}\` to confirm browser wiring before debugging.` : `- Run \`rig task info --task ${input.issueId}\` to confirm scope and artifact links before debugging.`
499
499
  ] : [
500
- "- Draft-only report: convert this into a beads task before assigning it to an agent run."
500
+ "- Draft-only report: convert this into a Rig task before assigning it to an agent run."
501
501
  ],
502
502
  "",
503
503
  "## Validation",
504
504
  "",
505
505
  "```bash",
506
- ...input.issueId ? [`bun run rig task validate --task ${input.issueId}`] : [],
506
+ ...input.issueId ? [`rig task validate --task ${input.issueId}`] : [],
507
507
  ...browserRequired ? [
508
508
  "bun run app:check:browser:hp-next",
509
509
  "bun run app:e2e:browser:hp-next"
@@ -650,7 +650,7 @@ async function executeTaskReportBug(context, args) {
650
650
  pending = outputRootResult.rest;
651
651
  const slugResult = takeOption(pending, "--slug");
652
652
  pending = slugResult.rest;
653
- requireNoExtraArgs(pending, "bun run rig report-bug [--no-prompt] [--no-beads] [--browser|--no-browser] --title <text> --url <url> [--asset <dragged-file>]");
653
+ requireNoExtraArgs(pending, "rig report-bug [--no-prompt] [--no-beads] [--browser|--no-browser] --title <text> --url <url> [--asset <dragged-file>]");
654
654
  let draft = {
655
655
  outputRoot: outputRootResult.value || "",
656
656
  title: titleResult.value,
@@ -755,7 +755,7 @@ async function executeTaskReportBug(context, args) {
755
755
  console.log(`Evidence assets: ${result.assetDir}`);
756
756
  if (taskConfigPath) {
757
757
  console.log(`Task config: ${taskConfigPath}`);
758
- console.log(`Run: bun run rig task info --task ${issueId}`);
758
+ console.log(`Run: rig task info --task ${issueId}`);
759
759
  }
760
760
  }
761
761
  return {
@@ -1578,7 +1578,7 @@ async function executeBrowser(context, args) {
1578
1578
  return { ok: true, group: "browser", command: "help" };
1579
1579
  }
1580
1580
  if (command === "explain") {
1581
- requireNoExtraArgs(rest, "bun run rig browser explain");
1581
+ requireNoExtraArgs(rest, "rig browser explain");
1582
1582
  console.log(browserAgentUsageText());
1583
1583
  return { ok: true, group: "browser", command: "explain" };
1584
1584
  }
@@ -1604,7 +1604,7 @@ ${browserHelpText()}`);
1604
1604
 
1605
1605
  ${browserHelpText()}`);
1606
1606
  }
1607
- requireNoExtraArgs(appRest, `bun run rig browser ${command} ${subcommand}`);
1607
+ requireNoExtraArgs(appRest, `rig browser ${command} ${subcommand}`);
1608
1608
  await context.runCommand(["bun", "run", `app:${subcommand}:browser:${appSlug}`]);
1609
1609
  return { ok: true, group: "browser", command: `${command}-${subcommand}` };
1610
1610
  }
@@ -1616,7 +1616,7 @@ ${browserHelpText()}`);
1616
1616
  };
1617
1617
  const packageScript = packageScripts[command];
1618
1618
  if (packageScript) {
1619
- requireNoExtraArgs(rest, `bun run rig browser ${command}`);
1619
+ requireNoExtraArgs(rest, `rig browser ${command}`);
1620
1620
  await context.runCommand(["bun", "run", "--filter=@rig/browser", packageScript]);
1621
1621
  return { ok: true, group: "browser", command };
1622
1622
  }
@@ -1643,7 +1643,7 @@ async function executeBrowserDemo(context, args) {
1643
1643
  pending = keepOpenFlag.rest;
1644
1644
  const noBuildFlag = takeFlag(pending, "--no-build");
1645
1645
  pending = noBuildFlag.rest;
1646
- requireNoExtraArgs(pending, "bun run rig browser demo [--port <n>] [--profile <name>] [--state-dir <path>] [--target-url <url>] [--keep-open] [--no-build]");
1646
+ requireNoExtraArgs(pending, "rig browser demo [--port <n>] [--profile <name>] [--state-dir <path>] [--target-url <url>] [--keep-open] [--no-build]");
1647
1647
  if (context.outputMode !== "text" || !process.stdin.isTTY || !process.stdout.isTTY) {
1648
1648
  throw new CliError2("rig browser demo requires an interactive TTY in text mode.");
1649
1649
  }
@@ -2154,17 +2154,17 @@ async function executeProfile(context, args) {
2154
2154
  const [command = "show", ...rest] = args;
2155
2155
  switch (command) {
2156
2156
  case "show":
2157
- requireNoExtraArgs(rest, "bun run rig profile show");
2157
+ requireNoExtraArgs(rest, "rig profile show");
2158
2158
  await withMutedConsole(context.outputMode === "json", () => showProfile(context.projectRoot));
2159
2159
  return { ok: true, group: "profile", command };
2160
2160
  case "set": {
2161
2161
  if (rest.length === 0) {
2162
- throw new CliError2("Usage: bun run rig profile set <claude-code|codex-cli|pi> or set [--model ...] [--runtime ...] [--plugin ...]");
2162
+ throw new CliError2("Usage: rig profile set <claude-code|codex-cli|pi> or set [--model ...] [--runtime ...] [--plugin ...]");
2163
2163
  }
2164
2164
  const preset = rest[0];
2165
2165
  if (preset && !preset.startsWith("-")) {
2166
2166
  if (rest.length !== 1) {
2167
- throw new CliError2("Usage: bun run rig profile set <claude-code|codex-cli|pi>");
2167
+ throw new CliError2("Usage: rig profile set <claude-code|codex-cli|pi>");
2168
2168
  }
2169
2169
  try {
2170
2170
  await withMutedConsole(context.outputMode === "json", () => setProfile(context.projectRoot, { preset }));
@@ -2180,7 +2180,7 @@ async function executeProfile(context, args) {
2180
2180
  pending = runtimeResult.rest;
2181
2181
  const pluginResult = takeOption(pending, "--plugin");
2182
2182
  pending = pluginResult.rest;
2183
- requireNoExtraArgs(pending, "bun run rig profile set [--model ...] [--runtime ...] [--plugin ...]");
2183
+ requireNoExtraArgs(pending, "rig profile set [--model ...] [--runtime ...] [--plugin ...]");
2184
2184
  if (!modelResult.value && !runtimeResult.value && !pluginResult.value) {
2185
2185
  throw new CliError2("Provide at least one of --model, --runtime, or --plugin.");
2186
2186
  }
@@ -2212,21 +2212,21 @@ async function executeReview(context, args) {
2212
2212
  const [command = "show", ...rest] = args;
2213
2213
  switch (command) {
2214
2214
  case "show":
2215
- requireNoExtraArgs(rest, "bun run rig review show");
2215
+ requireNoExtraArgs(rest, "rig review show");
2216
2216
  await withMutedConsole(context.outputMode === "json", () => showReviewProfile(context.projectRoot));
2217
2217
  return { ok: true, group: "review", command };
2218
2218
  case "set": {
2219
2219
  if (rest.length === 0) {
2220
- throw new CliError2("Usage: bun run rig review set <off|advisory|required> [--provider greptile]");
2220
+ throw new CliError2("Usage: rig review set <off|advisory|required> [--provider greptile]");
2221
2221
  }
2222
2222
  const mode = rest[0];
2223
2223
  if (!mode) {
2224
- throw new CliError2("Usage: bun run rig review set <off|advisory|required> [--provider greptile]");
2224
+ throw new CliError2("Usage: rig review set <off|advisory|required> [--provider greptile]");
2225
2225
  }
2226
2226
  let pending = rest.slice(1);
2227
2227
  const providerResult = takeOption(pending, "--provider");
2228
2228
  pending = providerResult.rest;
2229
- requireNoExtraArgs(pending, "bun run rig review set <off|advisory|required> [--provider greptile]");
2229
+ requireNoExtraArgs(pending, "rig review set <off|advisory|required> [--provider greptile]");
2230
2230
  try {
2231
2231
  await withMutedConsole(context.outputMode === "json", () => {
2232
2232
  return setReviewProfile(context.projectRoot, mode, providerResult.value);
@@ -2311,13 +2311,13 @@ async function executeRepo(context, args) {
2311
2311
  switch (command) {
2312
2312
  case "sync": {
2313
2313
  const { value: task, rest: remaining } = takeOption(rest, "--task");
2314
- requireNoExtraArgs(remaining, "bun run rig repo sync [--task <beads-id>]");
2314
+ requireNoExtraArgs(remaining, "rig repo sync [--task <task-id>]");
2315
2315
  withMutedConsole(context.outputMode === "json", () => repoEnsure(context.projectRoot, task || undefined));
2316
2316
  return { ok: true, group: "repo", command, details: { task: task || null } };
2317
2317
  }
2318
2318
  case "reset-baseline": {
2319
2319
  const { value: keepTaskStatusFlag, rest: remaining } = takeFlag(rest, "--keep-task-status");
2320
- requireNoExtraArgs(remaining, "bun run rig repo reset-baseline [--keep-task-status]");
2320
+ requireNoExtraArgs(remaining, "rig repo reset-baseline [--keep-task-status]");
2321
2321
  withMutedConsole(context.outputMode === "json", () => resetBaseline(context.projectRoot, keepTaskStatusFlag));
2322
2322
  return { ok: true, group: "repo", command, details: { keepTaskStatus: keepTaskStatusFlag } };
2323
2323
  }
@@ -2327,7 +2327,7 @@ async function executeRepo(context, args) {
2327
2327
  }
2328
2328
  async function executeGit(context, args) {
2329
2329
  if (args.length === 0) {
2330
- throw new CliError2("Usage: bun run rig git <git-flow args...>");
2330
+ throw new CliError2("Usage: rig git <git-flow args...>");
2331
2331
  }
2332
2332
  await enforceNativeCommandPolicy(context, args, {
2333
2333
  commandPrefix: "rig-agent git",
@@ -2348,7 +2348,7 @@ async function executeGit(context, args) {
2348
2348
  }
2349
2349
  async function executeHarness(context, args) {
2350
2350
  if (args.length === 0) {
2351
- throw new CliError2("Usage: bun run rig harness <harness args...>");
2351
+ throw new CliError2("Usage: rig harness <harness args...>");
2352
2352
  }
2353
2353
  await enforceNativeCommandPolicy(context, args, {
2354
2354
  commandPrefix: "rig-agent",
@@ -2457,7 +2457,7 @@ async function executePlugin(context, args) {
2457
2457
  const [command = "list", ...rest] = args;
2458
2458
  switch (command) {
2459
2459
  case "list": {
2460
- requireNoExtraArgs(rest, "bun run rig plugin list");
2460
+ requireNoExtraArgs(rest, "rig plugin list");
2461
2461
  const legacyPlugins = context.plugins.list();
2462
2462
  const declarative = [];
2463
2463
  const config = await loadRigConfigOrNull(context.projectRoot);
@@ -2524,8 +2524,8 @@ async function executePlugin(context, args) {
2524
2524
  }
2525
2525
  case "validate": {
2526
2526
  const { value: task, rest: remaining } = takeOption(rest, "--task");
2527
- requireNoExtraArgs(remaining, "bun run rig plugin validate --task <beads-id>");
2528
- const taskId = requireTask(task, "bun run rig plugin validate --task <beads-id>");
2527
+ requireNoExtraArgs(remaining, "rig plugin validate --task <task-id>");
2528
+ const taskId = requireTask(task, "rig plugin validate --task <task-id>");
2529
2529
  const results = await context.plugins.runValidators(taskId);
2530
2530
  const passed = results.filter((result) => result.passed).length;
2531
2531
  const failed = results.length - passed;
@@ -2665,7 +2665,7 @@ function resolveSelectedConnection(projectRoot, options = {}) {
2665
2665
  const global = readGlobalConnections(options);
2666
2666
  const connection = global.connections[repo.selected];
2667
2667
  if (!connection) {
2668
- throw new CliError2(`Selected Rig connection "${repo.selected}" was not found. Run \`rig connect list\` or \`rig connect use local\`.`, 1);
2668
+ throw new CliError2(`Selected Rig server "${repo.selected}" was not found. Run \`rig server list\` or \`rig server use local\`.`, 1);
2669
2669
  }
2670
2670
  return { alias: repo.selected, connection };
2671
2671
  }
@@ -3157,7 +3157,7 @@ async function runFastTaskRunPreflight(context, options = {}) {
3157
3157
  }
3158
3158
  }
3159
3159
  const repo = readRepoConnection(context.projectRoot);
3160
- checks.push(repo ? preflightCheck("project-link", "project linked to Rig connection", repo.project ? "pass" : "warn", `${repo.selected}${repo.project ? ` -> ${repo.project}` : ""}`, "Run `rig init --yes --repo owner/repo` to record the GitHub repo slug.") : preflightCheck("project-link", "project linked to Rig connection", legacyServerCompatibility ? "warn" : "fail", "missing .rig/state/connection.json", "Run `rig init` or `rig connect use <alias|local>`."));
3160
+ checks.push(repo ? preflightCheck("project-link", "project linked to Rig server", repo.project ? "pass" : "warn", `${repo.selected}${repo.project ? ` -> ${repo.project}` : ""}`, "Run `rig init --yes --repo owner/repo` to record the GitHub repo slug.") : preflightCheck("project-link", "project linked to Rig server", legacyServerCompatibility ? "warn" : "fail", "missing .rig/state/connection.json", "Run `rig init` or `rig server use <alias|local>`."));
3161
3161
  try {
3162
3162
  const auth = await request("/api/github/auth/status");
3163
3163
  checks.push(isAuthenticated(auth) ? preflightCheck("github-auth", "GitHub auth valid", "pass") : preflightCheck("github-auth", "GitHub auth valid", legacyServerCompatibility ? "warn" : "fail", "not authenticated", "Run `rig github auth import-gh` or `rig github auth token --token <token>`."));
@@ -3275,7 +3275,7 @@ async function executeQueue(context, args) {
3275
3275
  pending = failFastResult.rest;
3276
3276
  const skipProjectSyncResult = takeFlag(pending, "--skip-project-sync");
3277
3277
  pending = skipProjectSyncResult.rest;
3278
- requireNoExtraArgs(pending, "bun run rig queue run [--workers <n>] [--max-tasks <n>] [--action validate|verify|pipeline] [--isolation off|worktree] [--no-runtime-reuse] [--fail-fast] [--skip-project-sync]");
3278
+ requireNoExtraArgs(pending, "rig queue run [--workers <n>] [--max-tasks <n>] [--action validate|verify|pipeline] [--isolation off|worktree] [--no-runtime-reuse] [--fail-fast] [--skip-project-sync]");
3279
3279
  const workers = parsePositiveInt(workersResult.value, "--workers", 2);
3280
3280
  const maxTasks = parsePositiveInt(maxTasksResult.value, "--max-tasks", 10);
3281
3281
  const action = parseAction(actionResult.value);
@@ -3453,7 +3453,7 @@ async function executeAgent(context, args) {
3453
3453
  const [command = "list", ...rest] = args;
3454
3454
  switch (command) {
3455
3455
  case "list": {
3456
- requireNoExtraArgs(rest, "bun run rig agent list");
3456
+ requireNoExtraArgs(rest, "rig agent list");
3457
3457
  const runtimes = await listAgentRuntimes(context.projectRoot);
3458
3458
  if (context.outputMode === "text") {
3459
3459
  if (runtimes.length === 0) {
@@ -3474,12 +3474,12 @@ async function executeAgent(context, args) {
3474
3474
  pending = modeResult.rest;
3475
3475
  const taskResult = takeOption(pending, "--task");
3476
3476
  pending = taskResult.rest;
3477
- requireNoExtraArgs(pending, "bun run rig agent prepare --task <id> [--id <id>] [--mode worktree]");
3477
+ requireNoExtraArgs(pending, "rig agent prepare --task <id> [--id <id>] [--mode worktree]");
3478
3478
  const mode = parseIsolationMode(modeResult.value, false);
3479
3479
  const id = idResult.value || agentId("agent");
3480
3480
  const taskId = taskResult.value?.trim();
3481
3481
  if (!taskId) {
3482
- throw new CliError2("Usage: bun run rig agent prepare --task <id> [--id <id>] [--mode worktree]");
3482
+ throw new CliError2("Usage: rig agent prepare --task <id> [--id <id>] [--mode worktree]");
3483
3483
  }
3484
3484
  const runtime = await withMutedConsole(context.outputMode === "json", () => ensureAgentRuntime({
3485
3485
  projectRoot: context.projectRoot,
@@ -3497,7 +3497,7 @@ async function executeAgent(context, args) {
3497
3497
  case "run": {
3498
3498
  const { options, commandParts } = splitAtDoubleDash(rest);
3499
3499
  if (commandParts.length === 0) {
3500
- throw new CliError2("Usage: bun run rig agent run [--id <id>] [--mode worktree] [--skip-project-sync] -- <command...>");
3500
+ throw new CliError2("Usage: rig agent run [--id <id>] [--mode worktree] [--skip-project-sync] -- <command...>");
3501
3501
  }
3502
3502
  let pending = options;
3503
3503
  const idResult = takeOption(pending, "--id");
@@ -3508,12 +3508,12 @@ async function executeAgent(context, args) {
3508
3508
  pending = taskResult.rest;
3509
3509
  const skipProjectSyncResult = takeFlag(pending, "--skip-project-sync");
3510
3510
  pending = skipProjectSyncResult.rest;
3511
- requireNoExtraArgs(pending, "bun run rig agent run --task <id> [--id <id>] [--mode worktree] [--skip-project-sync] -- <command...>");
3511
+ requireNoExtraArgs(pending, "rig agent run --task <id> [--id <id>] [--mode worktree] [--skip-project-sync] -- <command...>");
3512
3512
  const mode = parseIsolationMode(modeResult.value, false);
3513
3513
  const id = idResult.value || agentId("agent-run");
3514
3514
  const taskId = taskResult.value?.trim();
3515
3515
  if (!taskId) {
3516
- throw new CliError2("Usage: bun run rig agent run --task <id> [--id <id>] [--mode worktree] [--skip-project-sync] -- <command...>");
3516
+ throw new CliError2("Usage: rig agent run --task <id> [--id <id>] [--mode worktree] [--skip-project-sync] -- <command...>");
3517
3517
  }
3518
3518
  await runProjectMainSyncPreflight(context, { disabled: skipProjectSyncResult.value });
3519
3519
  const createdAt = new Date().toISOString();
@@ -3627,7 +3627,7 @@ ${result.stderr.trim()}` : ""}`, result.exitCode);
3627
3627
  pending = allResult.rest;
3628
3628
  const idResult = takeOption(pending, "--id");
3629
3629
  pending = idResult.rest;
3630
- requireNoExtraArgs(pending, "bun run rig agent cleanup (--id <id> | --all)");
3630
+ requireNoExtraArgs(pending, "rig agent cleanup (--id <id> | --all)");
3631
3631
  if (!allResult.value && !idResult.value) {
3632
3632
  throw new CliError2("Provide --id <id> or --all.");
3633
3633
  }
@@ -3763,7 +3763,7 @@ async function executeDist(context, args) {
3763
3763
  switch (command) {
3764
3764
  case "build": {
3765
3765
  const { value: outputDir, rest: pending } = takeOption(rest, "--output-dir");
3766
- requireNoExtraArgs(pending, "bun run rig dist build [--output-dir <dir>]");
3766
+ requireNoExtraArgs(pending, "rig dist build [--output-dir <dir>]");
3767
3767
  const commandParts = ["bun", "run", "packages/cli/bin/build-rig-binaries.ts"];
3768
3768
  if (outputDir) {
3769
3769
  commandParts.push("--output-dir", outputDir);
@@ -3777,7 +3777,7 @@ async function executeDist(context, args) {
3777
3777
  pending = scopeResult.rest;
3778
3778
  const pathResult = takeOption(pending, "--path");
3779
3779
  pending = pathResult.rest;
3780
- requireNoExtraArgs(pending, "bun run rig dist install [--scope user|system] [--path <dir>]");
3780
+ requireNoExtraArgs(pending, "rig dist install [--scope user|system] [--path <dir>]");
3781
3781
  const scope = parseInstallScope(scopeResult.value);
3782
3782
  const installDir = resolveInstallDir(scope, pathResult.value);
3783
3783
  mkdirSync6(installDir, { recursive: true });
@@ -3820,7 +3820,7 @@ async function executeDist(context, args) {
3820
3820
  };
3821
3821
  }
3822
3822
  case "doctor": {
3823
- requireNoExtraArgs(rest, "bun run rig dist doctor");
3823
+ requireNoExtraArgs(rest, "rig dist doctor");
3824
3824
  const details = await runDistDoctor(context.projectRoot);
3825
3825
  if (context.outputMode === "text") {
3826
3826
  console.log(`bun: ${details.bun.available ? `ok (${details.bun.version})` : "missing"}`);
@@ -3831,7 +3831,7 @@ async function executeDist(context, args) {
3831
3831
  return { ok: true, group: "dist", command, details };
3832
3832
  }
3833
3833
  case "rebuild-agent": {
3834
- requireNoExtraArgs(rest, "bun run rig dist rebuild-agent");
3834
+ requireNoExtraArgs(rest, "rig dist rebuild-agent");
3835
3835
  const fp = await computeRuntimeImageFingerprint(context.projectRoot);
3836
3836
  const currentId = computeRuntimeImageId(fp);
3837
3837
  const imagesDir = resolve12(resolveControlPlaneMonorepoRuntimeDir(context.projectRoot), "images");
@@ -3983,6 +3983,414 @@ import {
3983
3983
  readJsonlFile as readJsonlFile3,
3984
3984
  resolveAuthorityRunDir as resolveAuthorityRunDir2
3985
3985
  } from "@rig/runtime/control-plane/authority-files";
3986
+
3987
+ // packages/cli/src/commands/_cli-format.ts
3988
+ import { log as log3, note as note3 } from "@clack/prompts";
3989
+ import pc3 from "picocolors";
3990
+ function stringField(record, key, fallback = "") {
3991
+ const value = record[key];
3992
+ return typeof value === "string" && value.trim() ? value.trim() : fallback;
3993
+ }
3994
+ function numberField(record, key) {
3995
+ const value = record[key];
3996
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
3997
+ }
3998
+ function arrayField(record, key) {
3999
+ const value = record[key];
4000
+ return Array.isArray(value) ? value.flatMap((entry) => typeof entry === "string" && entry.trim() ? [entry.trim()] : []) : [];
4001
+ }
4002
+ function rawObject(record) {
4003
+ const raw = record.raw;
4004
+ return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
4005
+ }
4006
+ function truncate(value, width) {
4007
+ if (value.length <= width)
4008
+ return value;
4009
+ if (width <= 1)
4010
+ return "\u2026";
4011
+ return `${value.slice(0, width - 1)}\u2026`;
4012
+ }
4013
+ function pad(value, width) {
4014
+ return value.length >= width ? value : `${value}${" ".repeat(width - value.length)}`;
4015
+ }
4016
+ function statusColor(status) {
4017
+ const normalized = status.toLowerCase();
4018
+ if (["completed", "merged", "closed", "done", "accepted", "pass", "selected", "approved"].includes(normalized))
4019
+ return pc3.green;
4020
+ if (["failed", "needs_attention", "needs-attention", "blocked", "error", "rejected"].includes(normalized))
4021
+ return pc3.red;
4022
+ if (["running", "reviewing", "validating", "in_progress", "in-progress", "remote"].includes(normalized))
4023
+ return pc3.cyan;
4024
+ if (["ready", "open", "queued", "created", "preparing", "local", "pending"].includes(normalized))
4025
+ return pc3.yellow;
4026
+ return pc3.dim;
4027
+ }
4028
+ function compactDate(value) {
4029
+ if (!value.trim())
4030
+ return "";
4031
+ const parsed = Date.parse(value);
4032
+ if (!Number.isFinite(parsed))
4033
+ return value;
4034
+ return new Date(parsed).toISOString().replace("T", " ").replace(/\.\d{3}Z$/, "Z");
4035
+ }
4036
+ function compactValue(value) {
4037
+ if (value === null || value === undefined)
4038
+ return "";
4039
+ if (typeof value === "string")
4040
+ return value;
4041
+ if (typeof value === "number" || typeof value === "boolean")
4042
+ return String(value);
4043
+ if (Array.isArray(value))
4044
+ return value.map(compactValue).filter(Boolean).join(", ");
4045
+ return JSON.stringify(value);
4046
+ }
4047
+ function firstString(record, keys, fallback = "") {
4048
+ for (const key of keys) {
4049
+ const value = stringField(record, key);
4050
+ if (value)
4051
+ return value;
4052
+ }
4053
+ return fallback;
4054
+ }
4055
+ function runIdOf(run) {
4056
+ return firstString(run, ["runId", "id"], "(unknown-run)");
4057
+ }
4058
+ function taskIdOf(run) {
4059
+ return firstString(run, ["taskId", "task", "task_id"]);
4060
+ }
4061
+ function runTitleOf(run) {
4062
+ return firstString(run, ["title", "summary", "name"], taskIdOf(run) || "(untitled)");
4063
+ }
4064
+ function requestIdOf(entry) {
4065
+ return firstString(entry, ["requestId", "id", "approvalId", "inputId"], "(unknown-request)");
4066
+ }
4067
+ function shouldUseClackOutput() {
4068
+ return Boolean(process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1";
4069
+ }
4070
+ function printFormattedOutput(message2, options = {}) {
4071
+ if (!shouldUseClackOutput()) {
4072
+ console.log(message2);
4073
+ return;
4074
+ }
4075
+ if (options.title)
4076
+ note3(message2, options.title);
4077
+ else
4078
+ log3.message(message2);
4079
+ }
4080
+ function formatStatusPill(status) {
4081
+ const label = status || "unknown";
4082
+ return statusColor(label)(`\u25CF ${label}`);
4083
+ }
4084
+ function formatSection(title, subtitle) {
4085
+ return `${pc3.bold(pc3.cyan("\u25C6"))} ${pc3.bold(title)}${subtitle ? pc3.dim(` \u2014 ${subtitle}`) : ""}`;
4086
+ }
4087
+ function formatSuccessCard(title, rows = []) {
4088
+ const body = rows.filter(([, value]) => value !== undefined && value !== null && String(value).length > 0).map(([key, value]) => `${pc3.dim("\u2502")} ${pc3.dim(key.padEnd(12))} ${value}`);
4089
+ return [formatSection(title), ...body].join(`
4090
+ `);
4091
+ }
4092
+ function formatNextSteps(steps) {
4093
+ if (steps.length === 0)
4094
+ return [];
4095
+ return [pc3.bold("Next"), ...steps.map((step) => `${pc3.dim("\u203A")} ${step}`)];
4096
+ }
4097
+ function formatTaskList(tasks, options = {}) {
4098
+ if (options.raw)
4099
+ return tasks.map((task) => JSON.stringify(task)).join(`
4100
+ `);
4101
+ if (tasks.length === 0)
4102
+ return [formatSection("Tasks", "none found"), ...formatNextSteps(["Try `rig server status` to confirm the selected server.", "Relax filters or run `rig task run --title ... --initial-prompt ...` for ad hoc work."])].join(`
4103
+ `);
4104
+ const rows = tasks.map((task) => {
4105
+ const raw = rawObject(task);
4106
+ const id = stringField(task, "id", "<unknown>");
4107
+ const status = stringField(task, "status", "unknown");
4108
+ const title = stringField(task, "title", "Untitled task");
4109
+ const source = stringField(task, "source", stringField(raw, "source", ""));
4110
+ const labels = arrayField(task, "labels").length > 0 ? arrayField(task, "labels") : arrayField(raw, "labels");
4111
+ return { id, status, title, source, labels };
4112
+ });
4113
+ const idWidth = Math.min(18, Math.max(4, ...rows.map((row) => row.id.length)));
4114
+ const statusWidth = Math.min(16, Math.max(6, ...rows.map((row) => row.status.length)));
4115
+ const header = `${pc3.bold(pad("TASK", idWidth))} ${pc3.bold(pad("STATUS", statusWidth))} ${pc3.bold("TITLE")}`;
4116
+ const body = rows.map((row) => {
4117
+ const labels = row.labels.length > 0 ? pc3.dim(` ${row.labels.slice(0, 4).map((label) => `#${label}`).join(" ")}`) : "";
4118
+ const source = row.source ? pc3.dim(` ${row.source}`) : "";
4119
+ return [
4120
+ pc3.bold(pad(truncate(row.id, idWidth), idWidth)),
4121
+ statusColor(row.status)(pad(truncate(row.status, statusWidth), statusWidth)),
4122
+ `${row.title}${labels}${source}`
4123
+ ].join(" ");
4124
+ });
4125
+ return [formatSection("Tasks", `${rows.length} shown`), header, ...body, "", ...formatNextSteps(["Run one: `rig task run <id>` or `rig task run --next`", "Attach later: `rig run attach <run-id> --follow`"])].join(`
4126
+ `);
4127
+ }
4128
+ function formatTaskCard(task, options = {}) {
4129
+ const raw = rawObject(task);
4130
+ const id = stringField(task, "id", stringField(raw, "id", "<unknown>"));
4131
+ const status = stringField(task, "status", stringField(raw, "status", "unknown"));
4132
+ const title = stringField(task, "title", stringField(raw, "title", "Untitled task"));
4133
+ const source = stringField(task, "source", stringField(raw, "source", ""));
4134
+ const url = stringField(task, "url", stringField(raw, "url", ""));
4135
+ const number = numberField(task, "number") ?? numberField(raw, "number");
4136
+ const labels = arrayField(task, "labels").length > 0 ? arrayField(task, "labels") : arrayField(raw, "labels");
4137
+ const assignees = arrayField(task, "assignees").length > 0 ? arrayField(task, "assignees") : arrayField(raw, "assignees");
4138
+ const readiness = compactValue(task.readiness ?? raw.readiness);
4139
+ const validators = compactValue(task.validators ?? raw.validators ?? task.validation ?? raw.validation);
4140
+ const rows = [
4141
+ ["task", pc3.bold(id)],
4142
+ ["status", formatStatusPill(status)],
4143
+ ["title", title],
4144
+ ["source", source],
4145
+ ["number", number],
4146
+ ["labels", labels.length ? labels.map((label) => `#${label}`).join(" ") : ""],
4147
+ ["assignees", assignees.join(", ")],
4148
+ ["readiness", readiness],
4149
+ ["validators", validators],
4150
+ ["url", url]
4151
+ ];
4152
+ return [
4153
+ formatSuccessCard(options.title ?? (options.selected ? "Selected task" : "Task"), rows),
4154
+ "",
4155
+ ...formatNextSteps([`Start: \`rig task run ${id}\``, `Details: \`rig task show ${id} --raw\``])
4156
+ ].join(`
4157
+ `);
4158
+ }
4159
+ function formatTaskDetails(task) {
4160
+ return formatTaskCard(task, { title: "Task details" });
4161
+ }
4162
+ function formatRunList(runs, options = {}) {
4163
+ if (runs.length === 0) {
4164
+ return [
4165
+ formatSection("Runs", "none recorded"),
4166
+ options.source === "server" ? pc3.dim("No runs recorded on the selected Rig server.") : pc3.dim("No runs recorded in .rig/runs."),
4167
+ "",
4168
+ ...formatNextSteps(["Start one: `rig task run --next`", "Check server: `rig server status`"])
4169
+ ].join(`
4170
+ `);
4171
+ }
4172
+ const rows = runs.map((run) => {
4173
+ const runId = stringField(run, "runId", stringField(run, "id", "(unknown-run)"));
4174
+ const status = stringField(run, "status", "unknown");
4175
+ const taskId = stringField(run, "taskId", "");
4176
+ const title = stringField(run, "title", taskId || "(untitled)");
4177
+ const runtime = stringField(run, "runtimeAdapter", "");
4178
+ return { runId, status, title, runtime };
4179
+ });
4180
+ const idWidth = Math.min(36, Math.max(6, ...rows.map((row) => row.runId.length)));
4181
+ const statusWidth = Math.min(16, Math.max(6, ...rows.map((row) => row.status.length)));
4182
+ const header = `${pc3.bold(pad("RUN", idWidth))} ${pc3.bold(pad("STATUS", statusWidth))} ${pc3.bold("TITLE")}`;
4183
+ const body = rows.map((row) => [
4184
+ pc3.bold(pad(truncate(row.runId, idWidth), idWidth)),
4185
+ statusColor(row.status)(pad(truncate(row.status, statusWidth), statusWidth)),
4186
+ `${row.title}${row.runtime ? pc3.dim(` ${row.runtime}`) : ""}`
4187
+ ].join(" "));
4188
+ return [formatSection("Runs", options.source === "server" ? "selected server" : "local state"), header, ...body, "", ...formatNextSteps(["Follow live: `rig run attach <run-id> --follow`", "Details: `rig run show <run-id>`"])].join(`
4189
+ `);
4190
+ }
4191
+ function formatSubmittedRun(input) {
4192
+ const rows = [["run", pc3.bold(input.runId)]];
4193
+ if (input.task) {
4194
+ const id = stringField(input.task, "id", "<unknown>");
4195
+ const status = stringField(input.task, "status", "unknown");
4196
+ const title = stringField(input.task, "title", "Untitled task");
4197
+ rows.push(["task", `${pc3.bold(id)} ${formatStatusPill(status)} ${title}`]);
4198
+ }
4199
+ const runtime = [input.runtimeAdapter || "pi", input.runtimeMode || "full-access", input.interactionMode || "default"].filter(Boolean).join(" \xB7 ");
4200
+ rows.push(["runtime", runtime]);
4201
+ return [
4202
+ formatSuccessCard("Run submitted", rows),
4203
+ "",
4204
+ ...formatNextSteps([
4205
+ `Attach: \`rig run attach ${input.runId} --follow\``,
4206
+ `Inspect: \`rig run show ${input.runId}\``,
4207
+ input.detached ? "Submitted detached; attach when you are ready." : "Interactive mode opens the native bundled Pi frontend."
4208
+ ])
4209
+ ].join(`
4210
+ `);
4211
+ }
4212
+ function formatRunCard(run, options = {}) {
4213
+ const raw = rawObject(run);
4214
+ const merged = { ...raw, ...run };
4215
+ const runId = runIdOf(merged);
4216
+ const status = firstString(merged, ["status"], "unknown");
4217
+ const taskId = taskIdOf(merged);
4218
+ const title = runTitleOf(merged);
4219
+ const runtime = firstString(merged, ["runtimeAdapter", "runtime", "adapter"]);
4220
+ const mode = firstString(merged, ["runtimeMode", "mode"]);
4221
+ const interaction = firstString(merged, ["interactionMode"]);
4222
+ const created = compactDate(firstString(merged, ["createdAt"]));
4223
+ const started = compactDate(firstString(merged, ["startedAt"]));
4224
+ const updated = compactDate(firstString(merged, ["updatedAt"]));
4225
+ const completed = compactDate(firstString(merged, ["completedAt", "finishedAt"]));
4226
+ const worktree = firstString(merged, ["worktreePath", "cwd", "projectRoot"]);
4227
+ const piSession = merged.piSession && typeof merged.piSession === "object" && !Array.isArray(merged.piSession) ? firstString(merged.piSession, ["sessionId", "id"]) : "";
4228
+ const timeline = Array.isArray(merged.timeline) ? merged.timeline.length : null;
4229
+ const approvals = Array.isArray(merged.approvals) ? merged.approvals.length : null;
4230
+ const inputs = Array.isArray(merged.userInputs) ? merged.userInputs.length : null;
4231
+ const rows = [
4232
+ ["run", pc3.bold(runId)],
4233
+ ["status", formatStatusPill(status)],
4234
+ ["task", taskId],
4235
+ ["title", title],
4236
+ ["runtime", [runtime, mode, interaction].filter(Boolean).join(" \xB7 ")],
4237
+ ["created", created],
4238
+ ["started", started],
4239
+ ["updated", updated],
4240
+ ["completed", completed],
4241
+ ["worktree", worktree],
4242
+ ["pi", piSession],
4243
+ ["timeline", timeline],
4244
+ ["approvals", approvals],
4245
+ ["inputs", inputs]
4246
+ ];
4247
+ return [
4248
+ formatSuccessCard(options.title ?? "Run details", rows),
4249
+ "",
4250
+ ...formatNextSteps([`Follow live: \`rig run attach ${runId} --follow\``, `Raw payload: \`rig run show ${runId} --raw\``])
4251
+ ].join(`
4252
+ `);
4253
+ }
4254
+ function formatRunStatus(summary, options = {}) {
4255
+ const activeRuns = summary.activeRuns ?? [];
4256
+ const recentRuns = summary.recentRuns ?? [];
4257
+ const lines = [formatSection("Run status", options.source === "server" ? "selected server" : "local state")];
4258
+ lines.push("", pc3.bold(`Active runs (${activeRuns.length})`));
4259
+ if (activeRuns.length === 0) {
4260
+ lines.push(pc3.dim("No active runs."));
4261
+ } else {
4262
+ for (const run of activeRuns) {
4263
+ lines.push(formatRunSummaryLine(run));
4264
+ }
4265
+ }
4266
+ lines.push("", pc3.bold(`Recent runs (${recentRuns.length})`));
4267
+ if (recentRuns.length === 0) {
4268
+ lines.push(pc3.dim("No recent terminal runs."));
4269
+ } else {
4270
+ for (const run of recentRuns.slice(0, 10)) {
4271
+ lines.push(formatRunSummaryLine(run));
4272
+ }
4273
+ }
4274
+ lines.push("", ...formatNextSteps(["Start work: `rig task run --next`", "Attach: `rig run attach <run-id> --follow`", "Details: `rig run show <run-id>`"]));
4275
+ return lines.join(`
4276
+ `);
4277
+ }
4278
+ function formatRunSummaryLine(run) {
4279
+ const record = run;
4280
+ const runId = runIdOf(record);
4281
+ const status = firstString(record, ["status"], "unknown");
4282
+ const taskId = taskIdOf(record);
4283
+ const title = runTitleOf(record);
4284
+ const runtime = firstString(record, ["runtimeAdapter", "runtime", "adapter"]);
4285
+ const descriptor = [taskId, title].filter(Boolean).join(" \xB7 ");
4286
+ return `${pc3.dim("\u2502")} ${pc3.bold(runId)} ${formatStatusPill(status)} ${descriptor}${runtime ? pc3.dim(` ${runtime}`) : ""}`;
4287
+ }
4288
+ function formatInboxList(kind, entries) {
4289
+ const title = kind === "approvals" ? "Approval inbox" : "Input inbox";
4290
+ if (entries.length === 0) {
4291
+ return [
4292
+ formatSection(title, "empty"),
4293
+ pc3.dim(kind === "approvals" ? "No pending approvals." : "No pending user-input requests."),
4294
+ "",
4295
+ ...formatNextSteps(["Check runs: `rig run status`", "Start work: `rig task run --next`"])
4296
+ ].join(`
4297
+ `);
4298
+ }
4299
+ const lines = [formatSection(title, `${entries.length} pending`)];
4300
+ for (const entry of entries) {
4301
+ const record = entry.record && typeof entry.record === "object" && !Array.isArray(entry.record) ? entry.record : entry;
4302
+ const runId = firstString(entry, ["runId"], firstString(record, ["runId"]));
4303
+ const taskId = firstString(entry, ["taskId"], firstString(record, ["taskId", "task"]));
4304
+ const requestId = requestIdOf(record);
4305
+ const status = firstString(record, ["status", "state"], "pending");
4306
+ const prompt = firstString(record, ["prompt", "message", "reason", "title", "summary"], kind === "approvals" ? "Approval requested" : "Input requested");
4307
+ lines.push(`${pc3.dim("\u2502")} ${pc3.bold(requestId)} ${formatStatusPill(status)} ${prompt}`);
4308
+ lines.push(`${pc3.dim("\u2502")} ${pc3.dim("run ")} ${runId || "(unknown-run)"}${taskId ? pc3.dim(` task ${taskId}`) : ""}`);
4309
+ }
4310
+ lines.push("", ...formatNextSteps(kind === "approvals" ? ["Resolve: `rig inbox approve --run <run-id> --request <request-id> --decision approve|reject`", "Rejoin: `rig run attach <run-id> --follow`"] : ["Respond: `rig inbox respond --run <run-id> --request <request-id> --answer key=value`", "Rejoin: `rig run attach <run-id> --follow`"]));
4311
+ return lines.join(`
4312
+ `);
4313
+ }
4314
+ function formatConnectionList(connections) {
4315
+ const rows = [["local", { kind: "local", mode: "auto" }], ...Object.entries(connections)];
4316
+ const aliasWidth = Math.min(24, Math.max(5, ...rows.map(([alias]) => alias.length)));
4317
+ const lines = rows.map(([alias, connection]) => [
4318
+ pc3.bold(pad(truncate(alias, aliasWidth), aliasWidth)),
4319
+ formatStatusPill(connection.kind),
4320
+ connection.kind === "remote" ? connection.baseUrl ?? "" : connection.mode ?? "local"
4321
+ ].join(" "));
4322
+ return [formatSection("Rig servers", `${rows.length} available`), `${pc3.bold(pad("ALIAS", aliasWidth))} ${pc3.bold("KIND")} ${pc3.bold("TARGET")}`, ...lines, "", ...formatNextSteps(["Select one: `rig server use <alias|local>`"])].join(`
4323
+ `);
4324
+ }
4325
+ function formatConnectionStatus(selected, connections) {
4326
+ const connection = selected === "local" ? { kind: "local", mode: "auto" } : connections[selected];
4327
+ const target = !connection ? "not configured" : connection.kind === "remote" ? connection.baseUrl : "local";
4328
+ return [
4329
+ formatSection("Rig server", "selected for this repo"),
4330
+ `${pc3.dim("\u2502")} ${pc3.dim("selected ")} ${pc3.bold(selected)}`,
4331
+ `${pc3.dim("\u2502")} ${pc3.dim("kind ")} ${formatStatusPill(connection?.kind ?? "unknown")}`,
4332
+ `${pc3.dim("\u2502")} ${pc3.dim("target ")} ${target ?? "not configured"}`,
4333
+ "",
4334
+ ...formatNextSteps(["Change: `rig server use <alias|local>`", "List saved servers: `rig server list`"])
4335
+ ].join(`
4336
+ `);
4337
+ }
4338
+
4339
+ // packages/cli/src/commands/inbox.ts
4340
+ function isRemoteConnectionSelected(projectRoot) {
4341
+ return resolveSelectedConnection(projectRoot)?.connection.kind === "remote";
4342
+ }
4343
+ function runMatches(entry, filters) {
4344
+ const runId = typeof entry.runId === "string" ? entry.runId : typeof entry.id === "string" ? entry.id : "";
4345
+ const taskId = typeof entry.taskId === "string" ? entry.taskId : "";
4346
+ return (!filters.run || runId === filters.run) && (!filters.task || taskId === filters.task);
4347
+ }
4348
+ function normalizeRemoteRunDetails(payload) {
4349
+ const run = payload.run;
4350
+ if (run && typeof run === "object" && !Array.isArray(run)) {
4351
+ return {
4352
+ ...run,
4353
+ ...Array.isArray(payload.timeline) ? { timeline: payload.timeline } : {},
4354
+ ...Array.isArray(payload.approvals) ? { approvals: payload.approvals } : {},
4355
+ ...Array.isArray(payload.userInputs) ? { userInputs: payload.userInputs } : {}
4356
+ };
4357
+ }
4358
+ return payload;
4359
+ }
4360
+ function remoteRecordsFromRun(run, kind) {
4361
+ const key = kind === "approvals" ? "approvals" : "userInputs";
4362
+ const direct = run[key];
4363
+ if (!Array.isArray(direct))
4364
+ return [];
4365
+ const runId = typeof run.runId === "string" ? run.runId : typeof run.id === "string" ? run.id : "";
4366
+ const taskId = typeof run.taskId === "string" ? run.taskId : "";
4367
+ return direct.filter((record) => Boolean(record && typeof record === "object" && !Array.isArray(record))).map((record) => ({ runId, taskId, record }));
4368
+ }
4369
+ async function listRemoteInboxRecords(context, kind, filters) {
4370
+ const runs = (await listRunsViaServer(context, { limit: 100 })).filter((entry) => runMatches(entry, filters));
4371
+ const records = [];
4372
+ for (const run of runs) {
4373
+ const runId = typeof run.runId === "string" ? run.runId : typeof run.id === "string" ? run.id : "";
4374
+ const detailed = runId ? normalizeRemoteRunDetails(await getRunDetailsViaServer(context, runId).catch(() => run)) : run;
4375
+ records.push(...remoteRecordsFromRun(detailed, kind));
4376
+ }
4377
+ return records;
4378
+ }
4379
+ function listLocalInboxRecords(context, kind, filters) {
4380
+ const fileName = kind === "approvals" ? "approvals.jsonl" : "user-input.jsonl";
4381
+ const runs = listAuthorityRuns(context.projectRoot).filter((entry) => (!filters.run || entry.runId === filters.run) && (!filters.task || entry.taskId === filters.task));
4382
+ return runs.flatMap((entry) => readJsonlFile3(resolve13(resolveAuthorityRunDir2(context.projectRoot, entry.runId), fileName)).map((record) => ({
4383
+ runId: entry.runId,
4384
+ taskId: entry.taskId ?? undefined,
4385
+ record
4386
+ })));
4387
+ }
4388
+ async function listInboxRecords(context, kind, filters) {
4389
+ if (isRemoteConnectionSelected(context.projectRoot)) {
4390
+ return listRemoteInboxRecords(context, kind, filters);
4391
+ }
4392
+ return listLocalInboxRecords(context, kind, filters);
4393
+ }
3986
4394
  async function executeInbox(context, args) {
3987
4395
  const [command = "approvals", ...rest] = args;
3988
4396
  switch (command) {
@@ -3992,16 +4400,10 @@ async function executeInbox(context, args) {
3992
4400
  pending = run.rest;
3993
4401
  const task = takeOption(pending, "--task");
3994
4402
  pending = task.rest;
3995
- requireNoExtraArgs(pending, "bun run rig inbox approvals [--run <id>] [--task <id>]");
3996
- const runs = listAuthorityRuns(context.projectRoot).filter((entry) => (!run.value || entry.runId === run.value) && (!task.value || entry.taskId === task.value));
3997
- const approvals = runs.flatMap((entry) => readJsonlFile3(resolve13(resolveAuthorityRunDir2(context.projectRoot, entry.runId), "approvals.jsonl")).map((record) => ({
3998
- runId: entry.runId,
3999
- record
4000
- })));
4403
+ requireNoExtraArgs(pending, "rig inbox approvals [--run <id>] [--task <id>]");
4404
+ const approvals = await listInboxRecords(context, "approvals", { run: run.value, task: task.value });
4001
4405
  if (context.outputMode === "text") {
4002
- for (const approval of approvals) {
4003
- console.log(JSON.stringify(approval));
4004
- }
4406
+ printFormattedOutput(formatInboxList("approvals", approvals));
4005
4407
  }
4006
4408
  return { ok: true, group: "inbox", command, details: { approvals } };
4007
4409
  }
@@ -4013,19 +4415,22 @@ async function executeInbox(context, args) {
4013
4415
  pending = request.rest;
4014
4416
  const decision = takeOption(pending, "--decision");
4015
4417
  pending = decision.rest;
4016
- const note3 = takeOption(pending, "--note");
4017
- pending = note3.rest;
4018
- requireNoExtraArgs(pending, "bun run rig inbox approve --run <id> --request <id> --decision approve|reject [--note <text>]");
4418
+ const note4 = takeOption(pending, "--note");
4419
+ pending = note4.rest;
4420
+ requireNoExtraArgs(pending, "rig inbox approve --run <id> --request <id> --decision approve|reject [--note <text>]");
4019
4421
  if (!run.value || !request.value || !decision.value) {
4020
4422
  throw new CliError2("approve requires --run, --request, and --decision.");
4021
4423
  }
4022
4424
  if (decision.value !== "approve" && decision.value !== "reject") {
4023
4425
  throw new CliError2("decision must be approve or reject.");
4024
4426
  }
4427
+ if (isRemoteConnectionSelected(context.projectRoot)) {
4428
+ throw new CliError2("Remote approval resolution is not available from this CLI yet; use the server UI/API or switch to local state for direct JSONL edits.", 2);
4429
+ }
4025
4430
  const approvalsPath = resolve13(resolveAuthorityRunDir2(context.projectRoot, run.value), "approvals.jsonl");
4026
4431
  const approvals = readJsonlFile3(approvalsPath);
4027
4432
  const resolvedAt = new Date().toISOString();
4028
- const next = approvals.map((entry) => entry.requestId === request.value || entry.id === request.value ? { ...entry, status: "resolved", decision: decision.value, note: note3.value ?? null, resolvedAt } : entry);
4433
+ const next = approvals.map((entry) => entry.requestId === request.value || entry.id === request.value ? { ...entry, status: "resolved", decision: decision.value, note: note4.value ?? null, resolvedAt } : entry);
4029
4434
  writeFileSync4(approvalsPath, `${next.map((entry) => JSON.stringify(entry)).join(`
4030
4435
  `)}
4031
4436
  `, "utf8");
@@ -4037,16 +4442,10 @@ async function executeInbox(context, args) {
4037
4442
  pending = run.rest;
4038
4443
  const task = takeOption(pending, "--task");
4039
4444
  pending = task.rest;
4040
- requireNoExtraArgs(pending, "bun run rig inbox inputs [--run <id>] [--task <id>]");
4041
- const runs = listAuthorityRuns(context.projectRoot).filter((entry) => (!run.value || entry.runId === run.value) && (!task.value || entry.taskId === task.value));
4042
- const requests = runs.flatMap((entry) => readJsonlFile3(resolve13(resolveAuthorityRunDir2(context.projectRoot, entry.runId), "user-input.jsonl")).map((record) => ({
4043
- runId: entry.runId,
4044
- record
4045
- })));
4445
+ requireNoExtraArgs(pending, "rig inbox inputs [--run <id>] [--task <id>]");
4446
+ const requests = await listInboxRecords(context, "inputs", { run: run.value, task: task.value });
4046
4447
  if (context.outputMode === "text") {
4047
- for (const request of requests) {
4048
- console.log(JSON.stringify(request));
4049
- }
4448
+ printFormattedOutput(formatInboxList("inputs", requests));
4050
4449
  }
4051
4450
  return { ok: true, group: "inbox", command, details: { requests } };
4052
4451
  }
@@ -4073,10 +4472,13 @@ async function executeInbox(context, args) {
4073
4472
  remaining.push(current);
4074
4473
  }
4075
4474
  }
4076
- requireNoExtraArgs(remaining, "bun run rig inbox respond --run <id> --request <id> --answer key=value [--answer key=value]");
4475
+ requireNoExtraArgs(remaining, "rig inbox respond --run <id> --request <id> --answer key=value [--answer key=value]");
4077
4476
  if (!run.value || !request.value || answers.length === 0) {
4078
4477
  throw new CliError2("respond requires --run, --request, and at least one --answer.");
4079
4478
  }
4479
+ if (isRemoteConnectionSelected(context.projectRoot)) {
4480
+ throw new CliError2("Remote input responses are not available from this CLI yet; use the server UI/API or switch to local state for direct JSONL edits.", 2);
4481
+ }
4080
4482
  const parsedAnswers = Object.fromEntries(answers.map((entry) => {
4081
4483
  const [key, ...restValue] = entry.split("=");
4082
4484
  return [key, restValue.join("=")];
@@ -4500,7 +4902,7 @@ async function runRigDoctorChecks(options) {
4500
4902
  const taskSourceKind = config?.taskSource?.kind;
4501
4903
  checks.push(taskSourceKind ? check("task-source", "task source configured", "pass", taskSourceKind) : check("task-source", "task source configured", "fail", "missing taskSource", "Configure taskSource in rig.config.ts."));
4502
4904
  const repo = readRepoConnection(projectRoot);
4503
- checks.push(repo ? check("project-link", "repo selected Rig connection", repo.project ? "pass" : "warn", `${repo.selected}${repo.project ? ` -> ${repo.project}` : ""}`, "Run `rig init --yes --repo owner/repo` to link this checkout to a GitHub repo slug.") : check("project-link", "repo selected Rig connection", "fail", "missing .rig/state/connection.json", "Run `rig init` or `rig connect use <alias|local>`."));
4905
+ checks.push(repo ? check("project-link", "repo selected Rig server", repo.project ? "pass" : "warn", `${repo.selected}${repo.project ? ` -> ${repo.project}` : ""}`, "Run `rig init --yes --repo owner/repo` to link this checkout to a GitHub repo slug.") : check("project-link", "repo selected Rig server", "fail", "missing .rig/state/connection.json", "Run `rig init` or `rig server use <alias|local>`."));
4504
4906
  const selected = (() => {
4505
4907
  try {
4506
4908
  return resolveSelectedConnection(projectRoot);
@@ -4508,7 +4910,7 @@ async function runRigDoctorChecks(options) {
4508
4910
  return null;
4509
4911
  }
4510
4912
  })();
4511
- checks.push(selected ? check("connection", "selected server connection", "pass", selected.connection.kind === "remote" ? selected.connection.baseUrl : "local auto") : check("connection", "selected server connection", repo ? "fail" : "warn", repo ? "selected alias is missing" : "will auto-start local server", repo ? "Run `rig connect list` and `rig connect use <alias|local>`." : undefined));
4913
+ checks.push(selected ? check("connection", "selected server connection", "pass", selected.connection.kind === "remote" ? selected.connection.baseUrl : "local auto") : check("connection", "selected server", repo ? "fail" : "warn", repo ? "selected alias is missing" : "will auto-start local server", repo ? "Run `rig server list` and `rig server use <alias|local>`." : undefined));
4512
4914
  let server = null;
4513
4915
  try {
4514
4916
  server = await (options.resolveServer ?? ensureServerForCli)(projectRoot);
@@ -5317,179 +5719,24 @@ Usage: rig init`, 1);
5317
5719
 
5318
5720
  // packages/cli/src/commands/connect.ts
5319
5721
  import { cancel as cancel2, isCancel as isCancel2, select as select2 } from "@clack/prompts";
5320
-
5321
- // packages/cli/src/commands/_cli-format.ts
5322
- import pc3 from "picocolors";
5323
- function stringField(record, key, fallback = "") {
5324
- const value = record[key];
5325
- return typeof value === "string" && value.trim() ? value.trim() : fallback;
5326
- }
5327
- function arrayField(record, key) {
5328
- const value = record[key];
5329
- return Array.isArray(value) ? value.flatMap((entry) => typeof entry === "string" && entry.trim() ? [entry.trim()] : []) : [];
5722
+ function usageName(options) {
5723
+ return `rig ${options.group}`;
5330
5724
  }
5331
- function rawObject(record) {
5332
- const raw = record.raw;
5333
- return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
5334
- }
5335
- function truncate(value, width) {
5336
- if (value.length <= width)
5337
- return value;
5338
- if (width <= 1)
5339
- return "\u2026";
5340
- return `${value.slice(0, width - 1)}\u2026`;
5341
- }
5342
- function pad(value, width) {
5343
- return value.length >= width ? value : `${value}${" ".repeat(width - value.length)}`;
5344
- }
5345
- function statusColor(status) {
5346
- const normalized = status.toLowerCase();
5347
- if (["completed", "merged", "closed", "done", "accepted", "pass", "selected"].includes(normalized))
5348
- return pc3.green;
5349
- if (["failed", "needs_attention", "needs-attention", "blocked", "error"].includes(normalized))
5350
- return pc3.red;
5351
- if (["running", "reviewing", "validating", "in_progress", "in-progress", "remote"].includes(normalized))
5352
- return pc3.cyan;
5353
- if (["ready", "open", "queued", "created", "preparing", "local"].includes(normalized))
5354
- return pc3.yellow;
5355
- return pc3.dim;
5356
- }
5357
- function formatStatusPill(status) {
5358
- const label = status || "unknown";
5359
- return statusColor(label)(`\u25CF ${label}`);
5360
- }
5361
- function formatSection(title, subtitle) {
5362
- return `${pc3.bold(pc3.cyan("\u25C6"))} ${pc3.bold(title)}${subtitle ? pc3.dim(` \u2014 ${subtitle}`) : ""}`;
5363
- }
5364
- function formatSuccessCard(title, rows = []) {
5365
- const body = rows.filter(([, value]) => value !== undefined && value !== null && String(value).length > 0).map(([key, value]) => `${pc3.dim("\u2502")} ${pc3.dim(key.padEnd(9))} ${value}`);
5366
- return [formatSection(title), ...body].join(`
5367
- `);
5368
- }
5369
- function formatNextSteps(steps) {
5370
- if (steps.length === 0)
5371
- return [];
5372
- return [pc3.bold("Next"), ...steps.map((step) => `${pc3.dim("\u203A")} ${step}`)];
5373
- }
5374
- function formatTaskList(tasks, options = {}) {
5375
- if (options.raw)
5376
- return tasks.map((task) => JSON.stringify(task)).join(`
5377
- `);
5378
- if (tasks.length === 0)
5379
- return [formatSection("Tasks", "none found"), ...formatNextSteps(["Try `rig server status` to confirm the selected server.", "Relax filters or run `rig task run --title ... --initial-prompt ...` for ad hoc work."])].join(`
5380
- `);
5381
- const rows = tasks.map((task) => {
5382
- const raw = rawObject(task);
5383
- const id = stringField(task, "id", "<unknown>");
5384
- const status = stringField(task, "status", "unknown");
5385
- const title = stringField(task, "title", "Untitled task");
5386
- const source = stringField(task, "source", stringField(raw, "source", ""));
5387
- const labels = arrayField(task, "labels").length > 0 ? arrayField(task, "labels") : arrayField(raw, "labels");
5388
- return { id, status, title, source, labels };
5389
- });
5390
- const idWidth = Math.min(18, Math.max(4, ...rows.map((row) => row.id.length)));
5391
- const statusWidth = Math.min(16, Math.max(6, ...rows.map((row) => row.status.length)));
5392
- const header = `${pc3.bold(pad("TASK", idWidth))} ${pc3.bold(pad("STATUS", statusWidth))} ${pc3.bold("TITLE")}`;
5393
- const body = rows.map((row) => {
5394
- const labels = row.labels.length > 0 ? pc3.dim(` ${row.labels.slice(0, 4).map((label) => `#${label}`).join(" ")}`) : "";
5395
- const source = row.source ? pc3.dim(` ${row.source}`) : "";
5396
- return [
5397
- pc3.bold(pad(truncate(row.id, idWidth), idWidth)),
5398
- statusColor(row.status)(pad(truncate(row.status, statusWidth), statusWidth)),
5399
- `${row.title}${labels}${source}`
5400
- ].join(" ");
5401
- });
5402
- return [formatSection("Tasks", `${rows.length} shown`), header, ...body, "", ...formatNextSteps(["Run one: `rig task run <id>` or `rig task run --next`", "Attach later: `rig run attach <run-id> --follow`"])].join(`
5403
- `);
5404
- }
5405
- function formatRunList(runs, options = {}) {
5406
- if (runs.length === 0) {
5407
- return [
5408
- formatSection("Runs", "none recorded"),
5409
- options.source === "server" ? pc3.dim("No runs recorded on the selected Rig server.") : pc3.dim("No runs recorded in .rig/runs."),
5410
- "",
5411
- ...formatNextSteps(["Start one: `rig task run --next`", "Check server: `rig server status`"])
5412
- ].join(`
5413
- `);
5414
- }
5415
- const rows = runs.map((run) => {
5416
- const runId = stringField(run, "runId", stringField(run, "id", "(unknown-run)"));
5417
- const status = stringField(run, "status", "unknown");
5418
- const taskId = stringField(run, "taskId", "");
5419
- const title = stringField(run, "title", taskId || "(untitled)");
5420
- const runtime = stringField(run, "runtimeAdapter", "");
5421
- return { runId, status, title, runtime };
5422
- });
5423
- const idWidth = Math.min(36, Math.max(6, ...rows.map((row) => row.runId.length)));
5424
- const statusWidth = Math.min(16, Math.max(6, ...rows.map((row) => row.status.length)));
5425
- const header = `${pc3.bold(pad("RUN", idWidth))} ${pc3.bold(pad("STATUS", statusWidth))} ${pc3.bold("TITLE")}`;
5426
- const body = rows.map((row) => [
5427
- pc3.bold(pad(truncate(row.runId, idWidth), idWidth)),
5428
- statusColor(row.status)(pad(truncate(row.status, statusWidth), statusWidth)),
5429
- `${row.title}${row.runtime ? pc3.dim(` ${row.runtime}`) : ""}`
5430
- ].join(" "));
5431
- return [formatSection("Runs", options.source === "server" ? "selected server" : "local state"), header, ...body, "", ...formatNextSteps(["Follow live: `rig run attach <run-id> --follow`", "Details: `rig run show --run <run-id>`"])].join(`
5432
- `);
5433
- }
5434
- function formatSubmittedRun(input) {
5435
- const rows = [["run", pc3.bold(input.runId)]];
5436
- if (input.task) {
5437
- const id = stringField(input.task, "id", "<unknown>");
5438
- const status = stringField(input.task, "status", "unknown");
5439
- const title = stringField(input.task, "title", "Untitled task");
5440
- rows.push(["task", `${pc3.bold(id)} ${formatStatusPill(status)} ${title}`]);
5441
- }
5442
- return [
5443
- formatSuccessCard("Run submitted", rows),
5444
- "",
5445
- ...formatNextSteps([`Attach: \`rig run attach ${input.runId} --follow\``, `Inspect: \`rig run show --run ${input.runId}\``])
5446
- ].join(`
5447
- `);
5448
- }
5449
- function formatConnectionList(connections) {
5450
- const rows = [["local", { kind: "local", mode: "auto" }], ...Object.entries(connections)];
5451
- const aliasWidth = Math.min(24, Math.max(5, ...rows.map(([alias]) => alias.length)));
5452
- const lines = rows.map(([alias, connection]) => [
5453
- pc3.bold(pad(truncate(alias, aliasWidth), aliasWidth)),
5454
- formatStatusPill(connection.kind),
5455
- connection.kind === "remote" ? connection.baseUrl ?? "" : connection.mode ?? "local"
5456
- ].join(" "));
5457
- return [formatSection("Rig servers", `${rows.length} available`), `${pc3.bold(pad("ALIAS", aliasWidth))} ${pc3.bold("KIND")} ${pc3.bold("TARGET")}`, ...lines, "", ...formatNextSteps(["Select one: `rig server use <alias|local>`"])].join(`
5458
- `);
5459
- }
5460
- function formatConnectionStatus(selected, connections) {
5461
- const connection = selected === "local" ? { kind: "local", mode: "auto" } : connections[selected];
5462
- const target = !connection ? "not configured" : connection.kind === "remote" ? connection.baseUrl : "local";
5463
- return [
5464
- formatSection("Rig server", "selected for this repo"),
5465
- `${pc3.dim("\u2502")} ${pc3.dim("selected ")} ${pc3.bold(selected)}`,
5466
- `${pc3.dim("\u2502")} ${pc3.dim("kind ")} ${formatStatusPill(connection?.kind ?? "unknown")}`,
5467
- `${pc3.dim("\u2502")} ${pc3.dim("target ")} ${target ?? "not configured"}`,
5468
- "",
5469
- ...formatNextSteps(["Change: `rig server use <alias|local>`", "List saved servers: `rig server list`"])
5470
- ].join(`
5471
- `);
5472
- }
5473
-
5474
- // packages/cli/src/commands/connect.ts
5475
- function usageName(options) {
5476
- return `rig ${options.group}`;
5477
- }
5478
- function parseConnection(alias, value, options) {
5479
- if (alias === "local" && !value)
5480
- return { kind: "local", mode: "auto" };
5481
- if (!value)
5482
- throw new CliError2(`Missing remote server URL. Usage: ${usageName(options)} add <alias> <url>`, 1);
5483
- let parsed;
5484
- try {
5485
- parsed = new URL(value);
5486
- } catch {
5487
- throw new CliError2(`Invalid Rig server URL: ${value}`, 1);
5488
- }
5489
- if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
5490
- throw new CliError2("Rig remote server URL must be http(s).", 1);
5491
- }
5492
- return { kind: "remote", baseUrl: parsed.toString().replace(/\/+$/, "") };
5725
+ function parseConnection(alias, value, options) {
5726
+ if (alias === "local" && !value)
5727
+ return { kind: "local", mode: "auto" };
5728
+ if (!value)
5729
+ throw new CliError2(`Missing remote server URL. Usage: ${usageName(options)} add <alias> <url>`, 1);
5730
+ let parsed;
5731
+ try {
5732
+ parsed = new URL(value);
5733
+ } catch {
5734
+ throw new CliError2(`Invalid Rig server URL: ${value}`, 1);
5735
+ }
5736
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
5737
+ throw new CliError2("Rig remote server URL must be http(s).", 1);
5738
+ }
5739
+ return { kind: "remote", baseUrl: parsed.toString().replace(/\/+$/, "") };
5493
5740
  }
5494
5741
  function printJsonOrText(context, payload, text2) {
5495
5742
  if (context.outputMode === "json") {
@@ -5896,8 +6143,8 @@ async function executeInspect(context, args) {
5896
6143
  switch (command) {
5897
6144
  case "logs": {
5898
6145
  const { value: task, rest: remaining } = takeOption(rest, "--task");
5899
- requireNoExtraArgs(remaining, "bun run rig inspect logs --task <beads-id>");
5900
- const requiredTask = requireTask(task, "bun run rig inspect logs --task <beads-id>");
6146
+ requireNoExtraArgs(remaining, "rig inspect logs --task <task-id>");
6147
+ const requiredTask = requireTask(task, "rig inspect logs --task <task-id>");
5901
6148
  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];
5902
6149
  if (!latestRun) {
5903
6150
  throw new CliError2(`No runs found for ${requiredTask}.`);
@@ -5911,8 +6158,8 @@ async function executeInspect(context, args) {
5911
6158
  }
5912
6159
  case "artifacts": {
5913
6160
  const { value: task, rest: remaining } = takeOption(rest, "--task");
5914
- requireNoExtraArgs(remaining, "bun run rig inspect artifacts --task <beads-id>");
5915
- const requiredTask = requireTask(task, "bun run rig inspect artifacts --task <beads-id>");
6161
+ requireNoExtraArgs(remaining, "rig inspect artifacts --task <task-id>");
6162
+ const requiredTask = requireTask(task, "rig inspect artifacts --task <task-id>");
5916
6163
  const artifactRoot = resolveTaskArtifactDirs(context.projectRoot, requiredTask).find((path) => existsSync11(path));
5917
6164
  if (!artifactRoot) {
5918
6165
  throw new CliError2(`No artifacts found for ${requiredTask}.`);
@@ -5926,8 +6173,8 @@ async function executeInspect(context, args) {
5926
6173
  previewPending = task.rest;
5927
6174
  const file = takeOption(previewPending, "--file");
5928
6175
  previewPending = file.rest;
5929
- requireNoExtraArgs(previewPending, "bun run rig inspect artifact --task <beads-id> --file <name>");
5930
- const requiredTask = requireTask(task.value, "bun run rig inspect artifact --task <beads-id> --file <name>");
6176
+ requireNoExtraArgs(previewPending, "rig inspect artifact --task <task-id> --file <name>");
6177
+ const requiredTask = requireTask(task.value, "rig inspect artifact --task <task-id> --file <name>");
5931
6178
  if (!file.value) {
5932
6179
  throw new CliError2("Missing --file for rig inspect artifact.");
5933
6180
  }
@@ -5956,7 +6203,7 @@ async function executeInspect(context, args) {
5956
6203
  }
5957
6204
  case "diff": {
5958
6205
  const { value: task, rest: remaining } = takeOption(rest, "--task");
5959
- requireNoExtraArgs(remaining, "bun run rig inspect diff [--task <beads-id>]");
6206
+ requireNoExtraArgs(remaining, "rig inspect diff [--task <task-id>]");
5960
6207
  if (task) {
5961
6208
  const files = changedFilesForTask(context.projectRoot, task, false);
5962
6209
  for (const file of files) {
@@ -5968,7 +6215,7 @@ async function executeInspect(context, args) {
5968
6215
  return { ok: true, group: "inspect", command, details: { task: task || null } };
5969
6216
  }
5970
6217
  case "failures": {
5971
- requireNoExtraArgs(rest, "bun run rig inspect failures");
6218
+ requireNoExtraArgs(rest, "rig inspect failures");
5972
6219
  const failed = resolveHarnessPaths2(context.projectRoot).failedApproachesPath;
5973
6220
  if (!existsSync11(failed)) {
5974
6221
  console.log("No failures recorded.");
@@ -5978,7 +6225,7 @@ async function executeInspect(context, args) {
5978
6225
  return { ok: true, group: "inspect", command };
5979
6226
  }
5980
6227
  case "graph":
5981
- requireNoExtraArgs(rest, "bun run rig inspect graph");
6228
+ requireNoExtraArgs(rest, "rig inspect graph");
5982
6229
  {
5983
6230
  const monorepoRoot = resolveMonorepoRoot2(context.projectRoot);
5984
6231
  const result = runCapture3(["br", "--no-db", "list", "--pretty"], monorepoRoot);
@@ -5989,7 +6236,7 @@ async function executeInspect(context, args) {
5989
6236
  }
5990
6237
  return { ok: true, group: "inspect", command };
5991
6238
  case "audit": {
5992
- requireNoExtraArgs(rest, "bun run rig inspect audit");
6239
+ requireNoExtraArgs(rest, "rig inspect audit");
5993
6240
  const auditPath = resolve19(resolveHarnessPaths2(context.projectRoot).logsDir, "audit.jsonl");
5994
6241
  if (!existsSync11(auditPath)) {
5995
6242
  console.log("No audit log found.");
@@ -6048,7 +6295,7 @@ async function executeInspector(context, args) {
6048
6295
  pending = secondsResult.rest;
6049
6296
  const pollMsResult = takeOption(pending, "--poll-ms");
6050
6297
  pending = pollMsResult.rest;
6051
- requireNoExtraArgs(pending, "bun run rig inspector stream [--once] [--seconds <n>] [--poll-ms <n>]");
6298
+ requireNoExtraArgs(pending, "rig inspector stream [--once] [--seconds <n>] [--poll-ms <n>]");
6052
6299
  const seconds = secondsResult.value ? parseRequiredPositiveInt(secondsResult.value, "--seconds") : null;
6053
6300
  const pollMs = pollMsResult.value ? parseRequiredPositiveInt(pollMsResult.value, "--poll-ms") : null;
6054
6301
  if (context.outputMode === "json" && !onceResult.value && !seconds) {
@@ -6142,7 +6389,7 @@ async function executeInspector(context, args) {
6142
6389
  let pending = rest;
6143
6390
  const scanIdResult = takeOption(pending, "--scan-id");
6144
6391
  pending = scanIdResult.rest;
6145
- requireNoExtraArgs(pending, "bun run rig inspector scan-upstream-drift [--scan-id <id>]");
6392
+ requireNoExtraArgs(pending, "rig inspector scan-upstream-drift [--scan-id <id>]");
6146
6393
  const connection = await ensureLocalRigServerConnection2(context.projectRoot);
6147
6394
  const response = await fetch(new URL("/api/inspector/tools/invoke", connection.baseUrl), {
6148
6395
  method: "POST",
@@ -6253,7 +6500,7 @@ async function executeRemote(context, args) {
6253
6500
  const [subcommand = "list", ...subRest] = rest;
6254
6501
  switch (subcommand) {
6255
6502
  case "list": {
6256
- requireNoExtraArgs(subRest, "bun run rig remote endpoint list");
6503
+ requireNoExtraArgs(subRest, "rig remote endpoint list");
6257
6504
  const endpoints = listManagedRemoteEndpoints(undefined, context.projectRoot);
6258
6505
  const redactedEndpoints = endpoints.map((endpoint2) => redactRemoteEndpoint(endpoint2));
6259
6506
  if (context.outputMode === "text") {
@@ -6277,7 +6524,7 @@ async function executeRemote(context, args) {
6277
6524
  pending2 = port.rest;
6278
6525
  const token = takeOption(pending2, "--token");
6279
6526
  pending2 = token.rest;
6280
- requireNoExtraArgs(pending2, "bun run rig remote endpoint add --alias <a> --host <h> --port <n> --token <t>");
6527
+ requireNoExtraArgs(pending2, "rig remote endpoint add --alias <a> --host <h> --port <n> --token <t>");
6281
6528
  if (!alias.value || !host.value || !token.value || !port.value) {
6282
6529
  throw new CliError2("remote endpoint add requires --alias, --host, --port, and --token.");
6283
6530
  }
@@ -6304,7 +6551,7 @@ async function executeRemote(context, args) {
6304
6551
  pending2 = port.rest;
6305
6552
  const token = takeOption(pending2, "--token");
6306
6553
  pending2 = token.rest;
6307
- requireNoExtraArgs(pending2, "bun run rig remote endpoint update --id <id> [--alias <a>] [--host <h>] [--port <n>] [--token <t>]");
6554
+ requireNoExtraArgs(pending2, "rig remote endpoint update --id <id> [--alias <a>] [--host <h>] [--port <n>] [--token <t>]");
6308
6555
  if (!endpointId.value && !alias.value) {
6309
6556
  throw new CliError2("remote endpoint update requires --id <id> or --alias <a>.");
6310
6557
  }
@@ -6327,7 +6574,7 @@ async function executeRemote(context, args) {
6327
6574
  let pending2 = subRest;
6328
6575
  const alias = takeOption(pending2, "--alias");
6329
6576
  pending2 = alias.rest;
6330
- requireNoExtraArgs(pending2, "bun run rig remote endpoint remove --alias <a>");
6577
+ requireNoExtraArgs(pending2, "rig remote endpoint remove --alias <a>");
6331
6578
  if (!alias.value) {
6332
6579
  throw new CliError2("remote endpoint remove requires --alias.");
6333
6580
  }
@@ -6344,7 +6591,7 @@ async function executeRemote(context, args) {
6344
6591
  let pending2 = subRest;
6345
6592
  const alias = takeOption(pending2, "--alias");
6346
6593
  pending2 = alias.rest;
6347
- requireNoExtraArgs(pending2, "bun run rig remote endpoint test --alias <a>");
6594
+ requireNoExtraArgs(pending2, "rig remote endpoint test --alias <a>");
6348
6595
  if (!alias.value) {
6349
6596
  throw new CliError2("remote endpoint test requires --alias.");
6350
6597
  }
@@ -6375,7 +6622,7 @@ async function executeRemote(context, args) {
6375
6622
  }
6376
6623
  }
6377
6624
  case "migrate": {
6378
- requireNoExtraArgs(subRest, "bun run rig remote endpoint migrate");
6625
+ requireNoExtraArgs(subRest, "rig remote endpoint migrate");
6379
6626
  const result = migrateManagedRemoteEndpoints(context.projectRoot);
6380
6627
  if (context.outputMode === "text") {
6381
6628
  console.log(`Imported ${result.imported} endpoint(s) from ${result.sourcePath}${result.skipped > 0 ? `, skipped ${result.skipped}` : ""}.`);
@@ -6383,7 +6630,7 @@ async function executeRemote(context, args) {
6383
6630
  return { ok: true, group: "remote", command: "endpoint migrate", details: result };
6384
6631
  }
6385
6632
  case "doctor": {
6386
- requireNoExtraArgs(subRest, "bun run rig remote endpoint doctor");
6633
+ requireNoExtraArgs(subRest, "rig remote endpoint doctor");
6387
6634
  const result = doctorManagedRemoteEndpoints(context.projectRoot);
6388
6635
  if (context.outputMode === "text") {
6389
6636
  console.log(JSON.stringify(result, null, 2));
@@ -6436,17 +6683,17 @@ async function executeRemote(context, args) {
6436
6683
  try {
6437
6684
  switch (command) {
6438
6685
  case "test": {
6439
- requireNoExtraArgs(pending, "bun run rig remote test [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
6686
+ requireNoExtraArgs(pending, "rig remote test [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
6440
6687
  const response = await withClient((client) => client.ping());
6441
6688
  return { ok: true, group: "remote", command, details: toDetails(response) };
6442
6689
  }
6443
6690
  case "status": {
6444
- requireNoExtraArgs(pending, "bun run rig remote status [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
6691
+ requireNoExtraArgs(pending, "rig remote status [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
6445
6692
  const response = await withClient((client) => client.getState());
6446
6693
  return { ok: true, group: "remote", command, details: toDetails(response) };
6447
6694
  }
6448
6695
  case "tasks": {
6449
- requireNoExtraArgs(pending, "bun run rig remote tasks [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
6696
+ requireNoExtraArgs(pending, "rig remote tasks [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
6450
6697
  const response = await withClient((client) => client.getTasks());
6451
6698
  return { ok: true, group: "remote", command, details: toDetails(response) };
6452
6699
  }
@@ -6456,7 +6703,7 @@ async function executeRemote(context, args) {
6456
6703
  watchPending = secondsResult.rest;
6457
6704
  const eventResult = takeOption(watchPending, "--event");
6458
6705
  watchPending = eventResult.rest;
6459
- requireNoExtraArgs(watchPending, "bun run rig remote watch [--seconds <n>] [--event <type>] [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
6706
+ requireNoExtraArgs(watchPending, "rig remote watch [--seconds <n>] [--event <type>] [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
6460
6707
  const seconds = parseOptionalPositiveInt(secondsResult.value, "--seconds");
6461
6708
  const eventFilter = eventResult.value || undefined;
6462
6709
  if (context.outputMode === "json" && !seconds) {
@@ -6525,7 +6772,7 @@ async function executeRemote(context, args) {
6525
6772
  case "stop":
6526
6773
  case "continue":
6527
6774
  case "refresh": {
6528
- requireNoExtraArgs(pending, `bun run rig remote ${command} [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
6775
+ requireNoExtraArgs(pending, `rig remote ${command} [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
6529
6776
  const response = await withClient(async (client) => {
6530
6777
  switch (command) {
6531
6778
  case "pause":
@@ -6548,7 +6795,7 @@ async function executeRemote(context, args) {
6548
6795
  let countPending = pending;
6549
6796
  const countResult = takeOption(countPending, "--count");
6550
6797
  countPending = countResult.rest;
6551
- requireNoExtraArgs(countPending, `bun run rig remote ${command} --count <n> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
6798
+ requireNoExtraArgs(countPending, `rig remote ${command} --count <n> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
6552
6799
  const count = parseRequiredPositiveInt(countResult.value, "--count");
6553
6800
  const response = await withClient(async (client) => command === "add-iterations" ? await client.addIterations(count) : await client.removeIterations(count));
6554
6801
  assertRemoteOperationSuccess(command, response);
@@ -6559,8 +6806,8 @@ async function executeRemote(context, args) {
6559
6806
  let taskPending = pending;
6560
6807
  const taskResult = takeOption(taskPending, "--task");
6561
6808
  taskPending = taskResult.rest;
6562
- requireNoExtraArgs(taskPending, `bun run rig remote ${command} --task <id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
6563
- const taskId = requireTask(taskResult.value, `bun run rig remote ${command} --task <id>`);
6809
+ requireNoExtraArgs(taskPending, `rig remote ${command} --task <id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
6810
+ const taskId = requireTask(taskResult.value, `rig remote ${command} --task <id>`);
6564
6811
  const response = await withClient(async (client) => command === "prompt-preview" ? await client.getPromptPreview(taskId) : await client.getIterationOutput(taskId));
6565
6812
  assertRemoteOperationSuccess(command, response);
6566
6813
  return { ok: true, group: "remote", command, details: toDetails(response) };
@@ -6573,7 +6820,7 @@ async function executeRemote(context, args) {
6573
6820
  orchestrationPending = maxIterationsResult.rest;
6574
6821
  const directMergeResult = takeFlag(orchestrationPending, "--direct-merge");
6575
6822
  orchestrationPending = directMergeResult.rest;
6576
- requireNoExtraArgs(orchestrationPending, "bun run rig remote orchestrate-start [--max-workers <n>] [--max-iterations <n>] [--direct-merge]");
6823
+ requireNoExtraArgs(orchestrationPending, "rig remote orchestrate-start [--max-workers <n>] [--max-iterations <n>] [--direct-merge]");
6577
6824
  const response = await withClient((client) => client.startOrchestration({
6578
6825
  maxWorkers: parseOptionalPositiveInt(maxWorkersResult.value, "--max-workers"),
6579
6826
  maxIterations: parseOptionalPositiveInt(maxIterationsResult.value, "--max-iterations"),
@@ -6594,8 +6841,8 @@ async function executeRemote(context, args) {
6594
6841
  let orchestrationPending = pending;
6595
6842
  const idResult = takeOption(orchestrationPending, "--id");
6596
6843
  orchestrationPending = idResult.rest;
6597
- requireNoExtraArgs(orchestrationPending, `bun run rig remote ${command} --id <orch-id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
6598
- const orchestrationId = requireTask(idResult.value, `bun run rig remote ${command} --id <orch-id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
6844
+ requireNoExtraArgs(orchestrationPending, `rig remote ${command} --id <orch-id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
6845
+ const orchestrationId = requireTask(idResult.value, `rig remote ${command} --id <orch-id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
6599
6846
  const response = await withClient(async (client) => {
6600
6847
  switch (command) {
6601
6848
  case "orchestrate-pause":
@@ -6659,8 +6906,8 @@ var CANONICAL_STAGES = [
6659
6906
  "Merge",
6660
6907
  "Complete"
6661
6908
  ];
6662
- function logDetail(log3) {
6663
- return typeof log3.detail === "string" ? log3.detail.trim() : "";
6909
+ function logDetail(log4) {
6910
+ return typeof log4.detail === "string" ? log4.detail.trim() : "";
6664
6911
  }
6665
6912
  function parseProviderProtocolLog(title, detail) {
6666
6913
  if (title.trim().toLowerCase() !== "agent output")
@@ -6707,12 +6954,12 @@ function renderOperatorSnapshot(snapshot) {
6707
6954
  const status = String(run.status ?? "unknown");
6708
6955
  const logs = snapshot.logs ?? [];
6709
6956
  const latestByStage = new Map;
6710
- for (const log3 of logs) {
6711
- const title = String(log3.title ?? "").toLowerCase();
6712
- const stageName = String(log3.stage ?? "").toLowerCase();
6957
+ for (const log4 of logs) {
6958
+ const title = String(log4.title ?? "").toLowerCase();
6959
+ const stageName = String(log4.stage ?? "").toLowerCase();
6713
6960
  const stage = CANONICAL_STAGES.find((candidate) => candidate.toLowerCase() === title || candidate.toLowerCase() === stageName);
6714
6961
  if (stage)
6715
- latestByStage.set(stage, log3);
6962
+ latestByStage.set(stage, log4);
6716
6963
  }
6717
6964
  const stageLines = CANONICAL_STAGES.flatMap((stage) => {
6718
6965
  const match = latestByStage.get(stage);
@@ -7516,7 +7763,7 @@ async function attachRunOperatorView(context, input) {
7516
7763
  }
7517
7764
 
7518
7765
  // packages/cli/src/commands/run.ts
7519
- function normalizeRemoteRunDetails(payload) {
7766
+ function normalizeRemoteRunDetails2(payload) {
7520
7767
  const run = payload.run;
7521
7768
  if (!run || typeof run !== "object" || Array.isArray(run))
7522
7769
  return null;
@@ -7528,11 +7775,11 @@ function normalizeRemoteRunDetails(payload) {
7528
7775
  };
7529
7776
  }
7530
7777
  var REMOTE_TERMINAL_RUN_STATUSES = new Set(["completed", "failed", "stopped", "cancelled", "canceled", "closed", "merged"]);
7531
- function isRemoteConnectionSelected(projectRoot) {
7778
+ function isRemoteConnectionSelected2(projectRoot) {
7532
7779
  return resolveSelectedConnection(projectRoot)?.connection.kind === "remote";
7533
7780
  }
7534
7781
  async function listRunsForSelectedConnection(context, options = {}) {
7535
- if (isRemoteConnectionSelected(context.projectRoot)) {
7782
+ if (isRemoteConnectionSelected2(context.projectRoot)) {
7536
7783
  return { runs: await listRunsViaServer(context, options), source: "server" };
7537
7784
  }
7538
7785
  return { runs: listAuthorityRuns3(context.projectRoot), source: "local" };
@@ -7541,9 +7788,6 @@ function runStringField(run, key, fallback = "") {
7541
7788
  const value = run[key];
7542
7789
  return typeof value === "string" && value.trim() ? value : fallback;
7543
7790
  }
7544
- function runDisplayTitle(run) {
7545
- return runStringField(run, "title", runStringField(run, "taskId", "(untitled)"));
7546
- }
7547
7791
  function buildServerRunStatus(runs) {
7548
7792
  const activeRuns = runs.filter((run) => !REMOTE_TERMINAL_RUN_STATUSES.has(runStringField(run, "status").toLowerCase()));
7549
7793
  const recentRuns = runs.filter((run) => REMOTE_TERMINAL_RUN_STATUSES.has(runStringField(run, "status").toLowerCase()));
@@ -7613,10 +7857,10 @@ async function executeRun(context, args) {
7613
7857
  const runtimeContext = loadRuntimeContextFromEnv2() ?? undefined;
7614
7858
  switch (command) {
7615
7859
  case "list": {
7616
- requireNoExtraArgs(rest, "bun run rig run list");
7860
+ requireNoExtraArgs(rest, "rig run list");
7617
7861
  const { runs, source } = await listRunsForSelectedConnection(context, { limit: 100 });
7618
7862
  if (context.outputMode === "text") {
7619
- console.log(formatRunList(runs, { source }));
7863
+ printFormattedOutput(formatRunList(runs, { source }));
7620
7864
  }
7621
7865
  return { ok: true, group: "run", command, details: { runs, source } };
7622
7866
  }
@@ -7626,7 +7870,7 @@ async function executeRun(context, args) {
7626
7870
  pending = run.rest;
7627
7871
  const purgeArtifacts = takeFlag(pending, "--purge-artifacts");
7628
7872
  pending = purgeArtifacts.rest;
7629
- requireNoExtraArgs(pending, "bun run rig run delete --run <id> [--purge-artifacts]");
7873
+ requireNoExtraArgs(pending, "rig run delete --run <id> [--purge-artifacts]");
7630
7874
  if (!run.value) {
7631
7875
  throw new CliError2("run delete requires --run <id>.");
7632
7876
  }
@@ -7656,7 +7900,7 @@ async function executeRun(context, args) {
7656
7900
  pending = keepRuntimes.rest;
7657
7901
  const keepQueue = takeFlag(pending, "--keep-queue");
7658
7902
  pending = keepQueue.rest;
7659
- requireNoExtraArgs(pending, "bun run rig run cleanup --all [--keep-artifacts] [--keep-runtimes] [--keep-queue]");
7903
+ requireNoExtraArgs(pending, "rig run cleanup --all [--keep-artifacts] [--keep-runtimes] [--keep-queue]");
7660
7904
  if (!all.value) {
7661
7905
  throw new CliError2("run cleanup currently requires --all.");
7662
7906
  }
@@ -7675,20 +7919,25 @@ async function executeRun(context, args) {
7675
7919
  }
7676
7920
  case "show": {
7677
7921
  let pending = rest;
7922
+ const rawResult = takeFlag(pending, "--raw");
7923
+ pending = rawResult.rest;
7678
7924
  const run = takeOption(pending, "--run");
7679
7925
  pending = run.rest;
7680
- requireNoExtraArgs(pending, "bun run rig run show --run <id>");
7681
- if (!run.value) {
7682
- throw new CliError2("run show requires --run <id>.");
7926
+ const positionalRunId = pending.length > 0 && pending[0] && !pending[0].startsWith("-") ? pending[0] : undefined;
7927
+ const extra = positionalRunId ? pending.slice(1) : pending;
7928
+ requireNoExtraArgs(extra, "rig run show <id>|--run <id> [--raw]");
7929
+ const runId = run.value ?? positionalRunId;
7930
+ if (!runId) {
7931
+ throw new CliError2("run show requires a run id.");
7683
7932
  }
7684
- const record = readAuthorityRun4(context.projectRoot, run.value) ?? normalizeRemoteRunDetails(await getRunDetailsViaServer(context, run.value).catch(() => ({})));
7933
+ const record = readAuthorityRun4(context.projectRoot, runId) ?? normalizeRemoteRunDetails2(await getRunDetailsViaServer(context, runId).catch(() => ({})));
7685
7934
  if (!record) {
7686
- throw new CliError2(`Run not found: ${run.value}`, 2);
7935
+ throw new CliError2(`Run not found: ${runId}`, 2);
7687
7936
  }
7688
7937
  if (context.outputMode === "text") {
7689
- console.log(JSON.stringify(record, null, 2));
7938
+ printFormattedOutput(rawResult.value ? JSON.stringify(record, null, 2) : formatRunCard(record));
7690
7939
  }
7691
- return { ok: true, group: "run", command, details: record };
7940
+ return { ok: true, group: "run", command, details: { ...record, rawOutput: rawResult.value } };
7692
7941
  }
7693
7942
  case "timeline": {
7694
7943
  let pending = rest;
@@ -7696,7 +7945,7 @@ async function executeRun(context, args) {
7696
7945
  pending = run.rest;
7697
7946
  const follow = takeFlag(pending, "--follow");
7698
7947
  pending = follow.rest;
7699
- requireNoExtraArgs(pending, "bun run rig run timeline --run <id> [--follow]");
7948
+ requireNoExtraArgs(pending, "rig run timeline --run <id> [--follow]");
7700
7949
  if (!run.value) {
7701
7950
  throw new CliError2("run timeline requires --run <id>.");
7702
7951
  }
@@ -7733,7 +7982,7 @@ async function executeRun(context, args) {
7733
7982
  pending = pollMs.rest;
7734
7983
  const positionalRunId = pending.length > 0 ? pending[0] : undefined;
7735
7984
  const extra = positionalRunId ? pending.slice(1) : pending;
7736
- requireNoExtraArgs(extra, "bun run rig run attach <run-id>|--run <run-id> [--message <text>] [--once|--follow] [--poll-ms <ms>]");
7985
+ requireNoExtraArgs(extra, "rig run attach <run-id>|--run <run-id> [--message <text>] [--once|--follow] [--poll-ms <ms>]");
7737
7986
  const runId = runOption.value ?? positionalRunId;
7738
7987
  if (!runId) {
7739
7988
  throw new CliError2("run attach requires a run id.", 2);
@@ -7753,28 +8002,18 @@ async function executeRun(context, args) {
7753
8002
  return { ok: true, group: "run", command, details: { ...attached, steered: attached.steered || steered } };
7754
8003
  }
7755
8004
  case "status": {
7756
- requireNoExtraArgs(rest, "bun run rig run status");
8005
+ requireNoExtraArgs(rest, "rig run status");
7757
8006
  if (context.dryRun) {
7758
8007
  if (context.outputMode === "text") {
7759
8008
  console.log("[dry-run] rig run status");
7760
8009
  }
7761
8010
  return { ok: true, group: "run", command };
7762
8011
  }
7763
- const summary = isRemoteConnectionSelected(context.projectRoot) ? buildServerRunStatus(await listRunsViaServer(context, { limit: 100 })) : runStatus(context.projectRoot, runtimeContext);
8012
+ const summary = isRemoteConnectionSelected2(context.projectRoot) ? buildServerRunStatus(await listRunsViaServer(context, { limit: 100 })) : runStatus(context.projectRoot, runtimeContext);
7764
8013
  const activeRuns = Array.isArray(summary.activeRuns) ? summary.activeRuns.filter((run) => Boolean(run && typeof run === "object" && !Array.isArray(run))) : [];
7765
8014
  const recentRuns = Array.isArray(summary.recentRuns) ? summary.recentRuns.filter((run) => Boolean(run && typeof run === "object" && !Array.isArray(run))) : [];
7766
8015
  if (context.outputMode === "text") {
7767
- console.log(`Active runs: ${activeRuns.length}`);
7768
- for (const run of activeRuns) {
7769
- console.log(`- ${runStringField(run, "runId", "(unknown-run)")} \xB7 ${runStringField(run, "status", "unknown")} \xB7 ${runStringField(run, "taskId", runDisplayTitle(run))}`);
7770
- }
7771
- if (recentRuns.length > 0) {
7772
- console.log("");
7773
- console.log("Recent runs:");
7774
- for (const run of recentRuns) {
7775
- console.log(`- ${runStringField(run, "runId", "(unknown-run)")} \xB7 ${runStringField(run, "status", "unknown")} \xB7 ${runStringField(run, "taskId", runDisplayTitle(run))}`);
7776
- }
7777
- }
8016
+ printFormattedOutput(formatRunStatus({ activeRuns, recentRuns, runs: Array.isArray(summary.runs) ? summary.runs : [...activeRuns, ...recentRuns] }, { source: isRemoteConnectionSelected2(context.projectRoot) ? "server" : "local" }));
7778
8017
  }
7779
8018
  return { ok: true, group: "run", command, details: summary };
7780
8019
  }
@@ -7798,7 +8037,7 @@ async function executeRun(context, args) {
7798
8037
  pending = pollResult.rest;
7799
8038
  const noServerResult = takeFlag(pending, "--no-server");
7800
8039
  pending = noServerResult.rest;
7801
- requireNoExtraArgs(pending, "bun run rig run start [--epic <id>] [--prompt-epic|--no-epic-prompt] [--ws-port <n>] [--server-host <host>] [--server-port <n>] [--poll-ms <n>] [--no-server]");
8040
+ requireNoExtraArgs(pending, "rig run start [--epic <id>] [--prompt-epic|--no-epic-prompt] [--ws-port <n>] [--server-host <host>] [--server-port <n>] [--poll-ms <n>] [--no-server]");
7802
8041
  if (promptEpicResult.value && noEpicPromptResult.value) {
7803
8042
  throw new CliError2("Cannot use --prompt-epic and --no-epic-prompt together.");
7804
8043
  }
@@ -7846,7 +8085,7 @@ async function executeRun(context, args) {
7846
8085
  };
7847
8086
  }
7848
8087
  case "resume": {
7849
- requireNoExtraArgs(rest, "bun run rig run resume");
8088
+ requireNoExtraArgs(rest, "rig run resume");
7850
8089
  if (context.dryRun) {
7851
8090
  if (context.outputMode === "text") {
7852
8091
  console.log("[dry-run] rig run resume");
@@ -7860,7 +8099,7 @@ async function executeRun(context, args) {
7860
8099
  return { ok: true, group: "run", command, details: resumed };
7861
8100
  }
7862
8101
  case "restart": {
7863
- requireNoExtraArgs(rest, "bun run rig run restart");
8102
+ requireNoExtraArgs(rest, "rig run restart");
7864
8103
  if (context.dryRun) {
7865
8104
  if (context.outputMode === "text") {
7866
8105
  console.log("[dry-run] rig run restart");
@@ -7877,7 +8116,7 @@ async function executeRun(context, args) {
7877
8116
  const runOption = takeOption(rest, "--run");
7878
8117
  const positionalRunId = runOption.rest.length > 0 ? runOption.rest[0] : undefined;
7879
8118
  const extra = positionalRunId ? runOption.rest.slice(1) : runOption.rest;
7880
- requireNoExtraArgs(extra, "bun run rig run stop [<run-id>|--run <id>]");
8119
+ requireNoExtraArgs(extra, "rig run stop [<run-id>|--run <id>]");
7881
8120
  const runId = runOption.value ?? positionalRunId;
7882
8121
  if (context.dryRun) {
7883
8122
  return {
@@ -8015,73 +8254,425 @@ async function executeServer(context, args, options) {
8015
8254
  throw new CliError2(`Unknown server command: ${command}`);
8016
8255
  }
8017
8256
  }
8018
-
8019
- // packages/cli/src/commands/task.ts
8020
- import { readFileSync as readFileSync9 } from "fs";
8021
- import { spawnSync as spawnSync3 } from "child_process";
8022
- import { resolve as resolve20 } from "path";
8023
- import { cancel as cancel4, confirm as confirm2, isCancel as isCancel4 } from "@clack/prompts";
8024
- import {
8025
- taskArtifactDir,
8026
- taskArtifacts,
8027
- taskArtifactWrite,
8028
- taskDeps,
8029
- taskInfo,
8030
- taskLookup as taskLookup2,
8031
- taskReady,
8032
- taskRecord,
8033
- taskReopen,
8034
- taskScope,
8035
- taskStatus as taskStatus2,
8036
- taskValidate,
8037
- taskVerify
8038
- } from "@rig/runtime/control-plane/native/task-ops";
8039
-
8040
- // packages/cli/src/commands/_task-picker.ts
8041
- import { cancel as cancel3, isCancel as isCancel3, select as select3 } from "@clack/prompts";
8042
- function taskId2(task) {
8043
- return typeof task.id === "string" && task.id.trim() ? task.id : "<unknown>";
8257
+
8258
+ // packages/cli/src/commands/task.ts
8259
+ import { readFileSync as readFileSync9 } from "fs";
8260
+ import { spawnSync as spawnSync3 } from "child_process";
8261
+ import { resolve as resolve20 } from "path";
8262
+ import { cancel as cancel4, confirm as confirm2, isCancel as isCancel4 } from "@clack/prompts";
8263
+ import {
8264
+ taskArtifactDir,
8265
+ taskArtifacts,
8266
+ taskArtifactWrite,
8267
+ taskDeps,
8268
+ taskInfo,
8269
+ taskLookup as taskLookup2,
8270
+ taskReady,
8271
+ taskRecord,
8272
+ taskReopen,
8273
+ taskScope,
8274
+ taskStatus as taskStatus2,
8275
+ taskValidate,
8276
+ taskVerify
8277
+ } from "@rig/runtime/control-plane/native/task-ops";
8278
+
8279
+ // packages/cli/src/commands/_task-picker.ts
8280
+ import { cancel as cancel3, isCancel as isCancel3, select as select3 } from "@clack/prompts";
8281
+ function taskId2(task) {
8282
+ return typeof task.id === "string" && task.id.trim() ? task.id : "<unknown>";
8283
+ }
8284
+ async function selectTaskWithTextPicker(tasks, io = {}) {
8285
+ if (tasks.length === 0)
8286
+ return null;
8287
+ if (tasks.length === 1)
8288
+ return tasks[0];
8289
+ const isTty = io.isTty ?? Boolean(process.stdin.isTTY && process.stdout.isTTY);
8290
+ if (!isTty) {
8291
+ throw new Error("task run requires an interactive terminal to pick a task; pass --task <id>, --next, or --detach with a task id.");
8292
+ }
8293
+ if (io.prompt || io.renderer) {
8294
+ const prompt = io.prompt ?? promptForTaskSelection;
8295
+ const renderer = io.renderer ?? { writeLine: (line) => process.stdout.write(`${line}
8296
+ `) };
8297
+ renderer.writeLine("Select Rig task:");
8298
+ for (const row of renderTaskPickerRows(tasks))
8299
+ renderer.writeLine(` ${row}`);
8300
+ const answer2 = (await prompt(`Task [1-${tasks.length}] or id: `)).trim();
8301
+ if (!answer2)
8302
+ return null;
8303
+ if (/^\d+$/.test(answer2)) {
8304
+ const index2 = Number.parseInt(answer2, 10) - 1;
8305
+ return tasks[index2] ?? null;
8306
+ }
8307
+ return tasks.find((task) => taskId2(task) === answer2) ?? null;
8308
+ }
8309
+ const options = tasks.map((task, index2) => ({
8310
+ value: `${index2}`,
8311
+ label: `${taskId2(task)} \xB7 ${typeof task.title === "string" && task.title.trim() ? task.title.trim() : "Untitled task"}`,
8312
+ hint: typeof task.status === "string" && task.status.trim() ? task.status.trim() : undefined
8313
+ }));
8314
+ const answer = await select3({
8315
+ message: "Select Rig task",
8316
+ options
8317
+ });
8318
+ if (isCancel3(answer)) {
8319
+ cancel3("No task selected.");
8320
+ return null;
8321
+ }
8322
+ const index = Number.parseInt(String(answer), 10);
8323
+ return Number.isFinite(index) ? tasks[index] ?? null : null;
8324
+ }
8325
+
8326
+ // packages/cli/src/commands/_help-catalog.ts
8327
+ import { intro as intro3, log as log4, note as note4, outro as outro3 } from "@clack/prompts";
8328
+ import pc4 from "picocolors";
8329
+ var TOP_LEVEL_SECTIONS = [
8330
+ {
8331
+ title: "Server",
8332
+ subtitle: "choose the local or remote Rig server that owns this repo",
8333
+ commands: [
8334
+ { command: "rig server status", description: "Show the selected local/remote server for this repo." },
8335
+ { command: "rig server use local", description: "Switch this repo back to the local Rig server." },
8336
+ { command: "rig server add <alias> <url>", description: "Save a remote Rig server alias." },
8337
+ { command: "rig server use <alias>", description: "Switch this repo to a saved remote server." },
8338
+ { command: "rig server list", description: "Show saved server aliases, including local." }
8339
+ ]
8340
+ },
8341
+ {
8342
+ title: "Tasks",
8343
+ subtitle: "find work, inspect it, and submit Pi-backed workers",
8344
+ commands: [
8345
+ { command: "rig task list", description: "List tasks from the selected task source/server." },
8346
+ { command: "rig task next", description: "Show the next matching task as a selected-task card." },
8347
+ { command: "rig task show <id>", description: "Show a human task summary; add --raw or --json for the full payload." },
8348
+ { command: "rig task run <id|--next> [--detach]", description: "Submit a task run; interactive mode follows with bundled Pi." }
8349
+ ]
8350
+ },
8351
+ {
8352
+ title: "Runs",
8353
+ subtitle: "observe, attach to, and stop live or recent runs",
8354
+ commands: [
8355
+ { command: "rig run list", description: "List recent runs from the selected server or local state." },
8356
+ { command: "rig run show <id>", description: "Show a human run summary; add --raw or --json for the full payload." },
8357
+ { command: "rig run attach <id> --follow", description: "Open the native bundled Pi live view for a worker run." },
8358
+ { command: "rig run stop <id>", description: "Request cancellation for a running worker." }
8359
+ ]
8360
+ },
8361
+ {
8362
+ title: "Review / inbox",
8363
+ subtitle: "clear blocked runs and configure completion review",
8364
+ commands: [
8365
+ { command: "rig inbox approvals", description: "List pending approval requests from local/server run state." },
8366
+ { command: "rig inbox inputs", description: "List pending user-input requests from local/server run state." },
8367
+ { command: "rig review show|set", description: "Inspect or change the review gate policy." }
8368
+ ]
8369
+ },
8370
+ {
8371
+ title: "Health / setup",
8372
+ subtitle: "bootstrap and diagnose the repo/server/GitHub/Pi path",
8373
+ commands: [
8374
+ { command: "rig init", description: "Interactive setup: config, GitHub auth, task source, server, checkout, Pi." },
8375
+ { command: "rig doctor", description: "Diagnose project/server/GitHub/task/Pi wiring." },
8376
+ { command: "rig github auth status", description: "Show GitHub auth state on the selected Rig server." }
8377
+ ]
8378
+ }
8379
+ ];
8380
+ var PRIMARY_GROUPS = [
8381
+ {
8382
+ name: "server",
8383
+ summary: "Choose, inspect, and start the Rig server that owns tasks and runs.",
8384
+ usage: ["rig server <status|list|add|use|start> [options]"],
8385
+ commands: [
8386
+ { command: "status", description: "Show the selected server for this repo.", primary: true },
8387
+ { command: "use local", description: "Switch this repo to the local Rig server.", primary: true },
8388
+ { command: "add <alias> <url>", description: "Save a remote Rig server URL.", primary: true },
8389
+ { command: "use <alias>", description: "Select a saved remote server alias.", primary: true },
8390
+ { command: "list", description: "List saved local/remote server aliases.", primary: true },
8391
+ { command: "start [--host <host>] [--port <n>]", description: "Start a local rig-server process." }
8392
+ ],
8393
+ examples: [
8394
+ "rig server status",
8395
+ "rig server add prod https://where.rig-does.work",
8396
+ "rig server use prod",
8397
+ "rig server use local",
8398
+ "rig server start --port 3773"
8399
+ ],
8400
+ next: ["Use `rig task list` to see server-owned work.", "Use `rig run list` or `rig run attach <id> --follow` to monitor runs."],
8401
+ advanced: ["Compatibility alias: `rig connect ...` remains callable."]
8402
+ },
8403
+ {
8404
+ name: "task",
8405
+ summary: "Find work, start Pi-backed runs, and validate task results.",
8406
+ usage: ["rig task <list|next|show|run> [options]"],
8407
+ commands: [
8408
+ { command: "list [--assignee <login|@me>] [--state open|closed]", description: "List tasks from the selected server/source.", primary: true },
8409
+ { command: "next [filters]", description: "Render the next matching task as a selected-task card.", primary: true },
8410
+ { command: "show <id>|--task <id> [--raw]", description: "Show a human task summary; --raw prints the full payload.", primary: true },
8411
+ { command: "run [#<issue>|<task-id>|--next|--task <id>]", description: "Submit a task run; interactive follows with bundled Pi.", primary: true },
8412
+ { command: "validate|verify [--task <id>]", description: "Run configured task checks/review gates." },
8413
+ { command: "artifacts|artifact-dir|artifact-write", description: "Inspect or write task artifacts." },
8414
+ { command: "report-bug", description: "Create a structured bug report/task." }
8415
+ ],
8416
+ examples: [
8417
+ "rig task list --assignee @me --limit 20",
8418
+ "rig task next",
8419
+ "rig task show 123 --raw",
8420
+ "rig task run --next",
8421
+ "rig task run #123 --runtime-adapter pi",
8422
+ "rig task run --title 'Investigate deploy drift' --initial-prompt 'Check server health'"
8423
+ ],
8424
+ next: ["Use `--detach` to submit without attaching.", "Use `rig run attach <run-id> --follow` to rejoin a live run."]
8425
+ },
8426
+ {
8427
+ name: "run",
8428
+ summary: "Observe, attach to, and control Rig runs.",
8429
+ usage: ["rig run <list|status|show|attach|stop> [options]"],
8430
+ commands: [
8431
+ { command: "list", description: "List recent runs from the selected server or local state.", primary: true },
8432
+ { command: "status", description: "Render active and recent run groups.", primary: true },
8433
+ { command: "show <id>|--run <id> [--raw]", description: "Show a human run summary; --raw prints the full payload.", primary: true },
8434
+ { command: "attach <run-id>|--run <id> [--follow]", description: "Attach to the run; --follow launches native bundled Pi for live Pi runs.", primary: true },
8435
+ { command: "stop [<run-id>|--run <id>]", description: "Request stop for one run or local active runs.", primary: true },
8436
+ { command: "timeline --run <id> [--follow]", description: "Stream raw run timeline events." },
8437
+ { command: "delete|cleanup", description: "Remove completed run records/artifacts." }
8438
+ ],
8439
+ examples: [
8440
+ "rig run list",
8441
+ "rig run status",
8442
+ "rig run show <run-id>",
8443
+ "rig run attach <run-id> --follow",
8444
+ "rig run stop <run-id>"
8445
+ ],
8446
+ next: ["Use `rig task run --next` to create a new run.", "Use `--json` when scripts need the full structured record."]
8447
+ },
8448
+ {
8449
+ name: "inbox",
8450
+ summary: "Review approval and user-input requests that block worker runs.",
8451
+ usage: ["rig inbox <approvals|approve|inputs|respond> [options]"],
8452
+ commands: [
8453
+ { command: "approvals [--run <id>] [--task <id>]", description: "List pending approvals.", primary: true },
8454
+ { command: "inputs [--run <id>] [--task <id>]", description: "List pending user-input requests.", primary: true },
8455
+ { command: "approve --run <id> --request <id> --decision approve|reject", description: "Resolve an approval request." },
8456
+ { command: "respond --run <id> --request <id> --answer key=value", description: "Answer a user-input request." }
8457
+ ],
8458
+ examples: [
8459
+ "rig inbox approvals",
8460
+ "rig inbox inputs --run <run-id>",
8461
+ "rig inbox approve --run <run-id> --request <request-id> --decision approve"
8462
+ ],
8463
+ next: ["Rejoin the run after resolving a block: `rig run attach <run-id> --follow`."]
8464
+ },
8465
+ {
8466
+ name: "review",
8467
+ summary: "Inspect or change completion review gate policy.",
8468
+ usage: ["rig review <show|set>"],
8469
+ commands: [
8470
+ { command: "show", description: "Show current review gate settings.", primary: true },
8471
+ { command: "set <off|advisory|required> [--provider greptile]", description: "Change review strictness/provider.", primary: true }
8472
+ ],
8473
+ examples: ["rig review show", "rig review set required --provider greptile"],
8474
+ next: ["Use `rig inbox approvals` for blocked run handoffs."]
8475
+ },
8476
+ {
8477
+ name: "init",
8478
+ summary: "Set up Rig for this repo: server, GitHub auth, checkout strategy, task source, and Pi wiring.",
8479
+ usage: ["rig init [--yes] [--server local|remote] [--repo owner/repo] [--remote-url <url>]"],
8480
+ commands: [
8481
+ { command: "init", description: "Interactive setup wizard for a new or existing Rig repo.", primary: true },
8482
+ { command: "init --yes", description: "Non-interactive setup using detected/default settings.", primary: true },
8483
+ { command: "init --server remote --remote-url <url>", description: "Link this repo to a remote Rig server.", primary: true },
8484
+ { command: "init --repair", description: "Repair missing private state without replacing project config." }
8485
+ ],
8486
+ examples: [
8487
+ "rig init",
8488
+ "rig init --yes --repo humanity-org/humanwork",
8489
+ "rig init --server remote --remote-url https://where.rig-does.work --repo owner/repo"
8490
+ ],
8491
+ next: ["After init, run `rig server status`.", "Then use `rig task list` and `rig task run --next` for day-to-day work."]
8492
+ },
8493
+ {
8494
+ name: "doctor",
8495
+ summary: "Diagnostics for project/server/GitHub/Pi state.",
8496
+ usage: ["rig doctor"],
8497
+ commands: [
8498
+ { command: "doctor", description: "Run setup and runtime diagnostics.", primary: true },
8499
+ { command: "check", description: "Compatibility spelling for diagnostics." }
8500
+ ],
8501
+ examples: ["rig doctor", "rig doctor --json"],
8502
+ next: ["Use `rig server status` and `rig github auth status` to inspect common failure points."]
8503
+ },
8504
+ {
8505
+ name: "github",
8506
+ summary: "GitHub auth helpers for the selected Rig server.",
8507
+ usage: ["rig github auth <status|import-gh|token>"],
8508
+ commands: [
8509
+ { command: "auth status", description: "Show GitHub auth state.", primary: true },
8510
+ { command: "auth import-gh", description: "Import the current `gh` token into the selected server." },
8511
+ { command: "auth token --token <token>", description: "Store a token on the selected server." }
8512
+ ],
8513
+ examples: ["rig github auth status", "rig github auth import-gh"],
8514
+ next: ["After auth is valid, use `rig task run --next`."]
8515
+ }
8516
+ ];
8517
+ var ADVANCED_GROUPS = [
8518
+ { name: "connect", summary: "Compatibility alias for `rig server` selection commands.", usage: ["rig connect <status|list|add|use>"], commands: [{ command: "status|list|add|use", description: "Use `rig server ...` for the primary UX." }] },
8519
+ { name: "setup", summary: "Bootstrap/check local setup.", usage: ["rig setup <bootstrap|check|preflight>"], commands: [{ command: "bootstrap|check|preflight", description: "Setup helpers." }] },
8520
+ { name: "inspect", summary: "Inspect logs, artifacts, graphs, failures.", usage: ["rig inspect <logs|artifacts|failures|graph|audit|diff>"], commands: [{ command: "logs --task <id>", description: "Inspect task logs." }] },
8521
+ { name: "repo", summary: "Repository sync/baseline helpers.", usage: ["rig repo <sync|reset-baseline>"], commands: [{ command: "sync", description: "Sync project repository state." }] },
8522
+ { name: "profile", summary: "Runtime profile/model defaults.", usage: ["rig profile <show|set>"], commands: [{ command: "show", description: "Show active profile." }] },
8523
+ { name: "browser", summary: "Browser/app diagnostics.", usage: ["rig browser <help|explain|demo|app>"], commands: [{ command: "help", description: "Browser command help." }] },
8524
+ { name: "plugin", summary: "Plugin validation/listing.", usage: ["rig plugin <list|validate>"], commands: [{ command: "list", description: "List plugins." }] },
8525
+ { name: "queue", summary: "Run task queues locally.", usage: ["rig queue run [options]"], commands: [{ command: "run", description: "Process queue work." }] },
8526
+ { name: "agent", summary: "Runtime agent workspace helpers.", usage: ["rig agent <list|prepare|run|cleanup>"], commands: [{ command: "list", description: "List prepared agents." }] },
8527
+ { name: "inspector", summary: "Event stream and drift scanners.", usage: ["rig inspector <stream|scan-upstream-drift>"], commands: [{ command: "stream", description: "Stream events." }] },
8528
+ { name: "dist", summary: "Build/install packaged Rig CLI.", usage: ["rig dist <build|install|doctor>"], commands: [{ command: "build", description: "Build distribution." }] },
8529
+ { name: "workspace", summary: "Workspace topology/service helpers.", usage: ["rig workspace <summary|topology|remote-hosts>"], commands: [{ command: "summary", description: "Show workspace summary." }] },
8530
+ { name: "remote", summary: "Compatibility remote orchestration controls.", usage: ["rig remote <status|watch|pause|resume|...>"], commands: [{ command: "status", description: "Show remote state." }] },
8531
+ { name: "git", summary: "Pass through to Rig git-flow helper.", usage: ["rig git <args...>"], commands: [{ command: "<args...>", description: "Advanced git flow operations." }] },
8532
+ { name: "harness", summary: "Pass through to runtime harness CLI.", usage: ["rig harness <args...>"], commands: [{ command: "<args...>", description: "Advanced harness operations." }] },
8533
+ { name: "test", summary: "Project test wrappers.", usage: ["rig test <unit|e2e|all>"], commands: [{ command: "all", description: "Run configured project tests." }] }
8534
+ ];
8535
+ var ADVANCED_COMMANDS = [
8536
+ { command: "rig server task-run ...", description: "Internal server-owned task execution entry point." },
8537
+ { command: "rig server notify-test [--event <type>]", description: "Internal event notification smoke command." },
8538
+ { command: "rig run start|start-serial|start-parallel", description: "Compatibility local run starters; prefer `rig task run ...`." },
8539
+ { command: "rig setup install-agent-shell", description: "Development helper for materializing the agent shell." },
8540
+ { command: "rig remote orchestrate-*", description: "Compatibility remote orchestration commands." }
8541
+ ];
8542
+ var ALL_GROUPS = [...PRIMARY_GROUPS, ...ADVANCED_GROUPS];
8543
+ function heading(title) {
8544
+ return pc4.bold(pc4.cyan(title));
8545
+ }
8546
+ function commandLine(command, description) {
8547
+ const commandColumn = command.length >= 38 ? `${command} ` : command.padEnd(38);
8548
+ return `${pc4.dim("\u2502")} ${pc4.bold(commandColumn)} ${description}`;
8549
+ }
8550
+ function renderCommandBlock(commands) {
8551
+ return commands.map((entry) => commandLine(entry.command, entry.description)).join(`
8552
+ `);
8553
+ }
8554
+ function renderGroup(group) {
8555
+ const lines = [
8556
+ `${heading(`rig ${group.name}`)} \u2014 ${group.summary}`,
8557
+ "",
8558
+ pc4.bold("Usage"),
8559
+ ...group.usage.map((line) => ` ${line}`),
8560
+ "",
8561
+ pc4.bold("Commands"),
8562
+ ...group.commands.map((entry) => commandLine(entry.command, entry.description))
8563
+ ];
8564
+ if (group.examples?.length) {
8565
+ lines.push("", pc4.bold("Examples"), ...group.examples.map((line) => ` ${pc4.dim("$")} ${line}`));
8566
+ }
8567
+ if (group.next?.length) {
8568
+ lines.push("", pc4.bold("Next steps"), ...group.next.map((line) => ` ${pc4.dim("\u203A")} ${line}`));
8569
+ }
8570
+ if (group.advanced?.length) {
8571
+ lines.push("", pc4.bold("Compatibility / advanced"), ...group.advanced.map((line) => ` ${pc4.dim("\u203A")} ${line}`));
8572
+ }
8573
+ return lines.join(`
8574
+ `);
8575
+ }
8576
+ function renderTopLevelHelp() {
8577
+ return [
8578
+ `${heading("rig")} ${pc4.dim("\u2014 server-owned task/run control plane for Pi-backed engineering work")}`,
8579
+ pc4.dim("Current path: select a server, choose a task, submit a run, attach with native Pi, clear inbox/review gates."),
8580
+ "",
8581
+ ...TOP_LEVEL_SECTIONS.flatMap((section) => [
8582
+ `${pc4.bold(pc4.magenta(`\u25C7 ${section.title}`))} \u2014 ${pc4.dim(section.subtitle)}`,
8583
+ renderCommandBlock(section.commands),
8584
+ ""
8585
+ ]),
8586
+ pc4.dim("More: `rig help --advanced` for dev/compatibility commands; `rig <group> --help` for rich per-group help; `rig --version` for the installed version."),
8587
+ "",
8588
+ pc4.bold("Global options"),
8589
+ commandLine("--project <path>", "Use a project root instead of auto-discovery."),
8590
+ commandLine("--json", "Emit structured output for scripts/agents."),
8591
+ commandLine("--dry-run", "Print the command plan without mutating state.")
8592
+ ].join(`
8593
+ `).trimEnd();
8594
+ }
8595
+ function renderAdvancedHelp() {
8596
+ return [
8597
+ `${heading("rig advanced")} \u2014 compatibility, diagnostics, and internal surfaces`,
8598
+ "",
8599
+ pc4.bold("Primary groups"),
8600
+ " server, task, run, inbox, review, init, doctor, github",
8601
+ "",
8602
+ pc4.bold("Advanced commands"),
8603
+ ...ADVANCED_COMMANDS.map((entry) => commandLine(entry.command, entry.description)),
8604
+ "",
8605
+ pc4.bold("Advanced groups"),
8606
+ ...ADVANCED_GROUPS.map((group) => commandLine(group.name, group.summary)),
8607
+ "",
8608
+ pc4.dim("All groups remain callable. Prefer `rig server`, `rig task`, `rig run`, `rig inbox`, and `rig review` for day-to-day work.")
8609
+ ].join(`
8610
+ `);
8611
+ }
8612
+ function renderGroupHelp(groupName) {
8613
+ const group = ALL_GROUPS.find((candidate) => candidate.name === groupName);
8614
+ return group ? renderGroup(group) : null;
8044
8615
  }
8045
- async function selectTaskWithTextPicker(tasks, io = {}) {
8046
- if (tasks.length === 0)
8047
- return null;
8048
- if (tasks.length === 1)
8049
- return tasks[0];
8050
- const isTty = io.isTty ?? Boolean(process.stdin.isTTY && process.stdout.isTTY);
8051
- if (!isTty) {
8052
- throw new Error("task run requires an interactive terminal to pick a task; pass --task <id>, --next, or --detach with a task id.");
8616
+ function shouldUseClackOutput2() {
8617
+ return Boolean(process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1";
8618
+ }
8619
+ function printTopLevelHelp() {
8620
+ if (!shouldUseClackOutput2()) {
8621
+ console.log(renderTopLevelHelp());
8622
+ return;
8053
8623
  }
8054
- if (io.prompt || io.renderer) {
8055
- const prompt = io.prompt ?? promptForTaskSelection;
8056
- const renderer = io.renderer ?? { writeLine: (line) => process.stdout.write(`${line}
8057
- `) };
8058
- renderer.writeLine("Select Rig task:");
8059
- for (const row of renderTaskPickerRows(tasks))
8060
- renderer.writeLine(` ${row}`);
8061
- const answer2 = (await prompt(`Task [1-${tasks.length}] or id: `)).trim();
8062
- if (!answer2)
8063
- return null;
8064
- if (/^\d+$/.test(answer2)) {
8065
- const index2 = Number.parseInt(answer2, 10) - 1;
8066
- return tasks[index2] ?? null;
8067
- }
8068
- return tasks.find((task) => taskId2(task) === answer2) ?? null;
8624
+ intro3("rig");
8625
+ for (const section of TOP_LEVEL_SECTIONS) {
8626
+ note4(renderCommandBlock(section.commands), `${section.title} \u2014 ${section.subtitle}`);
8069
8627
  }
8070
- const options = tasks.map((task, index2) => ({
8071
- value: `${index2}`,
8072
- label: `${taskId2(task)} \xB7 ${typeof task.title === "string" && task.title.trim() ? task.title.trim() : "Untitled task"}`,
8073
- hint: typeof task.status === "string" && task.status.trim() ? task.status.trim() : undefined
8074
- }));
8075
- const answer = await select3({
8076
- message: "Select Rig task",
8077
- options
8078
- });
8079
- if (isCancel3(answer)) {
8080
- cancel3("No task selected.");
8081
- return null;
8628
+ log4.info("More: rig help --advanced \xB7 rig <group> --help \xB7 rig --version");
8629
+ note4([
8630
+ commandLine("--project <path>", "Use a project root instead of auto-discovery."),
8631
+ commandLine("--json", "Emit structured output for scripts/agents."),
8632
+ commandLine("--dry-run", "Print the command plan without mutating state.")
8633
+ ].join(`
8634
+ `), "Global options");
8635
+ outro3("Server \u2192 task \u2192 run \u2192 inbox/review.");
8636
+ }
8637
+ function printAdvancedHelp() {
8638
+ if (!shouldUseClackOutput2()) {
8639
+ console.log(renderAdvancedHelp());
8640
+ return;
8082
8641
  }
8083
- const index = Number.parseInt(String(answer), 10);
8084
- return Number.isFinite(index) ? tasks[index] ?? null : null;
8642
+ intro3("rig advanced");
8643
+ note4(ADVANCED_COMMANDS.map((entry) => commandLine(entry.command, entry.description)).join(`
8644
+ `), "Advanced commands");
8645
+ note4(ADVANCED_GROUPS.map((group) => commandLine(group.name, group.summary)).join(`
8646
+ `), "Advanced groups");
8647
+ outro3("Primary daily flow: rig server \xB7 rig task \xB7 rig run \xB7 rig inbox \xB7 rig review.");
8648
+ }
8649
+ function printGroupHelpDocument(groupName) {
8650
+ const rendered = renderGroupHelp(groupName) ?? renderTopLevelHelp();
8651
+ if (!shouldUseClackOutput2()) {
8652
+ console.log(rendered);
8653
+ return;
8654
+ }
8655
+ const group = ALL_GROUPS.find((candidate) => candidate.name === groupName);
8656
+ if (!group) {
8657
+ printTopLevelHelp();
8658
+ return;
8659
+ }
8660
+ intro3(`rig ${group.name}`);
8661
+ note4(group.summary, "Purpose");
8662
+ note4(group.usage.join(`
8663
+ `), "Usage");
8664
+ note4(group.commands.map((entry) => commandLine(entry.command, entry.description)).join(`
8665
+ `), "Commands");
8666
+ if (group.examples?.length)
8667
+ note4(group.examples.map((line) => `$ ${line}`).join(`
8668
+ `), "Examples");
8669
+ if (group.next?.length)
8670
+ note4(group.next.map((line) => `\u203A ${line}`).join(`
8671
+ `), "Next steps");
8672
+ if (group.advanced?.length)
8673
+ log4.info(group.advanced.join(`
8674
+ `));
8675
+ outro3("Run with --json when scripts need structured output.");
8085
8676
  }
8086
8677
 
8087
8678
  // packages/cli/src/commands/task.ts
@@ -8235,27 +8826,30 @@ function summarizeTask(task, options = {}) {
8235
8826
  ...options.raw ? { raw: raw ?? task } : {}
8236
8827
  };
8237
8828
  }
8238
- function printTaskSummary(task) {
8239
- console.log(formatTaskList([task]));
8240
- }
8241
8829
  async function validatorRegistryForTaskCommands(projectRoot) {
8242
8830
  return buildPluginHostContext(projectRoot).then((ctx) => ctx?.validatorRegistry ?? undefined).catch(() => {
8243
8831
  return;
8244
8832
  });
8245
8833
  }
8246
8834
  async function executeTask(context, args, options) {
8247
- const [command = "info", ...rest] = args;
8835
+ if (args.length === 0) {
8836
+ if (context.outputMode === "text") {
8837
+ printGroupHelpDocument("task");
8838
+ }
8839
+ return { ok: true, group: "task", command: "help" };
8840
+ }
8841
+ const [command = "help", ...rest] = args;
8248
8842
  switch (command) {
8249
8843
  case "list": {
8250
8844
  let pending = rest;
8251
8845
  const rawResult = takeFlag(pending, "--raw");
8252
8846
  pending = rawResult.rest;
8253
8847
  const { filters, rest: remaining } = parseTaskFilters(pending);
8254
- requireNoExtraArgs(remaining, "bun run rig task list [--raw] [--assignee <login|@me>] [--assigned-to <login|me|@me>] [--state open|closed] [--status <status>] [--limit <n>]");
8848
+ requireNoExtraArgs(remaining, "rig task list [--raw] [--assignee <login|@me>] [--assigned-to <login|me|@me>] [--state open|closed] [--status <status>] [--limit <n>]");
8255
8849
  const tasks = await listWorkspaceTasksViaServer(context, filters);
8256
8850
  if (context.outputMode === "text") {
8257
8851
  const renderedTasks = rawResult.value ? tasks.map((task) => summarizeTask(task, { raw: true })) : tasks.map((task) => summarizeTask(task));
8258
- console.log(formatTaskList(renderedTasks, { raw: rawResult.value }));
8852
+ printFormattedOutput(formatTaskList(renderedTasks, { raw: rawResult.value }));
8259
8853
  }
8260
8854
  return {
8261
8855
  ok: true,
@@ -8265,10 +8859,13 @@ async function executeTask(context, args, options) {
8265
8859
  };
8266
8860
  }
8267
8861
  case "show": {
8268
- const taskOption = takeOption(rest, "--task");
8862
+ let pending = rest;
8863
+ const rawResult = takeFlag(pending, "--raw");
8864
+ pending = rawResult.rest;
8865
+ const taskOption = takeOption(pending, "--task");
8269
8866
  const positional = taskOption.rest.length > 0 && taskOption.rest[0] && !taskOption.rest[0].startsWith("-") ? taskOption.rest[0] : undefined;
8270
8867
  const remaining = positional ? taskOption.rest.slice(1) : taskOption.rest;
8271
- requireNoExtraArgs(remaining, "bun run rig task show <id>|--task <id>");
8868
+ requireNoExtraArgs(remaining, "rig task show <id>|--task <id> [--raw]");
8272
8869
  const taskId3 = normalizeTaskRunTaskId(taskOption.value ?? positional);
8273
8870
  if (!taskId3)
8274
8871
  throw new CliError2("task show requires a task id.", 2);
@@ -8276,19 +8873,20 @@ async function executeTask(context, args, options) {
8276
8873
  if (!task)
8277
8874
  throw new CliError2(`Task not found: ${taskId3}`, 3);
8278
8875
  const summary = summarizeTask(task, { raw: true });
8279
- if (context.outputMode === "text")
8280
- console.log(JSON.stringify(summary, null, 2));
8281
- return { ok: true, group: "task", command, details: { task: summary } };
8876
+ if (context.outputMode === "text") {
8877
+ printFormattedOutput(rawResult.value ? JSON.stringify(summary, null, 2) : formatTaskDetails(summary));
8878
+ }
8879
+ return { ok: true, group: "task", command, details: { task: summary, raw: rawResult.value } };
8282
8880
  }
8283
8881
  case "next": {
8284
8882
  const { filters, rest: remaining } = parseTaskFilters(rest);
8285
- requireNoExtraArgs(remaining, "bun run rig task next [--assignee <login|@me>] [--assigned-to <login|me|@me>] [--state open|closed] [--status <status>] [--limit <n>]");
8883
+ requireNoExtraArgs(remaining, "rig task next [--assignee <login|@me>] [--assigned-to <login|me|@me>] [--state open|closed] [--status <status>] [--limit <n>]");
8286
8884
  const selected = await selectNextWorkspaceTaskViaServer(context, filters);
8287
8885
  if (context.outputMode === "text") {
8288
8886
  if (selected.task) {
8289
- printTaskSummary(selected.task);
8887
+ printFormattedOutput(formatTaskCard(summarizeTask(selected.task, { raw: true }), { title: "Selected task", selected: true }));
8290
8888
  } else {
8291
- console.log("No matching tasks.");
8889
+ printFormattedOutput("No matching tasks.\n\nNext\n\u203A Try `rig task list` to inspect available work.\n\u203A Check server: `rig server status`");
8292
8890
  }
8293
8891
  }
8294
8892
  return {
@@ -8304,31 +8902,31 @@ async function executeTask(context, args, options) {
8304
8902
  }
8305
8903
  case "info": {
8306
8904
  const { value: task, rest: remaining } = takeOption(rest, "--task");
8307
- requireNoExtraArgs(remaining, "bun run rig task info [--task <beads-id>]");
8905
+ requireNoExtraArgs(remaining, "rig task info [--task <task-id>]");
8308
8906
  await withMutedConsole(context.outputMode === "json", () => taskInfo(context.projectRoot, task || undefined));
8309
8907
  return { ok: true, group: "task", command, details: { task: task || null } };
8310
8908
  }
8311
8909
  case "scope": {
8312
8910
  const filesFlag = takeFlag(rest, "--files");
8313
8911
  const { value: task, rest: remaining } = takeOption(filesFlag.rest, "--task");
8314
- requireNoExtraArgs(remaining, "bun run rig task scope [--task <id>] [--files]");
8912
+ requireNoExtraArgs(remaining, "rig task scope [--task <id>] [--files]");
8315
8913
  await withMutedConsole(context.outputMode === "json", () => taskScope(context.projectRoot, filesFlag.value, task || undefined));
8316
8914
  return { ok: true, group: "task", command, details: { files: filesFlag.value, task: task || null } };
8317
8915
  }
8318
8916
  case "deps":
8319
- requireNoExtraArgs(rest, "bun run rig task deps");
8917
+ requireNoExtraArgs(rest, "rig task deps");
8320
8918
  await withMutedConsole(context.outputMode === "json", () => taskDeps(context.projectRoot));
8321
8919
  return { ok: true, group: "task", command };
8322
8920
  case "status":
8323
- requireNoExtraArgs(rest, "bun run rig task status");
8921
+ requireNoExtraArgs(rest, "rig task status");
8324
8922
  withMutedConsole(context.outputMode === "json", () => taskStatus2(context.projectRoot));
8325
8923
  return { ok: true, group: "task", command };
8326
8924
  case "artifacts":
8327
- requireNoExtraArgs(rest, "bun run rig task artifacts");
8925
+ requireNoExtraArgs(rest, "rig task artifacts");
8328
8926
  withMutedConsole(context.outputMode === "json", () => taskArtifacts(context.projectRoot));
8329
8927
  return { ok: true, group: "task", command };
8330
8928
  case "artifact-dir": {
8331
- requireNoExtraArgs(rest, "bun run rig task artifact-dir");
8929
+ requireNoExtraArgs(rest, "rig task artifact-dir");
8332
8930
  const path = taskArtifactDir(context.projectRoot);
8333
8931
  if (context.outputMode === "text") {
8334
8932
  console.log(path);
@@ -8337,7 +8935,7 @@ async function executeTask(context, args, options) {
8337
8935
  }
8338
8936
  case "artifact-write": {
8339
8937
  if (rest.length < 1) {
8340
- throw new CliError2(`Usage: bun run rig task artifact-write <filename> [--file <path>]
8938
+ throw new CliError2(`Usage: rig task artifact-write <filename> [--file <path>]
8341
8939
  ` + ` Reads content from stdin (or --file), writes to the active task artifact dir.
8342
8940
  ` + " Example: echo '...' | rig task artifact-write collection-audit.md");
8343
8941
  }
@@ -8350,7 +8948,7 @@ async function executeTask(context, args, options) {
8350
8948
  content = await readStdin();
8351
8949
  }
8352
8950
  if (!artifactFilename) {
8353
- throw new CliError2("Usage: bun run rig task artifact-write <filename> [--file path]");
8951
+ throw new CliError2("Usage: rig task artifact-write <filename> [--file path]");
8354
8952
  }
8355
8953
  withMutedConsole(context.outputMode === "json", () => taskArtifactWrite(context.projectRoot, artifactFilename, content));
8356
8954
  return { ok: true, group: "task", command, details: { filename: artifactFilename } };
@@ -8359,11 +8957,11 @@ async function executeTask(context, args, options) {
8359
8957
  return options.executeTaskReportBug(context, rest);
8360
8958
  case "lookup": {
8361
8959
  if (rest.length !== 1) {
8362
- throw new CliError2("Usage: bun run rig task lookup <beads-id>");
8960
+ throw new CliError2("Usage: rig task lookup <task-id>");
8363
8961
  }
8364
8962
  const lookupId = rest[0];
8365
8963
  if (!lookupId) {
8366
- throw new CliError2("Usage: bun run rig task lookup <beads-id>");
8964
+ throw new CliError2("Usage: rig task lookup <task-id>");
8367
8965
  }
8368
8966
  const result = taskLookup2(context.projectRoot, lookupId);
8369
8967
  if (context.outputMode === "text") {
@@ -8373,17 +8971,17 @@ async function executeTask(context, args, options) {
8373
8971
  }
8374
8972
  case "record": {
8375
8973
  if (rest.length < 2) {
8376
- throw new CliError2("Usage: bun run rig task record <decision|failure> <text>");
8974
+ throw new CliError2("Usage: rig task record <decision|failure> <text>");
8377
8975
  }
8378
8976
  const type = rest[0];
8379
8977
  if (type !== "decision" && type !== "failure") {
8380
- throw new CliError2("Usage: bun run rig task record <decision|failure> <text>");
8978
+ throw new CliError2("Usage: rig task record <decision|failure> <text>");
8381
8979
  }
8382
8980
  withMutedConsole(context.outputMode === "json", () => taskRecord(context.projectRoot, type, rest.slice(1).join(" ")));
8383
8981
  return { ok: true, group: "task", command, details: { type: rest[0] } };
8384
8982
  }
8385
8983
  case "ready":
8386
- requireNoExtraArgs(rest, "bun run rig task ready");
8984
+ requireNoExtraArgs(rest, "rig task ready");
8387
8985
  await withMutedConsole(context.outputMode === "json", () => taskReady(context.projectRoot));
8388
8986
  return { ok: true, group: "task", command };
8389
8987
  case "run": {
@@ -8420,7 +9018,7 @@ async function executeTask(context, args, options) {
8420
9018
  if (positionalTaskId) {
8421
9019
  pending = pending.slice(1);
8422
9020
  }
8423
- requireNoExtraArgs(pending, "bun run rig task run [#<issue>|<task-id>] [--next] [--task <id>] [--detach] [--assignee <login|@me>] [--assigned-to <login|me|@me>] [--state open|closed] [--status <status>] [--limit <n>] [--title <text>] [--runtime-adapter claude-code|codex|pi] [--model <model>] [--runtime-mode <mode>] [--interaction-mode <mode>] [--initial-prompt <text>] [--pr auto|ask|off] [--no-pr] [--dirty-baseline head|dirty-snapshot] [--skip-project-sync]");
9021
+ requireNoExtraArgs(pending, "rig task run [#<issue>|<task-id>] [--next] [--task <id>] [--detach] [--assignee <login|@me>] [--assigned-to <login|me|@me>] [--state open|closed] [--status <status>] [--limit <n>] [--title <text>] [--runtime-adapter claude-code|codex|pi] [--model <model>] [--runtime-mode <mode>] [--interaction-mode <mode>] [--initial-prompt <text>] [--pr auto|ask|off] [--no-pr] [--dirty-baseline head|dirty-snapshot] [--skip-project-sync]");
8424
9022
  if (nextResult.value && (taskResult.value || positionalTaskId)) {
8425
9023
  throw new CliError2("task run cannot combine --next with an explicit task id.", 2);
8426
9024
  }
@@ -8474,10 +9072,24 @@ async function executeTask(context, args, options) {
8474
9072
  });
8475
9073
  let attachDetails = null;
8476
9074
  if (!detachResult.value && context.outputMode === "text") {
8477
- console.log(formatSubmittedRun({ runId: submitted.runId, task: selectedTask ? summarizeTask(selectedTask) : null }));
9075
+ printFormattedOutput(formatSubmittedRun({
9076
+ runId: submitted.runId,
9077
+ task: selectedTask ? summarizeTask(selectedTask) : null,
9078
+ runtimeAdapter,
9079
+ runtimeMode: runtimeModeResult.value || projectDefaults.runtimeMode || "full-access",
9080
+ interactionMode: interactionModeResult.value || "default",
9081
+ detached: false
9082
+ }));
8478
9083
  attachDetails = await attachRunOperatorView(context, { runId: submitted.runId, follow: true });
8479
9084
  } else if (context.outputMode === "text") {
8480
- console.log(formatSubmittedRun({ runId: submitted.runId, task: selectedTask ? summarizeTask(selectedTask) : null }));
9085
+ printFormattedOutput(formatSubmittedRun({
9086
+ runId: submitted.runId,
9087
+ task: selectedTask ? summarizeTask(selectedTask) : null,
9088
+ runtimeAdapter,
9089
+ runtimeMode: runtimeModeResult.value || projectDefaults.runtimeMode || "full-access",
9090
+ interactionMode: interactionModeResult.value || "default",
9091
+ detached: true
9092
+ }));
8481
9093
  }
8482
9094
  return {
8483
9095
  ok: true,
@@ -8501,7 +9113,7 @@ async function executeTask(context, args, options) {
8501
9113
  }
8502
9114
  case "validate": {
8503
9115
  const { value: task, rest: remaining } = takeOption(rest, "--task");
8504
- requireNoExtraArgs(remaining, "bun run rig task validate [--task <beads-id>]");
9116
+ requireNoExtraArgs(remaining, "rig task validate [--task <task-id>]");
8505
9117
  if (context.dryRun) {
8506
9118
  await context.runCommand(["rig", "task", "validate", ...task ? ["--task", task] : []]);
8507
9119
  return { ok: true, group: "task", command, details: { task: task || "active" } };
@@ -8514,7 +9126,7 @@ async function executeTask(context, args, options) {
8514
9126
  }
8515
9127
  case "verify": {
8516
9128
  const { value: task, rest: remaining } = takeOption(rest, "--task");
8517
- requireNoExtraArgs(remaining, "bun run rig task verify [--task <beads-id>]");
9129
+ requireNoExtraArgs(remaining, "rig task verify [--task <task-id>]");
8518
9130
  if (context.dryRun) {
8519
9131
  await context.runCommand(["rig", "task", "verify", ...task ? ["--task", task] : []]);
8520
9132
  return { ok: true, group: "task", command, details: { task: task || "active" } };
@@ -8527,15 +9139,15 @@ async function executeTask(context, args, options) {
8527
9139
  }
8528
9140
  case "reset": {
8529
9141
  const { value: task, rest: remaining } = takeOption(rest, "--task");
8530
- requireNoExtraArgs(remaining, "bun run rig task reset --task <beads-id>");
8531
- const requiredTask = requireTask(task, "bun run rig task reset --task <beads-id>");
9142
+ requireNoExtraArgs(remaining, "rig task reset --task <task-id>");
9143
+ const requiredTask = requireTask(task, "rig task reset --task <task-id>");
8532
9144
  await context.runCommand(["br", "--no-db", "update", requiredTask, "--status", "open"]);
8533
9145
  return { ok: true, group: "task", command, details: { task: requiredTask } };
8534
9146
  }
8535
9147
  case "details": {
8536
9148
  const { value: task, rest: remaining } = takeOption(rest, "--task");
8537
- requireNoExtraArgs(remaining, "bun run rig task details --task <beads-id>");
8538
- const requiredTask = requireTask(task, "bun run rig task details --task <beads-id>");
9149
+ requireNoExtraArgs(remaining, "rig task details --task <task-id>");
9150
+ const requiredTask = requireTask(task, "rig task details --task <task-id>");
8539
9151
  await withMutedConsole(context.outputMode === "json", () => taskInfo(context.projectRoot, requiredTask));
8540
9152
  return { ok: true, group: "task", command, details: { task: requiredTask } };
8541
9153
  }
@@ -8543,9 +9155,9 @@ async function executeTask(context, args, options) {
8543
9155
  const { value: task, rest: rest1 } = takeOption(rest, "--task");
8544
9156
  const allFlag = takeFlag(rest1, "--all");
8545
9157
  const { rest: remaining } = takeOption(allFlag.rest, "--reason");
8546
- requireNoExtraArgs(remaining, "bun run rig task reopen [--task <id> | --all] [--reason <text>]");
9158
+ requireNoExtraArgs(remaining, "rig task reopen [--task <id> | --all] [--reason <text>]");
8547
9159
  if (!allFlag.value && !task) {
8548
- throw new CliError2("Usage: bun run rig task reopen [--task <id> | --all] [--reason <text>]");
9160
+ throw new CliError2("Usage: rig task reopen [--task <id> | --all] [--reason <text>]");
8549
9161
  }
8550
9162
  const summary = withMutedConsole(context.outputMode === "json", () => taskReopen(context.projectRoot, {
8551
9163
  all: allFlag.value,
@@ -10580,15 +11192,15 @@ async function executeTest(context, args) {
10580
11192
  const [command = "unit", ...rest] = args;
10581
11193
  switch (command) {
10582
11194
  case "unit":
10583
- requireNoExtraArgs(rest, "bun run rig test unit");
11195
+ requireNoExtraArgs(rest, "rig test unit");
10584
11196
  await context.runCommand(["bun", "test", "tests/harness/", "--ignore", "tests/harness/e2e/**"]);
10585
11197
  return { ok: true, group: "test", command };
10586
11198
  case "e2e":
10587
- requireNoExtraArgs(rest, "bun run rig test e2e");
11199
+ requireNoExtraArgs(rest, "rig test e2e");
10588
11200
  await context.runCommand(["bun", "test", "tests/harness/e2e/"]);
10589
11201
  return { ok: true, group: "test", command };
10590
11202
  case "all":
10591
- requireNoExtraArgs(rest, "bun run rig test all");
11203
+ requireNoExtraArgs(rest, "rig test all");
10592
11204
  await context.runCommand(["bun", "test", "tests/harness/"]);
10593
11205
  return { ok: true, group: "test", command };
10594
11206
  default:
@@ -10608,7 +11220,7 @@ async function executeSetup(context, args) {
10608
11220
  const [command = "check", ...rest] = args;
10609
11221
  switch (command) {
10610
11222
  case "bootstrap":
10611
- requireNoExtraArgs(rest, "bun run rig setup bootstrap");
11223
+ requireNoExtraArgs(rest, "rig setup bootstrap");
10612
11224
  {
10613
11225
  const hostBash = Bun.which("bash") || "/bin/bash";
10614
11226
  const env = { ...process.env };
@@ -10631,21 +11243,21 @@ async function executeSetup(context, args) {
10631
11243
  }
10632
11244
  return { ok: true, group: "setup", command };
10633
11245
  case "check":
10634
- requireNoExtraArgs(rest, `bun run rig setup ${command}`);
11246
+ requireNoExtraArgs(rest, `rig setup ${command}`);
10635
11247
  {
10636
11248
  const checks = await withMutedConsole(context.outputMode === "json", () => runSetupCheck(context.projectRoot));
10637
11249
  return { ok: true, group: "setup", command, details: { checks, failures: countDoctorFailures(checks) } };
10638
11250
  }
10639
11251
  case "setup":
10640
- requireNoExtraArgs(rest, "bun run rig setup setup");
11252
+ requireNoExtraArgs(rest, "rig setup setup");
10641
11253
  withMutedConsole(context.outputMode === "json", () => runSetupInit(context.projectRoot));
10642
11254
  return { ok: true, group: "setup", command };
10643
11255
  case "preflight":
10644
- requireNoExtraArgs(rest, "bun run rig setup preflight");
11256
+ requireNoExtraArgs(rest, "rig setup preflight");
10645
11257
  await withMutedConsole(context.outputMode === "json", () => runSetupPreflight(context.projectRoot));
10646
11258
  return { ok: true, group: "setup", command };
10647
11259
  case "install-agent-shell":
10648
- requireNoExtraArgs(rest, "bun run rig setup install-agent-shell");
11260
+ requireNoExtraArgs(rest, "rig setup install-agent-shell");
10649
11261
  if (context.outputMode === "text") {
10650
11262
  console.log("install-agent-shell is deprecated. Runtime shells now use compiled rig-agent directly.");
10651
11263
  }
@@ -10710,7 +11322,7 @@ async function executeWorkspace(context, args) {
10710
11322
  const [command = "summary", ...rest] = args;
10711
11323
  switch (command) {
10712
11324
  case "summary": {
10713
- requireNoExtraArgs(rest, "bun run rig workspace summary");
11325
+ requireNoExtraArgs(rest, "rig workspace summary");
10714
11326
  const summary = await readWorkspaceSummary(context.projectRoot);
10715
11327
  if (context.outputMode === "text") {
10716
11328
  console.log("Workspace Summary");
@@ -10735,7 +11347,7 @@ Warnings:`);
10735
11347
  return { ok: true, group: "workspace", command, details: summary };
10736
11348
  }
10737
11349
  case "topology": {
10738
- requireNoExtraArgs(rest, "bun run rig workspace topology");
11350
+ requireNoExtraArgs(rest, "rig workspace topology");
10739
11351
  const topology = readWorkspaceTopology(context.projectRoot);
10740
11352
  if (context.outputMode === "text") {
10741
11353
  console.log(`Topology: ${topology.status}`);
@@ -10748,7 +11360,7 @@ Warnings:`);
10748
11360
  return { ok: true, group: "workspace", command, details: topology };
10749
11361
  }
10750
11362
  case "remote-hosts": {
10751
- requireNoExtraArgs(rest, "bun run rig workspace remote-hosts");
11363
+ requireNoExtraArgs(rest, "rig workspace remote-hosts");
10752
11364
  const fleet = readWorkspaceRemoteFleet(context.projectRoot);
10753
11365
  if (context.outputMode === "text") {
10754
11366
  console.log(`Remote Hosts: ${fleet.status}`);
@@ -10763,7 +11375,7 @@ Warnings:`);
10763
11375
  let pending = serviceRest;
10764
11376
  const services = takeOption(pending, "--service");
10765
11377
  pending = services.rest;
10766
- requireNoExtraArgs(pending, "bun run rig workspace service-fabric <status|up|verify|down> [--service <name>]");
11378
+ requireNoExtraArgs(pending, "rig workspace service-fabric <status|up|verify|down> [--service <name>]");
10767
11379
  if (action !== "status" && action !== "up" && action !== "verify" && action !== "down") {
10768
11380
  throw new CliError2(`Unknown workspace service-fabric action: ${action}`);
10769
11381
  }
@@ -10784,200 +11396,6 @@ Warnings:`);
10784
11396
  }
10785
11397
  }
10786
11398
 
10787
- // packages/cli/src/commands/_help-catalog.ts
10788
- import pc4 from "picocolors";
10789
- var PRIMARY_GROUPS = [
10790
- {
10791
- name: "init",
10792
- summary: "Set up Rig for this repo: server, GitHub auth, checkout strategy, task source, and Pi wiring.",
10793
- usage: ["rig init [--yes] [--server local|remote] [--repo owner/repo] [--remote-url <url>]"],
10794
- commands: [
10795
- { command: "init", description: "Interactive setup wizard for a new or existing Rig repo.", primary: true },
10796
- { command: "init --yes", description: "Non-interactive setup using detected/default settings.", primary: true },
10797
- { command: "init --server remote --remote-url <url>", description: "Link this repo to a remote Rig server.", primary: true },
10798
- { command: "init --repair", description: "Repair missing private state without replacing project config." }
10799
- ],
10800
- examples: [
10801
- "rig init",
10802
- "rig init --yes --repo humanity-org/humanwork",
10803
- "rig init --server remote --remote-url https://where.rig-does.work --repo owner/repo"
10804
- ],
10805
- next: ["After init, run `rig server status`.", "Then use `rig task list` and `rig task run --next` for day-to-day work."]
10806
- },
10807
- {
10808
- name: "server",
10809
- summary: "Choose, inspect, and start the Rig server that owns tasks and runs.",
10810
- usage: ["rig server <status|list|add|use|start> [options]"],
10811
- commands: [
10812
- { command: "status", description: "Show the selected server for this repo.", primary: true },
10813
- { command: "list", description: "List saved local/remote server aliases.", primary: true },
10814
- { command: "add <alias> <url>", description: "Save a remote Rig server URL.", primary: true },
10815
- { command: "use [alias|local]", description: "Select a server; prompts in an interactive TTY.", primary: true },
10816
- { command: "start [--host <host>] [--port <n>]", description: "Start a local rig-server process.", primary: true }
10817
- ],
10818
- examples: [
10819
- "rig server status",
10820
- "rig server add prod https://where.rig-does.work",
10821
- "rig server use prod",
10822
- "rig server use local",
10823
- "rig server start --port 3773"
10824
- ],
10825
- next: ["Use `rig task list` to see server-owned work.", "Use `rig run list` or `rig run attach <id> --follow` to monitor runs."],
10826
- advanced: ["Compatibility alias: `rig connect ...` remains callable."]
10827
- },
10828
- {
10829
- name: "task",
10830
- summary: "Find work, start Pi-backed runs, and validate task results.",
10831
- usage: ["rig task <list|next|show|run> [options]"],
10832
- commands: [
10833
- { command: "list [--assignee <login|@me>] [--state open|closed]", description: "List tasks from the selected server/source.", primary: true },
10834
- { command: "next [filters]", description: "Pick the next matching task.", primary: true },
10835
- { command: "show <id>|--task <id>", description: "Show task details.", primary: true },
10836
- { command: "run [#<issue>|<task-id>|--next|--task <id>]", description: "Submit a task run; interactive follows with bundled Pi.", primary: true },
10837
- { command: "validate|verify [--task <id>]", description: "Run configured task checks/review gates." },
10838
- { command: "artifacts|artifact-dir|artifact-write", description: "Inspect or write task artifacts." },
10839
- { command: "report-bug", description: "Create a structured bug report/task." }
10840
- ],
10841
- examples: [
10842
- "rig task list --assignee @me --limit 20",
10843
- "rig task run --next",
10844
- "rig task run #123 --runtime-adapter pi",
10845
- "rig task run --title 'Investigate deploy drift' --initial-prompt 'Check server health'"
10846
- ],
10847
- next: ["Use `--detach` to submit without attaching.", "Use `rig run attach <run-id> --follow` to rejoin a live run."]
10848
- },
10849
- {
10850
- name: "run",
10851
- summary: "Observe, attach to, and control Rig runs.",
10852
- usage: ["rig run <list|status|show|attach|stop> [options]"],
10853
- commands: [
10854
- { command: "list", description: "List recent runs from the selected server or local state.", primary: true },
10855
- { command: "status", description: "Summarize active and recent runs.", primary: true },
10856
- { command: "show --run <id>", description: "Show one run record.", primary: true },
10857
- { command: "attach <run-id>|--run <id> [--follow]", description: "Attach to the run; `--follow` launches native bundled Pi for live Pi runs.", primary: true },
10858
- { command: "stop [<run-id>|--run <id>]", description: "Request stop for one run or local active runs.", primary: true },
10859
- { command: "timeline --run <id> [--follow]", description: "Stream raw run timeline events." },
10860
- { command: "delete|cleanup", description: "Remove completed run records/artifacts." }
10861
- ],
10862
- examples: [
10863
- "rig run list",
10864
- "rig run attach 01234567-89ab-cdef-0123-456789abcdef --follow",
10865
- "rig run show --run <run-id>",
10866
- "rig run stop <run-id>"
10867
- ],
10868
- next: ["Use `rig task run --next` to create a new run.", "Use `--json` when scripts need the full structured record."]
10869
- }
10870
- ];
10871
- var ADVANCED_GROUPS = [
10872
- { name: "connect", summary: "Compatibility alias for `rig server` selection commands.", usage: ["rig connect <status|list|add|use>"], commands: [{ command: "status|list|add|use", description: "Use `rig server ...` for the primary UX." }] },
10873
- { name: "github", summary: "GitHub auth helpers.", usage: ["rig github auth <status|import-gh|token>"], commands: [{ command: "auth status", description: "Show GitHub auth state." }] },
10874
- { name: "doctor", summary: "Diagnostics for project/server/GitHub/Pi state.", usage: ["rig doctor [check|run|shared|...]"], commands: [{ command: "check", description: "Run diagnostics." }] },
10875
- { name: "setup", summary: "Bootstrap/check local setup.", usage: ["rig setup <bootstrap|check|preflight>"], commands: [{ command: "bootstrap|check|preflight", description: "Setup helpers." }] },
10876
- { name: "inspect", summary: "Inspect logs, artifacts, graphs, failures.", usage: ["rig inspect <logs|artifacts|failures|graph|audit|diff>"], commands: [{ command: "logs --task <id>", description: "Inspect task logs." }] },
10877
- { name: "repo", summary: "Repository sync/baseline helpers.", usage: ["rig repo <sync|reset-baseline>"], commands: [{ command: "sync", description: "Sync project repository state." }] },
10878
- { name: "profile", summary: "Runtime profile/model defaults.", usage: ["rig profile <show|set>"], commands: [{ command: "show", description: "Show active profile." }] },
10879
- { name: "review", summary: "Review policy configuration.", usage: ["rig review <show|set>"], commands: [{ command: "show", description: "Show review settings." }] },
10880
- { name: "browser", summary: "Browser/app diagnostics.", usage: ["rig browser <help|explain|demo|app>"], commands: [{ command: "help", description: "Browser command help." }] },
10881
- { name: "plugin", summary: "Plugin validation/listing.", usage: ["rig plugin <list|validate>"], commands: [{ command: "list", description: "List plugins." }] },
10882
- { name: "queue", summary: "Run task queues locally.", usage: ["rig queue run [options]"], commands: [{ command: "run", description: "Process queue work." }] },
10883
- { name: "agent", summary: "Runtime agent workspace helpers.", usage: ["rig agent <list|prepare|run|cleanup>"], commands: [{ command: "list", description: "List prepared agents." }] },
10884
- { name: "inspector", summary: "Event stream and drift scanners.", usage: ["rig inspector <stream|scan-upstream-drift>"], commands: [{ command: "stream", description: "Stream events." }] },
10885
- { name: "dist", summary: "Build/install packaged Rig CLI.", usage: ["rig dist <build|install|doctor>"], commands: [{ command: "build", description: "Build distribution." }] },
10886
- { name: "workspace", summary: "Workspace topology/service helpers.", usage: ["rig workspace <summary|topology|remote-hosts>"], commands: [{ command: "summary", description: "Show workspace summary." }] },
10887
- { name: "remote", summary: "Legacy remote orchestration controls.", usage: ["rig remote <status|watch|pause|resume|...>"], commands: [{ command: "status", description: "Show remote state." }] },
10888
- { name: "inbox", summary: "Approval/input inbox for blocked runs.", usage: ["rig inbox <approvals|approve|inputs|respond>"], commands: [{ command: "approvals", description: "List pending approvals." }] },
10889
- { name: "git", summary: "Pass through to Rig git-flow helper.", usage: ["rig git <args...>"], commands: [{ command: "<args...>", description: "Advanced git flow operations." }] },
10890
- { name: "harness", summary: "Pass through to runtime harness CLI.", usage: ["rig harness <args...>"], commands: [{ command: "<args...>", description: "Advanced harness operations." }] },
10891
- { name: "test", summary: "Project test wrappers.", usage: ["rig test <unit|e2e|all>"], commands: [{ command: "all", description: "Run configured project tests." }] }
10892
- ];
10893
- var ALL_GROUPS = [...PRIMARY_GROUPS, ...ADVANCED_GROUPS];
10894
- function heading(title) {
10895
- return pc4.bold(pc4.cyan(title));
10896
- }
10897
- function commandLine(command, description) {
10898
- const commandColumn = command.length >= 34 ? `${command} ` : command.padEnd(34);
10899
- return `${pc4.dim("\u2502")} ${pc4.bold(commandColumn)} ${description}`;
10900
- }
10901
- function renderGroup(group) {
10902
- const lines = [
10903
- `${heading(`rig ${group.name}`)} \u2014 ${group.summary}`,
10904
- "",
10905
- pc4.bold("Usage"),
10906
- ...group.usage.map((line) => ` ${line}`),
10907
- "",
10908
- pc4.bold("Commands"),
10909
- ...group.commands.map((entry) => commandLine(entry.command, entry.description))
10910
- ];
10911
- if (group.examples?.length) {
10912
- lines.push("", pc4.bold("Examples"), ...group.examples.map((line) => ` ${pc4.dim("$")} ${line}`));
10913
- }
10914
- if (group.next?.length) {
10915
- lines.push("", pc4.bold("Next steps"), ...group.next.map((line) => ` ${pc4.dim("\u203A")} ${line}`));
10916
- }
10917
- if (group.advanced?.length) {
10918
- lines.push("", pc4.bold("Compatibility / advanced"), ...group.advanced.map((line) => ` ${pc4.dim("\u203A")} ${line}`));
10919
- }
10920
- return lines.join(`
10921
- `);
10922
- }
10923
- function renderTopLevelHelp() {
10924
- return [
10925
- `${heading("rig")} ${pc4.dim("\u2014 server-owned task/run control plane for Pi-backed engineering work")}`,
10926
- pc4.dim("A repo-local CLI for setup, server selection, task runs, live attach, and completion review."),
10927
- "",
10928
- `${pc4.bold(pc4.magenta("\u25C7 Start here"))} \u2014 ${pc4.dim("bootstrap a repo and choose where Rig runs")}`,
10929
- commandLine("rig init", "Interactive setup: project config, GitHub auth, task source, server, checkout, Pi."),
10930
- commandLine("rig init --yes", "Non-interactive setup using detected defaults; good for repeatable installs."),
10931
- commandLine("rig server status", "Show whether this repo is using local Rig or a remote server."),
10932
- commandLine("rig server use <alias|local>", "Switch the server that owns task/run state for this repo."),
10933
- "",
10934
- `${pc4.bold(pc4.magenta("\u25C7 Daily task loop"))} \u2014 ${pc4.dim("find work, start a worker, and rejoin it later")}`,
10935
- commandLine("rig task list", "List tasks from the selected task source/server with status, labels, and source."),
10936
- commandLine("rig task next", "Pick the next matching task without starting it."),
10937
- commandLine("rig task run --next", "Start the next task and attach to the live bundled Pi frontend."),
10938
- commandLine("rig task run #123 --detach", "Submit a specific issue/task and return immediately."),
10939
- "",
10940
- `${pc4.bold(pc4.magenta("\u25C7 Live run control"))} \u2014 ${pc4.dim("observe, steer, stop, or inspect active runs")}`,
10941
- commandLine("rig run list", "Show recent/active runs from the selected server or local state."),
10942
- commandLine("rig run attach <run-id> --follow", "Open the native Pi live view for a worker-backed run."),
10943
- commandLine("rig run show --run <id>", "Print one run record; add `--json` for automation."),
10944
- commandLine("rig run stop <run-id>", "Request cancellation for a running worker."),
10945
- "",
10946
- `${pc4.bold(pc4.magenta("\u25C7 Core groups"))} \u2014 ${pc4.dim("run `rig <group> --help` for detailed commands and examples")}`,
10947
- ...PRIMARY_GROUPS.map((group) => commandLine(group.name, group.summary)),
10948
- commandLine("doctor", "Diagnose project/server/GitHub/task/Pi wiring when setup or runs misbehave."),
10949
- "",
10950
- `${pc4.bold(pc4.magenta("\u25C7 More"))}`,
10951
- commandLine("rig help --advanced", "Legacy, dev, diagnostics, browser, queue, agent, remote, git, harness commands."),
10952
- commandLine("rig <group> --help", "Rich per-group help with usage, descriptions, examples, and next steps."),
10953
- commandLine("rig --version", "Print the installed Rig CLI version."),
10954
- "",
10955
- `${pc4.bold(pc4.magenta("\u25C7 Global options"))}`,
10956
- commandLine("--project <path>", "Use a project root instead of auto-discovery."),
10957
- commandLine("--json", "Emit structured output for scripts/agents."),
10958
- commandLine("--dry-run", "Print the command plan without mutating state.")
10959
- ].join(`
10960
- `);
10961
- }
10962
- function renderAdvancedHelp() {
10963
- return [
10964
- `${heading("rig advanced")} \u2014 legacy, dev, and compatibility groups`,
10965
- "",
10966
- pc4.bold("Primary groups are still"),
10967
- " init, server, task, run",
10968
- "",
10969
- pc4.bold("Advanced groups"),
10970
- ...ADVANCED_GROUPS.map((group) => commandLine(group.name, group.summary)),
10971
- "",
10972
- pc4.dim("All groups remain callable. Prefer `rig server`, `rig task`, and `rig run` for day-to-day work.")
10973
- ].join(`
10974
- `);
10975
- }
10976
- function renderGroupHelp(groupName) {
10977
- const group = ALL_GROUPS.find((candidate) => candidate.name === groupName);
10978
- return group ? renderGroup(group) : null;
10979
- }
10980
-
10981
11399
  // packages/cli/src/commands.ts
10982
11400
  import { ensureProjectMainFreshBeforeRun as ensureProjectMainFreshBeforeRun2 } from "@rig/runtime/control-plane/project-main-pre-run-sync";
10983
11401
  var TOP_LEVEL_ALIASES = {
@@ -10989,7 +11407,7 @@ var TOP_LEVEL_ALIASES = {
10989
11407
  status: ["run", "status"],
10990
11408
  start: ["task", "run", "--next"],
10991
11409
  "start-parallel": ["run", "start-parallel"],
10992
- "start-serial": ["task", "run", "--next"],
11410
+ "start-serial": ["run", "start-serial"],
10993
11411
  resume: ["run", "resume"],
10994
11412
  stop: ["run", "stop"],
10995
11413
  ready: ["task", "ready"],
@@ -11045,7 +11463,7 @@ var GROUPS = new Set([
11045
11463
  "test"
11046
11464
  ]);
11047
11465
  function printGroupHelp(group) {
11048
- console.log(renderGroupHelp(group) ?? helpText());
11466
+ printGroupHelpDocument(group);
11049
11467
  }
11050
11468
  function isHelpArg(arg) {
11051
11469
  return arg === "--help" || arg === "-h" || arg === "help";
@@ -11055,7 +11473,7 @@ function helpText() {
11055
11473
  }
11056
11474
  async function execute(context, args) {
11057
11475
  if (args.length === 0) {
11058
- console.log(helpText());
11476
+ printTopLevelHelp();
11059
11477
  return { ok: true, group: "help", command: "show" };
11060
11478
  }
11061
11479
  const [first, ...rest] = args;
@@ -11066,14 +11484,14 @@ ${helpText()}`);
11066
11484
  }
11067
11485
  if (first === "help" || first === "--help" || first === "-h") {
11068
11486
  if (rest[0] === "--advanced") {
11069
- console.log(renderAdvancedHelp());
11487
+ printAdvancedHelp();
11070
11488
  return { ok: true, group: "help", command: "advanced" };
11071
11489
  }
11072
11490
  if (rest[0]) {
11073
- console.log(renderGroupHelp(rest[0]) ?? helpText());
11491
+ printGroupHelp(rest[0]);
11074
11492
  return { ok: true, group: "help", command: rest[0] };
11075
11493
  }
11076
- console.log(helpText());
11494
+ printTopLevelHelp();
11077
11495
  return { ok: true, group: "help", command: "show" };
11078
11496
  }
11079
11497
  if (first === "--version" || first === "-V" || first === "version") {