@h-rig/cli 0.0.6-alpha.3 → 0.0.6-alpha.31

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 (47) hide show
  1. package/dist/bin/rig.js +3562 -1125
  2. package/dist/src/commands/_authority-runs.js +1 -0
  3. package/dist/src/commands/_cli-format.js +369 -0
  4. package/dist/src/commands/_connection-state.js +1 -3
  5. package/dist/src/commands/_doctor-checks.js +13 -27
  6. package/dist/src/commands/_help-catalog.js +388 -0
  7. package/dist/src/commands/_operator-surface.js +204 -0
  8. package/dist/src/commands/_operator-view.js +861 -56
  9. package/dist/src/commands/_parsers.js +0 -2
  10. package/dist/src/commands/_pi-frontend.js +841 -0
  11. package/dist/src/commands/_pi-install.js +4 -3
  12. package/dist/src/commands/_pi-worker-bridge-extension.js +759 -0
  13. package/dist/src/commands/_policy.js +0 -2
  14. package/dist/src/commands/_preflight.js +32 -109
  15. package/dist/src/commands/_run-driver-helpers.js +0 -2
  16. package/dist/src/commands/_server-client.js +161 -31
  17. package/dist/src/commands/_snapshot-upload.js +8 -23
  18. package/dist/src/commands/_task-picker.js +44 -16
  19. package/dist/src/commands/agent.js +9 -9
  20. package/dist/src/commands/browser.js +4 -6
  21. package/dist/src/commands/connect.js +132 -25
  22. package/dist/src/commands/dist.js +4 -6
  23. package/dist/src/commands/doctor.js +13 -27
  24. package/dist/src/commands/github.js +10 -25
  25. package/dist/src/commands/inbox.js +351 -31
  26. package/dist/src/commands/init.js +298 -71
  27. package/dist/src/commands/inspect.js +10 -12
  28. package/dist/src/commands/inspector.js +2 -4
  29. package/dist/src/commands/plugin.js +81 -22
  30. package/dist/src/commands/profile-and-review.js +8 -10
  31. package/dist/src/commands/queue.js +2 -3
  32. package/dist/src/commands/remote.js +18 -20
  33. package/dist/src/commands/repo-git-harness.js +6 -8
  34. package/dist/src/commands/run.js +1157 -122
  35. package/dist/src/commands/server.js +217 -33
  36. package/dist/src/commands/setup.js +17 -37
  37. package/dist/src/commands/task-report-bug.js +5 -7
  38. package/dist/src/commands/task-run-driver.js +660 -73
  39. package/dist/src/commands/task.js +1542 -252
  40. package/dist/src/commands/test.js +3 -5
  41. package/dist/src/commands/workspace.js +4 -6
  42. package/dist/src/commands.js +3548 -1105
  43. package/dist/src/index.js +3562 -1128
  44. package/dist/src/launcher.js +5 -3
  45. package/dist/src/report-bug.js +3 -3
  46. package/dist/src/runner.js +5 -19
  47. package/package.json +6 -4
@@ -3,8 +3,6 @@
3
3
  import { EventBus } from "@rig/runtime/control-plane/runtime/events";
4
4
  import { CliError } from "@rig/runtime/control-plane/errors";
5
5
  import { evaluate, loadPolicy, resolveAction } from "@rig/runtime/control-plane/runtime/guard";
6
- import { PluginManager } from "@rig/runtime/control-plane/runtime/plugins";
7
- import { loadRuntimeContextFromEnv } from "@rig/runtime/control-plane/runtime/context";
8
6
  import { buildBinary } from "@rig/runtime/control-plane/runtime/isolation";
9
7
  import { CliError as CliError2 } from "@rig/runtime/control-plane/errors";
10
8
  function takeOption(args, option) {
@@ -60,11 +58,8 @@ function normalizeRuntimeAdapter(value) {
60
58
  return "claude-code";
61
59
  }
62
60
 
63
- // packages/cli/src/commands/_server-client.ts
64
- import { spawnSync } from "child_process";
65
- import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
66
- import { resolve as resolve2 } from "path";
67
- import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
61
+ // packages/cli/src/commands/connect.ts
62
+ import { cancel, isCancel, select } from "@clack/prompts";
68
63
 
69
64
  // packages/cli/src/commands/_connection-state.ts
70
65
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
@@ -91,6 +86,11 @@ function readJsonFile(path) {
91
86
  throw new CliError2(`Invalid Rig connection state at ${path}: ${error instanceof Error ? error.message : String(error)}`, 1);
92
87
  }
93
88
  }
89
+ function writeJsonFile2(path, value) {
90
+ mkdirSync(dirname(path), { recursive: true });
91
+ writeFileSync(path, `${JSON.stringify(value, null, 2)}
92
+ `, "utf8");
93
+ }
94
94
  function normalizeConnection(value) {
95
95
  if (!value || typeof value !== "object" || Array.isArray(value))
96
96
  return null;
@@ -120,6 +120,18 @@ function readGlobalConnections(options = {}) {
120
120
  }
121
121
  return { connections };
122
122
  }
123
+ function writeGlobalConnections(state, options = {}) {
124
+ writeJsonFile2(resolveGlobalConnectionsPath(options.env ?? process.env), state);
125
+ }
126
+ function upsertGlobalConnection(alias, connection, options = {}) {
127
+ const cleanAlias = alias.trim();
128
+ if (!cleanAlias)
129
+ throw new CliError2("Connection alias is required.", 1);
130
+ const state = readGlobalConnections(options);
131
+ state.connections[cleanAlias] = connection;
132
+ writeGlobalConnections(state, options);
133
+ return state;
134
+ }
123
135
  function readRepoConnection(projectRoot) {
124
136
  const payload = readJsonFile(resolveRepoConnectionPath(projectRoot));
125
137
  if (!payload || typeof payload !== "object" || Array.isArray(payload))
@@ -134,6 +146,9 @@ function readRepoConnection(projectRoot) {
134
146
  linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined
135
147
  };
136
148
  }
149
+ function writeRepoConnection(projectRoot, state) {
150
+ writeJsonFile2(resolveRepoConnectionPath(projectRoot), state);
151
+ }
137
152
  function resolveSelectedConnection(projectRoot, options = {}) {
138
153
  const repo = readRepoConnection(projectRoot);
139
154
  if (!repo)
@@ -143,13 +158,191 @@ function resolveSelectedConnection(projectRoot, options = {}) {
143
158
  const global = readGlobalConnections(options);
144
159
  const connection = global.connections[repo.selected];
145
160
  if (!connection) {
146
- throw new CliError2(`Selected Rig connection "${repo.selected}" was not found. Run \`rig connect list\` or \`rig connect use local\`.`, 1);
161
+ throw new CliError2(`Selected Rig server "${repo.selected}" was not found. Run \`rig server list\` or \`rig server use local\`.`, 1);
147
162
  }
148
163
  return { alias: repo.selected, connection };
149
164
  }
150
165
 
166
+ // packages/cli/src/commands/_cli-format.ts
167
+ import { log, note } from "@clack/prompts";
168
+ import pc from "picocolors";
169
+ function truncate(value, width) {
170
+ if (value.length <= width)
171
+ return value;
172
+ if (width <= 1)
173
+ return "\u2026";
174
+ return `${value.slice(0, width - 1)}\u2026`;
175
+ }
176
+ function pad(value, width) {
177
+ return value.length >= width ? value : `${value}${" ".repeat(width - value.length)}`;
178
+ }
179
+ function statusColor(status) {
180
+ const normalized = status.toLowerCase();
181
+ if (["completed", "merged", "closed", "done", "accepted", "pass", "selected", "approved"].includes(normalized))
182
+ return pc.green;
183
+ if (["failed", "needs_attention", "needs-attention", "blocked", "error", "rejected"].includes(normalized))
184
+ return pc.red;
185
+ if (["running", "reviewing", "validating", "in_progress", "in-progress", "remote"].includes(normalized))
186
+ return pc.cyan;
187
+ if (["ready", "open", "queued", "created", "preparing", "local", "pending"].includes(normalized))
188
+ return pc.yellow;
189
+ return pc.dim;
190
+ }
191
+ function formatStatusPill(status) {
192
+ const label = status || "unknown";
193
+ return statusColor(label)(`\u25CF ${label}`);
194
+ }
195
+ function formatSection(title, subtitle) {
196
+ return `${pc.bold(pc.cyan("\u25C6"))} ${pc.bold(title)}${subtitle ? pc.dim(` \u2014 ${subtitle}`) : ""}`;
197
+ }
198
+ function formatSuccessCard(title, rows = []) {
199
+ const body = rows.filter(([, value]) => value !== undefined && value !== null && String(value).length > 0).map(([key, value]) => `${pc.dim("\u2502")} ${pc.dim(key.padEnd(12))} ${value}`);
200
+ return [formatSection(title), ...body].join(`
201
+ `);
202
+ }
203
+ function formatNextSteps(steps) {
204
+ if (steps.length === 0)
205
+ return [];
206
+ return [pc.bold("Next"), ...steps.map((step) => `${pc.dim("\u203A")} ${step}`)];
207
+ }
208
+ function formatConnectionList(connections) {
209
+ const rows = [["local", { kind: "local", mode: "auto" }], ...Object.entries(connections)];
210
+ const aliasWidth = Math.min(24, Math.max(5, ...rows.map(([alias]) => alias.length)));
211
+ const lines = rows.map(([alias, connection]) => [
212
+ pc.bold(pad(truncate(alias, aliasWidth), aliasWidth)),
213
+ formatStatusPill(connection.kind),
214
+ connection.kind === "remote" ? connection.baseUrl ?? "" : connection.mode ?? "local"
215
+ ].join(" "));
216
+ return [formatSection("Rig servers", `${rows.length} available`), `${pc.bold(pad("ALIAS", aliasWidth))} ${pc.bold("KIND")} ${pc.bold("TARGET")}`, ...lines, "", ...formatNextSteps(["Select one: `rig server use <alias|local>`"])].join(`
217
+ `);
218
+ }
219
+ function formatConnectionStatus(selected, connections) {
220
+ const connection = selected === "local" ? { kind: "local", mode: "auto" } : connections[selected];
221
+ const target = !connection ? "not configured" : connection.kind === "remote" ? connection.baseUrl : "local";
222
+ return [
223
+ formatSection("Rig server", "selected for this repo"),
224
+ `${pc.dim("\u2502")} ${pc.dim("selected ")} ${pc.bold(selected)}`,
225
+ `${pc.dim("\u2502")} ${pc.dim("kind ")} ${formatStatusPill(connection?.kind ?? "unknown")}`,
226
+ `${pc.dim("\u2502")} ${pc.dim("target ")} ${target ?? "not configured"}`,
227
+ "",
228
+ ...formatNextSteps(["Change: `rig server use <alias|local>`", "List saved servers: `rig server list`"])
229
+ ].join(`
230
+ `);
231
+ }
232
+
233
+ // packages/cli/src/commands/connect.ts
234
+ function usageName(options) {
235
+ return `rig ${options.group}`;
236
+ }
237
+ function parseConnection(alias, value, options) {
238
+ if (alias === "local" && !value)
239
+ return { kind: "local", mode: "auto" };
240
+ if (!value)
241
+ throw new CliError2(`Missing remote server URL. Usage: ${usageName(options)} add <alias> <url>`, 1);
242
+ let parsed;
243
+ try {
244
+ parsed = new URL(value);
245
+ } catch {
246
+ throw new CliError2(`Invalid Rig server URL: ${value}`, 1);
247
+ }
248
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
249
+ throw new CliError2("Rig remote server URL must be http(s).", 1);
250
+ }
251
+ return { kind: "remote", baseUrl: parsed.toString().replace(/\/+$/, "") };
252
+ }
253
+ function printJsonOrText(context, payload, text) {
254
+ if (context.outputMode === "json") {
255
+ console.log(JSON.stringify(payload, null, 2));
256
+ } else {
257
+ console.log(text);
258
+ }
259
+ }
260
+ async function promptForConnectionAlias(context) {
261
+ const state = readGlobalConnections();
262
+ const repo = readRepoConnection(context.projectRoot);
263
+ const options = [
264
+ { value: "local", label: "local", hint: "Use/start a local Rig server" },
265
+ ...Object.entries(state.connections).map(([alias, connection]) => ({
266
+ value: alias,
267
+ label: alias,
268
+ hint: connection.kind === "remote" ? connection.baseUrl : "local"
269
+ }))
270
+ ].filter((option, index, all) => all.findIndex((candidate) => candidate.value === option.value) === index);
271
+ const answer = await select({
272
+ message: "Select Rig server for this repo",
273
+ initialValue: repo?.selected ?? "local",
274
+ options
275
+ });
276
+ if (isCancel(answer)) {
277
+ cancel("No server selected.");
278
+ throw new CliError2("No server selected.", 3);
279
+ }
280
+ return String(answer);
281
+ }
282
+ async function executeConnectionCommand(context, args, options) {
283
+ const [command, ...rest] = args;
284
+ switch (command ?? "status") {
285
+ case "list": {
286
+ requireNoExtraArgs(rest, `${usageName(options)} list`);
287
+ const state = readGlobalConnections();
288
+ printJsonOrText(context, state, formatConnectionList(state.connections));
289
+ return { ok: true, group: options.group, command: "list", details: state };
290
+ }
291
+ case "add": {
292
+ const [alias, url, ...extra] = rest;
293
+ if (!alias)
294
+ throw new CliError2(`Missing alias. Usage: ${usageName(options)} add <alias> <url>`, 1);
295
+ requireNoExtraArgs(extra, `${usageName(options)} add <alias> <url>`);
296
+ const connection = parseConnection(alias, url, options);
297
+ const state = upsertGlobalConnection(alias, connection);
298
+ printJsonOrText(context, { alias, connection }, formatSuccessCard("Rig server saved", [
299
+ ["alias", alias],
300
+ ["target", connection.kind === "remote" ? connection.baseUrl : "local"],
301
+ ["next", `${usageName(options)} use ${alias}`]
302
+ ]));
303
+ return { ok: true, group: options.group, command: "add", details: { alias, connection, count: Object.keys(state.connections).length } };
304
+ }
305
+ case "use": {
306
+ let [alias, ...extra] = rest;
307
+ requireNoExtraArgs(extra, `${usageName(options)} use <alias|local>`);
308
+ if (!alias && options.interactiveUse && context.outputMode === "text" && process.stdin.isTTY) {
309
+ alias = await promptForConnectionAlias(context);
310
+ }
311
+ if (!alias)
312
+ throw new CliError2(`Missing alias. Usage: ${usageName(options)} use <alias|local>`, 1);
313
+ if (alias !== "local") {
314
+ const state = readGlobalConnections();
315
+ if (!state.connections[alias])
316
+ throw new CliError2(`Unknown Rig server: ${alias}`, 1);
317
+ }
318
+ const repoState = { selected: alias, linkedAt: new Date().toISOString() };
319
+ writeRepoConnection(context.projectRoot, repoState);
320
+ printJsonOrText(context, repoState, formatSuccessCard("Rig server selected", [
321
+ ["selected", alias],
322
+ ["scope", "this repo"],
323
+ ["next", "rig task list"]
324
+ ]));
325
+ return { ok: true, group: options.group, command: "use", details: repoState };
326
+ }
327
+ case "status": {
328
+ requireNoExtraArgs(rest, `${usageName(options)} status`);
329
+ const repo = readRepoConnection(context.projectRoot);
330
+ const global = readGlobalConnections();
331
+ const details = { selected: repo?.selected ?? "local", repo, connections: global.connections };
332
+ printJsonOrText(context, details, formatConnectionStatus(details.selected, global.connections));
333
+ return { ok: true, group: options.group, command: "status", details };
334
+ }
335
+ default:
336
+ throw new CliError2(`Unknown ${options.group} command: ${String(command)}
337
+ Usage: ${usageName(options)} <list|add|use|status>`, 1);
338
+ }
339
+ }
340
+
151
341
  // packages/cli/src/commands/_server-client.ts
152
- var cachedGitHubBearerToken;
342
+ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
343
+ import { resolve as resolve2 } from "path";
344
+ import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
345
+ var scopedGitHubBearerTokens = new Map;
153
346
  function cleanToken(value) {
154
347
  const trimmed = value?.trim();
155
348
  return trimmed ? trimmed : null;
@@ -166,25 +359,13 @@ function readPrivateRemoteSessionToken(projectRoot) {
166
359
  }
167
360
  }
168
361
  function readGitHubBearerTokenForRemote(projectRoot) {
169
- if (cachedGitHubBearerToken !== undefined)
170
- return cachedGitHubBearerToken;
362
+ const scopedKey = resolve2(projectRoot);
363
+ if (scopedGitHubBearerTokens.has(scopedKey))
364
+ return scopedGitHubBearerTokens.get(scopedKey) ?? null;
171
365
  const privateSession = readPrivateRemoteSessionToken(projectRoot);
172
- if (privateSession) {
173
- cachedGitHubBearerToken = privateSession;
174
- return cachedGitHubBearerToken;
175
- }
176
- const envToken = cleanToken(process.env.RIG_GITHUB_TOKEN) ?? cleanToken(process.env.GITHUB_TOKEN) ?? cleanToken(process.env.GH_TOKEN);
177
- if (envToken) {
178
- cachedGitHubBearerToken = envToken;
179
- return cachedGitHubBearerToken;
180
- }
181
- const result = spawnSync("gh", ["auth", "token"], {
182
- encoding: "utf8",
183
- timeout: 5000,
184
- stdio: ["ignore", "pipe", "ignore"]
185
- });
186
- cachedGitHubBearerToken = result.status === 0 ? cleanToken(result.stdout) : null;
187
- return cachedGitHubBearerToken;
366
+ if (privateSession)
367
+ return privateSession;
368
+ return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
188
369
  }
189
370
  async function ensureServerForCli(projectRoot) {
190
371
  try {
@@ -286,7 +467,10 @@ async function submitTaskRunViaServer(context, input) {
286
467
 
287
468
  // packages/cli/src/commands/server.ts
288
469
  async function executeServer(context, args, options) {
289
- const [command = "start", ...rest] = args;
470
+ const [command = "status", ...rest] = args;
471
+ if (["status", "list", "add", "use"].includes(command)) {
472
+ return executeConnectionCommand(context, [command, ...rest], { group: "server", interactiveUse: true });
473
+ }
290
474
  switch (command) {
291
475
  case "start": {
292
476
  let pending = rest;
@@ -298,8 +482,8 @@ async function executeServer(context, args, options) {
298
482
  pending = pollResult.rest;
299
483
  const authTokenResult = takeOption(pending, "--auth-token");
300
484
  pending = authTokenResult.rest;
301
- requireNoExtraArgs(pending, "bun run rig server start [--host <host>] [--port <n>] [--poll-ms <n>] [--auth-token <token>]");
302
- const commandParts = ["bun", "run", "packages/server/src/server.ts", "start"];
485
+ requireNoExtraArgs(pending, "rig server start [--host <host>] [--port <n>] [--poll-ms <n>] [--auth-token <token>]");
486
+ const commandParts = ["rig-server", "start"];
303
487
  if (hostResult.value) {
304
488
  commandParts.push("--host", hostResult.value);
305
489
  }
@@ -321,8 +505,8 @@ async function executeServer(context, args, options) {
321
505
  let pending = rest;
322
506
  const eventResult = takeOption(pending, "--event");
323
507
  pending = eventResult.rest;
324
- requireNoExtraArgs(pending, "bun run rig server notify-test [--event <type>]");
325
- const commandParts = ["bun", "run", "packages/server/src/server.ts", "notify-test"];
508
+ requireNoExtraArgs(pending, "rig server notify-test [--event <type>]");
509
+ const commandParts = ["rig-server", "notify-test"];
326
510
  if (eventResult.value) {
327
511
  commandParts.push("--event", eventResult.value);
328
512
  }
@@ -349,7 +533,7 @@ async function executeServer(context, args, options) {
349
533
  pending = dirtyBaselineResult.rest;
350
534
  const prResult = takeOption(pending, "--pr");
351
535
  pending = prResult.rest;
352
- requireNoExtraArgs(pending, "bun run rig --run-id <run-id> server task-run [--task <id>] [--title <text>] [--runtime-adapter claude-code|codex|pi] [--model <model>] [--runtime-mode <mode>] [--interaction-mode <mode>] [--initial-prompt <text>] [--dirty-baseline head|dirty-snapshot] [--pr auto|ask|off]");
536
+ requireNoExtraArgs(pending, "rig --run-id <run-id> server task-run [--task <id>] [--title <text>] [--runtime-adapter claude-code|codex|pi] [--model <model>] [--runtime-mode <mode>] [--interaction-mode <mode>] [--initial-prompt <text>] [--dirty-baseline head|dirty-snapshot] [--pr auto|ask|off]");
353
537
  if (!taskResult.value && !initialPromptResult.value && !titleResult.value) {
354
538
  throw new CliError2("server task-run requires either --task <id> or --initial-prompt/--title for an ad hoc run.", 2);
355
539
  }
@@ -9,8 +9,6 @@ import { resolve as resolve6 } from "path";
9
9
  import { EventBus } from "@rig/runtime/control-plane/runtime/events";
10
10
  import { CliError } from "@rig/runtime/control-plane/errors";
11
11
  import { evaluate, loadPolicy, resolveAction } from "@rig/runtime/control-plane/runtime/guard";
12
- import { PluginManager } from "@rig/runtime/control-plane/runtime/plugins";
13
- import { loadRuntimeContextFromEnv } from "@rig/runtime/control-plane/runtime/context";
14
12
  import { buildBinary } from "@rig/runtime/control-plane/runtime/isolation";
15
13
  import { CliError as CliError2 } from "@rig/runtime/control-plane/errors";
16
14
  function requireNoExtraArgs(args, usage) {
@@ -102,7 +100,8 @@ function resolveControlPlaneDefinitionRoot(projectRoot) {
102
100
  import { existsSync, readFileSync, rmSync } from "fs";
103
101
  import { homedir } from "os";
104
102
  import { resolve as resolve2 } from "path";
105
- var PI_RIG_PACKAGE_NAME = "@rig/pi-rig";
103
+ var PI_RIG_PACKAGE_NAME = "@h-rig/pi-rig";
104
+ var LEGACY_PI_RIG_PACKAGE_NAME = "@rig/pi-rig";
106
105
  async function defaultCommandRunner(command, options = {}) {
107
106
  const proc = Bun.spawn(command, { cwd: options.cwd, stdout: "pipe", stderr: "pipe" });
108
107
  const [stdout, stderr, exitCode] = await Promise.all([
@@ -121,7 +120,7 @@ function resolvePiHomeDir(inputHomeDir) {
121
120
  function piListContainsPiRig(output) {
122
121
  return output.split(/\r?\n/).some((line) => {
123
122
  const normalized = line.trim();
124
- return normalized.includes(PI_RIG_PACKAGE_NAME) || /(?:^|[\\/])packages[\\/]pi-rig(?:$|\s)/.test(normalized);
123
+ return normalized.includes(PI_RIG_PACKAGE_NAME) || normalized.includes(LEGACY_PI_RIG_PACKAGE_NAME) || /(?:^|[\\/])packages[\\/]pi-rig(?:$|\s)/.test(normalized);
125
124
  });
126
125
  }
127
126
  async function safeRun(runner, command, options) {
@@ -252,17 +251,16 @@ function resolveSelectedConnection(projectRoot, options = {}) {
252
251
  const global = readGlobalConnections(options);
253
252
  const connection = global.connections[repo.selected];
254
253
  if (!connection) {
255
- throw new CliError2(`Selected Rig connection "${repo.selected}" was not found. Run \`rig connect list\` or \`rig connect use local\`.`, 1);
254
+ throw new CliError2(`Selected Rig server "${repo.selected}" was not found. Run \`rig server list\` or \`rig server use local\`.`, 1);
256
255
  }
257
256
  return { alias: repo.selected, connection };
258
257
  }
259
258
 
260
259
  // packages/cli/src/commands/_server-client.ts
261
- import { spawnSync } from "child_process";
262
260
  import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
263
261
  import { resolve as resolve4 } from "path";
264
262
  import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
265
- var cachedGitHubBearerToken;
263
+ var scopedGitHubBearerTokens = new Map;
266
264
  function cleanToken(value) {
267
265
  const trimmed = value?.trim();
268
266
  return trimmed ? trimmed : null;
@@ -279,25 +277,13 @@ function readPrivateRemoteSessionToken(projectRoot) {
279
277
  }
280
278
  }
281
279
  function readGitHubBearerTokenForRemote(projectRoot) {
282
- if (cachedGitHubBearerToken !== undefined)
283
- return cachedGitHubBearerToken;
280
+ const scopedKey = resolve4(projectRoot);
281
+ if (scopedGitHubBearerTokens.has(scopedKey))
282
+ return scopedGitHubBearerTokens.get(scopedKey) ?? null;
284
283
  const privateSession = readPrivateRemoteSessionToken(projectRoot);
285
- if (privateSession) {
286
- cachedGitHubBearerToken = privateSession;
287
- return cachedGitHubBearerToken;
288
- }
289
- const envToken = cleanToken(process.env.RIG_GITHUB_TOKEN) ?? cleanToken(process.env.GITHUB_TOKEN) ?? cleanToken(process.env.GH_TOKEN);
290
- if (envToken) {
291
- cachedGitHubBearerToken = envToken;
292
- return cachedGitHubBearerToken;
293
- }
294
- const result = spawnSync("gh", ["auth", "token"], {
295
- encoding: "utf8",
296
- timeout: 5000,
297
- stdio: ["ignore", "pipe", "ignore"]
298
- });
299
- cachedGitHubBearerToken = result.status === 0 ? cleanToken(result.stdout) : null;
300
- return cachedGitHubBearerToken;
284
+ if (privateSession)
285
+ return privateSession;
286
+ return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
301
287
  }
302
288
  async function ensureServerForCli(projectRoot) {
303
289
  try {
@@ -493,7 +479,7 @@ async function runRigDoctorChecks(options) {
493
479
  const taskSourceKind = config?.taskSource?.kind;
494
480
  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."));
495
481
  const repo = readRepoConnection(projectRoot);
496
- 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>`."));
482
+ 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>`."));
497
483
  const selected = (() => {
498
484
  try {
499
485
  return resolveSelectedConnection(projectRoot);
@@ -501,7 +487,7 @@ async function runRigDoctorChecks(options) {
501
487
  return null;
502
488
  }
503
489
  })();
504
- 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));
490
+ 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));
505
491
  let server = null;
506
492
  try {
507
493
  server = await (options.resolveServer ?? ensureServerForCli)(projectRoot);
@@ -587,7 +573,7 @@ async function executeSetup(context, args) {
587
573
  const [command = "check", ...rest] = args;
588
574
  switch (command) {
589
575
  case "bootstrap":
590
- requireNoExtraArgs(rest, "bun run rig setup bootstrap");
576
+ requireNoExtraArgs(rest, "rig setup bootstrap");
591
577
  {
592
578
  const hostBash = Bun.which("bash") || "/bin/bash";
593
579
  const env = { ...process.env };
@@ -610,25 +596,19 @@ async function executeSetup(context, args) {
610
596
  }
611
597
  return { ok: true, group: "setup", command };
612
598
  case "check":
613
- requireNoExtraArgs(rest, `bun run rig setup ${command}`);
599
+ requireNoExtraArgs(rest, `rig setup ${command}`);
614
600
  {
615
601
  const checks = await withMutedConsole(context.outputMode === "json", () => runSetupCheck(context.projectRoot));
616
602
  return { ok: true, group: "setup", command, details: { checks, failures: countDoctorFailures(checks) } };
617
603
  }
618
604
  case "setup":
619
- requireNoExtraArgs(rest, "bun run rig setup setup");
605
+ requireNoExtraArgs(rest, "rig setup setup");
620
606
  withMutedConsole(context.outputMode === "json", () => runSetupInit(context.projectRoot));
621
607
  return { ok: true, group: "setup", command };
622
608
  case "preflight":
623
- requireNoExtraArgs(rest, "bun run rig setup preflight");
609
+ requireNoExtraArgs(rest, "rig setup preflight");
624
610
  await withMutedConsole(context.outputMode === "json", () => runSetupPreflight(context.projectRoot));
625
611
  return { ok: true, group: "setup", command };
626
- case "install-agent-shell":
627
- requireNoExtraArgs(rest, "bun run rig setup install-agent-shell");
628
- if (context.outputMode === "text") {
629
- console.log("install-agent-shell is deprecated. Runtime shells now use compiled rig-agent directly.");
630
- }
631
- return { ok: true, group: "setup", command };
632
612
  default:
633
613
  throw new CliError2(`Unknown setup command: ${command}`);
634
614
  }
@@ -9,8 +9,6 @@ import pc from "picocolors";
9
9
  import { EventBus } from "@rig/runtime/control-plane/runtime/events";
10
10
  import { CliError } from "@rig/runtime/control-plane/errors";
11
11
  import { evaluate, loadPolicy, resolveAction } from "@rig/runtime/control-plane/runtime/guard";
12
- import { PluginManager } from "@rig/runtime/control-plane/runtime/plugins";
13
- import { loadRuntimeContextFromEnv } from "@rig/runtime/control-plane/runtime/context";
14
12
  import { buildBinary } from "@rig/runtime/control-plane/runtime/isolation";
15
13
  import { CliError as CliError2 } from "@rig/runtime/control-plane/errors";
16
14
  function formatCommand(parts) {
@@ -241,15 +239,15 @@ function buildBugReportMarkdown(input, browser, screenshots, assets) {
241
239
  ...input.issueId ? [
242
240
  `- Canonical task assets live under \`artifacts/${input.issueId}/bug-report/\`.`,
243
241
  `- Start with \`artifacts/${input.issueId}/bug-report/task.md\` and the files in \`artifacts/${input.issueId}/bug-report/assets/\`.`,
244
- 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.`
242
+ 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.`
245
243
  ] : [
246
- "- Draft-only report: convert this into a beads task before assigning it to an agent run."
244
+ "- Draft-only report: convert this into a Rig task before assigning it to an agent run."
247
245
  ],
248
246
  "",
249
247
  "## Validation",
250
248
  "",
251
249
  "```bash",
252
- ...input.issueId ? [`bun run rig task validate --task ${input.issueId}`] : [],
250
+ ...input.issueId ? [`rig task validate --task ${input.issueId}`] : [],
253
251
  ...browserRequired ? [
254
252
  "bun run app:check:browser:hp-next",
255
253
  "bun run app:e2e:browser:hp-next"
@@ -396,7 +394,7 @@ async function executeTaskReportBug(context, args) {
396
394
  pending = outputRootResult.rest;
397
395
  const slugResult = takeOption(pending, "--slug");
398
396
  pending = slugResult.rest;
399
- requireNoExtraArgs(pending, "bun run rig report-bug [--no-prompt] [--no-beads] [--browser|--no-browser] --title <text> --url <url> [--asset <dragged-file>]");
397
+ requireNoExtraArgs(pending, "rig report-bug [--no-prompt] [--no-beads] [--browser|--no-browser] --title <text> --url <url> [--asset <dragged-file>]");
400
398
  let draft = {
401
399
  outputRoot: outputRootResult.value || "",
402
400
  title: titleResult.value,
@@ -501,7 +499,7 @@ async function executeTaskReportBug(context, args) {
501
499
  console.log(`Evidence assets: ${result.assetDir}`);
502
500
  if (taskConfigPath) {
503
501
  console.log(`Task config: ${taskConfigPath}`);
504
- console.log(`Run: bun run rig task info --task ${issueId}`);
502
+ console.log(`Run: rig task info --task ${issueId}`);
505
503
  }
506
504
  }
507
505
  return {