@great-arrow/cli 0.1.39 → 0.1.41

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 +230 -120
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -706,7 +706,7 @@ var require_graceful_fs = __commonJS({
706
706
  }
707
707
  function ReadStream$open() {
708
708
  var that = this;
709
- open(that.path, that.flags, that.mode, function(err, fd) {
709
+ open2(that.path, that.flags, that.mode, function(err, fd) {
710
710
  if (err) {
711
711
  if (that.autoClose)
712
712
  that.destroy();
@@ -726,7 +726,7 @@ var require_graceful_fs = __commonJS({
726
726
  }
727
727
  function WriteStream$open() {
728
728
  var that = this;
729
- open(that.path, that.flags, that.mode, function(err, fd) {
729
+ open2(that.path, that.flags, that.mode, function(err, fd) {
730
730
  if (err) {
731
731
  that.destroy();
732
732
  that.emit("error", err);
@@ -743,8 +743,8 @@ var require_graceful_fs = __commonJS({
743
743
  return new fs7.WriteStream(path10, options);
744
744
  }
745
745
  var fs$open = fs7.open;
746
- fs7.open = open;
747
- function open(path10, flags, mode, cb) {
746
+ fs7.open = open2;
747
+ function open2(path10, flags, mode, cb) {
748
748
  if (typeof mode === "function")
749
749
  cb = mode, mode = null;
750
750
  return go$open(path10, flags, mode, cb);
@@ -1964,7 +1964,7 @@ var require_minimist = __commonJS({
1964
1964
  var require_rc = __commonJS({
1965
1965
  "node_modules/.pnpm/rc@1.2.8/node_modules/rc/index.js"(exports, module) {
1966
1966
  var cc = require_utils();
1967
- var join7 = __require("path").join;
1967
+ var join8 = __require("path").join;
1968
1968
  var deepExtend = require_deep_extend();
1969
1969
  var etc = "/etc";
1970
1970
  var win = process.platform === "win32";
@@ -1989,15 +1989,15 @@ var require_rc = __commonJS({
1989
1989
  }
1990
1990
  if (!win)
1991
1991
  [
1992
- join7(etc, name, "config"),
1993
- join7(etc, name + "rc")
1992
+ join8(etc, name, "config"),
1993
+ join8(etc, name + "rc")
1994
1994
  ].forEach(addConfigFile);
1995
1995
  if (home)
1996
1996
  [
1997
- join7(home, ".config", name, "config"),
1998
- join7(home, ".config", name),
1999
- join7(home, "." + name, "config"),
2000
- join7(home, "." + name + "rc")
1997
+ join8(home, ".config", name, "config"),
1998
+ join8(home, ".config", name),
1999
+ join8(home, "." + name, "config"),
2000
+ join8(home, "." + name + "rc")
2001
2001
  ].forEach(addConfigFile);
2002
2002
  addConfigFile(cc.find("." + name + "rc"));
2003
2003
  if (env4.config) addConfigFile(env4.config);
@@ -2680,7 +2680,7 @@ var require_graceful_fs2 = __commonJS({
2680
2680
  }
2681
2681
  function ReadStream$open() {
2682
2682
  var that = this;
2683
- open(that.path, that.flags, that.mode, function(err, fd) {
2683
+ open2(that.path, that.flags, that.mode, function(err, fd) {
2684
2684
  if (err) {
2685
2685
  if (that.autoClose)
2686
2686
  that.destroy();
@@ -2700,7 +2700,7 @@ var require_graceful_fs2 = __commonJS({
2700
2700
  }
2701
2701
  function WriteStream$open() {
2702
2702
  var that = this;
2703
- open(that.path, that.flags, that.mode, function(err, fd) {
2703
+ open2(that.path, that.flags, that.mode, function(err, fd) {
2704
2704
  if (err) {
2705
2705
  that.destroy();
2706
2706
  that.emit("error", err);
@@ -2717,8 +2717,8 @@ var require_graceful_fs2 = __commonJS({
2717
2717
  return new fs7.WriteStream(path10, options);
2718
2718
  }
2719
2719
  var fs$open = fs7.open;
2720
- fs7.open = open;
2721
- function open(path10, flags, mode, cb) {
2720
+ fs7.open = open2;
2721
+ function open2(path10, flags, mode, cb) {
2722
2722
  if (typeof mode === "function")
2723
2723
  cb = mode, mode = null;
2724
2724
  return go$open(path10, flags, mode, cb);
@@ -9399,7 +9399,7 @@ function isNodeError(value) {
9399
9399
 
9400
9400
  // src/lib/version.ts
9401
9401
  var CLI_PACKAGE_NAME = "@great-arrow/cli";
9402
- var CLI_VERSION = "0.1.39";
9402
+ var CLI_VERSION = "0.1.41";
9403
9403
  var GAD_INSTALL_VERSION = "2026.08.08";
9404
9404
  var GAD_INSTALL_MIN_VERSION = "2026.06.22";
9405
9405
  var GAD_INSTALL_HEADER = "X-GAD-Install-Version";
@@ -10000,10 +10000,10 @@ function isColorEnabled(noColorFlag) {
10000
10000
  }
10001
10001
  function createColor(noColorFlag) {
10002
10002
  const enabled2 = isColorEnabled(noColorFlag);
10003
- const wrap = (open, close) => {
10003
+ const wrap = (open2, close) => {
10004
10004
  return (text2) => {
10005
10005
  if (!enabled2) return text2;
10006
- return `\x1B[${open}m${text2}\x1B[${close}m`;
10006
+ return `\x1B[${open2}m${text2}\x1B[${close}m`;
10007
10007
  };
10008
10008
  };
10009
10009
  return {
@@ -10306,9 +10306,68 @@ var logoutCommand = new Command("logout").description("Remove stored authenticat
10306
10306
  });
10307
10307
 
10308
10308
  // src/lib/auth.ts
10309
+ import { mkdir as mkdir3, open, rm, stat } from "node:fs/promises";
10310
+ import { homedir as homedir3 } from "node:os";
10311
+ import { join as join3 } from "node:path";
10309
10312
  var DEFAULT_API_URL2 = "https://www.greatarrow.ai";
10310
10313
  var REFRESH_SKEW_MS = 12e4;
10311
10314
  var inflightRefresh = null;
10315
+ var REFRESH_LOCK_STALE_MS = 15e3;
10316
+ var REFRESH_LOCK_WAIT_MS = 5e3;
10317
+ var REFRESH_LOCK_POLL_MS = 100;
10318
+ function refreshLockPath() {
10319
+ return join3(homedir3(), ".great-arrow", "refresh.lock");
10320
+ }
10321
+ async function acquireRefreshLock() {
10322
+ const path10 = refreshLockPath();
10323
+ try {
10324
+ await mkdir3(join3(homedir3(), ".great-arrow"), { recursive: true });
10325
+ } catch (err) {
10326
+ debugSwallow("refresh-lock.mkdir", err);
10327
+ }
10328
+ const deadline = Date.now() + REFRESH_LOCK_WAIT_MS;
10329
+ for (; ; ) {
10330
+ try {
10331
+ const handle = await open(path10, "wx");
10332
+ await handle.writeFile(String(process.pid));
10333
+ await handle.close();
10334
+ return true;
10335
+ } catch (err) {
10336
+ if (err.code !== "EEXIST") return true;
10337
+ }
10338
+ const age = await stat(path10).then((st) => Date.now() - st.mtimeMs).catch(() => Number.POSITIVE_INFINITY);
10339
+ if (age > REFRESH_LOCK_STALE_MS) {
10340
+ try {
10341
+ await rm(path10, { force: true });
10342
+ } catch (err) {
10343
+ debugSwallow("refresh-lock.stale-rm", err);
10344
+ }
10345
+ continue;
10346
+ }
10347
+ if (Date.now() >= deadline) return false;
10348
+ await new Promise((r) => setTimeout(r, REFRESH_LOCK_POLL_MS));
10349
+ }
10350
+ }
10351
+ async function releaseRefreshLock() {
10352
+ try {
10353
+ await rm(refreshLockPath(), { force: true });
10354
+ } catch (err) {
10355
+ debugSwallow("refresh-lock.release", err);
10356
+ }
10357
+ }
10358
+ async function rotatedByAnotherProcess(ours) {
10359
+ let stored = null;
10360
+ try {
10361
+ stored = await loadStoredCredential();
10362
+ } catch (err) {
10363
+ debugSwallow("refresh.reread", err);
10364
+ }
10365
+ if (stored?.kind !== "oauth") return null;
10366
+ const theirs = stored.credential;
10367
+ if (theirs.refreshToken === ours.refreshToken) return null;
10368
+ if (Date.now() >= theirs.accessExpiresAt - REFRESH_SKEW_MS) return null;
10369
+ return theirs;
10370
+ }
10312
10371
  async function resolveAuth() {
10313
10372
  const config = await loadConfig();
10314
10373
  const configApiUrl = config.api_url || DEFAULT_API_URL2;
@@ -10367,7 +10426,10 @@ async function ensureFreshAccessToken(credential) {
10367
10426
  }
10368
10427
  }
10369
10428
  async function doRefresh(credential) {
10429
+ const held = await acquireRefreshLock();
10370
10430
  try {
10431
+ const theirs = await rotatedByAnotherProcess(credential);
10432
+ if (theirs) return theirs;
10371
10433
  const refreshed = await refreshTokens({
10372
10434
  apiUrl: credential.apiUrl,
10373
10435
  clientId: credential.clientId,
@@ -10381,6 +10443,8 @@ async function doRefresh(credential) {
10381
10443
  throw sessionExpired();
10382
10444
  }
10383
10445
  throw err;
10446
+ } finally {
10447
+ if (held) await releaseRefreshLock();
10384
10448
  }
10385
10449
  }
10386
10450
  function sessionExpired() {
@@ -12198,7 +12262,7 @@ var work_default = workCommand;
12198
12262
  // src/commands/worktree.ts
12199
12263
  import { execFileSync as execFileSync3 } from "node:child_process";
12200
12264
  import { existsSync, readFileSync as readFileSync2, statSync, writeFileSync } from "node:fs";
12201
- import { basename, dirname as dirname3, isAbsolute, join as join3, resolve } from "node:path";
12265
+ import { basename, dirname as dirname3, isAbsolute, join as join4, resolve } from "node:path";
12202
12266
  var realExec = (cmd, args, opts) => {
12203
12267
  const out = execFileSync3(cmd, args, {
12204
12268
  cwd: opts?.cwd,
@@ -12220,9 +12284,9 @@ function parseDefaultBranch(symbolicRef) {
12220
12284
  return match ? match[1] : null;
12221
12285
  }
12222
12286
  function detectPackageManager(repoRoot) {
12223
- if (existsSync(join3(repoRoot, "pnpm-lock.yaml"))) return "pnpm";
12224
- if (existsSync(join3(repoRoot, "bun.lockb"))) return "bun";
12225
- if (existsSync(join3(repoRoot, "yarn.lock"))) return "yarn";
12287
+ if (existsSync(join4(repoRoot, "pnpm-lock.yaml"))) return "pnpm";
12288
+ if (existsSync(join4(repoRoot, "bun.lockb"))) return "bun";
12289
+ if (existsSync(join4(repoRoot, "yarn.lock"))) return "yarn";
12226
12290
  return "npm";
12227
12291
  }
12228
12292
  function defaultWorktreeDir(repoRoot, branch) {
@@ -12230,7 +12294,7 @@ function defaultWorktreeDir(repoRoot, branch) {
12230
12294
  /[^A-Za-z0-9._-]+/g,
12231
12295
  "-"
12232
12296
  );
12233
- return join3(dirname3(repoRoot), `${basename(repoRoot)}-${slug}`);
12297
+ return join4(dirname3(repoRoot), `${basename(repoRoot)}-${slug}`);
12234
12298
  }
12235
12299
  var AGENT_PROCESS_RE = /(^|\/)(claude|kiro|cursor|codex)/i;
12236
12300
  function psField(pid, field) {
@@ -12253,7 +12317,7 @@ function findAgentPid(startPid) {
12253
12317
  return null;
12254
12318
  }
12255
12319
  function ownGitDir(worktreeDir) {
12256
- const dotGit = join3(worktreeDir, ".git");
12320
+ const dotGit = join4(worktreeDir, ".git");
12257
12321
  if (!existsSync(dotGit)) return null;
12258
12322
  if (statSync(dotGit).isDirectory()) return dotGit;
12259
12323
  const match = readFileSync2(dotGit, "utf8").trim().match(/^gitdir:\s*(.+)$/m);
@@ -12268,7 +12332,7 @@ function stampWorktreeOwner(worktreeDir) {
12268
12332
  const ownerPid = findAgentPid(process.ppid);
12269
12333
  if (!ownerPid) return null;
12270
12334
  writeFileSync(
12271
- join3(gitDir, "agent-owner.json"),
12335
+ join4(gitDir, "agent-owner.json"),
12272
12336
  JSON.stringify(
12273
12337
  {
12274
12338
  ownerPid,
@@ -12362,7 +12426,7 @@ function createTaskWorktree(opts) {
12362
12426
  const stampedPid = opts.stamp === false ? null : stampWorktreeOwner(dir);
12363
12427
  const packageManager = detectPackageManager(repoRoot);
12364
12428
  let installed = false;
12365
- if (opts.install !== false && existsSync(join3(repoRoot, "package.json"))) {
12429
+ if (opts.install !== false && existsSync(join4(repoRoot, "package.json"))) {
12366
12430
  exec2(packageManager, ["install"], { cwd: dir, inherit: true });
12367
12431
  installed = true;
12368
12432
  }
@@ -12431,7 +12495,7 @@ import {
12431
12495
  readFileSync as readFileSync3,
12432
12496
  writeFileSync as writeFileSync2
12433
12497
  } from "node:fs";
12434
- import { isAbsolute as isAbsolute2, join as join4, resolve as resolve2 } from "node:path";
12498
+ import { isAbsolute as isAbsolute2, join as join5, resolve as resolve2 } from "node:path";
12435
12499
  var GUARD_MARKER = "# gad-agent-guard v1";
12436
12500
  var SCHEMA_AUDIT_MARKER = "# gad-schema-audit v1";
12437
12501
  var GUARD_FILE = "gad-commit-guard.mjs";
@@ -12614,22 +12678,22 @@ function installCommitGuard(opts) {
12614
12678
  );
12615
12679
  }
12616
12680
  if (!isAbsolute2(commonDir)) commonDir = resolve2(repoRoot, commonDir);
12617
- const hooksDir = join4(commonDir, "hooks");
12681
+ const hooksDir = join5(commonDir, "hooks");
12618
12682
  mkdirSync(hooksDir, { recursive: true });
12619
- const guardPath = join4(hooksDir, GUARD_FILE);
12683
+ const guardPath = join5(hooksDir, GUARD_FILE);
12620
12684
  writeFileSync2(guardPath, buildGuardScript());
12621
12685
  chmodSync(guardPath, 493);
12622
- const huskyHook = join4(repoRoot, ".husky", "pre-commit");
12623
- const hookPath = existsSync2(huskyHook) ? huskyHook : join4(hooksDir, "pre-commit");
12686
+ const huskyHook = join5(repoRoot, ".husky", "pre-commit");
12687
+ const hookPath = existsSync2(huskyHook) ? huskyHook : join5(hooksDir, "pre-commit");
12624
12688
  const existing = existsSync2(hookPath) ? readFileSync3(hookPath, "utf8") : null;
12625
12689
  const plan = planHookInstall(existing);
12626
12690
  if (plan.action !== "noop") {
12627
12691
  writeFileSync2(hookPath, plan.content);
12628
12692
  }
12629
12693
  chmodSync(hookPath, 493);
12630
- const huskyDir = join4(repoRoot, ".husky");
12631
- const huskyPrePush = join4(huskyDir, "pre-push");
12632
- const schemaAuditHookPath = existsSync2(huskyPrePush) || existsSync2(huskyDir) ? huskyPrePush : join4(hooksDir, "pre-push");
12694
+ const huskyDir = join5(repoRoot, ".husky");
12695
+ const huskyPrePush = join5(huskyDir, "pre-push");
12696
+ const schemaAuditHookPath = existsSync2(huskyPrePush) || existsSync2(huskyDir) ? huskyPrePush : join5(hooksDir, "pre-push");
12633
12697
  const existingSchemaAuditHook = existsSync2(schemaAuditHookPath) ? readFileSync3(schemaAuditHookPath, "utf8") : null;
12634
12698
  const schemaAuditPlan = planSchemaAuditHookInstall(existingSchemaAuditHook);
12635
12699
  if (schemaAuditPlan.action !== "noop") {
@@ -12752,9 +12816,9 @@ function guardrailsCommand() {
12752
12816
 
12753
12817
  // src/commands/doctor.ts
12754
12818
  import { existsSync as existsSync3 } from "node:fs";
12755
- import { copyFile, mkdir as mkdir3, readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
12756
- import { homedir as homedir3 } from "node:os";
12757
- import { dirname as dirname4, join as join5 } from "node:path";
12819
+ import { copyFile, mkdir as mkdir4, readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
12820
+ import { homedir as homedir4 } from "node:os";
12821
+ import { dirname as dirname4, join as join6 } from "node:path";
12758
12822
 
12759
12823
  // src/lib/codex-config.ts
12760
12824
  import { execFileSync as execFileSync5 } from "node:child_process";
@@ -13543,6 +13607,53 @@ function inspectConfiguredHooks(hooks, deps) {
13543
13607
 
13544
13608
  // src/lib/mcp-doctor.ts
13545
13609
  import { createHash as createHash2 } from "node:crypto";
13610
+
13611
+ // src/lib/mcp-target.ts
13612
+ var GREAT_ARROW_HOSTS = /* @__PURE__ */ new Set([
13613
+ "greatarrow.ai",
13614
+ "www.greatarrow.ai",
13615
+ "greatarrowdigital.com",
13616
+ "www.greatarrowdigital.com"
13617
+ ]);
13618
+ function isGreatArrowEndpoint(value) {
13619
+ if (typeof value !== "string") return false;
13620
+ try {
13621
+ const url = new URL(value);
13622
+ return (url.protocol === "https:" || url.protocol === "http:") && GREAT_ARROW_HOSTS.has(url.hostname) && /^\/api\/mcp\/?$/.test(url.pathname);
13623
+ } catch {
13624
+ return false;
13625
+ }
13626
+ }
13627
+ function isGreatArrowExecutable(value) {
13628
+ if (typeof value !== "string") return false;
13629
+ return /^@great-arrow\/(?:cli|mcp-server)(?:@[^\s]+)?$/.test(value) || /(?:^|[/\\])(?:\.great-arrow|great-arrow-digital[/\\]scripts)[/\\]mcp-server\.mjs$/.test(
13630
+ value
13631
+ );
13632
+ }
13633
+ function tomlString(raw) {
13634
+ if (raw.startsWith("'")) return raw.slice(1, -1);
13635
+ try {
13636
+ const value = JSON.parse(raw);
13637
+ return typeof value === "string" ? value : void 0;
13638
+ } catch {
13639
+ return void 0;
13640
+ }
13641
+ }
13642
+ function codexTransportFields(body) {
13643
+ const entry = {};
13644
+ for (const match of body.matchAll(
13645
+ /^\s*(url|command)\s*=\s*("(?:\\.|[^"\\\r\n])*"|'[^'\r\n]*')/gm
13646
+ )) {
13647
+ entry[match[1]] = tomlString(match[2]);
13648
+ }
13649
+ const args = body.match(/^\s*args\s*=\s*\[([\s\S]*?)\]/m)?.[1];
13650
+ if (args !== void 0) {
13651
+ entry.args = [...args.matchAll(/"(?:\\.|[^"\\])*"|'[^']*'|#[^\r\n]*/g)].filter((match) => !match[0].startsWith("#")).map((match) => tomlString(match[0]));
13652
+ }
13653
+ return entry;
13654
+ }
13655
+
13656
+ // src/lib/mcp-doctor.ts
13546
13657
  var MCP_FAILURE_MESSAGE = {
13547
13658
  auth: "MCP rejected this machine's credential (401/403)",
13548
13659
  network: "Could not reach the MCP endpoint",
@@ -13665,21 +13776,17 @@ function knownConfigLocations(home, cwd, platform = process.platform, appData) {
13665
13776
  ];
13666
13777
  }
13667
13778
  var GREAT_ARROW_NAME = /great[-_ ]?arrow|ai[-_]memory/i;
13668
- var GREAT_ARROW_REF = /great[-_ ]?arrow|greatarrow|greatarrowdigital/i;
13669
13779
  function asObject2(value) {
13670
13780
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
13671
13781
  }
13672
13782
  function isGreatArrowServer(name, entry) {
13673
13783
  if (GREAT_ARROW_NAME.test(name)) return true;
13674
- const target = JSON.stringify([
13675
- entry.url,
13676
- entry.httpUrl,
13677
- entry.serverUrl,
13678
- entry.args,
13679
- entry.command,
13680
- entry.env
13681
- ]);
13682
- return GREAT_ARROW_REF.test(target);
13784
+ if ([entry.url, entry.httpUrl, entry.serverUrl].some(isGreatArrowEndpoint)) {
13785
+ return true;
13786
+ }
13787
+ return [entry.command, ...Array.isArray(entry.args) ? entry.args : []].some(
13788
+ isGreatArrowExecutable
13789
+ );
13683
13790
  }
13684
13791
  function classifySurface(entry, clientId, hooksInstalled) {
13685
13792
  if (typeof entry.command === "string" && entry.command.length > 0) {
@@ -13706,15 +13813,18 @@ function serverMapsFromJson(parsed, serversKey) {
13706
13813
  }
13707
13814
  function findCodexEntries(location, content) {
13708
13815
  const entries = [];
13709
- const sections = content.split(/^\s*\[(?=mcp_servers)/m).slice(1);
13816
+ const sections = content.split(/^\s*\[/m).slice(1);
13710
13817
  const seen = /* @__PURE__ */ new Set();
13711
13818
  for (const raw of sections) {
13712
13819
  const header = raw.slice(0, raw.indexOf("]"));
13713
- const match = header.match(/^mcp_servers\.(?:"([^"]+)"|([^.\s\]]+))/);
13714
- const name = match?.[1] ?? match?.[2];
13820
+ const match = header.match(
13821
+ /^mcp_servers\.(?:"([^"]+)"|'([^']+)'|([^.\s\]]+))$/
13822
+ );
13823
+ const name = match?.[1] ?? match?.[2] ?? match?.[3];
13715
13824
  if (!name || seen.has(name)) continue;
13716
13825
  const body = raw.slice(raw.indexOf("]") + 1);
13717
- if (!GREAT_ARROW_NAME.test(name) && !GREAT_ARROW_REF.test(body)) continue;
13826
+ const transport = codexTransportFields(body);
13827
+ if (!isGreatArrowServer(name, transport)) continue;
13718
13828
  seen.add(name);
13719
13829
  entries.push({
13720
13830
  clientId: location.clientId,
@@ -13722,7 +13832,7 @@ function findCodexEntries(location, content) {
13722
13832
  scope: location.scope,
13723
13833
  path: location.path,
13724
13834
  serverName: name,
13725
- surface: /^\s*command\s*=/m.test(body) ? "stdio" : "http"
13835
+ surface: typeof transport.command === "string" ? "stdio" : "http"
13726
13836
  });
13727
13837
  }
13728
13838
  return entries;
@@ -14239,7 +14349,7 @@ async function checkMcp(auth) {
14239
14349
  }
14240
14350
  }
14241
14351
  function defaultCodexConfigPath() {
14242
- return join5(homedir3(), ".codex", "config.toml");
14352
+ return join6(homedir4(), ".codex", "config.toml");
14243
14353
  }
14244
14354
  function codexIssuesToChecks(issues) {
14245
14355
  return issues.map((issue) => {
@@ -14283,7 +14393,7 @@ function codexCommand() {
14283
14393
  if (options.enforce) {
14284
14394
  const apiUrl = extractCodexGreatArrowApiUrl(content) ?? (await resolveAuth()).apiUrl;
14285
14395
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
14286
- await mkdir3(dirname4(configPath), { recursive: true });
14396
+ await mkdir4(dirname4(configPath), { recursive: true });
14287
14397
  if (content.trim()) {
14288
14398
  backupPath = `${configPath}.bak.${timestamp}`;
14289
14399
  await copyFile(configPath, backupPath);
@@ -14377,12 +14487,12 @@ function claudeCommand() {
14377
14487
  isTTY: isTTY(),
14378
14488
  noColor: g.noColor
14379
14489
  });
14380
- const home = homedir3();
14381
- const gaDir = join5(home, ".great-arrow");
14382
- const userConfigPath = join5(home, ".claude.json");
14383
- const settingsPath = join5(home, ".claude", "settings.json");
14384
- const hookConfigPath = join5(gaDir, "hook-config.json");
14385
- const glanceHookPath = join5(gaDir, "claude-glance-hook.mjs");
14490
+ const home = homedir4();
14491
+ const gaDir = join6(home, ".great-arrow");
14492
+ const userConfigPath = join6(home, ".claude.json");
14493
+ const settingsPath = join6(home, ".claude", "settings.json");
14494
+ const hookConfigPath = join6(gaDir, "hook-config.json");
14495
+ const glanceHookPath = join6(gaDir, "claude-glance-hook.mjs");
14386
14496
  const checks = [];
14387
14497
  const repairs = [];
14388
14498
  const backups = [];
@@ -14404,7 +14514,7 @@ function claudeCommand() {
14404
14514
  await copyFile(path10, backupPath);
14405
14515
  backups.push(backupPath);
14406
14516
  }
14407
- await mkdir3(dirname4(path10), { recursive: true });
14517
+ await mkdir4(dirname4(path10), { recursive: true });
14408
14518
  await writeFile3(path10, content, "utf8");
14409
14519
  };
14410
14520
  let auth = null;
@@ -14451,7 +14561,7 @@ function claudeCommand() {
14451
14561
  { signal: AbortSignal.timeout(1e4) }
14452
14562
  );
14453
14563
  if (res.ok) {
14454
- await mkdir3(gaDir, { recursive: true });
14564
+ await mkdir4(gaDir, { recursive: true });
14455
14565
  await writeFile3(glanceHookPath, await res.text(), {
14456
14566
  mode: 493
14457
14567
  });
@@ -14590,8 +14700,8 @@ function claudeCommand() {
14590
14700
  file: "/Library/Application Support/ClaudeCode/managed-settings.json"
14591
14701
  },
14592
14702
  { scope: "user", file: settingsPath },
14593
- { scope: "project", file: join5(cwd, ".claude", "settings.json") },
14594
- { scope: "local", file: join5(cwd, ".claude", "settings.local.json") }
14703
+ { scope: "project", file: join6(cwd, ".claude", "settings.json") },
14704
+ { scope: "local", file: join6(cwd, ".claude", "settings.local.json") }
14595
14705
  ];
14596
14706
  const configured = [];
14597
14707
  for (const { scope, file } of scopes) {
@@ -14660,12 +14770,12 @@ function claudeCommand() {
14660
14770
  });
14661
14771
  }
14662
14772
  function defaultJsonClientConfigs() {
14663
- const home = homedir3();
14773
+ const home = homedir4();
14664
14774
  return [
14665
- { name: "Claude Code", path: join5(home, ".claude.json") },
14666
- { name: "Cursor", path: join5(home, ".cursor", "mcp.json") },
14667
- { name: "Kiro", path: join5(home, ".kiro", "settings", "mcp.json") },
14668
- { name: "Gemini CLI", path: join5(home, ".gemini", "settings.json") }
14775
+ { name: "Claude Code", path: join6(home, ".claude.json") },
14776
+ { name: "Cursor", path: join6(home, ".cursor", "mcp.json") },
14777
+ { name: "Kiro", path: join6(home, ".kiro", "settings", "mcp.json") },
14778
+ { name: "Gemini CLI", path: join6(home, ".gemini", "settings.json") }
14669
14779
  ];
14670
14780
  }
14671
14781
  function clientsCommand() {
@@ -15311,14 +15421,14 @@ async function pathExists(path10) {
15311
15421
  }
15312
15422
  }
15313
15423
  async function installCodexConfig(apiUrl, token, repoUrl) {
15314
- const { homedir: homedir5 } = await import("node:os");
15315
- const { join: join7 } = await import("node:path");
15316
- const { chmod, copyFile: copyFile2, mkdir: mkdir5, readFile: readFile5, writeFile: writeFile5 } = await import("node:fs/promises");
15317
- const codexDir = join7(homedir5(), ".codex");
15318
- const configPath = join7(codexDir, "config.toml");
15319
- const envPath = join7(codexDir, ".env");
15424
+ const { homedir: homedir6 } = await import("node:os");
15425
+ const { join: join8 } = await import("node:path");
15426
+ const { chmod, copyFile: copyFile2, mkdir: mkdir6, readFile: readFile5, writeFile: writeFile5 } = await import("node:fs/promises");
15427
+ const codexDir = join8(homedir6(), ".codex");
15428
+ const configPath = join8(codexDir, "config.toml");
15429
+ const envPath = join8(codexDir, ".env");
15320
15430
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
15321
- await mkdir5(codexDir, { recursive: true });
15431
+ await mkdir6(codexDir, { recursive: true });
15322
15432
  const existingConfig = await pathExists(configPath) ? await readFile5(configPath, "utf8") : "";
15323
15433
  if (existingConfig.trim()) {
15324
15434
  await copyFile2(configPath, `${configPath}.bak.${timestamp}`);
@@ -15614,12 +15724,12 @@ var installCommand = new Command("install").description("Generate MCP configurat
15614
15724
  process.stdout.write(configJson2 + "\n");
15615
15725
  return;
15616
15726
  }
15617
- const { homedir: homedir5 } = await import("node:os");
15618
- const { join: join8 } = await import("node:path");
15619
- const { mkdir: mkdir5, readFile: readFile5, writeFile: writeFile6 } = await import("node:fs/promises");
15620
- const geminiDir = join8(homedir5(), ".gemini");
15621
- const mcpPath = join8(geminiDir, "settings.json");
15622
- await mkdir5(geminiDir, { recursive: true });
15727
+ const { homedir: homedir6 } = await import("node:os");
15728
+ const { join: join9 } = await import("node:path");
15729
+ const { mkdir: mkdir6, readFile: readFile5, writeFile: writeFile6 } = await import("node:fs/promises");
15730
+ const geminiDir = join9(homedir6(), ".gemini");
15731
+ const mcpPath = join9(geminiDir, "settings.json");
15732
+ await mkdir6(geminiDir, { recursive: true });
15623
15733
  let existingConfig = {};
15624
15734
  try {
15625
15735
  const content = await readFile5(mcpPath, "utf-8");
@@ -15640,14 +15750,14 @@ var installCommand = new Command("install").description("Generate MCP configurat
15640
15750
  "utf-8"
15641
15751
  );
15642
15752
  fmt.success(`Wrote gemini MCP config to ${mcpPath}`);
15643
- const agyMcpDir = join8(
15753
+ const agyMcpDir = join9(
15644
15754
  geminiDir,
15645
15755
  "antigravity-cli",
15646
15756
  "mcp",
15647
15757
  MCP_SERVER_NAME
15648
15758
  );
15649
- await mkdir5(agyMcpDir, { recursive: true });
15650
- const instructionsPath = join8(agyMcpDir, "instructions.md");
15759
+ await mkdir6(agyMcpDir, { recursive: true });
15760
+ const instructionsPath = join9(agyMcpDir, "instructions.md");
15651
15761
  const instructionsContent = `You are connected to greatarrow.ai - the user's private workspace memory + integrations brain.
15652
15762
 
15653
15763
  CRITICAL DIRECTIVE (MANDATORY STANDARD):
@@ -15679,8 +15789,8 @@ Always assume full autonomy to leverage these tools to their maximum extent.`;
15679
15789
  return;
15680
15790
  }
15681
15791
  const { writeFile: writeFile5 } = await import("node:fs/promises");
15682
- const { join: join7 } = await import("node:path");
15683
- const outputPath = join7(process.cwd(), ".mcp.json");
15792
+ const { join: join8 } = await import("node:path");
15793
+ const outputPath = join8(process.cwd(), ".mcp.json");
15684
15794
  await writeFile5(outputPath, configJson + "\n", { mode: 384 });
15685
15795
  fmt.success(`Wrote ${clientName} MCP config to .mcp.json`);
15686
15796
  if (await mcpJsonAtRiskOfCommit(process.cwd())) {
@@ -15711,13 +15821,13 @@ async function readKeychainOnly() {
15711
15821
  }
15712
15822
  }
15713
15823
  async function resolveProxyScript(override) {
15714
- const { homedir: homedir5 } = await import("node:os");
15715
- const { join: join7 } = await import("node:path");
15824
+ const { homedir: homedir6 } = await import("node:os");
15825
+ const { join: join8 } = await import("node:path");
15716
15826
  const candidates = [
15717
15827
  override,
15718
15828
  process.env.GAD_PROXY_SCRIPT,
15719
- join7(homedir5(), ".great-arrow", "mcp-server.mjs"),
15720
- join7(process.cwd(), "scripts", "mcp-server.mjs")
15829
+ join8(homedir6(), ".great-arrow", "mcp-server.mjs"),
15830
+ join8(process.cwd(), "scripts", "mcp-server.mjs")
15721
15831
  ].filter((c) => Boolean(c));
15722
15832
  for (const candidate of candidates) {
15723
15833
  if (await pathExists(candidate)) return candidate;
@@ -15741,13 +15851,13 @@ async function runProxyDiagnostics(scriptPath) {
15741
15851
  }
15742
15852
  }
15743
15853
  async function findLegacyStores(cwd) {
15744
- const { join: join7 } = await import("node:path");
15854
+ const { join: join8 } = await import("node:path");
15745
15855
  const { readdir } = await import("node:fs/promises");
15746
15856
  const dirs = /* @__PURE__ */ new Set([cwd]);
15747
15857
  try {
15748
- const worktreeRoot = join7(cwd, ".claude", "worktrees");
15858
+ const worktreeRoot = join8(cwd, ".claude", "worktrees");
15749
15859
  for (const entry of await readdir(worktreeRoot, { withFileTypes: true })) {
15750
- if (entry.isDirectory()) dirs.add(join7(worktreeRoot, entry.name));
15860
+ if (entry.isDirectory()) dirs.add(join8(worktreeRoot, entry.name));
15751
15861
  }
15752
15862
  } catch (err) {
15753
15863
  debugSwallow("mcp.findLegacyStores(worktrees)", err);
@@ -15769,18 +15879,18 @@ async function findLegacyStores(cwd) {
15769
15879
  }
15770
15880
  const stores = [];
15771
15881
  for (const dir of dirs) {
15772
- const path10 = join7(dir, ".mcp", OAUTH_CRED_FILENAME);
15882
+ const path10 = join8(dir, ".mcp", OAUTH_CRED_FILENAME);
15773
15883
  const raw = await readIfExists(path10);
15774
15884
  if (raw !== null) stores.push({ path: path10, raw });
15775
15885
  }
15776
15886
  return stores;
15777
15887
  }
15778
15888
  async function scanConnections() {
15779
- const { homedir: homedir5 } = await import("node:os");
15780
- const { join: join7 } = await import("node:path");
15781
- const home = homedir5();
15889
+ const { homedir: homedir6 } = await import("node:os");
15890
+ const { join: join8 } = await import("node:path");
15891
+ const home = homedir6();
15782
15892
  const hookSettings = await readIfExists(
15783
- join7(home, ".claude", "settings.json")
15893
+ join8(home, ".claude", "settings.json")
15784
15894
  );
15785
15895
  const hooksInstalled = hookSettings ? hasGreatArrowHooks(hookSettings) : false;
15786
15896
  const entries = [];
@@ -15813,16 +15923,16 @@ async function probeEndpoint() {
15813
15923
  }
15814
15924
  }
15815
15925
  async function applyMigration(plan) {
15816
- const { homedir: homedir5 } = await import("node:os");
15817
- const { join: join7 } = await import("node:path");
15818
- const { mkdir: mkdir5, rename, writeFile: writeFile5 } = await import("node:fs/promises");
15926
+ const { homedir: homedir6 } = await import("node:os");
15927
+ const { join: join8 } = await import("node:path");
15928
+ const { mkdir: mkdir6, rename, writeFile: writeFile5 } = await import("node:fs/promises");
15819
15929
  const applied = [];
15820
- const dir = join7(homedir5(), ".great-arrow");
15821
- await mkdir5(dir, { recursive: true, mode: 448 });
15930
+ const dir = join8(homedir6(), ".great-arrow");
15931
+ await mkdir6(dir, { recursive: true, mode: 448 });
15822
15932
  if (plan.seedFrom) {
15823
15933
  const raw = await readIfExists(plan.seedFrom);
15824
15934
  if (raw !== null) {
15825
- const target = join7(dir, OAUTH_CRED_FILENAME);
15935
+ const target = join8(dir, OAUTH_CRED_FILENAME);
15826
15936
  const tmp = `${target}.tmp`;
15827
15937
  await writeFile5(tmp, raw, { mode: 384 });
15828
15938
  await rename(tmp, target);
@@ -15832,7 +15942,7 @@ async function applyMigration(plan) {
15832
15942
  if (plan.syncKeychainToFile) {
15833
15943
  const raw = await readKeychainOnly();
15834
15944
  if (raw) {
15835
- const target = join7(dir, "credential");
15945
+ const target = join8(dir, "credential");
15836
15946
  const tmp = `${target}.tmp`;
15837
15947
  await writeFile5(tmp, raw, { mode: 384 });
15838
15948
  await rename(tmp, target);
@@ -15858,19 +15968,19 @@ var doctorSubcommand = new Command("doctor").description(
15858
15968
  noColor: false
15859
15969
  });
15860
15970
  const c = createColor(jsonFlag);
15861
- const { homedir: homedir5 } = await import("node:os");
15862
- const { join: join7 } = await import("node:path");
15863
- const home = homedir5();
15971
+ const { homedir: homedir6 } = await import("node:os");
15972
+ const { join: join8 } = await import("node:path");
15973
+ const home = homedir6();
15864
15974
  const proxyPath = await resolveProxyScript(options.proxy);
15865
15975
  const diagnostics = proxyPath ? await runProxyDiagnostics(proxyPath) : null;
15866
15976
  const entries = await scanConnections();
15867
15977
  const duplicates = detectDuplicates(entries);
15868
15978
  const keychain = await readKeychainOnly();
15869
15979
  const credentialFile = await readIfExists(
15870
- join7(home, ".great-arrow", "credential")
15980
+ join8(home, ".great-arrow", "credential")
15871
15981
  );
15872
15982
  const userStore = await readIfExists(
15873
- join7(home, ".great-arrow", OAUTH_CRED_FILENAME)
15983
+ join8(home, ".great-arrow", OAUTH_CRED_FILENAME)
15874
15984
  );
15875
15985
  const legacyStores = await findLegacyStores(process.cwd());
15876
15986
  const findings = [
@@ -16287,9 +16397,9 @@ function askCommand() {
16287
16397
  }
16288
16398
 
16289
16399
  // src/lib/glance-footer.ts
16290
- import { readFile as readFile4, writeFile as writeFile4, mkdir as mkdir4 } from "node:fs/promises";
16291
- import { homedir as homedir4 } from "node:os";
16292
- import { join as join6, dirname as dirname5 } from "node:path";
16400
+ import { readFile as readFile4, writeFile as writeFile4, mkdir as mkdir5 } from "node:fs/promises";
16401
+ import { homedir as homedir5 } from "node:os";
16402
+ import { join as join7, dirname as dirname5 } from "node:path";
16293
16403
 
16294
16404
  // src/lib/seen.ts
16295
16405
  var SEEN_TIMEOUT_MS = 1e3;
@@ -16619,7 +16729,7 @@ function shouldRequestTip(input) {
16619
16729
  return now - state.lastTipAt >= TIP_THROTTLE_INTERVAL_MS;
16620
16730
  }
16621
16731
  function getGlanceStatePath() {
16622
- return join6(homedir4(), ".gad", "glance-state.json");
16732
+ return join7(homedir5(), ".gad", "glance-state.json");
16623
16733
  }
16624
16734
  async function loadGlanceState() {
16625
16735
  try {
@@ -16635,7 +16745,7 @@ async function loadGlanceState() {
16635
16745
  }
16636
16746
  async function saveGlanceState(state) {
16637
16747
  const path10 = getGlanceStatePath();
16638
- await mkdir4(dirname5(path10), { recursive: true });
16748
+ await mkdir5(dirname5(path10), { recursive: true });
16639
16749
  await writeFile4(path10, JSON.stringify(state), "utf-8");
16640
16750
  }
16641
16751
  function glanceItemUrl(href, apiUrl) {
@@ -19680,18 +19790,18 @@ var proto = Object.defineProperties(() => {
19680
19790
  }
19681
19791
  }
19682
19792
  });
19683
- var createStyler = (open, close, parent) => {
19793
+ var createStyler = (open2, close, parent) => {
19684
19794
  let openAll;
19685
19795
  let closeAll;
19686
19796
  if (parent === void 0) {
19687
- openAll = open;
19797
+ openAll = open2;
19688
19798
  closeAll = close;
19689
19799
  } else {
19690
- openAll = parent.openAll + open;
19800
+ openAll = parent.openAll + open2;
19691
19801
  closeAll = close + parent.closeAll;
19692
19802
  }
19693
19803
  return {
19694
- open,
19804
+ open: open2,
19695
19805
  close,
19696
19806
  openAll,
19697
19807
  closeAll,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@great-arrow/cli",
3
- "version": "0.1.39",
3
+ "version": "0.1.41",
4
4
  "description": "GreatArrow.ai CLI tool",
5
5
  "type": "module",
6
6
  "bin": {