@h-rig/cli 0.0.6-alpha.50 → 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.
package/README.md CHANGED
@@ -21,7 +21,7 @@
21
21
 
22
22
  - CLI behavior should stay thin and delegate business logic into `@rig/runtime`.
23
23
  - `report-bug` uses `@clack/prompts` for its interactive wizard and asks whether Rig Browser is required.
24
- - `report-bug` creates a runnable beads `task` by default, writes committable evidence under `repos/spliter-monorepo/artifacts/<task-id>/bug-report/`, and upserts task-config wiring.
24
+ - `report-bug` creates a runnable beads `task` by default, writes committable evidence under `artifacts/<task-id>/bug-report/` (relative to the resolved monorepo root), and upserts task-config wiring.
25
25
  - `report-bug --no-beads` keeps the old draft-only behavior under `docs/bug-reports/`.
26
26
  - `report-bug --no-browser` skips `browser.json`, the `browser-required` label, browser validation, and browser helper commands while preserving task assets.
27
27
  - `report-bug` accepts drag-and-drop asset values through `--asset` and `--video`; copied files are stored under `bug-report/assets/` and indexed in `manifest.json`.
package/dist/bin/rig.js CHANGED
@@ -2949,6 +2949,20 @@ function readGitHubBearerTokenForRemote(projectRoot) {
2949
2949
  return privateSession;
2950
2950
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
2951
2951
  }
2952
+ function readStoredGitHubAuthToken(projectRoot) {
2953
+ const path = resolve11(projectRoot, ".rig", "state", "github-auth.json");
2954
+ if (!existsSync7(path))
2955
+ return null;
2956
+ try {
2957
+ const parsed = JSON.parse(readFileSync4(path, "utf8"));
2958
+ return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
2959
+ } catch {
2960
+ return null;
2961
+ }
2962
+ }
2963
+ function readLocalConnectionFallbackToken(projectRoot) {
2964
+ return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
2965
+ }
2952
2966
  async function ensureServerForCli(projectRoot) {
2953
2967
  try {
2954
2968
  const selected = resolveSelectedConnection(projectRoot);
@@ -2965,7 +2979,7 @@ async function ensureServerForCli(projectRoot) {
2965
2979
  const connection = await ensureLocalRigServerConnection(projectRoot);
2966
2980
  return {
2967
2981
  baseUrl: connection.baseUrl,
2968
- authToken: connection.authToken,
2982
+ authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
2969
2983
  connectionKind: "local",
2970
2984
  serverProjectRoot: resolve11(projectRoot)
2971
2985
  };
@@ -4778,7 +4792,7 @@ async function executeInbox(context, args) {
4778
4792
  init_runner();
4779
4793
  import { appendFileSync as appendFileSync2, existsSync as existsSync12, mkdirSync as mkdirSync8, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "fs";
4780
4794
  import { spawnSync } from "child_process";
4781
- import { resolve as resolve19 } from "path";
4795
+ import { basename as basename2, resolve as resolve19 } from "path";
4782
4796
  import { buildRigInitConfigSource } from "@rig/core";
4783
4797
  import { listGitHubProjects as listGitHubProjectsDirect, resolveProjectStatusField as resolveProjectStatusFieldDirect } from "@rig/server";
4784
4798
 
@@ -5646,11 +5660,48 @@ async function pollDeviceAuthUntilComplete(context, pollId, firstPayload) {
5646
5660
  } while (Date.now() < deadline);
5647
5661
  return last;
5648
5662
  }
5663
+ function runLocalFilesInit(context, options) {
5664
+ const projectRoot = context.projectRoot;
5665
+ ensureRigPrivateDirs(projectRoot);
5666
+ ensureGitignoreEntries(projectRoot);
5667
+ writeRepoConnection(projectRoot, { selected: "local", linkedAt: new Date().toISOString() });
5668
+ const configTsPath = resolve19(projectRoot, "rig.config.ts");
5669
+ const configExists = existsSync12(configTsPath) || existsSync12(resolve19(projectRoot, "rig.config.json"));
5670
+ if (configExists && !options.repair) {
5671
+ if (context.outputMode !== "json")
5672
+ console.log("rig.config already exists; leaving it unchanged. Pass --repair to rewrite it.");
5673
+ } else {
5674
+ const projectName = basename2(projectRoot) || "rig-project";
5675
+ writeFileSync6(configTsPath, buildRigInitConfigSource({
5676
+ projectName,
5677
+ taskSource: { kind: "files", path: "tasks" },
5678
+ useStandardPlugin: true
5679
+ }), "utf-8");
5680
+ }
5681
+ ensureRigConfigPackageDependencies(projectRoot);
5682
+ const tasksDir = resolve19(projectRoot, "tasks");
5683
+ if (!existsSync12(tasksDir)) {
5684
+ mkdirSync8(tasksDir, { recursive: true });
5685
+ writeFileSync6(resolve19(tasksDir, "T-1.json"), `${JSON.stringify({ id: "T-1", title: "My first Rig task", body: "Describe the change you want an agent to make." }, null, 2)}
5686
+ `, "utf-8");
5687
+ }
5688
+ if (context.outputMode !== "json") {
5689
+ console.log("Initialized a local files-source Rig project (no GitHub).");
5690
+ console.log(" tasks live in tasks/*.json \xB7 server: local");
5691
+ console.log("Next: `rig task list`, then `rig task run T-1`.");
5692
+ console.log("To wire GitHub later: `rig init --repair --repo owner/repo --github-auth gh`.");
5693
+ }
5694
+ return { ok: true, group: "init", command: "init", details: { mode: "local-files", projectRoot, taskSourcePath: "tasks" } };
5695
+ }
5649
5696
  async function runControlPlaneInit(context, options) {
5650
5697
  const projectRoot = context.projectRoot;
5651
5698
  const detectedSlug = options.repoSlug ?? detectOriginRepoSlug(projectRoot);
5652
5699
  if (!detectedSlug) {
5653
- throw new CliError2("Could not detect GitHub repo slug from origin. Pass --repo owner/repo.", 1);
5700
+ const authMethod2 = options.githubAuthMethod ?? (options.githubToken ? "token" : "skip");
5701
+ if ((options.server ?? "local") === "local" && authMethod2 === "skip") {
5702
+ return runLocalFilesInit(context, options);
5703
+ }
5704
+ throw new CliError2("Could not detect GitHub repo slug from origin. Pass --repo owner/repo \u2014 or run `rig init --yes --server local --github-auth skip` for a local files-source project without GitHub.", 1);
5654
5705
  }
5655
5706
  const repo = parseRepoSlug(detectedSlug);
5656
5707
  const serverKind = options.server ?? "local";
@@ -5994,6 +6045,9 @@ Usage: rig init [--server local|remote] [--remote-url <url>] [--repo owner/repo]
5994
6045
  if (parsed.rest.length > 0)
5995
6046
  throw new CliError2(`Unexpected arguments: ${parsed.rest.join(" ")}
5996
6047
  Usage: rig init`, 1);
6048
+ if (!process.stdin.isTTY) {
6049
+ throw new CliError2("rig init is interactive and needs a terminal. For scripts, pass flags: rig init --yes --server local --github-auth skip [--repo owner/repo].", 1);
6050
+ }
5997
6051
  return runInteractiveControlPlaneInit(context, await loadClackPrompts());
5998
6052
  }
5999
6053
 
@@ -12275,7 +12329,7 @@ async function executeGroup(context, group, args) {
12275
12329
  }
12276
12330
  // packages/cli/src/launcher.ts
12277
12331
  import { existsSync as existsSync17 } from "fs";
12278
- import { basename as basename2, resolve as resolve26 } from "path";
12332
+ import { basename as basename3, resolve as resolve26 } from "path";
12279
12333
  import { loadDotEnvSecrets } from "@rig/runtime/baked-secrets";
12280
12334
  import { RIG_DEFINITION_DIRNAME, RIG_STATE_DIRNAME, resolveNearestRigProjectRoot } from "@rig/runtime/layout";
12281
12335
  function parsePolicyMode(value) {
@@ -12300,7 +12354,7 @@ function resolveProjectRoot({
12300
12354
  return resolve26(cwd, envProjectRoot);
12301
12355
  }
12302
12356
  const fallbackImportDir = importDir ?? cwd;
12303
- const execName = basename2(execPath).toLowerCase();
12357
+ const execName = basename3(execPath).toLowerCase();
12304
12358
  const execCandidates = execName === "rig" || execName === "rig.exe" ? [resolve26(execPath, "..", "..")] : [];
12305
12359
  const candidates = [cwd, ...execCandidates, resolve26(fallbackImportDir, "..")];
12306
12360
  for (const candidate of candidates) {
@@ -141,6 +141,20 @@ function readGitHubBearerTokenForRemote(projectRoot) {
141
141
  return privateSession;
142
142
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
143
143
  }
144
+ function readStoredGitHubAuthToken(projectRoot) {
145
+ const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
146
+ if (!existsSync2(path))
147
+ return null;
148
+ try {
149
+ const parsed = JSON.parse(readFileSync2(path, "utf8"));
150
+ return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
151
+ } catch {
152
+ return null;
153
+ }
154
+ }
155
+ function readLocalConnectionFallbackToken(projectRoot) {
156
+ return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
157
+ }
144
158
  async function ensureServerForCli(projectRoot) {
145
159
  try {
146
160
  const selected = resolveSelectedConnection(projectRoot);
@@ -157,7 +171,7 @@ async function ensureServerForCli(projectRoot) {
157
171
  const connection = await ensureLocalRigServerConnection(projectRoot);
158
172
  return {
159
173
  baseUrl: connection.baseUrl,
160
- authToken: connection.authToken,
174
+ authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
161
175
  connectionKind: "local",
162
176
  serverProjectRoot: resolve2(projectRoot)
163
177
  };
@@ -136,6 +136,20 @@ function readGitHubBearerTokenForRemote(projectRoot) {
136
136
  return privateSession;
137
137
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
138
138
  }
139
+ function readStoredGitHubAuthToken(projectRoot) {
140
+ const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
141
+ if (!existsSync2(path))
142
+ return null;
143
+ try {
144
+ const parsed = JSON.parse(readFileSync2(path, "utf8"));
145
+ return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
146
+ } catch {
147
+ return null;
148
+ }
149
+ }
150
+ function readLocalConnectionFallbackToken(projectRoot) {
151
+ return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
152
+ }
139
153
  async function ensureServerForCli(projectRoot) {
140
154
  try {
141
155
  const selected = resolveSelectedConnection(projectRoot);
@@ -152,7 +166,7 @@ async function ensureServerForCli(projectRoot) {
152
166
  const connection = await ensureLocalRigServerConnection(projectRoot);
153
167
  return {
154
168
  baseUrl: connection.baseUrl,
155
- authToken: connection.authToken,
169
+ authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
156
170
  connectionKind: "local",
157
171
  serverProjectRoot: resolve2(projectRoot)
158
172
  };
@@ -146,6 +146,20 @@ function readGitHubBearerTokenForRemote(projectRoot) {
146
146
  return privateSession;
147
147
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
148
148
  }
149
+ function readStoredGitHubAuthToken(projectRoot) {
150
+ const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
151
+ if (!existsSync2(path))
152
+ return null;
153
+ try {
154
+ const parsed = JSON.parse(readFileSync2(path, "utf8"));
155
+ return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
156
+ } catch {
157
+ return null;
158
+ }
159
+ }
160
+ function readLocalConnectionFallbackToken(projectRoot) {
161
+ return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
162
+ }
149
163
  async function ensureServerForCli(projectRoot) {
150
164
  try {
151
165
  const selected = resolveSelectedConnection(projectRoot);
@@ -162,7 +176,7 @@ async function ensureServerForCli(projectRoot) {
162
176
  const connection = await ensureLocalRigServerConnection(projectRoot);
163
177
  return {
164
178
  baseUrl: connection.baseUrl,
165
- authToken: connection.authToken,
179
+ authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
166
180
  connectionKind: "local",
167
181
  serverProjectRoot: resolve2(projectRoot)
168
182
  };
@@ -139,6 +139,20 @@ function readGitHubBearerTokenForRemote(projectRoot) {
139
139
  return privateSession;
140
140
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
141
141
  }
142
+ function readStoredGitHubAuthToken(projectRoot) {
143
+ const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
144
+ if (!existsSync2(path))
145
+ return null;
146
+ try {
147
+ const parsed = JSON.parse(readFileSync2(path, "utf8"));
148
+ return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
149
+ } catch {
150
+ return null;
151
+ }
152
+ }
153
+ function readLocalConnectionFallbackToken(projectRoot) {
154
+ return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
155
+ }
142
156
  async function ensureServerForCli(projectRoot) {
143
157
  try {
144
158
  const selected = resolveSelectedConnection(projectRoot);
@@ -155,7 +169,7 @@ async function ensureServerForCli(projectRoot) {
155
169
  const connection = await ensureLocalRigServerConnection(projectRoot);
156
170
  return {
157
171
  baseUrl: connection.baseUrl,
158
- authToken: connection.authToken,
172
+ authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
159
173
  connectionKind: "local",
160
174
  serverProjectRoot: resolve2(projectRoot)
161
175
  };
@@ -136,6 +136,20 @@ function readGitHubBearerTokenForRemote(projectRoot) {
136
136
  return privateSession;
137
137
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
138
138
  }
139
+ function readStoredGitHubAuthToken(projectRoot) {
140
+ const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
141
+ if (!existsSync2(path))
142
+ return null;
143
+ try {
144
+ const parsed = JSON.parse(readFileSync2(path, "utf8"));
145
+ return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
146
+ } catch {
147
+ return null;
148
+ }
149
+ }
150
+ function readLocalConnectionFallbackToken(projectRoot) {
151
+ return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
152
+ }
139
153
  async function ensureServerForCli(projectRoot) {
140
154
  try {
141
155
  const selected = resolveSelectedConnection(projectRoot);
@@ -152,7 +166,7 @@ async function ensureServerForCli(projectRoot) {
152
166
  const connection = await ensureLocalRigServerConnection(projectRoot);
153
167
  return {
154
168
  baseUrl: connection.baseUrl,
155
- authToken: connection.authToken,
169
+ authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
156
170
  connectionKind: "local",
157
171
  serverProjectRoot: resolve2(projectRoot)
158
172
  };
@@ -135,6 +135,20 @@ function readGitHubBearerTokenForRemote(projectRoot) {
135
135
  return privateSession;
136
136
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
137
137
  }
138
+ function readStoredGitHubAuthToken(projectRoot) {
139
+ const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
140
+ if (!existsSync2(path))
141
+ return null;
142
+ try {
143
+ const parsed = JSON.parse(readFileSync2(path, "utf8"));
144
+ return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
145
+ } catch {
146
+ return null;
147
+ }
148
+ }
149
+ function readLocalConnectionFallbackToken(projectRoot) {
150
+ return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
151
+ }
138
152
  async function ensureServerForCli(projectRoot) {
139
153
  try {
140
154
  const selected = resolveSelectedConnection(projectRoot);
@@ -151,7 +165,7 @@ async function ensureServerForCli(projectRoot) {
151
165
  const connection = await ensureLocalRigServerConnection(projectRoot);
152
166
  return {
153
167
  baseUrl: connection.baseUrl,
154
- authToken: connection.authToken,
168
+ authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
155
169
  connectionKind: "local",
156
170
  serverProjectRoot: resolve2(projectRoot)
157
171
  };
@@ -140,6 +140,20 @@ function readGitHubBearerTokenForRemote(projectRoot) {
140
140
  return privateSession;
141
141
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
142
142
  }
143
+ function readStoredGitHubAuthToken(projectRoot) {
144
+ const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
145
+ if (!existsSync2(path))
146
+ return null;
147
+ try {
148
+ const parsed = JSON.parse(readFileSync2(path, "utf8"));
149
+ return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
150
+ } catch {
151
+ return null;
152
+ }
153
+ }
154
+ function readLocalConnectionFallbackToken(projectRoot) {
155
+ return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
156
+ }
143
157
  async function ensureServerForCli(projectRoot) {
144
158
  try {
145
159
  const selected = resolveSelectedConnection(projectRoot);
@@ -156,7 +170,7 @@ async function ensureServerForCli(projectRoot) {
156
170
  const connection = await ensureLocalRigServerConnection(projectRoot);
157
171
  return {
158
172
  baseUrl: connection.baseUrl,
159
- authToken: connection.authToken,
173
+ authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
160
174
  connectionKind: "local",
161
175
  serverProjectRoot: resolve2(projectRoot)
162
176
  };
@@ -140,6 +140,20 @@ function readGitHubBearerTokenForRemote(projectRoot) {
140
140
  return privateSession;
141
141
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
142
142
  }
143
+ function readStoredGitHubAuthToken(projectRoot) {
144
+ const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
145
+ if (!existsSync2(path))
146
+ return null;
147
+ try {
148
+ const parsed = JSON.parse(readFileSync2(path, "utf8"));
149
+ return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
150
+ } catch {
151
+ return null;
152
+ }
153
+ }
154
+ function readLocalConnectionFallbackToken(projectRoot) {
155
+ return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
156
+ }
143
157
  async function ensureServerForCli(projectRoot) {
144
158
  try {
145
159
  const selected = resolveSelectedConnection(projectRoot);
@@ -156,7 +170,7 @@ async function ensureServerForCli(projectRoot) {
156
170
  const connection = await ensureLocalRigServerConnection(projectRoot);
157
171
  return {
158
172
  baseUrl: connection.baseUrl,
159
- authToken: connection.authToken,
173
+ authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
160
174
  connectionKind: "local",
161
175
  serverProjectRoot: resolve2(projectRoot)
162
176
  };
@@ -145,6 +145,20 @@ function readGitHubBearerTokenForRemote(projectRoot) {
145
145
  return privateSession;
146
146
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
147
147
  }
148
+ function readStoredGitHubAuthToken(projectRoot) {
149
+ const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
150
+ if (!existsSync2(path))
151
+ return null;
152
+ try {
153
+ const parsed = JSON.parse(readFileSync2(path, "utf8"));
154
+ return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
155
+ } catch {
156
+ return null;
157
+ }
158
+ }
159
+ function readLocalConnectionFallbackToken(projectRoot) {
160
+ return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
161
+ }
148
162
  async function ensureServerForCli(projectRoot) {
149
163
  try {
150
164
  const selected = resolveSelectedConnection(projectRoot);
@@ -161,7 +175,7 @@ async function ensureServerForCli(projectRoot) {
161
175
  const connection = await ensureLocalRigServerConnection(projectRoot);
162
176
  return {
163
177
  baseUrl: connection.baseUrl,
164
- authToken: connection.authToken,
178
+ authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
165
179
  connectionKind: "local",
166
180
  serverProjectRoot: resolve2(projectRoot)
167
181
  };
@@ -157,6 +157,20 @@ function readGitHubBearerTokenForRemote(projectRoot) {
157
157
  return privateSession;
158
158
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
159
159
  }
160
+ function readStoredGitHubAuthToken(projectRoot) {
161
+ const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
162
+ if (!existsSync2(path))
163
+ return null;
164
+ try {
165
+ const parsed = JSON.parse(readFileSync2(path, "utf8"));
166
+ return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
167
+ } catch {
168
+ return null;
169
+ }
170
+ }
171
+ function readLocalConnectionFallbackToken(projectRoot) {
172
+ return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
173
+ }
160
174
  async function ensureServerForCli(projectRoot) {
161
175
  try {
162
176
  const selected = resolveSelectedConnection(projectRoot);
@@ -173,7 +187,7 @@ async function ensureServerForCli(projectRoot) {
173
187
  const connection = await ensureLocalRigServerConnection(projectRoot);
174
188
  return {
175
189
  baseUrl: connection.baseUrl,
176
- authToken: connection.authToken,
190
+ authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
177
191
  connectionKind: "local",
178
192
  serverProjectRoot: resolve2(projectRoot)
179
193
  };
@@ -251,6 +251,20 @@ function readGitHubBearerTokenForRemote(projectRoot) {
251
251
  return privateSession;
252
252
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
253
253
  }
254
+ function readStoredGitHubAuthToken(projectRoot) {
255
+ const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
256
+ if (!existsSync2(path))
257
+ return null;
258
+ try {
259
+ const parsed = JSON.parse(readFileSync2(path, "utf8"));
260
+ return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
261
+ } catch {
262
+ return null;
263
+ }
264
+ }
265
+ function readLocalConnectionFallbackToken(projectRoot) {
266
+ return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
267
+ }
254
268
  async function ensureServerForCli(projectRoot) {
255
269
  try {
256
270
  const selected = resolveSelectedConnection(projectRoot);
@@ -267,7 +281,7 @@ async function ensureServerForCli(projectRoot) {
267
281
  const connection = await ensureLocalRigServerConnection(projectRoot);
268
282
  return {
269
283
  baseUrl: connection.baseUrl,
270
- authToken: connection.authToken,
284
+ authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
271
285
  connectionKind: "local",
272
286
  serverProjectRoot: resolve2(projectRoot)
273
287
  };
@@ -4,7 +4,7 @@ var __require = import.meta.require;
4
4
  // packages/cli/src/commands/init.ts
5
5
  import { appendFileSync, existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync5, writeFileSync as writeFileSync2 } from "fs";
6
6
  import { spawnSync } from "child_process";
7
- import { resolve as resolve6 } from "path";
7
+ import { basename, resolve as resolve6 } from "path";
8
8
 
9
9
  // packages/cli/src/runner.ts
10
10
  import { EventBus } from "@rig/runtime/control-plane/runtime/events";
@@ -191,6 +191,20 @@ function readGitHubBearerTokenForRemote(projectRoot) {
191
191
  return privateSession;
192
192
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
193
193
  }
194
+ function readStoredGitHubAuthToken(projectRoot) {
195
+ const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
196
+ if (!existsSync2(path))
197
+ return null;
198
+ try {
199
+ const parsed = JSON.parse(readFileSync2(path, "utf8"));
200
+ return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
201
+ } catch {
202
+ return null;
203
+ }
204
+ }
205
+ function readLocalConnectionFallbackToken(projectRoot) {
206
+ return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
207
+ }
194
208
  async function ensureServerForCli(projectRoot) {
195
209
  try {
196
210
  const selected = resolveSelectedConnection(projectRoot);
@@ -207,7 +221,7 @@ async function ensureServerForCli(projectRoot) {
207
221
  const connection = await ensureLocalRigServerConnection(projectRoot);
208
222
  return {
209
223
  baseUrl: connection.baseUrl,
210
- authToken: connection.authToken,
224
+ authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
211
225
  connectionKind: "local",
212
226
  serverProjectRoot: resolve2(projectRoot)
213
227
  };
@@ -1231,11 +1245,48 @@ async function pollDeviceAuthUntilComplete(context, pollId, firstPayload) {
1231
1245
  } while (Date.now() < deadline);
1232
1246
  return last;
1233
1247
  }
1248
+ function runLocalFilesInit(context, options) {
1249
+ const projectRoot = context.projectRoot;
1250
+ ensureRigPrivateDirs(projectRoot);
1251
+ ensureGitignoreEntries(projectRoot);
1252
+ writeRepoConnection(projectRoot, { selected: "local", linkedAt: new Date().toISOString() });
1253
+ const configTsPath = resolve6(projectRoot, "rig.config.ts");
1254
+ const configExists = existsSync5(configTsPath) || existsSync5(resolve6(projectRoot, "rig.config.json"));
1255
+ if (configExists && !options.repair) {
1256
+ if (context.outputMode !== "json")
1257
+ console.log("rig.config already exists; leaving it unchanged. Pass --repair to rewrite it.");
1258
+ } else {
1259
+ const projectName = basename(projectRoot) || "rig-project";
1260
+ writeFileSync2(configTsPath, buildRigInitConfigSource({
1261
+ projectName,
1262
+ taskSource: { kind: "files", path: "tasks" },
1263
+ useStandardPlugin: true
1264
+ }), "utf-8");
1265
+ }
1266
+ ensureRigConfigPackageDependencies(projectRoot);
1267
+ const tasksDir = resolve6(projectRoot, "tasks");
1268
+ if (!existsSync5(tasksDir)) {
1269
+ mkdirSync2(tasksDir, { recursive: true });
1270
+ writeFileSync2(resolve6(tasksDir, "T-1.json"), `${JSON.stringify({ id: "T-1", title: "My first Rig task", body: "Describe the change you want an agent to make." }, null, 2)}
1271
+ `, "utf-8");
1272
+ }
1273
+ if (context.outputMode !== "json") {
1274
+ console.log("Initialized a local files-source Rig project (no GitHub).");
1275
+ console.log(" tasks live in tasks/*.json \xB7 server: local");
1276
+ console.log("Next: `rig task list`, then `rig task run T-1`.");
1277
+ console.log("To wire GitHub later: `rig init --repair --repo owner/repo --github-auth gh`.");
1278
+ }
1279
+ return { ok: true, group: "init", command: "init", details: { mode: "local-files", projectRoot, taskSourcePath: "tasks" } };
1280
+ }
1234
1281
  async function runControlPlaneInit(context, options) {
1235
1282
  const projectRoot = context.projectRoot;
1236
1283
  const detectedSlug = options.repoSlug ?? detectOriginRepoSlug(projectRoot);
1237
1284
  if (!detectedSlug) {
1238
- throw new CliError2("Could not detect GitHub repo slug from origin. Pass --repo owner/repo.", 1);
1285
+ const authMethod2 = options.githubAuthMethod ?? (options.githubToken ? "token" : "skip");
1286
+ if ((options.server ?? "local") === "local" && authMethod2 === "skip") {
1287
+ return runLocalFilesInit(context, options);
1288
+ }
1289
+ throw new CliError2("Could not detect GitHub repo slug from origin. Pass --repo owner/repo \u2014 or run `rig init --yes --server local --github-auth skip` for a local files-source project without GitHub.", 1);
1239
1290
  }
1240
1291
  const repo = parseRepoSlug(detectedSlug);
1241
1292
  const serverKind = options.server ?? "local";
@@ -1579,6 +1630,9 @@ Usage: rig init [--server local|remote] [--remote-url <url>] [--repo owner/repo]
1579
1630
  if (parsed.rest.length > 0)
1580
1631
  throw new CliError2(`Unexpected arguments: ${parsed.rest.join(" ")}
1581
1632
  Usage: rig init`, 1);
1633
+ if (!process.stdin.isTTY) {
1634
+ throw new CliError2("rig init is interactive and needs a terminal. For scripts, pass flags: rig init --yes --server local --github-auth skip [--repo owner/repo].", 1);
1635
+ }
1582
1636
  return runInteractiveControlPlaneInit(context, await loadClackPrompts());
1583
1637
  }
1584
1638
  export {
@@ -182,6 +182,20 @@ function readGitHubBearerTokenForRemote(projectRoot) {
182
182
  return privateSession;
183
183
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
184
184
  }
185
+ function readStoredGitHubAuthToken(projectRoot) {
186
+ const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
187
+ if (!existsSync2(path))
188
+ return null;
189
+ try {
190
+ const parsed = JSON.parse(readFileSync2(path, "utf8"));
191
+ return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
192
+ } catch {
193
+ return null;
194
+ }
195
+ }
196
+ function readLocalConnectionFallbackToken(projectRoot) {
197
+ return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
198
+ }
185
199
  async function ensureServerForCli(projectRoot) {
186
200
  try {
187
201
  const selected = resolveSelectedConnection(projectRoot);
@@ -198,7 +212,7 @@ async function ensureServerForCli(projectRoot) {
198
212
  const connection = await ensureLocalRigServerConnection(projectRoot);
199
213
  return {
200
214
  baseUrl: connection.baseUrl,
201
- authToken: connection.authToken,
215
+ authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
202
216
  connectionKind: "local",
203
217
  serverProjectRoot: resolve2(projectRoot)
204
218
  };
@@ -206,6 +206,20 @@ function readGitHubBearerTokenForRemote(projectRoot) {
206
206
  return privateSession;
207
207
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
208
208
  }
209
+ function readStoredGitHubAuthToken(projectRoot) {
210
+ const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
211
+ if (!existsSync2(path))
212
+ return null;
213
+ try {
214
+ const parsed = JSON.parse(readFileSync2(path, "utf8"));
215
+ return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
216
+ } catch {
217
+ return null;
218
+ }
219
+ }
220
+ function readLocalConnectionFallbackToken(projectRoot) {
221
+ return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
222
+ }
209
223
  async function ensureServerForCli(projectRoot) {
210
224
  try {
211
225
  const selected = resolveSelectedConnection(projectRoot);
@@ -222,7 +236,7 @@ async function ensureServerForCli(projectRoot) {
222
236
  const connection = await ensureLocalRigServerConnection(projectRoot);
223
237
  return {
224
238
  baseUrl: connection.baseUrl,
225
- authToken: connection.authToken,
239
+ authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
226
240
  connectionKind: "local",
227
241
  serverProjectRoot: resolve2(projectRoot)
228
242
  };
@@ -377,6 +377,20 @@ function readGitHubBearerTokenForRemote(projectRoot) {
377
377
  return privateSession;
378
378
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
379
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;
389
+ }
390
+ }
391
+ function readLocalConnectionFallbackToken(projectRoot) {
392
+ return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
393
+ }
380
394
  async function ensureServerForCli(projectRoot) {
381
395
  try {
382
396
  const selected = resolveSelectedConnection(projectRoot);
@@ -393,7 +407,7 @@ async function ensureServerForCli(projectRoot) {
393
407
  const connection = await ensureLocalRigServerConnection(projectRoot);
394
408
  return {
395
409
  baseUrl: connection.baseUrl,
396
- authToken: connection.authToken,
410
+ authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
397
411
  connectionKind: "local",
398
412
  serverProjectRoot: resolve2(projectRoot)
399
413
  };
@@ -300,6 +300,20 @@ function readGitHubBearerTokenForRemote(projectRoot) {
300
300
  return privateSession;
301
301
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
302
302
  }
303
+ function readStoredGitHubAuthToken(projectRoot) {
304
+ const path = resolve4(projectRoot, ".rig", "state", "github-auth.json");
305
+ if (!existsSync3(path))
306
+ return null;
307
+ try {
308
+ const parsed = JSON.parse(readFileSync3(path, "utf8"));
309
+ return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
310
+ } catch {
311
+ return null;
312
+ }
313
+ }
314
+ function readLocalConnectionFallbackToken(projectRoot) {
315
+ return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
316
+ }
303
317
  async function ensureServerForCli(projectRoot) {
304
318
  try {
305
319
  const selected = resolveSelectedConnection(projectRoot);
@@ -316,7 +330,7 @@ async function ensureServerForCli(projectRoot) {
316
330
  const connection = await ensureLocalRigServerConnection(projectRoot);
317
331
  return {
318
332
  baseUrl: connection.baseUrl,
319
- authToken: connection.authToken,
333
+ authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
320
334
  connectionKind: "local",
321
335
  serverProjectRoot: resolve4(projectRoot)
322
336
  };
@@ -516,6 +516,20 @@ function readGitHubBearerTokenForRemote(projectRoot) {
516
516
  return privateSession;
517
517
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
518
518
  }
519
+ function readStoredGitHubAuthToken(projectRoot) {
520
+ const path = resolve5(projectRoot, ".rig", "state", "github-auth.json");
521
+ if (!existsSync3(path))
522
+ return null;
523
+ try {
524
+ const parsed = JSON.parse(readFileSync3(path, "utf8"));
525
+ return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
526
+ } catch {
527
+ return null;
528
+ }
529
+ }
530
+ function readLocalConnectionFallbackToken(projectRoot) {
531
+ return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
532
+ }
519
533
  async function ensureServerForCli(projectRoot) {
520
534
  try {
521
535
  const selected = resolveSelectedConnection(projectRoot);
@@ -532,7 +546,7 @@ async function ensureServerForCli(projectRoot) {
532
546
  const connection = await ensureLocalRigServerConnection(projectRoot);
533
547
  return {
534
548
  baseUrl: connection.baseUrl,
535
- authToken: connection.authToken,
549
+ authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
536
550
  connectionKind: "local",
537
551
  serverProjectRoot: resolve5(projectRoot)
538
552
  };
@@ -229,6 +229,20 @@ function readGitHubBearerTokenForRemote(projectRoot) {
229
229
  return privateSession;
230
230
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
231
231
  }
232
+ function readStoredGitHubAuthToken(projectRoot) {
233
+ const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
234
+ if (!existsSync2(path))
235
+ return null;
236
+ try {
237
+ const parsed = JSON.parse(readFileSync2(path, "utf8"));
238
+ return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
239
+ } catch {
240
+ return null;
241
+ }
242
+ }
243
+ function readLocalConnectionFallbackToken(projectRoot) {
244
+ return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
245
+ }
232
246
  async function ensureServerForCli(projectRoot) {
233
247
  try {
234
248
  const selected = resolveSelectedConnection(projectRoot);
@@ -245,7 +259,7 @@ async function ensureServerForCli(projectRoot) {
245
259
  const connection = await ensureLocalRigServerConnection(projectRoot);
246
260
  return {
247
261
  baseUrl: connection.baseUrl,
248
- authToken: connection.authToken,
262
+ authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
249
263
  connectionKind: "local",
250
264
  serverProjectRoot: resolve2(projectRoot)
251
265
  };
@@ -2755,6 +2755,20 @@ function readGitHubBearerTokenForRemote(projectRoot) {
2755
2755
  return privateSession;
2756
2756
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
2757
2757
  }
2758
+ function readStoredGitHubAuthToken(projectRoot) {
2759
+ const path = resolve10(projectRoot, ".rig", "state", "github-auth.json");
2760
+ if (!existsSync6(path))
2761
+ return null;
2762
+ try {
2763
+ const parsed = JSON.parse(readFileSync4(path, "utf8"));
2764
+ return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
2765
+ } catch {
2766
+ return null;
2767
+ }
2768
+ }
2769
+ function readLocalConnectionFallbackToken(projectRoot) {
2770
+ return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
2771
+ }
2758
2772
  async function ensureServerForCli(projectRoot) {
2759
2773
  try {
2760
2774
  const selected = resolveSelectedConnection(projectRoot);
@@ -2771,7 +2785,7 @@ async function ensureServerForCli(projectRoot) {
2771
2785
  const connection = await ensureLocalRigServerConnection(projectRoot);
2772
2786
  return {
2773
2787
  baseUrl: connection.baseUrl,
2774
- authToken: connection.authToken,
2788
+ authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
2775
2789
  connectionKind: "local",
2776
2790
  serverProjectRoot: resolve10(projectRoot)
2777
2791
  };
@@ -4584,7 +4598,7 @@ async function executeInbox(context, args) {
4584
4598
  init_runner();
4585
4599
  import { appendFileSync as appendFileSync2, existsSync as existsSync11, mkdirSync as mkdirSync7, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "fs";
4586
4600
  import { spawnSync } from "child_process";
4587
- import { resolve as resolve18 } from "path";
4601
+ import { basename as basename2, resolve as resolve18 } from "path";
4588
4602
  import { buildRigInitConfigSource } from "@rig/core";
4589
4603
  import { listGitHubProjects as listGitHubProjectsDirect, resolveProjectStatusField as resolveProjectStatusFieldDirect } from "@rig/server";
4590
4604
 
@@ -5452,11 +5466,48 @@ async function pollDeviceAuthUntilComplete(context, pollId, firstPayload) {
5452
5466
  } while (Date.now() < deadline);
5453
5467
  return last;
5454
5468
  }
5469
+ function runLocalFilesInit(context, options) {
5470
+ const projectRoot = context.projectRoot;
5471
+ ensureRigPrivateDirs(projectRoot);
5472
+ ensureGitignoreEntries(projectRoot);
5473
+ writeRepoConnection(projectRoot, { selected: "local", linkedAt: new Date().toISOString() });
5474
+ const configTsPath = resolve18(projectRoot, "rig.config.ts");
5475
+ const configExists = existsSync11(configTsPath) || existsSync11(resolve18(projectRoot, "rig.config.json"));
5476
+ if (configExists && !options.repair) {
5477
+ if (context.outputMode !== "json")
5478
+ console.log("rig.config already exists; leaving it unchanged. Pass --repair to rewrite it.");
5479
+ } else {
5480
+ const projectName = basename2(projectRoot) || "rig-project";
5481
+ writeFileSync6(configTsPath, buildRigInitConfigSource({
5482
+ projectName,
5483
+ taskSource: { kind: "files", path: "tasks" },
5484
+ useStandardPlugin: true
5485
+ }), "utf-8");
5486
+ }
5487
+ ensureRigConfigPackageDependencies(projectRoot);
5488
+ const tasksDir = resolve18(projectRoot, "tasks");
5489
+ if (!existsSync11(tasksDir)) {
5490
+ mkdirSync7(tasksDir, { recursive: true });
5491
+ writeFileSync6(resolve18(tasksDir, "T-1.json"), `${JSON.stringify({ id: "T-1", title: "My first Rig task", body: "Describe the change you want an agent to make." }, null, 2)}
5492
+ `, "utf-8");
5493
+ }
5494
+ if (context.outputMode !== "json") {
5495
+ console.log("Initialized a local files-source Rig project (no GitHub).");
5496
+ console.log(" tasks live in tasks/*.json \xB7 server: local");
5497
+ console.log("Next: `rig task list`, then `rig task run T-1`.");
5498
+ console.log("To wire GitHub later: `rig init --repair --repo owner/repo --github-auth gh`.");
5499
+ }
5500
+ return { ok: true, group: "init", command: "init", details: { mode: "local-files", projectRoot, taskSourcePath: "tasks" } };
5501
+ }
5455
5502
  async function runControlPlaneInit(context, options) {
5456
5503
  const projectRoot = context.projectRoot;
5457
5504
  const detectedSlug = options.repoSlug ?? detectOriginRepoSlug(projectRoot);
5458
5505
  if (!detectedSlug) {
5459
- throw new CliError2("Could not detect GitHub repo slug from origin. Pass --repo owner/repo.", 1);
5506
+ const authMethod2 = options.githubAuthMethod ?? (options.githubToken ? "token" : "skip");
5507
+ if ((options.server ?? "local") === "local" && authMethod2 === "skip") {
5508
+ return runLocalFilesInit(context, options);
5509
+ }
5510
+ throw new CliError2("Could not detect GitHub repo slug from origin. Pass --repo owner/repo \u2014 or run `rig init --yes --server local --github-auth skip` for a local files-source project without GitHub.", 1);
5460
5511
  }
5461
5512
  const repo = parseRepoSlug(detectedSlug);
5462
5513
  const serverKind = options.server ?? "local";
@@ -5800,6 +5851,9 @@ Usage: rig init [--server local|remote] [--remote-url <url>] [--repo owner/repo]
5800
5851
  if (parsed.rest.length > 0)
5801
5852
  throw new CliError2(`Unexpected arguments: ${parsed.rest.join(" ")}
5802
5853
  Usage: rig init`, 1);
5854
+ if (!process.stdin.isTTY) {
5855
+ throw new CliError2("rig init is interactive and needs a terminal. For scripts, pass flags: rig init --yes --server local --github-auth skip [--repo owner/repo].", 1);
5856
+ }
5803
5857
  return runInteractiveControlPlaneInit(context, await loadClackPrompts());
5804
5858
  }
5805
5859
 
package/dist/src/index.js CHANGED
@@ -2945,6 +2945,20 @@ function readGitHubBearerTokenForRemote(projectRoot) {
2945
2945
  return privateSession;
2946
2946
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
2947
2947
  }
2948
+ function readStoredGitHubAuthToken(projectRoot) {
2949
+ const path = resolve11(projectRoot, ".rig", "state", "github-auth.json");
2950
+ if (!existsSync7(path))
2951
+ return null;
2952
+ try {
2953
+ const parsed = JSON.parse(readFileSync4(path, "utf8"));
2954
+ return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
2955
+ } catch {
2956
+ return null;
2957
+ }
2958
+ }
2959
+ function readLocalConnectionFallbackToken(projectRoot) {
2960
+ return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
2961
+ }
2948
2962
  async function ensureServerForCli(projectRoot) {
2949
2963
  try {
2950
2964
  const selected = resolveSelectedConnection(projectRoot);
@@ -2961,7 +2975,7 @@ async function ensureServerForCli(projectRoot) {
2961
2975
  const connection = await ensureLocalRigServerConnection(projectRoot);
2962
2976
  return {
2963
2977
  baseUrl: connection.baseUrl,
2964
- authToken: connection.authToken,
2978
+ authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
2965
2979
  connectionKind: "local",
2966
2980
  serverProjectRoot: resolve11(projectRoot)
2967
2981
  };
@@ -4774,7 +4788,7 @@ async function executeInbox(context, args) {
4774
4788
  init_runner();
4775
4789
  import { appendFileSync as appendFileSync2, existsSync as existsSync12, mkdirSync as mkdirSync8, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "fs";
4776
4790
  import { spawnSync } from "child_process";
4777
- import { resolve as resolve19 } from "path";
4791
+ import { basename as basename2, resolve as resolve19 } from "path";
4778
4792
  import { buildRigInitConfigSource } from "@rig/core";
4779
4793
  import { listGitHubProjects as listGitHubProjectsDirect, resolveProjectStatusField as resolveProjectStatusFieldDirect } from "@rig/server";
4780
4794
 
@@ -5642,11 +5656,48 @@ async function pollDeviceAuthUntilComplete(context, pollId, firstPayload) {
5642
5656
  } while (Date.now() < deadline);
5643
5657
  return last;
5644
5658
  }
5659
+ function runLocalFilesInit(context, options) {
5660
+ const projectRoot = context.projectRoot;
5661
+ ensureRigPrivateDirs(projectRoot);
5662
+ ensureGitignoreEntries(projectRoot);
5663
+ writeRepoConnection(projectRoot, { selected: "local", linkedAt: new Date().toISOString() });
5664
+ const configTsPath = resolve19(projectRoot, "rig.config.ts");
5665
+ const configExists = existsSync12(configTsPath) || existsSync12(resolve19(projectRoot, "rig.config.json"));
5666
+ if (configExists && !options.repair) {
5667
+ if (context.outputMode !== "json")
5668
+ console.log("rig.config already exists; leaving it unchanged. Pass --repair to rewrite it.");
5669
+ } else {
5670
+ const projectName = basename2(projectRoot) || "rig-project";
5671
+ writeFileSync6(configTsPath, buildRigInitConfigSource({
5672
+ projectName,
5673
+ taskSource: { kind: "files", path: "tasks" },
5674
+ useStandardPlugin: true
5675
+ }), "utf-8");
5676
+ }
5677
+ ensureRigConfigPackageDependencies(projectRoot);
5678
+ const tasksDir = resolve19(projectRoot, "tasks");
5679
+ if (!existsSync12(tasksDir)) {
5680
+ mkdirSync8(tasksDir, { recursive: true });
5681
+ writeFileSync6(resolve19(tasksDir, "T-1.json"), `${JSON.stringify({ id: "T-1", title: "My first Rig task", body: "Describe the change you want an agent to make." }, null, 2)}
5682
+ `, "utf-8");
5683
+ }
5684
+ if (context.outputMode !== "json") {
5685
+ console.log("Initialized a local files-source Rig project (no GitHub).");
5686
+ console.log(" tasks live in tasks/*.json \xB7 server: local");
5687
+ console.log("Next: `rig task list`, then `rig task run T-1`.");
5688
+ console.log("To wire GitHub later: `rig init --repair --repo owner/repo --github-auth gh`.");
5689
+ }
5690
+ return { ok: true, group: "init", command: "init", details: { mode: "local-files", projectRoot, taskSourcePath: "tasks" } };
5691
+ }
5645
5692
  async function runControlPlaneInit(context, options) {
5646
5693
  const projectRoot = context.projectRoot;
5647
5694
  const detectedSlug = options.repoSlug ?? detectOriginRepoSlug(projectRoot);
5648
5695
  if (!detectedSlug) {
5649
- throw new CliError2("Could not detect GitHub repo slug from origin. Pass --repo owner/repo.", 1);
5696
+ const authMethod2 = options.githubAuthMethod ?? (options.githubToken ? "token" : "skip");
5697
+ if ((options.server ?? "local") === "local" && authMethod2 === "skip") {
5698
+ return runLocalFilesInit(context, options);
5699
+ }
5700
+ throw new CliError2("Could not detect GitHub repo slug from origin. Pass --repo owner/repo \u2014 or run `rig init --yes --server local --github-auth skip` for a local files-source project without GitHub.", 1);
5650
5701
  }
5651
5702
  const repo = parseRepoSlug(detectedSlug);
5652
5703
  const serverKind = options.server ?? "local";
@@ -5990,6 +6041,9 @@ Usage: rig init [--server local|remote] [--remote-url <url>] [--repo owner/repo]
5990
6041
  if (parsed.rest.length > 0)
5991
6042
  throw new CliError2(`Unexpected arguments: ${parsed.rest.join(" ")}
5992
6043
  Usage: rig init`, 1);
6044
+ if (!process.stdin.isTTY) {
6045
+ throw new CliError2("rig init is interactive and needs a terminal. For scripts, pass flags: rig init --yes --server local --github-auth skip [--repo owner/repo].", 1);
6046
+ }
5993
6047
  return runInteractiveControlPlaneInit(context, await loadClackPrompts());
5994
6048
  }
5995
6049
 
@@ -12288,7 +12342,7 @@ var __testOnly = {
12288
12342
  };
12289
12343
  // packages/cli/src/launcher.ts
12290
12344
  import { existsSync as existsSync17 } from "fs";
12291
- import { basename as basename2, resolve as resolve26 } from "path";
12345
+ import { basename as basename3, resolve as resolve26 } from "path";
12292
12346
  import { loadDotEnvSecrets } from "@rig/runtime/baked-secrets";
12293
12347
  import { RIG_DEFINITION_DIRNAME, RIG_STATE_DIRNAME, resolveNearestRigProjectRoot } from "@rig/runtime/layout";
12294
12348
  function parsePolicyMode(value) {
@@ -12313,7 +12367,7 @@ function resolveProjectRoot({
12313
12367
  return resolve26(cwd, envProjectRoot);
12314
12368
  }
12315
12369
  const fallbackImportDir = importDir ?? cwd;
12316
- const execName = basename2(execPath).toLowerCase();
12370
+ const execName = basename3(execPath).toLowerCase();
12317
12371
  const execCandidates = execName === "rig" || execName === "rig.exe" ? [resolve26(execPath, "..", "..")] : [];
12318
12372
  const candidates = [cwd, ...execCandidates, resolve26(fallbackImportDir, "..")];
12319
12373
  for (const candidate of candidates) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@h-rig/cli",
3
- "version": "0.0.6-alpha.50",
3
+ "version": "0.0.6-alpha.51",
4
4
  "type": "module",
5
5
  "description": "Rig package",
6
6
  "license": "UNLICENSED",
@@ -23,12 +23,12 @@
23
23
  },
24
24
  "dependencies": {
25
25
  "@clack/prompts": "^1.2.0",
26
- "@earendil-works/pi-coding-agent": "npm:@h-rig/pi-coding-agent@0.0.6-alpha.50",
27
- "@rig/client": "npm:@h-rig/client@0.0.6-alpha.50",
28
- "@rig/core": "npm:@h-rig/core@0.0.6-alpha.50",
29
- "@rig/runtime": "npm:@h-rig/runtime@0.0.6-alpha.50",
30
- "@rig/server": "npm:@h-rig/server@0.0.6-alpha.50",
31
- "@rig/standard-plugin": "npm:@h-rig/standard-plugin@0.0.6-alpha.50",
26
+ "@earendil-works/pi-coding-agent": "npm:@h-rig/pi-coding-agent@0.0.6-alpha.51",
27
+ "@rig/client": "npm:@h-rig/client@0.0.6-alpha.51",
28
+ "@rig/core": "npm:@h-rig/core@0.0.6-alpha.51",
29
+ "@rig/runtime": "npm:@h-rig/runtime@0.0.6-alpha.51",
30
+ "@rig/server": "npm:@h-rig/server@0.0.6-alpha.51",
31
+ "@rig/standard-plugin": "npm:@h-rig/standard-plugin@0.0.6-alpha.51",
32
32
  "picocolors": "^1.1.1"
33
33
  }
34
34
  }