@h-rig/cli 0.0.6-alpha.82 → 0.0.6-alpha.84

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 (206) hide show
  1. package/dist/bin/build-rig-binaries.js +40 -8
  2. package/dist/bin/rig.js +23402 -14577
  3. package/dist/src/app/board.js +217 -41
  4. package/dist/src/app-opentui/adapters/command.d.ts +2 -0
  5. package/dist/src/app-opentui/adapters/command.js +329 -0
  6. package/dist/src/app-opentui/adapters/common.js +2 -2
  7. package/dist/src/app-opentui/adapters/doctor.d.ts +0 -2
  8. package/dist/src/app-opentui/adapters/doctor.js +64 -39
  9. package/dist/src/app-opentui/adapters/family.d.ts +62 -0
  10. package/dist/src/app-opentui/adapters/family.js +14305 -0
  11. package/dist/src/app-opentui/adapters/fleet.d.ts +0 -2
  12. package/dist/src/app-opentui/adapters/fleet.js +90 -60
  13. package/dist/src/app-opentui/adapters/inbox.d.ts +12 -2
  14. package/dist/src/app-opentui/adapters/inbox.js +137 -78
  15. package/dist/src/app-opentui/adapters/init.d.ts +0 -2
  16. package/dist/src/app-opentui/adapters/init.js +85 -47
  17. package/dist/src/app-opentui/adapters/inspect.d.ts +52 -0
  18. package/dist/src/app-opentui/adapters/inspect.js +1024 -0
  19. package/dist/src/app-opentui/adapters/pi-attach.d.ts +15 -6
  20. package/dist/src/app-opentui/adapters/pi-attach.js +442 -125
  21. package/dist/src/app-opentui/adapters/pi.d.ts +23 -0
  22. package/dist/src/app-opentui/adapters/pi.js +363 -0
  23. package/dist/src/app-opentui/adapters/plugin.d.ts +84 -0
  24. package/dist/src/app-opentui/adapters/plugin.js +544 -0
  25. package/dist/src/app-opentui/adapters/repo.d.ts +37 -0
  26. package/dist/src/app-opentui/adapters/repo.js +186 -0
  27. package/dist/src/app-opentui/adapters/run-detail.d.ts +9 -2
  28. package/dist/src/app-opentui/adapters/run-detail.js +180 -63
  29. package/dist/src/app-opentui/adapters/server.d.ts +10 -2
  30. package/dist/src/app-opentui/adapters/server.js +191 -45
  31. package/dist/src/app-opentui/adapters/tasks.d.ts +11 -2
  32. package/dist/src/app-opentui/adapters/tasks.js +1123 -143
  33. package/dist/src/app-opentui/adapters/workspace.d.ts +49 -0
  34. package/dist/src/app-opentui/adapters/workspace.js +333 -0
  35. package/dist/src/app-opentui/autocomplete.d.ts +20 -0
  36. package/dist/src/app-opentui/autocomplete.js +576 -0
  37. package/dist/src/app-opentui/bootstrap.d.ts +1 -6
  38. package/dist/src/app-opentui/bootstrap.js +25252 -16474
  39. package/dist/src/app-opentui/command-palette.d.ts +3 -0
  40. package/dist/src/app-opentui/command-palette.js +1010 -0
  41. package/dist/src/app-opentui/command-pty-host.d.ts +62 -0
  42. package/dist/src/app-opentui/command-pty-host.js +248 -0
  43. package/dist/src/app-opentui/drone.js +8 -6
  44. package/dist/src/app-opentui/events.js +1 -1
  45. package/dist/src/app-opentui/fleet-stats.d.ts +32 -0
  46. package/dist/src/app-opentui/fleet-stats.js +114 -0
  47. package/dist/src/app-opentui/focus-manager.d.ts +14 -0
  48. package/dist/src/app-opentui/focus-manager.js +24 -0
  49. package/dist/src/app-opentui/index.js +5431 -2797
  50. package/dist/src/app-opentui/intent.js +179 -50
  51. package/dist/src/app-opentui/keymap.d.ts +21 -0
  52. package/dist/src/app-opentui/keymap.js +1748 -0
  53. package/dist/src/app-opentui/launch-routing.d.ts +16 -0
  54. package/dist/src/app-opentui/launch-routing.js +55 -0
  55. package/dist/src/app-opentui/layout.d.ts +7 -0
  56. package/dist/src/app-opentui/layout.js +13 -6
  57. package/dist/src/app-opentui/list-search.d.ts +24 -0
  58. package/dist/src/app-opentui/list-search.js +88 -1
  59. package/dist/src/app-opentui/pi-host-child.js +99 -17
  60. package/dist/src/app-opentui/pi-pty-host.d.ts +14 -0
  61. package/dist/src/app-opentui/pi-pty-host.js +30 -14
  62. package/dist/src/app-opentui/react/App.d.ts +9 -0
  63. package/dist/src/app-opentui/react/App.js +5144 -0
  64. package/dist/src/app-opentui/react/Backdrop.d.ts +5 -0
  65. package/dist/src/app-opentui/react/Backdrop.js +1834 -0
  66. package/dist/src/app-opentui/react/ChromeHost.d.ts +5 -0
  67. package/dist/src/app-opentui/react/ChromeHost.js +2942 -0
  68. package/dist/src/app-opentui/react/SceneFrameView.d.ts +7 -0
  69. package/dist/src/app-opentui/react/SceneFrameView.js +529 -0
  70. package/dist/src/app-opentui/react/context.d.ts +17 -0
  71. package/dist/src/app-opentui/react/context.js +37 -0
  72. package/dist/src/app-opentui/react/launch.d.ts +2 -0
  73. package/dist/src/app-opentui/react/launch.js +5743 -0
  74. package/dist/src/app-opentui/react/nav.d.ts +18 -0
  75. package/dist/src/app-opentui/react/nav.js +54 -0
  76. package/dist/src/app-opentui/react/scroll.d.ts +12 -0
  77. package/dist/src/app-opentui/react/scroll.js +21 -0
  78. package/dist/src/app-opentui/react/syntax.d.ts +2 -0
  79. package/dist/src/app-opentui/react/syntax.js +64 -0
  80. package/dist/src/app-opentui/registry.js +20428 -4828
  81. package/dist/src/app-opentui/render/ascii-fleet.d.ts +15 -0
  82. package/dist/src/app-opentui/render/ascii-fleet.js +82 -0
  83. package/dist/src/app-opentui/render/constants.d.ts +31 -0
  84. package/dist/src/app-opentui/render/constants.js +66 -0
  85. package/dist/src/app-opentui/render/graphics.d.ts +2 -1
  86. package/dist/src/app-opentui/render/graphics.js +228 -46
  87. package/dist/src/app-opentui/render/image-visual-layer-worker.js +469 -930
  88. package/dist/src/app-opentui/render/image-visual-layer.d.ts +25 -10
  89. package/dist/src/app-opentui/render/image-visual-layer.js +448 -329
  90. package/dist/src/app-opentui/render/native-host.d.ts +37 -0
  91. package/dist/src/app-opentui/render/native-host.js +179 -0
  92. package/dist/src/app-opentui/render/panel-layout.d.ts +38 -0
  93. package/dist/src/app-opentui/render/panel-layout.js +48 -0
  94. package/dist/src/app-opentui/render/panels.d.ts +2 -0
  95. package/dist/src/app-opentui/render/panels.js +78 -38
  96. package/dist/src/app-opentui/render/preloader.d.ts +10 -0
  97. package/dist/src/app-opentui/render/preloader.js +165 -0
  98. package/dist/src/app-opentui/render/scene.d.ts +53 -1
  99. package/dist/src/app-opentui/render/scene.js +195 -6
  100. package/dist/src/app-opentui/render/text.d.ts +7 -1
  101. package/dist/src/app-opentui/render/text.js +15 -8
  102. package/dist/src/app-opentui/render/type-bar.d.ts +2 -1
  103. package/dist/src/app-opentui/render/type-bar.js +113 -39
  104. package/dist/src/app-opentui/runtime-resources.d.ts +16 -0
  105. package/dist/src/app-opentui/runtime-resources.js +62 -0
  106. package/dist/src/app-opentui/runtime.d.ts +44 -1
  107. package/dist/src/app-opentui/runtime.js +5415 -2738
  108. package/dist/src/app-opentui/scenes/command.d.ts +3 -0
  109. package/dist/src/app-opentui/scenes/command.js +117 -0
  110. package/dist/src/app-opentui/scenes/doctor.d.ts +2 -1
  111. package/dist/src/app-opentui/scenes/doctor.js +221 -17
  112. package/dist/src/app-opentui/scenes/error.js +60 -20
  113. package/dist/src/app-opentui/scenes/family-domains/agent.d.ts +2 -0
  114. package/dist/src/app-opentui/scenes/family-domains/agent.js +348 -0
  115. package/dist/src/app-opentui/scenes/family-domains/browser.d.ts +2 -0
  116. package/dist/src/app-opentui/scenes/family-domains/browser.js +195 -0
  117. package/dist/src/app-opentui/scenes/family-domains/dist.d.ts +2 -0
  118. package/dist/src/app-opentui/scenes/family-domains/dist.js +243 -0
  119. package/dist/src/app-opentui/scenes/family-domains/git.d.ts +2 -0
  120. package/dist/src/app-opentui/scenes/family-domains/git.js +195 -0
  121. package/dist/src/app-opentui/scenes/family-domains/github.d.ts +2 -0
  122. package/dist/src/app-opentui/scenes/family-domains/github.js +274 -0
  123. package/dist/src/app-opentui/scenes/family-domains/harness.d.ts +2 -0
  124. package/dist/src/app-opentui/scenes/family-domains/harness.js +152 -0
  125. package/dist/src/app-opentui/scenes/family-domains/index.d.ts +4 -0
  126. package/dist/src/app-opentui/scenes/family-domains/index.js +1679 -0
  127. package/dist/src/app-opentui/scenes/family-domains/kit.d.ts +76 -0
  128. package/dist/src/app-opentui/scenes/family-domains/kit.js +305 -0
  129. package/dist/src/app-opentui/scenes/family-domains/profile.d.ts +2 -0
  130. package/dist/src/app-opentui/scenes/family-domains/profile.js +212 -0
  131. package/dist/src/app-opentui/scenes/family-domains/queue.d.ts +2 -0
  132. package/dist/src/app-opentui/scenes/family-domains/queue.js +146 -0
  133. package/dist/src/app-opentui/scenes/family-domains/remote.d.ts +2 -0
  134. package/dist/src/app-opentui/scenes/family-domains/remote.js +518 -0
  135. package/dist/src/app-opentui/scenes/family-domains/review.d.ts +2 -0
  136. package/dist/src/app-opentui/scenes/family-domains/review.js +280 -0
  137. package/dist/src/app-opentui/scenes/family-domains/setup.d.ts +2 -0
  138. package/dist/src/app-opentui/scenes/family-domains/setup.js +267 -0
  139. package/dist/src/app-opentui/scenes/family-domains/stats.d.ts +2 -0
  140. package/dist/src/app-opentui/scenes/family-domains/stats.js +370 -0
  141. package/dist/src/app-opentui/scenes/family.d.ts +3 -0
  142. package/dist/src/app-opentui/scenes/family.js +2144 -0
  143. package/dist/src/app-opentui/scenes/fleet.js +552 -43
  144. package/dist/src/app-opentui/scenes/handoff.js +342 -35
  145. package/dist/src/app-opentui/scenes/help.js +640 -56
  146. package/dist/src/app-opentui/scenes/inbox.d.ts +2 -1
  147. package/dist/src/app-opentui/scenes/inbox.js +329 -21
  148. package/dist/src/app-opentui/scenes/init.d.ts +2 -1
  149. package/dist/src/app-opentui/scenes/init.js +120 -34
  150. package/dist/src/app-opentui/scenes/inspect.d.ts +3 -0
  151. package/dist/src/app-opentui/scenes/inspect.js +793 -0
  152. package/dist/src/app-opentui/scenes/main.d.ts +2 -1
  153. package/dist/src/app-opentui/scenes/main.js +264 -29
  154. package/dist/src/app-opentui/scenes/pi.d.ts +3 -0
  155. package/dist/src/app-opentui/scenes/pi.js +508 -0
  156. package/dist/src/app-opentui/scenes/plugin.d.ts +3 -0
  157. package/dist/src/app-opentui/scenes/plugin.js +486 -0
  158. package/dist/src/app-opentui/scenes/repo.d.ts +3 -0
  159. package/dist/src/app-opentui/scenes/repo.js +424 -0
  160. package/dist/src/app-opentui/scenes/run-detail.d.ts +2 -1
  161. package/dist/src/app-opentui/scenes/run-detail.js +362 -35
  162. package/dist/src/app-opentui/scenes/server.d.ts +2 -1
  163. package/dist/src/app-opentui/scenes/server.js +243 -26
  164. package/dist/src/app-opentui/scenes/tasks.js +518 -41
  165. package/dist/src/app-opentui/scenes/workspace.d.ts +3 -0
  166. package/dist/src/app-opentui/scenes/workspace.js +426 -0
  167. package/dist/src/app-opentui/selectable.d.ts +19 -0
  168. package/dist/src/app-opentui/selectable.js +79 -0
  169. package/dist/src/app-opentui/state.js +129 -36
  170. package/dist/src/app-opentui/surface-catalog.d.ts +20 -0
  171. package/dist/src/app-opentui/surface-catalog.js +540 -0
  172. package/dist/src/app-opentui/terminal-capabilities.d.ts +7 -0
  173. package/dist/src/app-opentui/terminal-capabilities.js +15 -0
  174. package/dist/src/app-opentui/theme.d.ts +28 -6
  175. package/dist/src/app-opentui/theme.js +61 -8
  176. package/dist/src/app-opentui/types.d.ts +130 -5
  177. package/dist/src/commands/_authority-runs.d.ts +1 -1
  178. package/dist/src/commands/_authority-runs.js +2 -12
  179. package/dist/src/commands/_doctor-checks.js +62 -13
  180. package/dist/src/commands/_help-catalog.js +95 -15
  181. package/dist/src/commands/_operator-view.js +97 -15
  182. package/dist/src/commands/_pi-frontend.d.ts +2 -0
  183. package/dist/src/commands/_pi-frontend.js +97 -13
  184. package/dist/src/commands/_preflight.js +64 -14
  185. package/dist/src/commands/_server-client.js +82 -18
  186. package/dist/src/commands/_server-events.d.ts +26 -0
  187. package/dist/src/commands/_server-events.js +310 -0
  188. package/dist/src/commands/_snapshot-upload.js +62 -13
  189. package/dist/src/commands/agent.js +2 -12
  190. package/dist/src/commands/connect.js +7 -1
  191. package/dist/src/commands/doctor.js +62 -13
  192. package/dist/src/commands/github.js +144 -23
  193. package/dist/src/commands/inbox.js +62 -13
  194. package/dist/src/commands/init.js +82 -18
  195. package/dist/src/commands/inspect.js +62 -13
  196. package/dist/src/commands/run.js +100 -15
  197. package/dist/src/commands/server.js +71 -26
  198. package/dist/src/commands/setup.js +62 -13
  199. package/dist/src/commands/stats.js +157 -28
  200. package/dist/src/commands/task-run-driver.js +64 -25
  201. package/dist/src/commands/task.js +196 -43
  202. package/dist/src/commands.js +419 -123
  203. package/dist/src/index.js +426 -130
  204. package/package.json +11 -10
  205. package/dist/src/app-opentui/render/image-visual-layer-native-canvas.d.ts +0 -2
  206. package/dist/src/app-opentui/render/image-visual-layer-native-canvas.js +0 -1484
@@ -55,18 +55,8 @@ import {
55
55
  import { resolveMonorepoRoot } from "@rig/runtime/control-plane/native/utils";
56
56
 
57
57
  // packages/cli/src/commands/_authority-runs.ts
58
- function normalizeRuntimeAdapter(value) {
59
- const normalized = value?.trim().toLowerCase();
60
- if (!normalized) {
61
- return "pi";
62
- }
63
- if (normalized === "codex" || normalized === "codex-cli" || normalized === "codex-app-server" || normalized === "gpt-codex") {
64
- return "codex";
65
- }
66
- if (normalized === "pi" || normalized === "rig-pi" || normalized === "@rig/pi") {
67
- return "pi";
68
- }
69
- return "claude-code";
58
+ function normalizeRuntimeAdapter(_value) {
59
+ return "pi";
70
60
  }
71
61
 
72
62
  // packages/cli/src/app/drone-ui.ts
@@ -459,7 +449,13 @@ async function executeConnectionCommand(context, args, options) {
459
449
  if (!state.connections[alias])
460
450
  throw new CliError(`Unknown Rig server: ${alias}`, 1, { hint: "Run `rig server list` to see saved aliases, or save one with `rig server add <alias> <url>`." });
461
451
  }
462
- const repoState = { selected: alias, linkedAt: new Date().toISOString() };
452
+ const previousRepo = readRepoConnection(context.projectRoot);
453
+ const repoState = {
454
+ selected: alias,
455
+ ...previousRepo?.project ? { project: previousRepo.project } : {},
456
+ linkedAt: new Date().toISOString(),
457
+ ...previousRepo?.serverProjectRoot && previousRepo.selected === alias ? { serverProjectRoot: previousRepo.serverProjectRoot } : {}
458
+ };
463
459
  writeRepoConnection(context.projectRoot, repoState);
464
460
  printJsonOrText(context, repoState, formatSuccessCard("Rig server selected", [
465
461
  ["selected", alias],
@@ -495,17 +491,21 @@ function cleanToken(value) {
495
491
  const trimmed = value?.trim();
496
492
  return trimmed ? trimmed : null;
497
493
  }
498
- function readPrivateRemoteSessionToken(projectRoot) {
494
+ function readRemoteAuthState(projectRoot) {
499
495
  const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
500
496
  if (!existsSync2(path))
501
497
  return null;
502
498
  try {
503
499
  const parsed = JSON.parse(readFileSync2(path, "utf8"));
504
- return cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined);
500
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
505
501
  } catch {
506
502
  return null;
507
503
  }
508
504
  }
505
+ function readPrivateRemoteSessionToken(projectRoot) {
506
+ const parsed = readRemoteAuthState(projectRoot);
507
+ return parsed ? cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined) : null;
508
+ }
509
509
  function readGitHubBearerTokenForRemote(projectRoot) {
510
510
  const scopedKey = resolve2(projectRoot);
511
511
  if (scopedGitHubBearerTokens.has(scopedKey))
@@ -516,15 +516,25 @@ function readGitHubBearerTokenForRemote(projectRoot) {
516
516
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
517
517
  }
518
518
  function readStoredGitHubAuthToken(projectRoot) {
519
- const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
520
- if (!existsSync2(path))
519
+ const parsed = readRemoteAuthState(projectRoot);
520
+ return parsed ? cleanToken(typeof parsed.token === "string" ? parsed.token : undefined) : null;
521
+ }
522
+ function inferRemoteServerProjectRootFromAuthState(projectRoot) {
523
+ const repo = readRepoConnection(projectRoot);
524
+ const slug = repo?.project?.trim();
525
+ if (!slug || !/^[^/]+\/[^/]+$/.test(slug))
521
526
  return null;
522
- try {
523
- const parsed = JSON.parse(readFileSync2(path, "utf8"));
524
- return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
525
- } catch {
527
+ const auth = readRemoteAuthState(projectRoot);
528
+ const authUpdatedAt = typeof auth?.updatedAt === "string" ? Date.parse(auth.updatedAt) : Number.NaN;
529
+ const repoLinkedAt = typeof repo?.linkedAt === "string" ? Date.parse(repo.linkedAt) : Number.NaN;
530
+ if (Number.isFinite(authUpdatedAt) && Number.isFinite(repoLinkedAt) && authUpdatedAt + 1000 < repoLinkedAt)
526
531
  return null;
527
- }
532
+ const checkoutBaseDir = typeof auth?.checkoutBaseDir === "string" && auth.checkoutBaseDir.trim() ? auth.checkoutBaseDir.trim() : null;
533
+ if (!checkoutBaseDir)
534
+ return null;
535
+ const inferred = `${checkoutBaseDir.replace(/\/+$/, "")}/${slug}`;
536
+ writeRepoServerProjectRoot(projectRoot, inferred);
537
+ return inferred;
528
538
  }
529
539
  function readLocalConnectionFallbackToken(projectRoot) {
530
540
  return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
@@ -535,7 +545,7 @@ async function ensureServerForCli(projectRoot) {
535
545
  if (selected?.connection.kind === "remote") {
536
546
  reportServerPhase(`Connecting to ${selected.alias}\u2026`);
537
547
  const authToken = readGitHubBearerTokenForRemote(projectRoot);
538
- const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
548
+ const serverProjectRoot = selected.serverProjectRoot ?? inferRemoteServerProjectRootFromAuthState(projectRoot) ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
539
549
  return {
540
550
  baseUrl: selected.connection.baseUrl,
541
551
  authToken,
@@ -564,7 +574,10 @@ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken)
564
574
  if (!slug)
565
575
  return null;
566
576
  try {
567
- const response = await fetch(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`, {
577
+ const url = new URL(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`);
578
+ if (authToken && queryAuthFallbackEnabled())
579
+ url.searchParams.set("rt", authToken);
580
+ const response = await fetch(url, {
568
581
  headers: mergeHeaders(undefined, authToken)
569
582
  });
570
583
  if (!response.ok)
@@ -581,10 +594,23 @@ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken)
581
594
  return null;
582
595
  }
583
596
  }
597
+ function mergeCookie(existing, name, value) {
598
+ const encoded = `${name}=${encodeURIComponent(value)}`;
599
+ if (!existing?.trim())
600
+ return encoded;
601
+ const parts = existing.split(";").map((part) => part.trim()).filter((part) => part && !part.startsWith(`${name}=`));
602
+ return [...parts, encoded].join("; ");
603
+ }
604
+ function queryAuthFallbackEnabled(env = process.env) {
605
+ return env.RIG_ENABLE_QUERY_AUTH_FALLBACK === "1" || env.RIG_QUERY_AUTH_FALLBACK === "1";
606
+ }
584
607
  function mergeHeaders(headers, authToken) {
585
608
  const merged = new Headers(headers);
586
609
  if (authToken) {
587
- merged.set("authorization", `Bearer ${authToken}`);
610
+ const bearer = `Bearer ${authToken}`;
611
+ merged.set("authorization", bearer);
612
+ merged.set("x-auth", bearer);
613
+ merged.set("cookie", mergeCookie(merged.get("cookie"), "rig_auth", authToken));
588
614
  }
589
615
  return merged;
590
616
  }
@@ -645,15 +671,34 @@ async function buildServerFailureContext(projectRoot, server) {
645
671
  hint: "Check the selected server with `rig server status`, or switch with `rig server use <alias|local>`."
646
672
  };
647
673
  }
674
+ function isLoopbackRemoteBaseUrl(baseUrl) {
675
+ try {
676
+ const host = new URL(baseUrl).hostname.toLowerCase();
677
+ return host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]";
678
+ } catch {
679
+ return false;
680
+ }
681
+ }
682
+ function canUseRemoteWithoutProjectRoot(pathname) {
683
+ return pathname === "/health" || pathname === "/api/health" || pathname === "/api/server/status" || pathname === "/api/server/project-root" || pathname.startsWith("/api/github/auth/") || pathname === "/api/projects" || pathname.startsWith("/api/projects/");
684
+ }
648
685
  async function requestServerJson(context, pathname, init = {}) {
649
686
  const server = await ensureServerForCli(context.projectRoot);
687
+ const requestUrl = new URL(`${server.baseUrl}${pathname}`);
688
+ if (server.connectionKind === "remote" && !server.serverProjectRoot && !canUseRemoteWithoutProjectRoot(requestUrl.pathname) && (server.authToken || !isLoopbackRemoteBaseUrl(server.baseUrl))) {
689
+ const repo = readRepoConnection(context.projectRoot);
690
+ throw new CliError(`Remote server is selected for ${repo?.project ?? "this repo"}, but this checkout has no server-host project root link.`, 1, { hint: "Run `rig init --repair` or `rig init --yes --repo owner/repo --server remote` to repair the remote project link before task/run commands." });
691
+ }
650
692
  const headers = mergeHeaders(init.headers, server.authToken);
651
693
  if (server.serverProjectRoot)
652
694
  headers.set("x-rig-project-root", server.serverProjectRoot);
695
+ if (server.connectionKind === "remote" && server.authToken && queryAuthFallbackEnabled()) {
696
+ requestUrl.searchParams.set("rt", server.authToken);
697
+ }
653
698
  reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
654
699
  let response;
655
700
  try {
656
- response = await fetch(`${server.baseUrl}${pathname}`, {
701
+ response = await fetch(requestUrl, {
657
702
  ...init,
658
703
  headers
659
704
  });
@@ -298,17 +298,21 @@ function cleanToken(value) {
298
298
  const trimmed = value?.trim();
299
299
  return trimmed ? trimmed : null;
300
300
  }
301
- function readPrivateRemoteSessionToken(projectRoot) {
301
+ function readRemoteAuthState(projectRoot) {
302
302
  const path = resolve4(projectRoot, ".rig", "state", "github-auth.json");
303
303
  if (!existsSync3(path))
304
304
  return null;
305
305
  try {
306
306
  const parsed = JSON.parse(readFileSync3(path, "utf8"));
307
- return cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined);
307
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
308
308
  } catch {
309
309
  return null;
310
310
  }
311
311
  }
312
+ function readPrivateRemoteSessionToken(projectRoot) {
313
+ const parsed = readRemoteAuthState(projectRoot);
314
+ return parsed ? cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined) : null;
315
+ }
312
316
  function readGitHubBearerTokenForRemote(projectRoot) {
313
317
  const scopedKey = resolve4(projectRoot);
314
318
  if (scopedGitHubBearerTokens.has(scopedKey))
@@ -319,15 +323,25 @@ function readGitHubBearerTokenForRemote(projectRoot) {
319
323
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
320
324
  }
321
325
  function readStoredGitHubAuthToken(projectRoot) {
322
- const path = resolve4(projectRoot, ".rig", "state", "github-auth.json");
323
- if (!existsSync3(path))
326
+ const parsed = readRemoteAuthState(projectRoot);
327
+ return parsed ? cleanToken(typeof parsed.token === "string" ? parsed.token : undefined) : null;
328
+ }
329
+ function inferRemoteServerProjectRootFromAuthState(projectRoot) {
330
+ const repo = readRepoConnection(projectRoot);
331
+ const slug = repo?.project?.trim();
332
+ if (!slug || !/^[^/]+\/[^/]+$/.test(slug))
324
333
  return null;
325
- try {
326
- const parsed = JSON.parse(readFileSync3(path, "utf8"));
327
- return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
328
- } catch {
334
+ const auth = readRemoteAuthState(projectRoot);
335
+ const authUpdatedAt = typeof auth?.updatedAt === "string" ? Date.parse(auth.updatedAt) : Number.NaN;
336
+ const repoLinkedAt = typeof repo?.linkedAt === "string" ? Date.parse(repo.linkedAt) : Number.NaN;
337
+ if (Number.isFinite(authUpdatedAt) && Number.isFinite(repoLinkedAt) && authUpdatedAt + 1000 < repoLinkedAt)
329
338
  return null;
330
- }
339
+ const checkoutBaseDir = typeof auth?.checkoutBaseDir === "string" && auth.checkoutBaseDir.trim() ? auth.checkoutBaseDir.trim() : null;
340
+ if (!checkoutBaseDir)
341
+ return null;
342
+ const inferred = `${checkoutBaseDir.replace(/\/+$/, "")}/${slug}`;
343
+ writeRepoServerProjectRoot(projectRoot, inferred);
344
+ return inferred;
331
345
  }
332
346
  function readLocalConnectionFallbackToken(projectRoot) {
333
347
  return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
@@ -338,7 +352,7 @@ async function ensureServerForCli(projectRoot) {
338
352
  if (selected?.connection.kind === "remote") {
339
353
  reportServerPhase(`Connecting to ${selected.alias}\u2026`);
340
354
  const authToken = readGitHubBearerTokenForRemote(projectRoot);
341
- const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
355
+ const serverProjectRoot = selected.serverProjectRoot ?? inferRemoteServerProjectRootFromAuthState(projectRoot) ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
342
356
  return {
343
357
  baseUrl: selected.connection.baseUrl,
344
358
  authToken,
@@ -367,7 +381,10 @@ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken)
367
381
  if (!slug)
368
382
  return null;
369
383
  try {
370
- const response = await fetch(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`, {
384
+ const url = new URL(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`);
385
+ if (authToken && queryAuthFallbackEnabled())
386
+ url.searchParams.set("rt", authToken);
387
+ const response = await fetch(url, {
371
388
  headers: mergeHeaders(undefined, authToken)
372
389
  });
373
390
  if (!response.ok)
@@ -384,10 +401,23 @@ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken)
384
401
  return null;
385
402
  }
386
403
  }
404
+ function mergeCookie(existing, name, value) {
405
+ const encoded = `${name}=${encodeURIComponent(value)}`;
406
+ if (!existing?.trim())
407
+ return encoded;
408
+ const parts = existing.split(";").map((part) => part.trim()).filter((part) => part && !part.startsWith(`${name}=`));
409
+ return [...parts, encoded].join("; ");
410
+ }
411
+ function queryAuthFallbackEnabled(env = process.env) {
412
+ return env.RIG_ENABLE_QUERY_AUTH_FALLBACK === "1" || env.RIG_QUERY_AUTH_FALLBACK === "1";
413
+ }
387
414
  function mergeHeaders(headers, authToken) {
388
415
  const merged = new Headers(headers);
389
416
  if (authToken) {
390
- merged.set("authorization", `Bearer ${authToken}`);
417
+ const bearer = `Bearer ${authToken}`;
418
+ merged.set("authorization", bearer);
419
+ merged.set("x-auth", bearer);
420
+ merged.set("cookie", mergeCookie(merged.get("cookie"), "rig_auth", authToken));
391
421
  }
392
422
  return merged;
393
423
  }
@@ -448,15 +478,34 @@ async function buildServerFailureContext(projectRoot, server) {
448
478
  hint: "Check the selected server with `rig server status`, or switch with `rig server use <alias|local>`."
449
479
  };
450
480
  }
481
+ function isLoopbackRemoteBaseUrl(baseUrl) {
482
+ try {
483
+ const host = new URL(baseUrl).hostname.toLowerCase();
484
+ return host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]";
485
+ } catch {
486
+ return false;
487
+ }
488
+ }
489
+ function canUseRemoteWithoutProjectRoot(pathname) {
490
+ return pathname === "/health" || pathname === "/api/health" || pathname === "/api/server/status" || pathname === "/api/server/project-root" || pathname.startsWith("/api/github/auth/") || pathname === "/api/projects" || pathname.startsWith("/api/projects/");
491
+ }
451
492
  async function requestServerJson(context, pathname, init = {}) {
452
493
  const server = await ensureServerForCli(context.projectRoot);
494
+ const requestUrl = new URL(`${server.baseUrl}${pathname}`);
495
+ if (server.connectionKind === "remote" && !server.serverProjectRoot && !canUseRemoteWithoutProjectRoot(requestUrl.pathname) && (server.authToken || !isLoopbackRemoteBaseUrl(server.baseUrl))) {
496
+ const repo = readRepoConnection(context.projectRoot);
497
+ throw new CliError(`Remote server is selected for ${repo?.project ?? "this repo"}, but this checkout has no server-host project root link.`, 1, { hint: "Run `rig init --repair` or `rig init --yes --repo owner/repo --server remote` to repair the remote project link before task/run commands." });
498
+ }
453
499
  const headers = mergeHeaders(init.headers, server.authToken);
454
500
  if (server.serverProjectRoot)
455
501
  headers.set("x-rig-project-root", server.serverProjectRoot);
502
+ if (server.connectionKind === "remote" && server.authToken && queryAuthFallbackEnabled()) {
503
+ requestUrl.searchParams.set("rt", server.authToken);
504
+ }
456
505
  reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
457
506
  let response;
458
507
  try {
459
- response = await fetch(`${server.baseUrl}${pathname}`, {
508
+ response = await fetch(requestUrl, {
460
509
  ...init,
461
510
  headers
462
511
  });
@@ -165,17 +165,21 @@ function cleanToken(value) {
165
165
  const trimmed = value?.trim();
166
166
  return trimmed ? trimmed : null;
167
167
  }
168
- function readPrivateRemoteSessionToken(projectRoot) {
168
+ function readRemoteAuthState(projectRoot) {
169
169
  const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
170
170
  if (!existsSync2(path))
171
171
  return null;
172
172
  try {
173
173
  const parsed = JSON.parse(readFileSync2(path, "utf8"));
174
- return cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined);
174
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
175
175
  } catch {
176
176
  return null;
177
177
  }
178
178
  }
179
+ function readPrivateRemoteSessionToken(projectRoot) {
180
+ const parsed = readRemoteAuthState(projectRoot);
181
+ return parsed ? cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined) : null;
182
+ }
179
183
  function readGitHubBearerTokenForRemote(projectRoot) {
180
184
  const scopedKey = resolve2(projectRoot);
181
185
  if (scopedGitHubBearerTokens.has(scopedKey))
@@ -186,15 +190,25 @@ function readGitHubBearerTokenForRemote(projectRoot) {
186
190
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
187
191
  }
188
192
  function readStoredGitHubAuthToken(projectRoot) {
189
- const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
190
- if (!existsSync2(path))
193
+ const parsed = readRemoteAuthState(projectRoot);
194
+ return parsed ? cleanToken(typeof parsed.token === "string" ? parsed.token : undefined) : null;
195
+ }
196
+ function inferRemoteServerProjectRootFromAuthState(projectRoot) {
197
+ const repo = readRepoConnection(projectRoot);
198
+ const slug = repo?.project?.trim();
199
+ if (!slug || !/^[^/]+\/[^/]+$/.test(slug))
191
200
  return null;
192
- try {
193
- const parsed = JSON.parse(readFileSync2(path, "utf8"));
194
- return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
195
- } catch {
201
+ const auth = readRemoteAuthState(projectRoot);
202
+ const authUpdatedAt = typeof auth?.updatedAt === "string" ? Date.parse(auth.updatedAt) : Number.NaN;
203
+ const repoLinkedAt = typeof repo?.linkedAt === "string" ? Date.parse(repo.linkedAt) : Number.NaN;
204
+ if (Number.isFinite(authUpdatedAt) && Number.isFinite(repoLinkedAt) && authUpdatedAt + 1000 < repoLinkedAt)
196
205
  return null;
197
- }
206
+ const checkoutBaseDir = typeof auth?.checkoutBaseDir === "string" && auth.checkoutBaseDir.trim() ? auth.checkoutBaseDir.trim() : null;
207
+ if (!checkoutBaseDir)
208
+ return null;
209
+ const inferred = `${checkoutBaseDir.replace(/\/+$/, "")}/${slug}`;
210
+ writeRepoServerProjectRoot(projectRoot, inferred);
211
+ return inferred;
198
212
  }
199
213
  function readLocalConnectionFallbackToken(projectRoot) {
200
214
  return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
@@ -205,7 +219,7 @@ async function ensureServerForCli(projectRoot) {
205
219
  if (selected?.connection.kind === "remote") {
206
220
  reportServerPhase(`Connecting to ${selected.alias}\u2026`);
207
221
  const authToken = readGitHubBearerTokenForRemote(projectRoot);
208
- const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
222
+ const serverProjectRoot = selected.serverProjectRoot ?? inferRemoteServerProjectRootFromAuthState(projectRoot) ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
209
223
  return {
210
224
  baseUrl: selected.connection.baseUrl,
211
225
  authToken,
@@ -234,7 +248,10 @@ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken)
234
248
  if (!slug)
235
249
  return null;
236
250
  try {
237
- const response = await fetch(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`, {
251
+ const url = new URL(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`);
252
+ if (authToken && queryAuthFallbackEnabled())
253
+ url.searchParams.set("rt", authToken);
254
+ const response = await fetch(url, {
238
255
  headers: mergeHeaders(undefined, authToken)
239
256
  });
240
257
  if (!response.ok)
@@ -251,10 +268,23 @@ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken)
251
268
  return null;
252
269
  }
253
270
  }
271
+ function mergeCookie(existing, name, value) {
272
+ const encoded = `${name}=${encodeURIComponent(value)}`;
273
+ if (!existing?.trim())
274
+ return encoded;
275
+ const parts = existing.split(";").map((part) => part.trim()).filter((part) => part && !part.startsWith(`${name}=`));
276
+ return [...parts, encoded].join("; ");
277
+ }
278
+ function queryAuthFallbackEnabled(env = process.env) {
279
+ return env.RIG_ENABLE_QUERY_AUTH_FALLBACK === "1" || env.RIG_QUERY_AUTH_FALLBACK === "1";
280
+ }
254
281
  function mergeHeaders(headers, authToken) {
255
282
  const merged = new Headers(headers);
256
283
  if (authToken) {
257
- merged.set("authorization", `Bearer ${authToken}`);
284
+ const bearer = `Bearer ${authToken}`;
285
+ merged.set("authorization", bearer);
286
+ merged.set("x-auth", bearer);
287
+ merged.set("cookie", mergeCookie(merged.get("cookie"), "rig_auth", authToken));
258
288
  }
259
289
  return merged;
260
290
  }
@@ -315,15 +345,34 @@ async function buildServerFailureContext(projectRoot, server) {
315
345
  hint: "Check the selected server with `rig server status`, or switch with `rig server use <alias|local>`."
316
346
  };
317
347
  }
348
+ function isLoopbackRemoteBaseUrl(baseUrl) {
349
+ try {
350
+ const host = new URL(baseUrl).hostname.toLowerCase();
351
+ return host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]";
352
+ } catch {
353
+ return false;
354
+ }
355
+ }
356
+ function canUseRemoteWithoutProjectRoot(pathname) {
357
+ return pathname === "/health" || pathname === "/api/health" || pathname === "/api/server/status" || pathname === "/api/server/project-root" || pathname.startsWith("/api/github/auth/") || pathname === "/api/projects" || pathname.startsWith("/api/projects/");
358
+ }
318
359
  async function requestServerJson(context, pathname, init = {}) {
319
360
  const server = await ensureServerForCli(context.projectRoot);
361
+ const requestUrl = new URL(`${server.baseUrl}${pathname}`);
362
+ if (server.connectionKind === "remote" && !server.serverProjectRoot && !canUseRemoteWithoutProjectRoot(requestUrl.pathname) && (server.authToken || !isLoopbackRemoteBaseUrl(server.baseUrl))) {
363
+ const repo = readRepoConnection(context.projectRoot);
364
+ throw new CliError(`Remote server is selected for ${repo?.project ?? "this repo"}, but this checkout has no server-host project root link.`, 1, { hint: "Run `rig init --repair` or `rig init --yes --repo owner/repo --server remote` to repair the remote project link before task/run commands." });
365
+ }
320
366
  const headers = mergeHeaders(init.headers, server.authToken);
321
367
  if (server.serverProjectRoot)
322
368
  headers.set("x-rig-project-root", server.serverProjectRoot);
369
+ if (server.connectionKind === "remote" && server.authToken && queryAuthFallbackEnabled()) {
370
+ requestUrl.searchParams.set("rt", server.authToken);
371
+ }
323
372
  reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
324
373
  let response;
325
374
  try {
326
- response = await fetch(`${server.baseUrl}${pathname}`, {
375
+ response = await fetch(requestUrl, {
327
376
  ...init,
328
377
  headers
329
378
  });
@@ -840,30 +889,62 @@ var PRIMARY_GROUPS = [
840
889
  }
841
890
  ];
842
891
  var ADVANCED_GROUPS = [
843
- { name: "setup", summary: "Bootstrap/check local setup.", usage: ["rig setup <bootstrap|check|preflight>"], commands: [{ command: "bootstrap|check|preflight", description: "Setup helpers." }] },
844
- { name: "profile", summary: "Runtime profile/model defaults.", usage: ["rig profile <show|set>"], commands: [{ command: "show", description: "Show active profile." }] },
892
+ {
893
+ name: "setup",
894
+ summary: "Bootstrap/check local setup.",
895
+ usage: ["rig setup <bootstrap|check|preflight>"],
896
+ commands: [
897
+ { command: "bootstrap", description: "Bootstrap local setup dependencies.", primary: true },
898
+ { command: "check", description: "Check local setup state (toolchain, deps, config).", primary: true },
899
+ { command: "preflight", description: "Run preflight checks before a run.", primary: true }
900
+ ]
901
+ },
902
+ {
903
+ name: "profile",
904
+ summary: "Runtime profile/model defaults.",
905
+ usage: ["rig profile <show|set>"],
906
+ commands: [
907
+ { command: "show", description: "Show the active execution profile.", primary: true },
908
+ { command: "set [--model <model>] [--runtime <runtime>] [--plugin <plugin>]", description: "Set model/runtime/plugin profile defaults.", primary: true }
909
+ ]
910
+ },
845
911
  {
846
912
  name: "review",
847
913
  summary: "Inspect or change completion review gate policy.",
848
914
  usage: ["rig review <show|set>"],
849
915
  commands: [
850
916
  { command: "show", description: "Show current review gate settings." },
851
- { command: "set <off|advisory|required> [--provider greptile]", description: "Change review strictness/provider." }
917
+ { command: "set <off|advisory|required> [--provider <provider>]", description: "Change review strictness/provider (e.g. --provider greptile)." }
852
918
  ],
853
919
  examples: ["rig review show", "rig review set required --provider greptile"],
854
920
  next: ["Use `rig inbox approvals` for blocked run handoffs."]
855
921
  },
856
922
  {
857
923
  name: "browser",
858
- summary: "Browser/app diagnostics for browser-required tasks.",
859
- usage: ["rig browser <help|explain|demo|app|hp-next> [options]"],
924
+ summary: "Browser workstation actions for browser-required tasks: launch, check, CDP probe, profile reset, and app-specific smokes.",
925
+ usage: ["rig browser <help|explain|demo|hp-next|cdp-probe|profile-persistence|profile-lock-check|smoke-test> [options]"],
860
926
  commands: [
861
- { command: "help", description: "Rich browser command help (canonical: `rig browser help`)." },
862
- { command: "explain", description: "Explain the browser-required task contract." },
863
- { command: "demo", description: "Run browser demo flows against a local page." },
864
- { command: "app", description: "Launch the Rig Browser workstation app." },
865
- { command: "hp-next <dev|check|e2e|reset>", description: "Drive the hp-next browser test harness." }
866
- ]
927
+ { command: "help", description: "Rich browser command help (canonical: `rig browser help`).", primary: true },
928
+ { command: "explain", description: "Explain the browser-required task contract and runtime helper commands.", primary: true },
929
+ { command: "demo [--port <n>] [--profile <name>] [--state-dir <path>] [--target-url <url>] [--keep-open] [--no-build]", description: "Run a guided real browser/agent demo flow.", primary: true },
930
+ { command: "hp-next dev", description: "Start hp-next Rig Browser in dev/watch mode.", primary: true },
931
+ { command: "hp-next start", description: "Build/start the hp-next browser workstation without watch mode.", primary: true },
932
+ { command: "hp-next check", description: "Validate the hp-next CDP endpoint on the configured port.", primary: true },
933
+ { command: "hp-next e2e", description: "Run hp-next browser e2e smoke checks through Rig Browser.", primary: true },
934
+ { command: "hp-next reset", description: "Reset the hp-next browser profile when stale browser state is suspected.", primary: true },
935
+ { command: "cdp-probe", description: "Run an isolated CDP attach/evaluate/layout probe." },
936
+ { command: "profile-persistence", description: "Verify a named browser profile persists browser state." },
937
+ { command: "profile-lock-check", description: "Verify concurrent launches reject the same profile." },
938
+ { command: "smoke-test", description: "Run the browser package smoke test." }
939
+ ],
940
+ examples: [
941
+ "rig browser help",
942
+ "rig browser hp-next check",
943
+ "rig browser hp-next e2e",
944
+ "rig browser cdp-probe",
945
+ "rig browser profile-lock-check"
946
+ ],
947
+ next: ["Inside a task run, use rig-browser-launch, rig-browser-check, and rig-browser-attach-info from the worker PATH."]
867
948
  },
868
949
  {
869
950
  name: "pi",
@@ -878,12 +959,60 @@ var ADVANCED_GROUPS = [
878
959
  examples: ["rig pi search subagents", "rig pi add pi-subagents", "rig pi list"],
879
960
  next: ["Config-managed extensions: declare `runtime: { pi: { packages: [...] } }` in rig.config.ts \u2014 workers pick them up automatically."]
880
961
  },
881
- { name: "queue", summary: "Run task queues locally.", usage: ["rig queue run [options]"], commands: [{ command: "run", description: "Process queue work." }] },
882
- { name: "agent", summary: "Runtime agent workspace helpers.", usage: ["rig agent <list|prepare|run|cleanup>"], commands: [{ command: "list", description: "List prepared agents." }] },
962
+ {
963
+ name: "queue",
964
+ summary: "Run task queues locally.",
965
+ usage: ["rig queue run [--workers <n>] [--max-tasks <n>] [--action validate|verify|pipeline] [--isolation off|worktree] [--no-runtime-reuse] [--fail-fast] [--skip-project-sync]"],
966
+ commands: [
967
+ { command: "run [--workers <n>] [--max-tasks <n>] [--action validate|verify|pipeline] [--isolation off|worktree] [--no-runtime-reuse] [--fail-fast] [--skip-project-sync]", description: "Process queue work: drain matching tasks with N workers, optional per-task action and isolation.", primary: true }
968
+ ]
969
+ },
970
+ {
971
+ name: "agent",
972
+ summary: "Runtime agent workspace helpers.",
973
+ usage: ["rig agent <list|prepare|run|cleanup>"],
974
+ commands: [
975
+ { command: "list", description: "List prepared agent runtimes.", primary: true },
976
+ { command: "prepare [--id <id>] [--mode <mode>] [--task <task>]", description: "Prepare an isolated agent runtime workspace.", primary: true },
977
+ { command: "run [--id <id>] [--mode <mode>] [--task <task>] [--skip-project-sync]", description: "Prepare (if needed) and run an agent in its workspace.", primary: true },
978
+ { command: "cleanup [--all] [--id <id>]", description: "Remove prepared agent workspaces.", primary: true }
979
+ ]
980
+ },
883
981
  { name: "inspector", summary: "Event stream and drift scanners.", usage: ["rig inspector <stream|scan-upstream-drift>"], commands: [{ command: "stream", description: "Stream events." }] },
884
- { name: "dist", summary: "Build/install packaged Rig CLI.", usage: ["rig dist <build|install|doctor>"], commands: [{ command: "build", description: "Build distribution." }] },
982
+ {
983
+ name: "dist",
984
+ summary: "Build/install packaged Rig CLI.",
985
+ usage: ["rig dist <build|install|doctor|rebuild-agent>"],
986
+ commands: [
987
+ { command: "build [--output-dir <dir>]", description: "Build the distributable Rig CLI.", primary: true },
988
+ { command: "install [--scope <scope>] [--path <path>]", description: "Install the built CLI to a scope/path.", primary: true },
989
+ { command: "doctor", description: "Diagnose the dist toolchain and install state.", primary: true },
990
+ { command: "rebuild-agent", description: "Rebuild the agent runtime image, pruning stale images.", primary: true }
991
+ ]
992
+ },
885
993
  { name: "workspace", summary: "Workspace topology/service helpers.", usage: ["rig workspace <summary|topology|remote-hosts>"], commands: [{ command: "summary", description: "Show workspace summary." }] },
886
- { name: "remote", summary: "Compatibility remote orchestration controls.", usage: ["rig remote <status|watch|pause|resume|...>"], commands: [{ command: "status", description: "Show remote state." }] },
994
+ {
995
+ name: "remote",
996
+ summary: "Compatibility remote orchestration controls.",
997
+ usage: ["rig remote <status|tasks|watch|pause|resume|continue|stop|refresh|add-iterations|remove-iterations|endpoint ...>"],
998
+ commands: [
999
+ { command: "status [--remote <alias>]", description: "Show the remote orchestration state.", primary: true },
1000
+ { command: "tasks [--remote <alias>]", description: "List the remote's tracked tasks.", primary: true },
1001
+ { command: "watch [--remote <alias>] [--seconds <n>] [--event <type>]", description: "Stream remote orchestration events.", primary: true },
1002
+ { command: "pause [--remote <alias>]", description: "Pause the running remote orchestration.", primary: true },
1003
+ { command: "resume [--remote <alias>] [--max-workers <n>] [--max-iterations <n>] [--direct-merge]", description: "Resume the remote with optional tuning.", primary: true },
1004
+ { command: "continue [--remote <alias>]", description: "Continue a paused remote orchestration.", primary: true },
1005
+ { command: "stop [--remote <alias>]", description: "Stop the remote orchestration.", primary: true },
1006
+ { command: "refresh [--remote <alias>]", description: "Refresh remote state.", primary: true },
1007
+ { command: "add-iterations [--count <n>] [--remote <alias>]", description: "Grant the remote more iterations.", primary: true },
1008
+ { command: "remove-iterations [--count <n>] [--remote <alias>]", description: "Reduce the remote's iteration budget.", primary: true },
1009
+ { command: "endpoint list", description: "List configured remote endpoints.", primary: true },
1010
+ { command: "endpoint add --alias <alias> --host <host> --port <n> [--token <token>]", description: "Register a remote endpoint.", primary: true },
1011
+ { command: "endpoint remove --alias <alias>", description: "Remove a remote endpoint.", primary: true },
1012
+ { command: "endpoint test [--alias <alias>]", description: "Test connectivity to a remote endpoint.", primary: true },
1013
+ { command: "endpoint doctor", description: "Diagnose remote endpoint configuration.", primary: true }
1014
+ ]
1015
+ },
887
1016
  { name: "git", summary: "Pass through to Rig git-flow helper.", usage: ["rig git <args...>"], commands: [{ command: "<args...>", description: "Advanced git flow operations." }] },
888
1017
  { name: "harness", summary: "Pass through to runtime harness CLI.", usage: ["rig harness <args...>"], commands: [{ command: "<args...>", description: "Advanced harness operations." }] },
889
1018
  { name: "test", summary: "Project test wrappers.", usage: ["rig test <unit|e2e|all>"], commands: [{ command: "all", description: "Run configured project tests." }] }