@tryarcanist/cli 0.1.163 → 0.1.165

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 (3) hide show
  1. package/README.md +3 -0
  2. package/dist/index.js +222 -161
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -272,10 +272,13 @@ Creates a scheduled automation for a GitHub repo. Create/delete require a write-
272
272
 
273
273
  ```bash
274
274
  arcanist automations create your-org/your-repo "summarize new regressions" --cron "*/15 * * * *"
275
+ arcanist automations create your-org/your-repo "audit N+1s" --cron "0 13 * * 5" --model gpt-5.5
275
276
  printf "summarize new regressions" | arcanist automations create your-org/your-repo --prompt-stdin --cron "*/15 * * * *" --json
276
277
  arcanist automations create https://github.com/your-org/your-repo - --cron "0 14 * * 1-5" --name "Weekday summary"
277
278
  ```
278
279
 
280
+ Use `--model <model>` to pin the model for sessions started by the automation. Backend is derived from the model; non-codex backends such as Claude or opencode are limited to Arcanist team businesses. When `--model` is omitted the codex backend default is used.
281
+
279
282
  JSON mode prints the created rule. Human-readable mode prints the rule ID, repo, normalized cron, and next fire time.
280
283
 
281
284
  ### `arcanist automations list`
package/dist/index.js CHANGED
@@ -495,161 +495,6 @@ async function whoamiCommand(options, command) {
495
495
  });
496
496
  }
497
497
 
498
- // ../../shared/github/repo-url.ts
499
- function parseGithubRepoFullName(value) {
500
- const shorthand = value.match(/^([a-zA-Z0-9_.-]+)\/([a-zA-Z0-9_.-]+)$/);
501
- if (shorthand) return { owner: shorthand[1], repo: shorthand[2] };
502
- const ssh = value.match(/git@[^:]+:([^/]+)\/([^/]+?)(?:\.git)?$/);
503
- if (ssh) return { owner: ssh[1], repo: ssh[2] };
504
- const https = value.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?\/?$/);
505
- if (https) return { owner: https[1], repo: https[2] };
506
- return null;
507
- }
508
-
509
- // src/commands/automations.ts
510
- var AUTOMATION_ERROR_HINTS = {
511
- invalid_cron: "Use a standard five-field cron expression, for example: */15 * * * *",
512
- repo_not_available: "Check that the token owner has GitHub access and Arcanist is installed for that repo.",
513
- duplicate_rule: "An enabled automation already exists for this repo, cron, and prompt.",
514
- rule_cap_reached: "Delete or disable an existing automation before creating another one. The cap is 20 enabled rules.",
515
- installation_unresolved: "Reconnect or reinstall the GitHub integration for that repository, then retry."
516
- };
517
- async function createAutomationCommand(repoUrl, promptArg, options, command) {
518
- const repo = parseAutomationRepo(repoUrl);
519
- const prompt = await resolvePromptInput(promptArg, options);
520
- const runtime = getRuntimeOptions(command, options);
521
- const config = requireConfig(runtime);
522
- const body = {
523
- repoOwner: repo.owner,
524
- repoName: repo.repo,
525
- cron: options.cron,
526
- prompt
527
- };
528
- if (options.name !== void 0) body.name = options.name;
529
- const payload = await automationApiFetch(config, "/api/automation/schedules", {
530
- method: "POST",
531
- body: JSON.stringify(body)
532
- });
533
- if (isJson(command, options)) {
534
- writeJson(payload.data);
535
- return;
536
- }
537
- printAutomationRule(payload.data);
538
- }
539
- async function listAutomationsCommand(options, command) {
540
- const runtime = getRuntimeOptions(command, options);
541
- const config = requireConfig(runtime);
542
- const items = [];
543
- let cursor = options.cursor;
544
- let nextCursor = null;
545
- do {
546
- const query = new URLSearchParams();
547
- if (options.limit) query.set("limit", options.limit);
548
- if (cursor) query.set("cursor", cursor);
549
- const payload = await automationApiFetch(
550
- config,
551
- `/api/automation/schedules${query.size ? `?${query.toString()}` : ""}`
552
- );
553
- items.push(...payload.data.items);
554
- nextCursor = payload.data.nextCursor;
555
- cursor = nextCursor ?? void 0;
556
- } while (options.all === true && nextCursor);
557
- const output = { items, nextCursor: options.all === true ? null : nextCursor };
558
- if (isJson(command, options)) {
559
- writeJson(output);
560
- return;
561
- }
562
- if (items.length === 0) {
563
- console.log("No automations found.");
564
- return;
565
- }
566
- for (const rule of items) {
567
- console.log(
568
- `${rule.id} ${rule.repoOwner}/${rule.repoName} ${rule.normalizedCron} ${String(rule.enabled)} ${formatTime(rule.nextFireAt)}`
569
- );
570
- }
571
- if (output.nextCursor) console.log(`Next cursor: ${output.nextCursor}`);
572
- }
573
- async function deleteAutomationCommand(id, options, command) {
574
- if (isJson(command, options) && options.yes !== true) {
575
- throw new CliError("user", "`automations delete --json` requires --yes.");
576
- }
577
- if (options.yes !== true) {
578
- await confirmOrThrow(`Delete automation ${id}?`);
579
- }
580
- const runtime = getRuntimeOptions(command, options);
581
- const config = requireConfig(runtime);
582
- await automationApiFetchText(config, `/api/automation/schedules/${encodeURIComponent(id)}`, { method: "DELETE" });
583
- if (isJson(command, options)) {
584
- writeJson({ ok: true, id });
585
- return;
586
- }
587
- console.log(`Deleted automation ${id}.`);
588
- }
589
- function parseAutomationRepo(value) {
590
- if (/^git@/i.test(value) && !/^git@github\.com:/i.test(value)) {
591
- throw new CliError("user", "repo-url must be owner/name or a GitHub URL.");
592
- }
593
- const parsed = parseGithubRepoFullName(value);
594
- if (!parsed) throw new CliError("user", "repo-url must be owner/name or a GitHub URL.");
595
- return { owner: parsed.owner, repo: parsed.repo };
596
- }
597
- async function automationApiFetch(config, path, init) {
598
- try {
599
- return await apiFetch(config, path, init);
600
- } catch (err) {
601
- throw mapAutomationApiError(err);
602
- }
603
- }
604
- async function automationApiFetchText(config, path, init) {
605
- try {
606
- return await apiFetchText(config, path, init);
607
- } catch (err) {
608
- throw mapAutomationApiError(err);
609
- }
610
- }
611
- function mapAutomationApiError(err) {
612
- if (!(err instanceof ApiError)) {
613
- return err instanceof CliError ? err : new CliError("server", err instanceof Error ? err.message : String(err));
614
- }
615
- const parsed = parseApiErrorBody2(err.body);
616
- const serverCode = parsed?.error;
617
- return new CliError(codeForStatus(err.status), parsed?.message || serverCode || err.message, {
618
- exitCode: err.exitCode,
619
- hint: serverCode ? AUTOMATION_ERROR_HINTS[serverCode] : void 0,
620
- requestId: err.requestId
621
- });
622
- }
623
- function parseApiErrorBody2(body) {
624
- try {
625
- const parsed = JSON.parse(body);
626
- if (!parsed || typeof parsed !== "object") return null;
627
- const record = parsed;
628
- return {
629
- error: typeof record.error === "string" ? record.error : void 0,
630
- message: typeof record.message === "string" ? record.message : void 0
631
- };
632
- } catch {
633
- return null;
634
- }
635
- }
636
- function codeForStatus(status) {
637
- if (status === 401 || status === 403) return "auth";
638
- if (status === 404) return "not_found";
639
- if (status === 409) return "conflict";
640
- if (status >= 500) return "server";
641
- return "user";
642
- }
643
- function printAutomationRule(rule) {
644
- console.log(`ID: ${rule.id}`);
645
- console.log(`Repo: ${rule.repoOwner}/${rule.repoName}`);
646
- console.log(`Cron: ${rule.normalizedCron}`);
647
- console.log(`Next fire: ${formatTime(rule.nextFireAt)}`);
648
- }
649
- function formatTime(value) {
650
- return typeof value === "number" ? new Date(value).toISOString() : "none";
651
- }
652
-
653
498
  // ../../shared/agent/agent-runtime-backend.ts
654
499
  var CODEX_AGENT_RUNTIME_BACKEND = "codex";
655
500
  var CLAUDE_CODE_AGENT_RUNTIME_BACKEND = "claude_code";
@@ -953,12 +798,18 @@ function extractModelId(raw) {
953
798
  if (!value) return void 0;
954
799
  return splitModelIdentifier(value)?.modelID;
955
800
  }
801
+ function getAgentRuntimeBackendForModel(modelId) {
802
+ return getBackendsForModel(modelId)?.[0];
803
+ }
956
804
  function getSessionStartModelIdsForBackend(backend) {
957
805
  return SESSION_START_MODEL_IDS_BY_BACKEND[backend];
958
806
  }
959
807
  function isSessionStartModelAllowedForBackend(modelId, backend) {
960
808
  return VALID_SESSION_START_MODEL_IDS_BY_BACKEND[backend].has(modelId);
961
809
  }
810
+ function getBackendsForModel(modelId) {
811
+ return MODEL_DEFINITIONS_BY_ID[modelId]?.backends;
812
+ }
962
813
  function getProviderForModel(modelId) {
963
814
  return MODEL_PROVIDERS[modelId] ?? "openai";
964
815
  }
@@ -1018,6 +869,184 @@ var CODEX_SUBSCRIPTION_SESSION_START_MODEL_PROVIDER_GROUPS = buildModelProviderG
1018
869
  )
1019
870
  );
1020
871
 
872
+ // ../../shared/github/repo-url.ts
873
+ function parseGithubRepoFullName(value) {
874
+ const shorthand = value.match(/^([a-zA-Z0-9_.-]+)\/([a-zA-Z0-9_.-]+)$/);
875
+ if (shorthand) return { owner: shorthand[1], repo: shorthand[2] };
876
+ const ssh = value.match(/git@[^:]+:([^/]+)\/([^/]+?)(?:\.git)?$/);
877
+ if (ssh) return { owner: ssh[1], repo: ssh[2] };
878
+ const https = value.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?\/?$/);
879
+ if (https) return { owner: https[1], repo: https[2] };
880
+ return null;
881
+ }
882
+
883
+ // src/commands/automations.ts
884
+ var AUTOMATION_ERROR_HINTS = {
885
+ invalid_cron: "Use a standard five-field cron expression, for example: */15 * * * *",
886
+ invalid_model: "Model is unknown or not selectable for its backend. Run `arcanist automations create --help` for allowed models.",
887
+ repo_not_available: "Check that the token owner has GitHub access and Arcanist is installed for that repo.",
888
+ duplicate_rule: "An enabled automation already exists for this repo, cron, and prompt.",
889
+ rule_cap_reached: "Delete or disable an existing automation before creating another one. The cap is 20 enabled rules.",
890
+ installation_unresolved: "Reconnect or reinstall the GitHub integration for that repository, then retry.",
891
+ model_not_available: "That model's backend (Claude/opencode) is limited to Arcanist team businesses; use the codex default or a codex model."
892
+ };
893
+ async function createAutomationCommand(repoUrl, promptArg, options, command) {
894
+ const repo = parseAutomationRepo(repoUrl);
895
+ const prompt = await resolvePromptInput(promptArg, options);
896
+ const runtime = getRuntimeOptions(command, options);
897
+ const config = requireConfig(runtime);
898
+ let normalizedModel;
899
+ if (options.model !== void 0) {
900
+ normalizedModel = extractModelId(options.model);
901
+ const backend = resolveAutomationModelBackend(options.model, normalizedModel);
902
+ if (normalizedModel === void 0 || !isSessionStartModelAllowedForBackend(normalizedModel, backend)) {
903
+ const allowed = getSessionStartModelIdsForBackend(backend).join(", ");
904
+ throw new CliError("user", `Model '${options.model}' is not selectable. Allowed: ${allowed}.`);
905
+ }
906
+ }
907
+ const body = {
908
+ repoOwner: repo.owner,
909
+ repoName: repo.repo,
910
+ cron: options.cron,
911
+ prompt
912
+ };
913
+ if (options.name !== void 0) body.name = options.name;
914
+ if (options.model !== void 0) body.modelId = normalizedModel;
915
+ const payload = await automationApiFetch(config, "/api/automation/schedules", {
916
+ method: "POST",
917
+ body: JSON.stringify(body)
918
+ });
919
+ if (isJson(command, options)) {
920
+ writeJson(payload.data);
921
+ return;
922
+ }
923
+ printAutomationRule(payload.data);
924
+ }
925
+ async function listAutomationsCommand(options, command) {
926
+ const runtime = getRuntimeOptions(command, options);
927
+ const config = requireConfig(runtime);
928
+ const items = [];
929
+ let cursor = options.cursor;
930
+ let nextCursor = null;
931
+ do {
932
+ const query = new URLSearchParams();
933
+ if (options.limit) query.set("limit", options.limit);
934
+ if (cursor) query.set("cursor", cursor);
935
+ const payload = await automationApiFetch(
936
+ config,
937
+ `/api/automation/schedules${query.size ? `?${query.toString()}` : ""}`
938
+ );
939
+ items.push(...payload.data.items);
940
+ nextCursor = payload.data.nextCursor;
941
+ cursor = nextCursor ?? void 0;
942
+ } while (options.all === true && nextCursor);
943
+ const output = { items, nextCursor: options.all === true ? null : nextCursor };
944
+ if (isJson(command, options)) {
945
+ writeJson(output);
946
+ return;
947
+ }
948
+ if (items.length === 0) {
949
+ console.log("No automations found.");
950
+ return;
951
+ }
952
+ for (const rule of items) {
953
+ console.log(
954
+ `${rule.id} ${rule.repoOwner}/${rule.repoName} ${rule.normalizedCron} ${String(rule.enabled)} ${formatTime(rule.nextFireAt)}`
955
+ );
956
+ }
957
+ if (output.nextCursor) console.log(`Next cursor: ${output.nextCursor}`);
958
+ }
959
+ async function deleteAutomationCommand(id, options, command) {
960
+ if (isJson(command, options) && options.yes !== true) {
961
+ throw new CliError("user", "`automations delete --json` requires --yes.");
962
+ }
963
+ if (options.yes !== true) {
964
+ await confirmOrThrow(`Delete automation ${id}?`);
965
+ }
966
+ const runtime = getRuntimeOptions(command, options);
967
+ const config = requireConfig(runtime);
968
+ await automationApiFetchText(config, `/api/automation/schedules/${encodeURIComponent(id)}`, { method: "DELETE" });
969
+ if (isJson(command, options)) {
970
+ writeJson({ ok: true, id });
971
+ return;
972
+ }
973
+ console.log(`Deleted automation ${id}.`);
974
+ }
975
+ function parseAutomationRepo(value) {
976
+ if (/^git@/i.test(value) && !/^git@github\.com:/i.test(value)) {
977
+ throw new CliError("user", "repo-url must be owner/name or a GitHub URL.");
978
+ }
979
+ const parsed = parseGithubRepoFullName(value);
980
+ if (!parsed) throw new CliError("user", "repo-url must be owner/name or a GitHub URL.");
981
+ return { owner: parsed.owner, repo: parsed.repo };
982
+ }
983
+ function resolveAutomationModelBackend(rawModel, normalizedModel) {
984
+ if (normalizedModel) {
985
+ const backend = getAgentRuntimeBackendForModel(normalizedModel);
986
+ if (backend) return backend;
987
+ }
988
+ const provider = rawModel.match(/^([a-z]+)[/:]/i)?.[1]?.toLowerCase();
989
+ if (provider === "anthropic") return CLAUDE_CODE_AGENT_RUNTIME_BACKEND;
990
+ if (provider === "baseten") return OPENCODE_AGENT_RUNTIME_BACKEND;
991
+ return CODEX_AGENT_RUNTIME_BACKEND;
992
+ }
993
+ async function automationApiFetch(config, path, init) {
994
+ try {
995
+ return await apiFetch(config, path, init);
996
+ } catch (err) {
997
+ throw mapAutomationApiError(err);
998
+ }
999
+ }
1000
+ async function automationApiFetchText(config, path, init) {
1001
+ try {
1002
+ return await apiFetchText(config, path, init);
1003
+ } catch (err) {
1004
+ throw mapAutomationApiError(err);
1005
+ }
1006
+ }
1007
+ function mapAutomationApiError(err) {
1008
+ if (!(err instanceof ApiError)) {
1009
+ return err instanceof CliError ? err : new CliError("server", err instanceof Error ? err.message : String(err));
1010
+ }
1011
+ const parsed = parseApiErrorBody2(err.body);
1012
+ const serverCode = parsed?.error;
1013
+ return new CliError(codeForStatus(err.status), parsed?.message || serverCode || err.message, {
1014
+ exitCode: err.exitCode,
1015
+ hint: serverCode ? AUTOMATION_ERROR_HINTS[serverCode] : void 0,
1016
+ requestId: err.requestId
1017
+ });
1018
+ }
1019
+ function parseApiErrorBody2(body) {
1020
+ try {
1021
+ const parsed = JSON.parse(body);
1022
+ if (!parsed || typeof parsed !== "object") return null;
1023
+ const record = parsed;
1024
+ return {
1025
+ error: typeof record.error === "string" ? record.error : void 0,
1026
+ message: typeof record.message === "string" ? record.message : void 0
1027
+ };
1028
+ } catch {
1029
+ return null;
1030
+ }
1031
+ }
1032
+ function codeForStatus(status) {
1033
+ if (status === 401 || status === 403) return "auth";
1034
+ if (status === 404) return "not_found";
1035
+ if (status === 409) return "conflict";
1036
+ if (status >= 500) return "server";
1037
+ return "user";
1038
+ }
1039
+ function printAutomationRule(rule) {
1040
+ console.log(`ID: ${rule.id}`);
1041
+ console.log(`Repo: ${rule.repoOwner}/${rule.repoName}`);
1042
+ console.log(`Cron: ${rule.normalizedCron}`);
1043
+ if (rule.modelId) console.log(`Model: ${rule.modelId}`);
1044
+ console.log(`Next fire: ${formatTime(rule.nextFireAt)}`);
1045
+ }
1046
+ function formatTime(value) {
1047
+ return typeof value === "number" ? new Date(value).toISOString() : "none";
1048
+ }
1049
+
1021
1050
  // ../../shared/utils/timing.ts
1022
1051
  function sleep(ms) {
1023
1052
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -1351,6 +1380,28 @@ function getRawSessionEventKind(event) {
1351
1380
  return bridgeEventType ?? event.phase;
1352
1381
  }
1353
1382
  }
1383
+ function getRawSessionEventTimestamp(event) {
1384
+ if (isCanonicalRawSessionEvent(event)) {
1385
+ return Number.isFinite(event.timestampMs) && Number.isFinite(new Date(event.timestampMs).getTime()) ? new Date(event.timestampMs).toISOString() : void 0;
1386
+ }
1387
+ const dataTimestamp = event.data?.timestamp;
1388
+ if (typeof dataTimestamp === "string" && dataTimestamp.length > 0 || typeof dataTimestamp === "number") {
1389
+ const parsed = new Date(dataTimestamp);
1390
+ if (Number.isFinite(parsed.getTime())) return parsed.toISOString();
1391
+ }
1392
+ const topLevelTimestamp = event.timestamp;
1393
+ if (typeof topLevelTimestamp === "string" && topLevelTimestamp.length > 0 || typeof topLevelTimestamp === "number") {
1394
+ const parsed = new Date(topLevelTimestamp);
1395
+ if (Number.isFinite(parsed.getTime())) return parsed.toISOString();
1396
+ }
1397
+ return void 0;
1398
+ }
1399
+ function getRawSessionEventTimestampMs(event) {
1400
+ const iso = getRawSessionEventTimestamp(event);
1401
+ if (!iso) return void 0;
1402
+ const ms = Date.parse(iso);
1403
+ return Number.isFinite(ms) ? ms : void 0;
1404
+ }
1354
1405
  function getRawSessionEventData(event) {
1355
1406
  if (!isCanonicalRawSessionEvent(event)) {
1356
1407
  return isRecord(event.data) ? event.data : void 0;
@@ -1500,7 +1551,7 @@ function canAppendAcrossNonContentInterstitials(events, state, key, existingIdx)
1500
1551
  function resolvePromptId(data) {
1501
1552
  return typeof data?.promptId === "string" ? data.promptId : void 0;
1502
1553
  }
1503
- function coalesceStreamDelta(events, state, type, streamId, text, promptId) {
1554
+ function coalesceStreamDelta(events, state, type, streamId, text, promptId, timestampMs) {
1504
1555
  const key = streamableKey(type, streamId);
1505
1556
  const existingText = state.concatByStreamId.get(key) ?? "";
1506
1557
  const existingIdx = state.streamableIndexById.get(key);
@@ -1511,6 +1562,10 @@ function coalesceStreamDelta(events, state, type, streamId, text, promptId) {
1511
1562
  existing.text += text;
1512
1563
  state.concatByStreamId.set(key, existingText + text);
1513
1564
  if (!existing.promptId && promptId) existing.promptId = promptId;
1565
+ if (existing.type === "reasoning" && timestampMs !== void 0) {
1566
+ if (existing.startedAtMs === void 0) existing.startedAtMs = timestampMs;
1567
+ existing.endedAtMs = timestampMs;
1568
+ }
1514
1569
  return true;
1515
1570
  }
1516
1571
  if (existingIdx === events.length - 1 || !appendableText) return false;
@@ -1536,7 +1591,8 @@ function coalesceStreamDelta(events, state, type, streamId, text, promptId) {
1536
1591
  id: resolveSegmentId(streamId, segmentOrdinal),
1537
1592
  ...segmentOrdinal > 0 ? { streamId } : {},
1538
1593
  text,
1539
- ...promptId ? { promptId } : {}
1594
+ ...promptId ? { promptId } : {},
1595
+ ...timestampMs !== void 0 ? { startedAtMs: timestampMs, endedAtMs: timestampMs } : {}
1540
1596
  });
1541
1597
  }
1542
1598
  return true;
@@ -1810,14 +1866,15 @@ function projectPatch(data, index) {
1810
1866
  ...resolvePromptId(data) ? { promptId: resolvePromptId(data) } : {}
1811
1867
  };
1812
1868
  }
1813
- function projectStream(type, data, state) {
1869
+ function projectStream(type, data, state, timestampMs) {
1814
1870
  coalesceStreamDelta(
1815
1871
  state.merged,
1816
1872
  state.streams,
1817
1873
  type,
1818
1874
  resolveEventId(data, type, state.merged.length),
1819
1875
  resolveTextValue(data),
1820
- resolvePromptId(data)
1876
+ resolvePromptId(data),
1877
+ timestampMs
1821
1878
  );
1822
1879
  }
1823
1880
  function projectToolCall(data, state) {
@@ -1959,7 +2016,7 @@ function flattenSessionEvents(raw) {
1959
2016
  pushEvent(state, projectRawCodex(data, state.merged.length));
1960
2017
  break;
1961
2018
  case "reasoning":
1962
- projectStream("reasoning", data, state);
2019
+ projectStream("reasoning", data, state, getRawSessionEventTimestampMs(normalized.raw));
1963
2020
  break;
1964
2021
  case "text":
1965
2022
  projectStream("text", data, state);
@@ -4697,11 +4754,15 @@ Examples:
4697
4754
  `
4698
4755
  ).action((sessionId, options, command) => usageCommand(sessionId, options, command));
4699
4756
  var automations = program.command("automations").description("Automation commands");
4700
- automations.command("create").description("Create a scheduled automation").argument("<repo-url>", "Repository URL").argument("[prompt]", "Prompt to run, or '-' to read stdin").requiredOption("--cron <expr>", "Cron expression").option("--name <name>", "Automation display name").option("--prompt-stdin", "Read prompt from stdin").addHelpText(
4757
+ automations.command("create").description("Create a scheduled automation").argument("<repo-url>", "Repository URL").argument("[prompt]", "Prompt to run, or '-' to read stdin").requiredOption("--cron <expr>", "Cron expression").option("--name <name>", "Automation display name").option(
4758
+ "--model <model>",
4759
+ "Model to pin for this automation's sessions (e.g. gpt-5.5, claude-opus-4-8). Defaults to the codex backend default."
4760
+ ).option("--prompt-stdin", "Read prompt from stdin").addHelpText(
4701
4761
  "after",
4702
4762
  `
4703
4763
  Examples:
4704
4764
  arcanist automations create tryarcanist/arcanist "summarize regressions" --cron "*/15 * * * *"
4765
+ arcanist automations create tryarcanist/arcanist "audit N+1s" --cron "0 13 * * 5" --model gpt-5.5
4705
4766
  printf "summarize regressions" | arcanist automations create tryarcanist/arcanist --prompt-stdin --cron "*/15 * * * *" --json
4706
4767
  `
4707
4768
  ).action((repoUrl, prompt, options, command) => createAutomationCommand(repoUrl, prompt, options, command));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tryarcanist/cli",
3
- "version": "0.1.163",
3
+ "version": "0.1.165",
4
4
  "description": "CLI for Arcanist — create and manage coding agent sessions",
5
5
  "type": "module",
6
6
  "bin": {