@tryarcanist/cli 0.1.206 → 0.1.208

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 (2) hide show
  1. package/dist/index.js +291 -22
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -8,8 +8,9 @@ import { Command } from "commander";
8
8
  import { execFileSync, spawn } from "child_process";
9
9
  import { existsSync as existsSync2, rmSync } from "fs";
10
10
  import { mkdtemp, readFile, rm } from "fs/promises";
11
- import { tmpdir } from "os";
11
+ import { homedir as homedir2, tmpdir } from "os";
12
12
  import { join as join2 } from "path";
13
+ import { createInterface as createInterface2 } from "readline/promises";
13
14
 
14
15
  // src/api.ts
15
16
  import { createRequire } from "module";
@@ -253,6 +254,8 @@ var CONFIG_DIR = join(homedir(), ".arcanist");
253
254
  var CONFIG_FILE = join(CONFIG_DIR, "config.json");
254
255
  var PROJECT_CONFIG_FILE = ".arcanist-cli.json";
255
256
  var DEFAULT_API_URL = "https://app.tryarcanist.com";
257
+ var SANDBOX_CLI_AUTH_WAIT_TIMEOUT_MS = 1e4;
258
+ var SANDBOX_CLI_AUTH_WAIT_INTERVAL_MS = 100;
256
259
  function loadFileConfig() {
257
260
  try {
258
261
  return JSON.parse(readFileSync(CONFIG_FILE, "utf-8"));
@@ -261,11 +264,11 @@ function loadFileConfig() {
261
264
  }
262
265
  }
263
266
  function loadConfig(overrides = {}) {
264
- const fileConfig = loadFileConfig();
265
267
  const completeEnvOrFlagConfig = resolveCompleteEnvOrFlagConfig(overrides);
266
268
  if (completeEnvOrFlagConfig) return validateAndNormalizeConfig(completeEnvOrFlagConfig);
267
269
  const projectConfig = loadProjectConfig();
268
270
  const envOrFlagConfig = resolveEnvOrFlagConfig(overrides, projectConfig !== null);
271
+ const fileConfig = !projectConfig && shouldWaitForSandboxCliAuth() ? waitForSandboxCliAuthConfig() : loadFileConfig();
269
272
  const apiUrl = envOrFlagConfig?.apiUrl ?? projectConfig?.apiUrl ?? fileConfig?.apiUrl;
270
273
  const token = envOrFlagConfig?.token ?? projectConfig?.token ?? fileConfig?.token;
271
274
  if (!apiUrl || !token) return null;
@@ -352,6 +355,24 @@ function validateAndNormalizeConfig(config) {
352
355
  if (urlError) throw new CliError("user", urlError);
353
356
  return { apiUrl: normalizeBaseUrl(config.apiUrl), token: config.token };
354
357
  }
358
+ function shouldWaitForSandboxCliAuth() {
359
+ const pendingPath = process.env.ARCANIST_CLI_AUTH_PENDING_PATH;
360
+ return Boolean(pendingPath && existsSync(pendingPath));
361
+ }
362
+ function waitForSandboxCliAuthConfig() {
363
+ const readyPath = process.env.ARCANIST_CLI_AUTH_READY_PATH;
364
+ const failedPath = process.env.ARCANIST_CLI_AUTH_FAILED_PATH;
365
+ const deadline = Date.now() + SANDBOX_CLI_AUTH_WAIT_TIMEOUT_MS;
366
+ while (Date.now() <= deadline) {
367
+ if (readyPath && existsSync(readyPath)) return loadFileConfig();
368
+ if (failedPath && existsSync(failedPath)) return null;
369
+ sleepSync(SANDBOX_CLI_AUTH_WAIT_INTERVAL_MS);
370
+ }
371
+ return readyPath && existsSync(readyPath) ? loadFileConfig() : null;
372
+ }
373
+ function sleepSync(ms) {
374
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
375
+ }
355
376
  function findGitRoot(cwd) {
356
377
  let current = cwd;
357
378
  while (true) {
@@ -628,7 +649,19 @@ var GROK_SUBSCRIPTION_CLI_CONFIG = {
628
649
  // "…"}} — so the credential fields live one level down and the token field
629
650
  // is named `key`. Token detection scans nested objects.
630
651
  tokenFields: ["access_token", "refresh_token", "key"],
631
- installHint: "Install the Grok CLI (https://x.ai/cli), or point at it with --grok-path <path> or ARCANIST_GROK_BIN."
652
+ installHint: "Install the Grok CLI (https://x.ai/cli), or point at it with --grok-path <path> or ARCANIST_GROK_BIN.",
653
+ // Official Grok Build installer: installs `grok` (plus an `agent` alias)
654
+ // under ~/.grok/bin, symlinks into ~/.local/bin or /usr/local/bin when
655
+ // writable, and appends PATH exports to shell rc files itself.
656
+ installer: {
657
+ command: "curl -fsSL https://x.ai/cli/install.sh | bash",
658
+ binCandidates: (home) => [
659
+ join2(home, ".grok", "bin", "grok"),
660
+ join2(home, ".local", "bin", "grok"),
661
+ "/usr/local/bin/grok"
662
+ ],
663
+ postInstallNote: "Grok CLI installed. Restart your shell if `grok` is not found on PATH later."
664
+ }
632
665
  };
633
666
  var CURSOR_SUBSCRIPTION_CLI_CONFIG = {
634
667
  harness: "cursor",
@@ -659,6 +692,15 @@ var CURSOR_SUBSCRIPTION_CLI_CONFIG = {
659
692
  { service: "cursor-access-token", field: "accessToken", required: true },
660
693
  { service: "cursor-refresh-token", field: "refreshToken", required: false }
661
694
  ]
695
+ },
696
+ // Official Cursor CLI installer: installs to ~/.local/bin. Installers have
697
+ // shipped the binary as both `cursor-agent` and `agent` (the 2026-07
698
+ // installer's success message says `agent`), so probe both — unambiguous
699
+ // name first, since `agent` is also Grok's alias.
700
+ installer: {
701
+ command: "curl https://cursor.com/install -fsS | bash",
702
+ binCandidates: (home) => [join2(home, ".local", "bin", "cursor-agent"), join2(home, ".local", "bin", "agent")],
703
+ postInstallNote: 'Cursor CLI installed to ~/.local/bin. Add it to your PATH for future shells: export PATH="$HOME/.local/bin:$PATH"'
662
704
  }
663
705
  };
664
706
  function subscriptionBasePath(harness) {
@@ -667,6 +709,69 @@ function subscriptionBasePath(harness) {
667
709
  function resolveVendorBin(config, optionPath) {
668
710
  return optionPath?.trim() || process.env[config.binEnvVar]?.trim() || config.defaultBin;
669
711
  }
712
+ var VendorBinaryMissingError = class extends CliError {
713
+ constructor(config, binPath) {
714
+ super("user", `Could not find the \`${binPath}\` executable.`, { hint: config.installHint });
715
+ this.name = "VendorBinaryMissingError";
716
+ }
717
+ };
718
+ function runVendorInstall(config, command) {
719
+ return new Promise((resolve2, reject) => {
720
+ const child = spawn("bash", ["-c", command], { stdio: ["inherit", 2, "inherit"] });
721
+ child.on("error", (err) => {
722
+ reject(
723
+ new CliError("user", `Failed to run the ${config.displayName} CLI installer: ${err.message}`, {
724
+ hint: config.installHint
725
+ })
726
+ );
727
+ });
728
+ child.on("close", (code) => {
729
+ if (code === 0) {
730
+ resolve2();
731
+ return;
732
+ }
733
+ reject(
734
+ new CliError("user", `The ${config.displayName} CLI installer exited with code ${code ?? "unknown"}.`, {
735
+ hint: config.installHint
736
+ })
737
+ );
738
+ });
739
+ });
740
+ }
741
+ async function offerVendorInstall(config, explicitBinPath) {
742
+ const installer = config.installer;
743
+ if (!installer || explicitBinPath) return null;
744
+ if (process.platform !== "linux" && process.platform !== "darwin") return null;
745
+ if (!process.stdin.isTTY || !process.stdout.isTTY) return null;
746
+ console.error(`Could not find the \`${config.defaultBin}\` executable.`);
747
+ console.error(`Install it now by running: ${installer.command}`);
748
+ const rl = createInterface2({ input: process.stdin, output: process.stderr });
749
+ let answer;
750
+ try {
751
+ answer = (await rl.question("Proceed? [y/N] ")).trim().toLowerCase();
752
+ } finally {
753
+ rl.close();
754
+ }
755
+ if (answer !== "y" && answer !== "yes") return null;
756
+ await runVendorInstall(config, installer.command);
757
+ for (const candidate of installer.binCandidates(homedir2())) {
758
+ if (existsSync2(candidate)) {
759
+ if (installer.postInstallNote) console.error(installer.postInstallNote);
760
+ return candidate;
761
+ }
762
+ }
763
+ return config.defaultBin;
764
+ }
765
+ async function runVendorLoginWithInstallOffer(config, binPath, tempHome, explicitBinPath) {
766
+ try {
767
+ await runVendorLogin(config, binPath, tempHome);
768
+ } catch (err) {
769
+ if (!(err instanceof VendorBinaryMissingError)) throw err;
770
+ const installedBin = await offerVendorInstall(config, explicitBinPath);
771
+ if (!installedBin) throw err;
772
+ await runVendorLogin(config, installedBin, tempHome);
773
+ }
774
+ }
670
775
  function runVendorLogin(config, binPath, tempHome) {
671
776
  return new Promise((resolve2, reject) => {
672
777
  const child = spawn(binPath, config.loginArgs, {
@@ -675,7 +780,7 @@ function runVendorLogin(config, binPath, tempHome) {
675
780
  });
676
781
  child.on("error", (err) => {
677
782
  if (err.code === "ENOENT") {
678
- reject(new CliError("user", `Could not find the \`${binPath}\` executable.`, { hint: config.installHint }));
783
+ reject(new VendorBinaryMissingError(config, binPath));
679
784
  return;
680
785
  }
681
786
  reject(new CliError("user", `Failed to launch \`${binPath} ${config.loginArgs.join(" ")}\`: ${err.message}`));
@@ -753,6 +858,7 @@ async function setSubscriptionEnabled(apiConfig, harness, enabled) {
753
858
  async function agentSubscriptionLoginCommand(config, options, command) {
754
859
  const { config: apiConfig } = resolveBusinessContext(command, options);
755
860
  const binPath = resolveVendorBin(config, options.binPath);
861
+ const explicitBinPath = Boolean(options.binPath?.trim() || process.env[config.binEnvVar]?.trim());
756
862
  let tempHome;
757
863
  const handleSigint = () => {
758
864
  if (tempHome) {
@@ -768,11 +874,11 @@ async function agentSubscriptionLoginCommand(config, options, command) {
768
874
  const captureViaKeychain = process.platform === "darwin" && config.darwinKeychain !== void 0;
769
875
  let authJson;
770
876
  if (captureViaKeychain) {
771
- await runVendorLogin(config, binPath, null);
877
+ await runVendorLoginWithInstallOffer(config, binPath, null, explicitBinPath);
772
878
  authJson = readDarwinKeychainAuthJson(config);
773
879
  } else {
774
880
  tempHome = await mkdtemp(join2(tmpdir(), `arcanist-${config.harness}-`));
775
- await runVendorLogin(config, binPath, tempHome);
881
+ await runVendorLoginWithInstallOffer(config, binPath, tempHome, explicitBinPath);
776
882
  authJson = await readLoginAuthJson(config, tempHome);
777
883
  }
778
884
  const state = await apiFetch(
@@ -879,18 +985,21 @@ var CODEX_AGENT_RUNTIME_BACKEND = "codex";
879
985
  var CLAUDE_CODE_AGENT_RUNTIME_BACKEND = "claude_code";
880
986
  var OPENCODE_AGENT_RUNTIME_BACKEND = "opencode";
881
987
  var CURSOR_AGENT_RUNTIME_BACKEND = "cursor";
988
+ var GROK_AGENT_RUNTIME_BACKEND = "grok";
882
989
  var AGENT_RUNTIME_BACKENDS = [
883
990
  CODEX_AGENT_RUNTIME_BACKEND,
884
991
  CLAUDE_CODE_AGENT_RUNTIME_BACKEND,
885
992
  OPENCODE_AGENT_RUNTIME_BACKEND,
886
- CURSOR_AGENT_RUNTIME_BACKEND
993
+ CURSOR_AGENT_RUNTIME_BACKEND,
994
+ GROK_AGENT_RUNTIME_BACKEND
887
995
  ];
888
996
  var AGENT_RUNTIME_BACKEND_NAMES = {
889
997
  [CODEX_AGENT_RUNTIME_BACKEND]: "Codex",
890
998
  [CLAUDE_CODE_AGENT_RUNTIME_BACKEND]: "Claude Code",
891
999
  // "opencode" is intentionally lowercase to match the project's brand name.
892
1000
  [OPENCODE_AGENT_RUNTIME_BACKEND]: "opencode",
893
- [CURSOR_AGENT_RUNTIME_BACKEND]: "Cursor"
1001
+ [CURSOR_AGENT_RUNTIME_BACKEND]: "Cursor",
1002
+ [GROK_AGENT_RUNTIME_BACKEND]: "Grok Build"
894
1003
  };
895
1004
  function isAgentRuntimeBackend(value) {
896
1005
  return AGENT_RUNTIME_BACKENDS.includes(value);
@@ -933,17 +1042,27 @@ var BasetenModel = {
933
1042
  KimiK27Code: "kimi-k2.7-code"
934
1043
  };
935
1044
  var XaiModel = {
936
- Grok45: "grok-4.5"
1045
+ Grok45: "grok-4.5",
1046
+ Grok43: "grok-4.3",
1047
+ Grok420Reasoning: "grok-4.20-0309-reasoning",
1048
+ Grok420NonReasoning: "grok-4.20-0309-non-reasoning",
1049
+ Grok420MultiAgent: "grok-4.20-multi-agent-0309",
1050
+ GrokBuild01: "grok-build-0.1"
937
1051
  };
938
1052
  var CursorModel = {
939
1053
  Composer25: "composer-2.5"
940
1054
  };
1055
+ var GrokBuildModel = {
1056
+ Grok45Byos: "grok-4.5-byos",
1057
+ GrokComposer25Fast: "grok-composer-2.5-fast"
1058
+ };
941
1059
  var MODEL_PROVIDERS_SET = /* @__PURE__ */ new Set([
942
1060
  "openai",
943
1061
  "anthropic",
944
1062
  "baseten",
945
1063
  "xai",
946
- "cursor"
1064
+ "cursor",
1065
+ "grok"
947
1066
  ]);
948
1067
  var BACKEND_DESKTOP_IMAGE_FEEDBACK_CONFIGS = {
949
1068
  [CODEX_AGENT_RUNTIME_BACKEND]: {
@@ -1258,19 +1377,126 @@ var MODEL_REGISTRY = [
1258
1377
  pricing: { inputPerMillion: 0.95, outputPerMillion: 4, cacheReadPerMillion: 0.16 },
1259
1378
  sessionStart: { eligible: true, isDefault: true }
1260
1379
  },
1380
+ // xAI models (all text/chat models from https://docs.x.ai/docs/models,
1381
+ // verified 2026-07-15). All run on the opencode backend through the
1382
+ // OpenAI-compatible Chat Completions API at api.x.ai. No reasoning config
1383
+ // for any of them: xAI documents `reasoning_effort` for grok-4.3 only
1384
+ // (https://docs.x.ai/docs/api-reference), AND the opencode backend
1385
+ // intentionally passes no reasoning parameters to OSS providers
1386
+ // (variantReasoning: intentional in backend-capabilities.ts) — grok-4.3's
1387
+ // server-side default (`low`) applies. Pricing records both tiers: xAI
1388
+ // bills the whole request at long-context rates once the prompt crosses
1389
+ // 200k tokens, expressed via `longContext` (bridge cost estimates only).
1261
1390
  {
1262
1391
  id: XaiModel.Grok45,
1263
1392
  name: "Grok 4.5",
1264
1393
  provider: "xai",
1265
1394
  backends: [OPENCODE_AGENT_RUNTIME_BACKEND],
1266
1395
  contextWindow: 5e5,
1267
- // No reasoning config on purpose: xAI's chat-completions reference
1268
- // (verified 2026-07-14, https://docs.x.ai/docs/api-reference) documents
1269
- // `reasoning_effort` as supported only by grok-4.3, so grok-4.5 is
1270
- // classified no-reasoning per the registry rule. Pricing/context verified
1271
- // 2026-07-14 against https://docs.x.ai/docs/pricing ($2/M in, $6/M out,
1272
- // 500k context); no cached-input rate is documented, so none is recorded.
1273
- pricing: { inputPerMillion: 2, outputPerMillion: 6 },
1396
+ // Verified 2026-07-15 against https://docs.x.ai/docs/pricing: $2/M in,
1397
+ // $6/M out, $0.50/M cached input below 200k prompt tokens; $4/$12/$1.00
1398
+ // at or above it. 500k context.
1399
+ pricing: {
1400
+ inputPerMillion: 2,
1401
+ outputPerMillion: 6,
1402
+ cacheReadPerMillion: 0.5,
1403
+ longContext: { thresholdTokens: 2e5, inputPerMillion: 4, outputPerMillion: 12, cacheReadPerMillion: 1 }
1404
+ },
1405
+ sessionStart: { eligible: true }
1406
+ },
1407
+ {
1408
+ id: XaiModel.Grok43,
1409
+ name: "Grok 4.3",
1410
+ provider: "xai",
1411
+ backends: [OPENCODE_AGENT_RUNTIME_BACKEND],
1412
+ contextWindow: 1e6,
1413
+ // Verified 2026-07-15 against https://docs.x.ai/docs/pricing: $1.25/M in,
1414
+ // $2.50/M out, $0.20/M cached input below 200k prompt tokens;
1415
+ // $2.50/$5.00/$0.40 at or above it. 1M context.
1416
+ pricing: {
1417
+ inputPerMillion: 1.25,
1418
+ outputPerMillion: 2.5,
1419
+ cacheReadPerMillion: 0.2,
1420
+ longContext: { thresholdTokens: 2e5, inputPerMillion: 2.5, outputPerMillion: 5, cacheReadPerMillion: 0.4 }
1421
+ },
1422
+ sessionStart: { eligible: true }
1423
+ },
1424
+ {
1425
+ id: XaiModel.Grok420Reasoning,
1426
+ name: "Grok 4.20 Reasoning",
1427
+ provider: "xai",
1428
+ backends: [OPENCODE_AGENT_RUNTIME_BACKEND],
1429
+ contextWindow: 1e6,
1430
+ // xAI encodes reasoning in distinct model ids for the 4.20 line (like
1431
+ // Cursor), not a per-request parameter. Verified 2026-07-15 against
1432
+ // https://docs.x.ai/docs/pricing: $1.25/M in, $2.50/M out, $0.20/M cached
1433
+ // input below 200k prompt tokens; $2.50/$5.00/$0.40 at or above it. 1M context.
1434
+ pricing: {
1435
+ inputPerMillion: 1.25,
1436
+ outputPerMillion: 2.5,
1437
+ cacheReadPerMillion: 0.2,
1438
+ longContext: { thresholdTokens: 2e5, inputPerMillion: 2.5, outputPerMillion: 5, cacheReadPerMillion: 0.4 }
1439
+ },
1440
+ sessionStart: { eligible: true }
1441
+ },
1442
+ {
1443
+ id: XaiModel.Grok420NonReasoning,
1444
+ name: "Grok 4.20 Non-Reasoning",
1445
+ provider: "xai",
1446
+ backends: [OPENCODE_AGENT_RUNTIME_BACKEND],
1447
+ contextWindow: 1e6,
1448
+ // Verified 2026-07-15 against https://docs.x.ai/docs/pricing: $1.25/M in,
1449
+ // $2.50/M out, $0.20/M cached input below 200k prompt tokens;
1450
+ // $2.50/$5.00/$0.40 at or above it. 1M context.
1451
+ pricing: {
1452
+ inputPerMillion: 1.25,
1453
+ outputPerMillion: 2.5,
1454
+ cacheReadPerMillion: 0.2,
1455
+ longContext: { thresholdTokens: 2e5, inputPerMillion: 2.5, outputPerMillion: 5, cacheReadPerMillion: 0.4 }
1456
+ },
1457
+ sessionStart: { eligible: true }
1458
+ },
1459
+ {
1460
+ id: XaiModel.Grok420MultiAgent,
1461
+ name: "Grok 4.20 Multi-Agent",
1462
+ provider: "xai",
1463
+ backends: [OPENCODE_AGENT_RUNTIME_BACKEND],
1464
+ contextWindow: 1e6,
1465
+ // Verified 2026-07-15 against https://docs.x.ai/docs/pricing: $1.25/M in,
1466
+ // $2.50/M out, $0.20/M cached input below 200k prompt tokens;
1467
+ // $2.50/$5.00/$0.40 at or above it. 1M context.
1468
+ pricing: {
1469
+ inputPerMillion: 1.25,
1470
+ outputPerMillion: 2.5,
1471
+ cacheReadPerMillion: 0.2,
1472
+ longContext: { thresholdTokens: 2e5, inputPerMillion: 2.5, outputPerMillion: 5, cacheReadPerMillion: 0.4 }
1473
+ },
1474
+ sessionStart: { eligible: true },
1475
+ // Cannot run a coding-agent session on a standard xAI key (verified
1476
+ // 2026-07-15 against api.x.ai with our production key): chat completions
1477
+ // rejects the model outright ("Multi Agent requests are not allowed on
1478
+ // chat completions") and the Responses API 400s any request carrying
1479
+ // client-side tools ("Client-side tools for multi-agent models require
1480
+ // beta access") — and the harness always sends tools. Hidden from the
1481
+ // picker until xAI grants beta access; CLI/API selection stays open for
1482
+ // retesting.
1483
+ visibility: "internal_probe"
1484
+ },
1485
+ {
1486
+ id: XaiModel.GrokBuild01,
1487
+ name: "Grok Build 0.1",
1488
+ provider: "xai",
1489
+ backends: [OPENCODE_AGENT_RUNTIME_BACKEND],
1490
+ contextWindow: 256e3,
1491
+ // Verified 2026-07-15 against https://docs.x.ai/docs/pricing: $1/M in,
1492
+ // $2/M out, $0.20/M cached input below 200k prompt tokens; $2/$4/$0.40 at
1493
+ // or above it. 256k context.
1494
+ pricing: {
1495
+ inputPerMillion: 1,
1496
+ outputPerMillion: 2,
1497
+ cacheReadPerMillion: 0.2,
1498
+ longContext: { thresholdTokens: 2e5, inputPerMillion: 2, outputPerMillion: 4, cacheReadPerMillion: 0.4 }
1499
+ },
1274
1500
  sessionStart: { eligible: true }
1275
1501
  },
1276
1502
  {
@@ -1286,9 +1512,42 @@ var MODEL_REGISTRY = [
1286
1512
  // published for Composer 2.5 (checked cursor.com/docs/models 2026-07-15),
1287
1513
  // so none is recorded.
1288
1514
  costTracked: false,
1515
+ sessionStart: { eligible: true, isDefault: true }
1516
+ },
1517
+ {
1518
+ id: GrokBuildModel.Grok45Byos,
1519
+ name: "Grok 4.5 (Subscription)",
1520
+ provider: "grok",
1521
+ backends: [GROK_AGENT_RUNTIME_BACKEND],
1522
+ // Wire id `grok-4.5` (the CLI's subscription default) collides with the
1523
+ // xai/opencode registry id, so the Arcanist id is suffixed and the wire id
1524
+ // rides providerModelId. Billed through the user's Grok subscription via
1525
+ // the Grok Build CLI (cli-chat-proxy.grok.com); Arcanist does not meter it
1526
+ // (costTracked: false requires pricing to stay undefined). Context window
1527
+ // verified 2026-07-15 against https://docs.x.ai/docs/models (grok-4.5,
1528
+ // 500k). No reasoning config: the CLI's --reasoning-effort is documented
1529
+ // for reasoning models only and grok-4.5 is classified no-reasoning per
1530
+ // the xai registry entries above.
1531
+ providerModelId: "grok-4.5",
1532
+ contextWindow: 5e5,
1533
+ costTracked: false,
1289
1534
  sessionStart: { eligible: true, isDefault: true },
1290
- // Internal probe: hidden from the public model picker; selectable via
1291
- // CLI/API only while the cursor backend is gated.
1535
+ // Internal probe (ARC-1704): hidden from the public model picker;
1536
+ // CLI/API-selectable by internal Arcanist businesses only.
1537
+ visibility: "internal_probe"
1538
+ },
1539
+ {
1540
+ id: GrokBuildModel.GrokComposer25Fast,
1541
+ name: "Grok Composer 2.5 Fast",
1542
+ provider: "grok",
1543
+ backends: [GROK_AGENT_RUNTIME_BACKEND],
1544
+ // Cursor's Composer 2.5 Fast served through Grok Build (verified in
1545
+ // `grok models` 0.2.101 under a live subscription, 2026-07-15). Wire id
1546
+ // matches the registry id, so no providerModelId. Context window is not
1547
+ // published for Composer variants (cursor.com/docs/models), so none is
1548
+ // recorded. Subscription-billed, not metered by Arcanist.
1549
+ costTracked: false,
1550
+ sessionStart: { eligible: true },
1292
1551
  visibility: "internal_probe"
1293
1552
  }
1294
1553
  ];
@@ -1297,7 +1556,8 @@ var MODEL_PROVIDER_NAMES = {
1297
1556
  anthropic: "Anthropic",
1298
1557
  baseten: "Baseten",
1299
1558
  xai: "xAI",
1300
- cursor: "Cursor"
1559
+ cursor: "Cursor",
1560
+ grok: "Grok Build"
1301
1561
  };
1302
1562
  function buildSessionStartModelIdsByBackend() {
1303
1563
  const byBackend = Object.fromEntries(AGENT_RUNTIME_BACKENDS.map((backend) => [backend, []]));
@@ -1337,7 +1597,8 @@ var VALID_SESSION_START_MODEL_IDS_BY_BACKEND = {
1337
1597
  SESSION_START_MODEL_IDS_BY_BACKEND[CLAUDE_CODE_AGENT_RUNTIME_BACKEND]
1338
1598
  ),
1339
1599
  [OPENCODE_AGENT_RUNTIME_BACKEND]: new Set(SESSION_START_MODEL_IDS_BY_BACKEND[OPENCODE_AGENT_RUNTIME_BACKEND]),
1340
- [CURSOR_AGENT_RUNTIME_BACKEND]: new Set(SESSION_START_MODEL_IDS_BY_BACKEND[CURSOR_AGENT_RUNTIME_BACKEND])
1600
+ [CURSOR_AGENT_RUNTIME_BACKEND]: new Set(SESSION_START_MODEL_IDS_BY_BACKEND[CURSOR_AGENT_RUNTIME_BACKEND]),
1601
+ [GROK_AGENT_RUNTIME_BACKEND]: new Set(SESSION_START_MODEL_IDS_BY_BACKEND[GROK_AGENT_RUNTIME_BACKEND])
1341
1602
  };
1342
1603
  var MODEL_CONTEXT_WINDOWS = {
1343
1604
  ...Object.fromEntries(
@@ -1806,6 +2067,7 @@ var PHASES = [
1806
2067
  "review_listening",
1807
2068
  "completed",
1808
2069
  "superseded",
2070
+ "needs_you",
1809
2071
  "blocked",
1810
2072
  "failed",
1811
2073
  "stopped",
@@ -1814,6 +2076,7 @@ var PHASES = [
1814
2076
  var TERMINAL_PHASES_ARRAY = [
1815
2077
  "completed",
1816
2078
  "superseded",
2079
+ "needs_you",
1817
2080
  "blocked",
1818
2081
  "failed",
1819
2082
  "stopped",
@@ -1827,7 +2090,7 @@ var CHILD_SLOT_RELEASE_PHASES = new Set(
1827
2090
  TERMINAL_PHASES_ARRAY.filter((phase) => phase !== "stopped")
1828
2091
  );
1829
2092
  var ARCHIVABLE_STALE_TERMINAL_PHASES_ARRAY = TERMINAL_PHASES_ARRAY.filter(
1830
- (phase) => phase !== "archived" && phase !== "blocked" && phase !== "stopped"
2093
+ (phase) => phase !== "archived" && phase !== "needs_you" && phase !== "blocked" && phase !== "stopped"
1831
2094
  );
1832
2095
  function isTerminalPhase(phase, _sessionKind) {
1833
2096
  return TERMINAL_PHASES.has(phase);
@@ -2944,6 +3207,7 @@ var SCAFFOLDING_LINE_PATTERNS = [
2944
3207
  /^IMPORTANT: The content above is /i,
2945
3208
  /^Previous Slack message\b/i,
2946
3209
  /^Current Slack message author:/i,
3210
+ /^Current Slack channel:/i,
2947
3211
  /^Thread context(?:\s*\([^)]*\))?\s*[.:]/i,
2948
3212
  // Synthetic bootstrap prefix only: a single-token repo URL/ref value. A
2949
3213
  // user's prose line like "Repository: our monorepo is huge" has spaces and
@@ -2960,6 +3224,7 @@ var SCAFFOLDING_MARKERS = [
2960
3224
  /^IMPORTANT: The content above is /im,
2961
3225
  /^Previous Slack message\b/im,
2962
3226
  /^Current Slack message author:/im,
3227
+ /^Current Slack channel:/im,
2963
3228
  /^Repository:\s+\S+$/im,
2964
3229
  /^\[arcanist:review-loop\b/im
2965
3230
  ];
@@ -5971,6 +6236,8 @@ Runs the Grok CLI device-authorization login locally under a temporary HOME, the
5971
6236
  resulting auth.json to Arcanist (encrypted, per user) and activates the selector. Your workspace
5972
6237
  must have Grok subscription auth enabled. The credential is never written to your default ~/.grok.
5973
6238
  Grok BYOS session execution is not live yet; the credential is stored for when it ships.
6239
+ If the grok CLI is not installed, you will be offered its official install script ([y/N] prompt,
6240
+ interactive terminals only).
5974
6241
 
5975
6242
  Examples:
5976
6243
  arcanist grok login
@@ -5996,6 +6263,8 @@ captured auth credential to Arcanist (encrypted, per user) and activates the sel
5996
6263
  workspace must have Cursor subscription auth enabled. Cursor's login-token location is not
5997
6264
  formally documented; if capture fails, use a Cursor API key in Settings instead. Cursor BYOS
5998
6265
  session execution is not live yet; the credential is stored for when it ships.
6266
+ If the cursor-agent CLI is not installed, you will be offered its official install script
6267
+ ([y/N] prompt, interactive terminals only).
5999
6268
 
6000
6269
  Examples:
6001
6270
  arcanist cursor login
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tryarcanist/cli",
3
- "version": "0.1.206",
3
+ "version": "0.1.208",
4
4
  "description": "CLI for Arcanist — create and manage coding agent sessions",
5
5
  "type": "module",
6
6
  "bin": {