@h-rig/cli 0.0.6-alpha.5 → 0.0.6-alpha.51

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 (50) hide show
  1. package/README.md +1 -1
  2. package/dist/bin/rig.js +4129 -1207
  3. package/dist/src/commands/_cli-format.js +369 -0
  4. package/dist/src/commands/_connection-state.js +12 -6
  5. package/dist/src/commands/_doctor-checks.js +79 -34
  6. package/dist/src/commands/_help-catalog.js +445 -0
  7. package/dist/src/commands/_operator-surface.js +220 -0
  8. package/dist/src/commands/_operator-view.js +1124 -64
  9. package/dist/src/commands/_parsers.js +0 -2
  10. package/dist/src/commands/_pi-frontend.js +1080 -0
  11. package/dist/src/commands/_pi-install.js +4 -3
  12. package/dist/src/commands/_pi-remote-session.js +771 -0
  13. package/dist/src/commands/_pi-worker-bridge-extension.js +834 -0
  14. package/dist/src/commands/_policy.js +0 -2
  15. package/dist/src/commands/_preflight.js +98 -116
  16. package/dist/src/commands/_run-driver-helpers.js +2 -2
  17. package/dist/src/commands/_server-client.js +225 -48
  18. package/dist/src/commands/_snapshot-upload.js +74 -30
  19. package/dist/src/commands/_spinner.js +63 -0
  20. package/dist/src/commands/_task-picker.js +44 -16
  21. package/dist/src/commands/agent.js +8 -9
  22. package/dist/src/commands/browser.js +4 -6
  23. package/dist/src/commands/connect.js +134 -26
  24. package/dist/src/commands/dist.js +4 -6
  25. package/dist/src/commands/doctor.js +79 -34
  26. package/dist/src/commands/github.js +76 -32
  27. package/dist/src/commands/inbox.js +410 -31
  28. package/dist/src/commands/init.js +398 -90
  29. package/dist/src/commands/inspect.js +296 -23
  30. package/dist/src/commands/inspector.js +2 -4
  31. package/dist/src/commands/pi.js +168 -0
  32. package/dist/src/commands/plugin.js +81 -22
  33. package/dist/src/commands/profile-and-review.js +8 -10
  34. package/dist/src/commands/queue.js +2 -3
  35. package/dist/src/commands/remote.js +18 -20
  36. package/dist/src/commands/repo-git-harness.js +6 -8
  37. package/dist/src/commands/run.js +1422 -131
  38. package/dist/src/commands/server.js +280 -40
  39. package/dist/src/commands/setup.js +84 -45
  40. package/dist/src/commands/task-report-bug.js +5 -7
  41. package/dist/src/commands/task-run-driver.js +676 -70
  42. package/dist/src/commands/task.js +1861 -260
  43. package/dist/src/commands/test.js +3 -5
  44. package/dist/src/commands/workspace.js +4 -6
  45. package/dist/src/commands.js +4111 -1183
  46. package/dist/src/index.js +4122 -1203
  47. package/dist/src/launcher.js +5 -3
  48. package/dist/src/report-bug.js +3 -3
  49. package/dist/src/runner.js +5 -19
  50. package/package.json +7 -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) {
@@ -34,6 +32,9 @@ Usage: ${usage}`);
34
32
  }
35
33
  }
36
34
 
35
+ // packages/cli/src/commands/server.ts
36
+ import { resolveRigServerCommand } from "@rig/runtime/local-server";
37
+
37
38
  // packages/cli/src/commands/_authority-runs.ts
38
39
  import {
39
40
  readAuthorityRun,
@@ -60,11 +61,8 @@ function normalizeRuntimeAdapter(value) {
60
61
  return "claude-code";
61
62
  }
62
63
 
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";
64
+ // packages/cli/src/commands/connect.ts
65
+ import { cancel, isCancel, select } from "@clack/prompts";
68
66
 
69
67
  // packages/cli/src/commands/_connection-state.ts
70
68
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
@@ -91,6 +89,11 @@ function readJsonFile(path) {
91
89
  throw new CliError2(`Invalid Rig connection state at ${path}: ${error instanceof Error ? error.message : String(error)}`, 1);
92
90
  }
93
91
  }
92
+ function writeJsonFile2(path, value) {
93
+ mkdirSync(dirname(path), { recursive: true });
94
+ writeFileSync(path, `${JSON.stringify(value, null, 2)}
95
+ `, "utf8");
96
+ }
94
97
  function normalizeConnection(value) {
95
98
  if (!value || typeof value !== "object" || Array.isArray(value))
96
99
  return null;
@@ -120,6 +123,18 @@ function readGlobalConnections(options = {}) {
120
123
  }
121
124
  return { connections };
122
125
  }
126
+ function writeGlobalConnections(state, options = {}) {
127
+ writeJsonFile2(resolveGlobalConnectionsPath(options.env ?? process.env), state);
128
+ }
129
+ function upsertGlobalConnection(alias, connection, options = {}) {
130
+ const cleanAlias = alias.trim();
131
+ if (!cleanAlias)
132
+ throw new CliError2("Connection alias is required.", 1);
133
+ const state = readGlobalConnections(options);
134
+ state.connections[cleanAlias] = connection;
135
+ writeGlobalConnections(state, options);
136
+ return state;
137
+ }
123
138
  function readRepoConnection(projectRoot) {
124
139
  const payload = readJsonFile(resolveRepoConnectionPath(projectRoot));
125
140
  if (!payload || typeof payload !== "object" || Array.isArray(payload))
@@ -131,25 +146,213 @@ function readRepoConnection(projectRoot) {
131
146
  return {
132
147
  selected,
133
148
  project: typeof record.project === "string" ? record.project : undefined,
134
- linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined
149
+ linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined,
150
+ serverProjectRoot: typeof record.serverProjectRoot === "string" && record.serverProjectRoot.trim() ? record.serverProjectRoot.trim() : undefined
135
151
  };
136
152
  }
153
+ function writeRepoConnection(projectRoot, state) {
154
+ writeJsonFile2(resolveRepoConnectionPath(projectRoot), state);
155
+ }
137
156
  function resolveSelectedConnection(projectRoot, options = {}) {
138
157
  const repo = readRepoConnection(projectRoot);
139
158
  if (!repo)
140
159
  return null;
141
160
  if (repo.selected === "local")
142
- return { alias: "local", connection: { kind: "local", mode: "auto" } };
161
+ return { alias: "local", connection: { kind: "local", mode: "auto" }, serverProjectRoot: repo.serverProjectRoot };
143
162
  const global = readGlobalConnections(options);
144
163
  const connection = global.connections[repo.selected];
145
164
  if (!connection) {
146
- throw new CliError2(`Selected Rig connection "${repo.selected}" was not found. Run \`rig connect list\` or \`rig connect use local\`.`, 1);
165
+ throw new CliError2(`Selected Rig server "${repo.selected}" was not found. Run \`rig server list\` or \`rig server use local\`.`, 1);
166
+ }
167
+ return { alias: repo.selected, connection, serverProjectRoot: repo.serverProjectRoot };
168
+ }
169
+ function writeRepoServerProjectRoot(projectRoot, serverProjectRoot) {
170
+ const repo = readRepoConnection(projectRoot);
171
+ if (!repo)
172
+ return;
173
+ writeRepoConnection(projectRoot, { ...repo, serverProjectRoot });
174
+ }
175
+
176
+ // packages/cli/src/commands/_cli-format.ts
177
+ import { log, note } from "@clack/prompts";
178
+ import pc from "picocolors";
179
+ function truncate(value, width) {
180
+ if (value.length <= width)
181
+ return value;
182
+ if (width <= 1)
183
+ return "\u2026";
184
+ return `${value.slice(0, width - 1)}\u2026`;
185
+ }
186
+ function pad(value, width) {
187
+ return value.length >= width ? value : `${value}${" ".repeat(width - value.length)}`;
188
+ }
189
+ function statusColor(status) {
190
+ const normalized = status.toLowerCase();
191
+ if (["completed", "merged", "closed", "done", "accepted", "pass", "selected", "approved"].includes(normalized))
192
+ return pc.green;
193
+ if (["failed", "needs_attention", "needs-attention", "blocked", "error", "rejected"].includes(normalized))
194
+ return pc.red;
195
+ if (["running", "reviewing", "validating", "in_progress", "in-progress", "remote"].includes(normalized))
196
+ return pc.cyan;
197
+ if (["ready", "open", "queued", "created", "preparing", "local", "pending"].includes(normalized))
198
+ return pc.yellow;
199
+ return pc.dim;
200
+ }
201
+ function formatStatusPill(status) {
202
+ const label = status || "unknown";
203
+ return statusColor(label)(`\u25CF ${label}`);
204
+ }
205
+ function formatSection(title, subtitle) {
206
+ return `${pc.bold(pc.cyan("\u25C6"))} ${pc.bold(title)}${subtitle ? pc.dim(` \u2014 ${subtitle}`) : ""}`;
207
+ }
208
+ function formatSuccessCard(title, rows = []) {
209
+ 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}`);
210
+ return [formatSection(title), ...body].join(`
211
+ `);
212
+ }
213
+ function formatNextSteps(steps) {
214
+ if (steps.length === 0)
215
+ return [];
216
+ return [pc.bold("Next"), ...steps.map((step) => `${pc.dim("\u203A")} ${step}`)];
217
+ }
218
+ function formatConnectionList(connections) {
219
+ const rows = [["local", { kind: "local", mode: "auto" }], ...Object.entries(connections)];
220
+ const aliasWidth = Math.min(24, Math.max(5, ...rows.map(([alias]) => alias.length)));
221
+ const lines = rows.map(([alias, connection]) => [
222
+ pc.bold(pad(truncate(alias, aliasWidth), aliasWidth)),
223
+ formatStatusPill(connection.kind),
224
+ connection.kind === "remote" ? connection.baseUrl ?? "" : connection.mode ?? "local"
225
+ ].join(" "));
226
+ 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(`
227
+ `);
228
+ }
229
+ function formatConnectionStatus(selected, connections) {
230
+ const connection = selected === "local" ? { kind: "local", mode: "auto" } : connections[selected];
231
+ const target = !connection ? "not configured" : connection.kind === "remote" ? connection.baseUrl : "local";
232
+ return [
233
+ formatSection("Rig server", "selected for this repo"),
234
+ `${pc.dim("\u2502")} ${pc.dim("selected ")} ${pc.bold(selected)}`,
235
+ `${pc.dim("\u2502")} ${pc.dim("kind ")} ${formatStatusPill(connection?.kind ?? "unknown")}`,
236
+ `${pc.dim("\u2502")} ${pc.dim("target ")} ${target ?? "not configured"}`,
237
+ "",
238
+ ...formatNextSteps(["Change: `rig server use <alias|local>`", "List saved servers: `rig server list`"])
239
+ ].join(`
240
+ `);
241
+ }
242
+
243
+ // packages/cli/src/commands/connect.ts
244
+ function usageName(options) {
245
+ return `rig ${options.group}`;
246
+ }
247
+ function parseConnection(alias, value, options) {
248
+ if (alias === "local" && !value)
249
+ return { kind: "local", mode: "auto" };
250
+ if (!value)
251
+ throw new CliError2(`Missing remote server URL. Usage: ${usageName(options)} add <alias> <url>`, 1);
252
+ let parsed;
253
+ try {
254
+ parsed = new URL(value);
255
+ } catch {
256
+ throw new CliError2(`Invalid Rig server URL: ${value}`, 1);
257
+ }
258
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
259
+ throw new CliError2("Rig remote server URL must be http(s).", 1);
260
+ }
261
+ return { kind: "remote", baseUrl: parsed.toString().replace(/\/+$/, "") };
262
+ }
263
+ function printJsonOrText(context, payload, text) {
264
+ if (context.outputMode === "json") {
265
+ console.log(JSON.stringify(payload, null, 2));
266
+ } else {
267
+ console.log(text);
268
+ }
269
+ }
270
+ async function promptForConnectionAlias(context) {
271
+ const state = readGlobalConnections();
272
+ const repo = readRepoConnection(context.projectRoot);
273
+ const options = [
274
+ { value: "local", label: "local", hint: "Use/start a local Rig server" },
275
+ ...Object.entries(state.connections).map(([alias, connection]) => ({
276
+ value: alias,
277
+ label: alias,
278
+ hint: connection.kind === "remote" ? connection.baseUrl : "local"
279
+ }))
280
+ ].filter((option, index, all) => all.findIndex((candidate) => candidate.value === option.value) === index);
281
+ const answer = await select({
282
+ message: "Select Rig server for this repo",
283
+ initialValue: repo?.selected ?? "local",
284
+ options
285
+ });
286
+ if (isCancel(answer)) {
287
+ cancel("No server selected.");
288
+ throw new CliError2("No server selected.", 3);
289
+ }
290
+ return String(answer);
291
+ }
292
+ async function executeConnectionCommand(context, args, options) {
293
+ const [command, ...rest] = args;
294
+ switch (command ?? "status") {
295
+ case "list": {
296
+ requireNoExtraArgs(rest, `${usageName(options)} list`);
297
+ const state = readGlobalConnections();
298
+ printJsonOrText(context, state, formatConnectionList(state.connections));
299
+ return { ok: true, group: options.group, command: "list", details: state };
300
+ }
301
+ case "add": {
302
+ const [alias, url, ...extra] = rest;
303
+ if (!alias)
304
+ throw new CliError2(`Missing alias. Usage: ${usageName(options)} add <alias> <url>`, 1);
305
+ requireNoExtraArgs(extra, `${usageName(options)} add <alias> <url>`);
306
+ const connection = parseConnection(alias, url, options);
307
+ const state = upsertGlobalConnection(alias, connection);
308
+ printJsonOrText(context, { alias, connection }, formatSuccessCard("Rig server saved", [
309
+ ["alias", alias],
310
+ ["target", connection.kind === "remote" ? connection.baseUrl : "local"],
311
+ ["next", `${usageName(options)} use ${alias}`]
312
+ ]));
313
+ return { ok: true, group: options.group, command: "add", details: { alias, connection, count: Object.keys(state.connections).length } };
314
+ }
315
+ case "use": {
316
+ let [alias, ...extra] = rest;
317
+ requireNoExtraArgs(extra, `${usageName(options)} use <alias|local>`);
318
+ if (!alias && options.interactiveUse && context.outputMode === "text" && process.stdin.isTTY) {
319
+ alias = await promptForConnectionAlias(context);
320
+ }
321
+ if (!alias)
322
+ throw new CliError2(`Missing alias. Usage: ${usageName(options)} use <alias|local>`, 1);
323
+ if (alias !== "local") {
324
+ const state = readGlobalConnections();
325
+ if (!state.connections[alias])
326
+ throw new CliError2(`Unknown Rig server: ${alias}`, 1);
327
+ }
328
+ const repoState = { selected: alias, linkedAt: new Date().toISOString() };
329
+ writeRepoConnection(context.projectRoot, repoState);
330
+ printJsonOrText(context, repoState, formatSuccessCard("Rig server selected", [
331
+ ["selected", alias],
332
+ ["scope", "this repo"],
333
+ ["next", "rig task list"]
334
+ ]));
335
+ return { ok: true, group: options.group, command: "use", details: repoState };
336
+ }
337
+ case "status": {
338
+ requireNoExtraArgs(rest, `${usageName(options)} status`);
339
+ const repo = readRepoConnection(context.projectRoot);
340
+ const global = readGlobalConnections();
341
+ const details = { selected: repo?.selected ?? "local", repo, connections: global.connections };
342
+ printJsonOrText(context, details, formatConnectionStatus(details.selected, global.connections));
343
+ return { ok: true, group: options.group, command: "status", details };
344
+ }
345
+ default:
346
+ throw new CliError2(`Unknown ${options.group} command: ${String(command)}
347
+ Usage: ${usageName(options)} <list|add|use|status>`, 1);
147
348
  }
148
- return { alias: repo.selected, connection };
149
349
  }
150
350
 
151
351
  // packages/cli/src/commands/_server-client.ts
152
- var cachedGitHubBearerToken;
352
+ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
353
+ import { resolve as resolve2 } from "path";
354
+ import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
355
+ var scopedGitHubBearerTokens = new Map;
153
356
  function cleanToken(value) {
154
357
  const trimmed = value?.trim();
155
358
  return trimmed ? trimmed : null;
@@ -166,41 +369,47 @@ function readPrivateRemoteSessionToken(projectRoot) {
166
369
  }
167
370
  }
168
371
  function readGitHubBearerTokenForRemote(projectRoot) {
169
- if (cachedGitHubBearerToken !== undefined)
170
- return cachedGitHubBearerToken;
372
+ const scopedKey = resolve2(projectRoot);
373
+ if (scopedGitHubBearerTokens.has(scopedKey))
374
+ return scopedGitHubBearerTokens.get(scopedKey) ?? null;
171
375
  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;
376
+ if (privateSession)
377
+ return privateSession;
378
+ return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
379
+ }
380
+ function readStoredGitHubAuthToken(projectRoot) {
381
+ const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
382
+ if (!existsSync2(path))
383
+ return null;
384
+ try {
385
+ const parsed = JSON.parse(readFileSync2(path, "utf8"));
386
+ return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
387
+ } catch {
388
+ return null;
180
389
  }
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;
390
+ }
391
+ function readLocalConnectionFallbackToken(projectRoot) {
392
+ return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
188
393
  }
189
394
  async function ensureServerForCli(projectRoot) {
190
395
  try {
191
396
  const selected = resolveSelectedConnection(projectRoot);
192
397
  if (selected?.connection.kind === "remote") {
398
+ const authToken = readGitHubBearerTokenForRemote(projectRoot);
399
+ const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
193
400
  return {
194
401
  baseUrl: selected.connection.baseUrl,
195
- authToken: readGitHubBearerTokenForRemote(projectRoot),
196
- connectionKind: "remote"
402
+ authToken,
403
+ connectionKind: "remote",
404
+ serverProjectRoot
197
405
  };
198
406
  }
199
407
  const connection = await ensureLocalRigServerConnection(projectRoot);
200
408
  return {
201
409
  baseUrl: connection.baseUrl,
202
- authToken: connection.authToken,
203
- connectionKind: "local"
410
+ authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
411
+ connectionKind: "local",
412
+ serverProjectRoot: resolve2(projectRoot)
204
413
  };
205
414
  } catch (error) {
206
415
  if (error instanceof Error) {
@@ -209,6 +418,29 @@ async function ensureServerForCli(projectRoot) {
209
418
  throw error;
210
419
  }
211
420
  }
421
+ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken) {
422
+ const repo = readRepoConnection(projectRoot);
423
+ const slug = repo?.project?.trim();
424
+ if (!slug)
425
+ return null;
426
+ try {
427
+ const response = await fetch(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`, {
428
+ headers: mergeHeaders(undefined, authToken)
429
+ });
430
+ if (!response.ok)
431
+ return null;
432
+ const payload = await response.json();
433
+ const project = payload.project && typeof payload.project === "object" && !Array.isArray(payload.project) ? payload.project : null;
434
+ const checkouts = Array.isArray(project?.checkouts) ? project.checkouts : [];
435
+ const latestCheckout = [...checkouts].reverse().find((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry) && typeof entry.path === "string"));
436
+ const path = typeof latestCheckout?.path === "string" && latestCheckout.path.trim() ? latestCheckout.path.trim() : null;
437
+ if (path)
438
+ writeRepoServerProjectRoot(projectRoot, path);
439
+ return path;
440
+ } catch {
441
+ return null;
442
+ }
443
+ }
212
444
  function mergeHeaders(headers, authToken) {
213
445
  const merged = new Headers(headers);
214
446
  if (authToken) {
@@ -233,9 +465,12 @@ function diagnosticMessage(payload) {
233
465
  }
234
466
  async function requestServerJson(context, pathname, init = {}) {
235
467
  const server = await ensureServerForCli(context.projectRoot);
468
+ const headers = mergeHeaders(init.headers, server.authToken);
469
+ if (server.serverProjectRoot)
470
+ headers.set("x-rig-project-root", server.serverProjectRoot);
236
471
  const response = await fetch(`${server.baseUrl}${pathname}`, {
237
472
  ...init,
238
- headers: mergeHeaders(init.headers, server.authToken)
473
+ headers
239
474
  });
240
475
  const text = await response.text();
241
476
  const payload = text.trim().length > 0 ? (() => {
@@ -286,7 +521,10 @@ async function submitTaskRunViaServer(context, input) {
286
521
 
287
522
  // packages/cli/src/commands/server.ts
288
523
  async function executeServer(context, args, options) {
289
- const [command = "start", ...rest] = args;
524
+ const [command = "status", ...rest] = args;
525
+ if (["status", "list", "add", "use"].includes(command)) {
526
+ return executeConnectionCommand(context, [command, ...rest], { group: "server", interactiveUse: true });
527
+ }
290
528
  switch (command) {
291
529
  case "start": {
292
530
  let pending = rest;
@@ -298,8 +536,9 @@ async function executeServer(context, args, options) {
298
536
  pending = pollResult.rest;
299
537
  const authTokenResult = takeOption(pending, "--auth-token");
300
538
  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"];
539
+ requireNoExtraArgs(pending, "rig server start [--host <host>] [--port <n>] [--poll-ms <n>] [--auth-token <token>]");
540
+ const serverCommand = resolveRigServerCommand(context.projectRoot);
541
+ const commandParts = [serverCommand.command, ...serverCommand.commandArgs, "start"];
303
542
  if (hostResult.value) {
304
543
  commandParts.push("--host", hostResult.value);
305
544
  }
@@ -321,8 +560,9 @@ async function executeServer(context, args, options) {
321
560
  let pending = rest;
322
561
  const eventResult = takeOption(pending, "--event");
323
562
  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"];
563
+ requireNoExtraArgs(pending, "rig server notify-test [--event <type>]");
564
+ const serverCommand = resolveRigServerCommand(context.projectRoot);
565
+ const commandParts = [serverCommand.command, ...serverCommand.commandArgs, "notify-test"];
326
566
  if (eventResult.value) {
327
567
  commandParts.push("--event", eventResult.value);
328
568
  }
@@ -349,7 +589,7 @@ async function executeServer(context, args, options) {
349
589
  pending = dirtyBaselineResult.rest;
350
590
  const prResult = takeOption(pending, "--pr");
351
591
  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]");
592
+ 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
593
  if (!taskResult.value && !initialPromptResult.value && !titleResult.value) {
354
594
  throw new CliError2("server task-run requires either --task <id> or --initial-prompt/--title for an ad hoc run.", 2);
355
595
  }