claudish 7.33.0 → 7.35.0

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 +788 -319
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -651,7 +651,7 @@ var init_onepassword_config = __esm(() => {
651
651
  });
652
652
 
653
653
  // src/version.ts
654
- var VERSION = "7.33.0";
654
+ var VERSION = "7.35.0";
655
655
 
656
656
  // src/logger.ts
657
657
  var exports_logger = {};
@@ -27783,7 +27783,7 @@ var init_provider_definitions = __esm(() => {
27783
27783
  apiKeyEnvVar: "",
27784
27784
  apiKeyDescription: "Antigravity (shared OAuth token)",
27785
27785
  apiKeyUrl: "https://antigravity.google/",
27786
- oauthLoginSlug: "gemini",
27786
+ oauthLoginSlug: "antigravity",
27787
27787
  shortcuts: ["ag", "antigravity", "go"],
27788
27788
  shortestPrefix: "ag",
27789
27789
  legacyPrefixes: [
@@ -28373,31 +28373,25 @@ function locateAgyBinary() {
28373
28373
  const fallback = join8(homedir8(), ".local", "bin", "agy");
28374
28374
  return existsSync6(fallback) ? fallback : null;
28375
28375
  }
28376
- function defaultExtractCreds() {
28376
+ function defaultDeleteStore() {
28377
+ if (process.platform !== "darwin")
28378
+ return;
28379
+ try {
28380
+ execFileSync("security", ["delete-generic-password", "-s", KC_SERVICE, "-a", KC_ACCOUNT], {
28381
+ stdio: ["ignore", "ignore", "ignore"]
28382
+ });
28383
+ } catch {}
28384
+ }
28385
+ function defaultRunAgyRefresh() {
28377
28386
  const agy = locateAgyBinary();
28378
- if (!agy) {
28379
- logStderr("[Antigravity] Could not locate the `agy` binary \u2014 self-refresh is unavailable.");
28380
- return [];
28381
- }
28382
- let dump;
28387
+ if (!agy)
28388
+ return;
28383
28389
  try {
28384
- dump = execFileSync("strings", [agy], {
28385
- encoding: "utf8",
28386
- maxBuffer: 128 * 1024 * 1024
28390
+ execFileSync(agy, ["models"], {
28391
+ stdio: ["ignore", "ignore", "ignore"],
28392
+ timeout: AGY_REFRESH_TIMEOUT_MS
28387
28393
  });
28388
- } catch {
28389
- logStderr("[Antigravity] `strings` failed on the agy binary \u2014 self-refresh is unavailable.");
28390
- return [];
28391
- }
28392
- const clientIds = Array.from(new Set(dump.match(/[0-9]{6,}-[a-z0-9]+\.apps\.googleusercontent\.com/g) ?? []));
28393
- const secrets = Array.from(new Set(dump.match(/GOCSPX-[A-Za-z0-9_-]{20,}/g) ?? []));
28394
- const combos = [];
28395
- for (const clientId of clientIds) {
28396
- for (const clientSecret of secrets) {
28397
- combos.push({ clientId, clientSecret });
28398
- }
28399
- }
28400
- return combos;
28394
+ } catch {}
28401
28395
  }
28402
28396
  function parseRecord(raw) {
28403
28397
  if (!raw)
@@ -28417,9 +28411,6 @@ function parseRecord(raw) {
28417
28411
  return null;
28418
28412
  }
28419
28413
  }
28420
- function encodeRecord(rec) {
28421
- return PREFIX + Buffer.from(JSON.stringify(rec), "utf8").toString("base64");
28422
- }
28423
28414
  function readSharedAntigravityToken(deps = defaultDeps) {
28424
28415
  const rec = parseRecord(deps.readStore());
28425
28416
  return rec ? rec.token : null;
@@ -28437,14 +28428,9 @@ function hasSharedAntigravityToken(deps = defaultDeps) {
28437
28428
  cachedHasToken = { at: now, value };
28438
28429
  return value;
28439
28430
  }
28440
- function writeSharedAntigravityToken(tok, deps = defaultDeps) {
28441
- const existing = parseRecord(deps.readStore());
28442
- const base = existing ?? { token: tok };
28443
- const merged = {
28444
- ...base,
28445
- token: { ...base.token, ...tok }
28446
- };
28447
- deps.writeStore(encodeRecord(merged));
28431
+ function deleteSharedAntigravityToken(deps = defaultDeps) {
28432
+ (deps.deleteStore ?? defaultDeleteStore)();
28433
+ _resetAntigravityTokenState();
28448
28434
  }
28449
28435
  function needsRefresh(tok, now) {
28450
28436
  const expMs = Date.parse(tok.expiry);
@@ -28452,57 +28438,25 @@ function needsRefresh(tok, now) {
28452
28438
  return true;
28453
28439
  return now >= expMs - EXPIRY_SKEW_MS;
28454
28440
  }
28455
- async function refreshToken(tok, deps) {
28456
- const combos = cachedCred ? [cachedCred] : deps.extractCreds();
28457
- if (combos.length === 0) {
28458
- throw new Error("[Antigravity] Access token expired and no OAuth client credentials could be extracted " + "from the `agy` binary to refresh it. Re-run the Antigravity CLI to refresh your session, " + "or use g@<model> with GEMINI_API_KEY.");
28459
- }
28460
- let lastStatus = 0;
28461
- let lastBody = "";
28462
- for (const cred of combos) {
28463
- const res = await deps.fetch(REFRESH_ENDPOINT, {
28464
- method: "POST",
28465
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
28466
- body: new URLSearchParams({
28467
- client_id: cred.clientId,
28468
- client_secret: cred.clientSecret,
28469
- refresh_token: tok.refresh_token,
28470
- grant_type: "refresh_token"
28471
- })
28472
- });
28473
- if (res.ok) {
28474
- cachedCred = cred;
28475
- const j = await res.json();
28476
- const expiry = new Date(deps.now() + j.expires_in * 1000).toISOString();
28477
- return {
28478
- access_token: j.access_token,
28479
- token_type: tok.token_type || "Bearer",
28480
- refresh_token: j.refresh_token || tok.refresh_token,
28481
- expiry
28482
- };
28483
- }
28484
- lastStatus = res.status;
28485
- lastBody = await res.text().catch(() => "");
28486
- }
28487
- throw new Error(`[Antigravity] Token refresh failed for all ${combos.length} client-cred combo(s) ` + `(last HTTP ${lastStatus}${lastBody ? `: ${lastBody.slice(0, 200)}` : ""}). ` + "Re-run the Antigravity CLI to refresh your session, or use g@<model> with GEMINI_API_KEY.");
28488
- }
28489
28441
  async function resolveValidToken(deps) {
28490
28442
  if (process.platform !== "darwin") {
28491
28443
  throw new Error("[Antigravity] The shared Antigravity token store is macOS-only for now. " + "Use g@<model> with GEMINI_API_KEY on this platform.");
28492
28444
  }
28493
28445
  const rec = parseRecord(deps.readStore());
28494
28446
  if (!rec) {
28495
- throw new Error("[Antigravity] No Antigravity session found. Install Antigravity and sign in " + "(the `agy` CLI), or use g@<model> with GEMINI_API_KEY " + "(get one at https://aistudio.google.com/app/apikey).");
28447
+ throw new Error("[Antigravity] No Antigravity session found. Sign in with `claudish login antigravity`, " + "or use g@<model> with GEMINI_API_KEY " + "(get one at https://aistudio.google.com/app/apikey).");
28448
+ }
28449
+ if (!needsRefresh(rec.token, deps.now())) {
28450
+ return rec.token.access_token;
28496
28451
  }
28497
- const tok = rec.token;
28498
- if (!needsRefresh(tok, deps.now())) {
28499
- return tok.access_token;
28452
+ log("[Antigravity] Access token expired/near-expiry \u2014 asking the Antigravity CLI to refresh.");
28453
+ deps.runAgyRefresh();
28454
+ const refreshedRec = parseRecord(deps.readStore());
28455
+ if (refreshedRec && !needsRefresh(refreshedRec.token, deps.now())) {
28456
+ log("[Antigravity] Shared token refreshed by the Antigravity CLI.");
28457
+ return refreshedRec.token.access_token;
28500
28458
  }
28501
- log("[Antigravity] Access token expired/near-expiry \u2014 refreshing.");
28502
- const refreshed = await refreshToken(tok, deps);
28503
- writeSharedAntigravityToken(refreshed, deps);
28504
- log("[Antigravity] Token refreshed and written back to the shared store.");
28505
- return refreshed.access_token;
28459
+ throw new Error("[Antigravity] Antigravity session expired and couldn't be refreshed. " + "Run `claudish login antigravity` (installs/authenticates the Antigravity CLI).");
28506
28460
  }
28507
28461
  function getValidAntigravityAccessToken(deps = defaultDeps) {
28508
28462
  if (inFlight)
@@ -28512,14 +28466,18 @@ function getValidAntigravityAccessToken(deps = defaultDeps) {
28512
28466
  });
28513
28467
  return inFlight;
28514
28468
  }
28515
- var KC_SERVICE = "gemini", KC_ACCOUNT = "antigravity", PREFIX = "go-keyring-base64:", REFRESH_ENDPOINT = "https://oauth2.googleapis.com/token", EXPIRY_SKEW_MS = 120000, defaultDeps, cachedHasToken = null, HAS_TOKEN_TTL_MS = 5000, cachedCred = null, inFlight = null;
28469
+ function _resetAntigravityTokenState() {
28470
+ inFlight = null;
28471
+ cachedHasToken = null;
28472
+ }
28473
+ var KC_SERVICE = "gemini", KC_ACCOUNT = "antigravity", PREFIX = "go-keyring-base64:", EXPIRY_SKEW_MS = 120000, AGY_REFRESH_TIMEOUT_MS = 40000, defaultDeps, cachedHasToken = null, HAS_TOKEN_TTL_MS = 5000, inFlight = null;
28516
28474
  var init_antigravity_token = __esm(() => {
28517
28475
  init_logger();
28518
28476
  defaultDeps = {
28519
28477
  readStore: defaultReadStore,
28520
28478
  writeStore: defaultWriteStore,
28521
- extractCreds: defaultExtractCreds,
28522
- fetch: (input, init) => fetch(input, init),
28479
+ deleteStore: defaultDeleteStore,
28480
+ runAgyRefresh: defaultRunAgyRefresh,
28523
28481
  now: () => Date.now()
28524
28482
  };
28525
28483
  });
@@ -31574,6 +31532,7 @@ var init_routing_hints = __esm(() => {
31574
31532
  kimi: { loginFlag: "login kimi", apiKeyEnvVar: "MOONSHOT_API_KEY" },
31575
31533
  google: { loginFlag: "login gemini", apiKeyEnvVar: "GEMINI_API_KEY" },
31576
31534
  "gemini-codeassist": { loginFlag: "login gemini", apiKeyEnvVar: "GEMINI_API_KEY" },
31535
+ antigravity: { loginFlag: "login antigravity" },
31577
31536
  openai: { apiKeyEnvVar: "OPENAI_API_KEY" },
31578
31537
  "openai-codex": { loginFlag: "login codex", apiKeyEnvVar: "OPENAI_CODEX_API_KEY" },
31579
31538
  minimax: { apiKeyEnvVar: "MINIMAX_API_KEY" },
@@ -38442,6 +38401,145 @@ var init_journal = __esm(() => {
38442
38401
  PRUNE_TO_BYTES = Math.floor(MAX_JOURNAL_BYTES * 0.6);
38443
38402
  });
38444
38403
 
38404
+ // src/behavior/telemetry/aggregate.ts
38405
+ import { createHash as createHash4, randomBytes as randomBytes4 } from "crypto";
38406
+ import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync9 } from "fs";
38407
+ import { homedir as homedir19 } from "os";
38408
+ import { dirname as dirname7, join as join19 } from "path";
38409
+ function contextBucket(inputTokens) {
38410
+ if (inputTokens < 50000)
38411
+ return "0-50k";
38412
+ if (inputTokens < 1e5)
38413
+ return "50-100k";
38414
+ if (inputTokens < 150000)
38415
+ return "100-150k";
38416
+ if (inputTokens < 200000)
38417
+ return "150-200k";
38418
+ return "200k+";
38419
+ }
38420
+ function hashSessionId(rawSessionId, model) {
38421
+ return createHash4("sha256").update(`${SESSION_SALT}:${rawSessionId}:${model}`).digest("hex");
38422
+ }
38423
+ function setTelemetryConsent(value) {
38424
+ consent = value;
38425
+ }
38426
+ function enabled() {
38427
+ return consent;
38428
+ }
38429
+ function stateFor(rawSessionId, model, provider) {
38430
+ const key = `${rawSessionId}|${model}`;
38431
+ let state = sessions.get(key);
38432
+ if (!state) {
38433
+ while (sessions.size >= MAX_TRACKED_SESSIONS) {
38434
+ const oldest = sessions.keys().next().value;
38435
+ if (oldest === undefined)
38436
+ break;
38437
+ sessions.delete(oldest);
38438
+ }
38439
+ const now = new Date().toISOString();
38440
+ state = {
38441
+ sessionId: hashSessionId(rawSessionId, model),
38442
+ model,
38443
+ provider,
38444
+ startedAt: now,
38445
+ endedAt: now,
38446
+ turns: 0,
38447
+ maxInputTokens: 0,
38448
+ decisions: new Map
38449
+ };
38450
+ sessions.set(key, state);
38451
+ }
38452
+ return state;
38453
+ }
38454
+ function recordTelemetryTurn(p) {
38455
+ if (!enabled() || !p.sessionId)
38456
+ return;
38457
+ const state = stateFor(p.sessionId, p.model, p.provider);
38458
+ if (!state)
38459
+ return;
38460
+ state.turns++;
38461
+ state.endedAt = new Date().toISOString();
38462
+ if (typeof p.inputTokens === "number" && p.inputTokens > state.maxInputTokens) {
38463
+ state.maxInputTokens = p.inputTokens;
38464
+ }
38465
+ }
38466
+ function recordTelemetryDecision(p) {
38467
+ if (!enabled() || !p.sessionId)
38468
+ return;
38469
+ const state = stateFor(p.sessionId, p.model, p.provider);
38470
+ if (!state)
38471
+ return;
38472
+ const key = `${p.ruleId ?? ""}|${p.surface}|${p.toolName ?? ""}`;
38473
+ let agg = state.decisions.get(key);
38474
+ if (!agg) {
38475
+ if (state.decisions.size >= MAX_DECISION_KEYS)
38476
+ return;
38477
+ agg = {
38478
+ rule_id: p.ruleId,
38479
+ surface: p.surface,
38480
+ tool_name: p.toolName,
38481
+ counts: {},
38482
+ path_relations: {}
38483
+ };
38484
+ state.decisions.set(key, agg);
38485
+ }
38486
+ agg.counts[p.decision] = (agg.counts[p.decision] ?? 0) + 1;
38487
+ if (p.pathRelation) {
38488
+ agg.path_relations[p.pathRelation] = (agg.path_relations[p.pathRelation] ?? 0) + 1;
38489
+ }
38490
+ state.endedAt = new Date().toISOString();
38491
+ }
38492
+ function toReport(state) {
38493
+ return {
38494
+ schema_version: TELEMETRY_SCHEMA_VERSION,
38495
+ session_id: state.sessionId,
38496
+ started_at: state.startedAt,
38497
+ ended_at: state.endedAt,
38498
+ claudish_version: VERSION,
38499
+ platform: process.platform,
38500
+ model_id: state.model,
38501
+ provider_name: state.provider,
38502
+ context_bucket: contextBucket(state.maxInputTokens),
38503
+ turns: state.turns,
38504
+ decisions: [...state.decisions.values()]
38505
+ };
38506
+ }
38507
+ function pendingReports() {
38508
+ return [...sessions.values()].map(toReport);
38509
+ }
38510
+ function outboxPath() {
38511
+ return join19(homedir19(), ".claudish", "behavior-outbox.jsonl");
38512
+ }
38513
+ function spoolPendingSync(path = outboxPath()) {
38514
+ if (sessions.size === 0)
38515
+ return 0;
38516
+ const reports = pendingReports().filter((r) => r.turns > 0 || r.decisions.length > 0);
38517
+ sessions.clear();
38518
+ if (reports.length === 0)
38519
+ return 0;
38520
+ try {
38521
+ mkdirSync9(dirname7(path), { recursive: true });
38522
+ appendFileSync3(path, `${reports.map((r) => JSON.stringify(r)).join(`
38523
+ `)}
38524
+ `);
38525
+ return reports.length;
38526
+ } catch (err) {
38527
+ log(`[behavior:telemetry] could not spool: ${err}`);
38528
+ return 0;
38529
+ }
38530
+ }
38531
+ var TELEMETRY_SCHEMA_VERSION = 1, SESSION_SALT, MAX_TRACKED_SESSIONS = 32, MAX_DECISION_KEYS = 200, sessions, consent = false;
38532
+ var init_aggregate = __esm(() => {
38533
+ init_logger();
38534
+ SESSION_SALT = randomBytes4(32).toString("hex");
38535
+ sessions = new Map;
38536
+ process.on("exit", () => {
38537
+ try {
38538
+ spoolPendingSync();
38539
+ } catch {}
38540
+ });
38541
+ });
38542
+
38445
38543
  // src/behavior/observer/digest.ts
38446
38544
  var exports_digest = {};
38447
38545
  __export(exports_digest, {
@@ -38633,10 +38731,10 @@ __export(exports_live_log, {
38633
38731
  recordLiveDivergence: () => recordLiveDivergence
38634
38732
  });
38635
38733
  import { appendFile as appendFile3 } from "fs/promises";
38636
- import { homedir as homedir19 } from "os";
38637
- import { join as join19 } from "path";
38734
+ import { homedir as homedir20 } from "os";
38735
+ import { join as join20 } from "path";
38638
38736
  function defaultPath() {
38639
- return join19(homedir19(), ".claudish", "behavior-divergences.jsonl");
38737
+ return join20(homedir20(), ".claudish", "behavior-divergences.jsonl");
38640
38738
  }
38641
38739
  async function recordLiveDivergence(entry, path = defaultPath()) {
38642
38740
  try {
@@ -38650,6 +38748,109 @@ var init_live_log = __esm(() => {
38650
38748
  init_logger();
38651
38749
  });
38652
38750
 
38751
+ // src/behavior/telemetry/upload.ts
38752
+ var exports_upload = {};
38753
+ __export(exports_upload, {
38754
+ resetDrainState: () => resetDrainState,
38755
+ drainOutbox: () => drainOutbox
38756
+ });
38757
+ import { readFile as readFile2, rename as rename2, unlink, writeFile as writeFile2 } from "fs/promises";
38758
+ function sleep2(ms) {
38759
+ return new Promise((resolve) => setTimeout(resolve, ms));
38760
+ }
38761
+ async function post(report) {
38762
+ const controller = new AbortController;
38763
+ const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
38764
+ try {
38765
+ const res = await fetch(ENDPOINT, {
38766
+ method: "POST",
38767
+ headers: { "Content-Type": "application/json" },
38768
+ body: JSON.stringify(report),
38769
+ signal: controller.signal
38770
+ });
38771
+ if (res.status === 202)
38772
+ return "sent";
38773
+ if (res.status === 400) {
38774
+ log("[behavior:telemetry] rejected as malformed (400), dropping");
38775
+ return "drop";
38776
+ }
38777
+ if (res.status === 429) {
38778
+ log("[behavior:telemetry] rate limited, deferring to next run");
38779
+ return "retry";
38780
+ }
38781
+ return res.status >= 500 ? "retry" : "drop";
38782
+ } catch {
38783
+ return "retry";
38784
+ } finally {
38785
+ clearTimeout(timer);
38786
+ }
38787
+ }
38788
+ function parseOutbox(content) {
38789
+ const out = [];
38790
+ for (const line of content.split(`
38791
+ `)) {
38792
+ if (!line.trim())
38793
+ continue;
38794
+ try {
38795
+ const parsed = JSON.parse(line);
38796
+ if (parsed && typeof parsed.session_id === "string")
38797
+ out.push(parsed);
38798
+ } catch {}
38799
+ }
38800
+ return out;
38801
+ }
38802
+ async function persistRemaining(path, remaining) {
38803
+ if (remaining.length === 0) {
38804
+ await unlink(path).catch(() => {});
38805
+ return;
38806
+ }
38807
+ const kept = remaining.slice(-MAX_OUTBOX_ENTRIES);
38808
+ const tmp = `${path}.draining`;
38809
+ await writeFile2(tmp, `${kept.map((r) => JSON.stringify(r)).join(`
38810
+ `)}
38811
+ `);
38812
+ await rename2(tmp, path);
38813
+ }
38814
+ async function drainOutbox(path = outboxPath()) {
38815
+ if (drained)
38816
+ return { sent: 0, kept: 0 };
38817
+ drained = true;
38818
+ try {
38819
+ const content = await readFile2(path, "utf8").catch(() => "");
38820
+ const reports = parseOutbox(content);
38821
+ if (reports.length === 0)
38822
+ return { sent: 0, kept: 0 };
38823
+ const batch = reports.slice(-MAX_DRAIN_PER_RUN).reverse();
38824
+ const older = reports.slice(0, Math.max(0, reports.length - MAX_DRAIN_PER_RUN));
38825
+ const keep = [];
38826
+ let sent = 0;
38827
+ for (let i = 0;i < batch.length; i++) {
38828
+ if (i > 0)
38829
+ await sleep2(SEND_INTERVAL_MS);
38830
+ const outcome = await post(batch[i]);
38831
+ if (outcome === "sent")
38832
+ sent++;
38833
+ else if (outcome === "retry")
38834
+ keep.push(batch[i]);
38835
+ }
38836
+ await persistRemaining(path, [...older, ...keep]);
38837
+ if (sent > 0)
38838
+ log(`[behavior:telemetry] delivered ${sent} session report(s)`);
38839
+ return { sent, kept: keep.length };
38840
+ } catch (err) {
38841
+ log(`[behavior:telemetry] drain failed: ${err}`);
38842
+ return { sent: 0, kept: 0 };
38843
+ }
38844
+ }
38845
+ function resetDrainState() {
38846
+ drained = false;
38847
+ }
38848
+ var ENDPOINT = "https://claudish.com/v1/behavior", REQUEST_TIMEOUT_MS = 15000, SEND_INTERVAL_MS = 1100, MAX_DRAIN_PER_RUN = 50, MAX_OUTBOX_ENTRIES = 200, drained = false;
38849
+ var init_upload = __esm(() => {
38850
+ init_logger();
38851
+ init_aggregate();
38852
+ });
38853
+
38653
38854
  // src/behavior/engine.ts
38654
38855
  class BehaviorSession {
38655
38856
  active;
@@ -38754,6 +38955,14 @@ class BehaviorSession {
38754
38955
  interceptsTool(toolName) {
38755
38956
  return this.bufferedTools.has(toolName);
38756
38957
  }
38958
+ noteTurnComplete(inputTokens) {
38959
+ recordTelemetryTurn({
38960
+ sessionId: this.sessionId,
38961
+ model: this.modelId,
38962
+ provider: this.providerName,
38963
+ inputTokens
38964
+ });
38965
+ }
38757
38966
  observeText(text, kind = "text") {
38758
38967
  if (!this.watchesOutput || !text)
38759
38968
  return;
@@ -38882,6 +39091,17 @@ class BehaviorSession {
38882
39091
  return changed ? JSON.stringify(args) : null;
38883
39092
  }
38884
39093
  journal(surface, decision, detail) {
39094
+ const pathRelation = classifyPath(detail.observedPath, detail.expectedPath);
39095
+ recordTelemetryDecision({
39096
+ sessionId: this.sessionId,
39097
+ model: this.modelId,
39098
+ provider: this.providerName,
39099
+ surface,
39100
+ decision,
39101
+ ruleId: detail.ruleId,
39102
+ toolName: detail.toolName,
39103
+ pathRelation
39104
+ });
38885
39105
  recordDecision({
38886
39106
  ts: new Date().toISOString(),
38887
39107
  model: this.modelId,
@@ -38891,7 +39111,7 @@ class BehaviorSession {
38891
39111
  ruleId: detail.ruleId,
38892
39112
  toolName: detail.toolName,
38893
39113
  argKeys: detail.argKeys,
38894
- pathRelation: classifyPath(detail.observedPath, detail.expectedPath),
39114
+ pathRelation,
38895
39115
  local: {
38896
39116
  observedPath: detail.observedPath,
38897
39117
  expectedPath: detail.expectedPath,
@@ -38985,6 +39205,11 @@ class BehaviorEngine {
38985
39205
  constructor(config2, rules) {
38986
39206
  this.config = config2;
38987
39207
  this.rules = rules;
39208
+ const optedIn = config2.telemetry?.enabled === true;
39209
+ setTelemetryConsent(optedIn);
39210
+ if (optedIn) {
39211
+ Promise.resolve().then(() => (init_upload(), exports_upload)).then((m) => m.drainOutbox()).catch((err) => log(`[behavior:telemetry] drain unavailable: ${err}`));
39212
+ }
38988
39213
  }
38989
39214
  queueCorrection(key, text) {
38990
39215
  const list = this.corrections.get(key) ?? [];
@@ -39032,6 +39257,7 @@ var init_engine = __esm(() => {
39032
39257
  init_config();
39033
39258
  init_harness();
39034
39259
  init_journal();
39260
+ init_aggregate();
39035
39261
  MAX_OBSERVED_CHARS = 64 * 1024;
39036
39262
  });
39037
39263
 
@@ -39165,9 +39391,9 @@ var init_hooks = __esm(() => {
39165
39391
  });
39166
39392
 
39167
39393
  // src/behavior/observer/corpus.ts
39168
- import { appendFileSync as appendFileSync3, readFileSync as readFileSync12, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
39169
- import { homedir as homedir20 } from "os";
39170
- import { join as join20 } from "path";
39394
+ import { appendFileSync as appendFileSync4, readFileSync as readFileSync12, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
39395
+ import { homedir as homedir21 } from "os";
39396
+ import { join as join21 } from "path";
39171
39397
  function directoryOf2(filePath) {
39172
39398
  const slash = filePath.lastIndexOf("/");
39173
39399
  return slash > 0 ? filePath.slice(0, slash) : undefined;
@@ -39246,28 +39472,28 @@ function listTranscripts(root) {
39246
39472
  return files;
39247
39473
  }
39248
39474
  for (const project of projects) {
39249
- const dir = join20(root, project);
39475
+ const dir = join21(root, project);
39250
39476
  try {
39251
39477
  if (!statSync2(dir).isDirectory())
39252
39478
  continue;
39253
39479
  for (const f of readdirSync2(dir)) {
39254
39480
  if (f.endsWith(".jsonl"))
39255
- files.push(join20(dir, f));
39481
+ files.push(join21(dir, f));
39256
39482
  }
39257
39483
  } catch {}
39258
39484
  }
39259
39485
  return files;
39260
39486
  }
39261
39487
  function buildCorpus(options = {}) {
39262
- const root = options.projectsRoot ?? join20(homedir20(), ".claude", "projects");
39488
+ const root = options.projectsRoot ?? join21(homedir21(), ".claude", "projects");
39263
39489
  const files = listTranscripts(root);
39264
39490
  const records = [];
39265
39491
  for (const f of files)
39266
39492
  records.push(...replayTranscript(f));
39267
39493
  if (options.write && records.length > 0) {
39268
- const outputPath = options.outputPath ?? join20(homedir20(), ".claudish", "behavior-divergences.jsonl");
39494
+ const outputPath = options.outputPath ?? join21(homedir21(), ".claudish", "behavior-divergences.jsonl");
39269
39495
  try {
39270
- appendFileSync3(outputPath, `${records.map((r) => JSON.stringify(r)).join(`
39496
+ appendFileSync4(outputPath, `${records.map((r) => JSON.stringify(r)).join(`
39271
39497
  `)}
39272
39498
  `);
39273
39499
  return { scanned: files.length, records, outputPath };
@@ -39307,6 +39533,8 @@ var init_behavior = __esm(() => {
39307
39533
  init_digest();
39308
39534
  init_client();
39309
39535
  init_corpus();
39536
+ init_aggregate();
39537
+ init_upload();
39310
39538
  BUILTIN_RULES = [...PLAN_MODE_RULES];
39311
39539
  hookRules = [];
39312
39540
  });
@@ -39877,17 +40105,17 @@ var init_vision_proxy = __esm(() => {
39877
40105
  // src/stats-buffer.ts
39878
40106
  import {
39879
40107
  existsSync as existsSync15,
39880
- mkdirSync as mkdirSync9,
40108
+ mkdirSync as mkdirSync10,
39881
40109
  readFileSync as readFileSync13,
39882
40110
  renameSync,
39883
40111
  unlinkSync as unlinkSync5,
39884
40112
  writeFileSync as writeFileSync9
39885
40113
  } from "fs";
39886
- import { homedir as homedir21 } from "os";
39887
- import { join as join21 } from "path";
40114
+ import { homedir as homedir22 } from "os";
40115
+ import { join as join22 } from "path";
39888
40116
  function ensureDir() {
39889
40117
  if (!existsSync15(CLAUDISH_DIR)) {
39890
- mkdirSync9(CLAUDISH_DIR, { recursive: true });
40118
+ mkdirSync10(CLAUDISH_DIR, { recursive: true });
39891
40119
  }
39892
40120
  }
39893
40121
  function readFromDisk() {
@@ -39919,7 +40147,7 @@ function writeToDisk(events) {
39919
40147
  ensureDir();
39920
40148
  const trimmed = enforceSizeCap([...events]);
39921
40149
  const payload = { version: 1, events: trimmed };
39922
- const tmpFile = join21(CLAUDISH_DIR, `stats-buffer.tmp.${process.pid}.json`);
40150
+ const tmpFile = join22(CLAUDISH_DIR, `stats-buffer.tmp.${process.pid}.json`);
39923
40151
  writeFileSync9(tmpFile, JSON.stringify(payload, null, 2), "utf-8");
39924
40152
  renameSync(tmpFile, BUFFER_FILE);
39925
40153
  memoryCache = trimmed;
@@ -39992,8 +40220,8 @@ function syncFlushOnExit() {
39992
40220
  var BUFFER_MAX_BYTES, CLAUDISH_DIR, BUFFER_FILE, memoryCache = null, eventsSinceLastFlush = 0, flushScheduled = false;
39993
40221
  var init_stats_buffer = __esm(() => {
39994
40222
  BUFFER_MAX_BYTES = 64 * 1024;
39995
- CLAUDISH_DIR = join21(homedir21(), ".claudish");
39996
- BUFFER_FILE = join21(CLAUDISH_DIR, "stats-buffer.json");
40223
+ CLAUDISH_DIR = join22(homedir22(), ".claudish");
40224
+ BUFFER_FILE = join22(CLAUDISH_DIR, "stats-buffer.json");
39997
40225
  process.on("exit", syncFlushOnExit);
39998
40226
  process.on("SIGTERM", () => {
39999
40227
  try {
@@ -40130,7 +40358,7 @@ __export(exports_telemetry, {
40130
40358
  classifyError: () => classifyError,
40131
40359
  buildReport: () => buildReport
40132
40360
  });
40133
- import { randomBytes as randomBytes4 } from "crypto";
40361
+ import { randomBytes as randomBytes5 } from "crypto";
40134
40362
  function getVersion() {
40135
40363
  return VERSION;
40136
40364
  }
@@ -40398,7 +40626,7 @@ function initTelemetry(_config) {
40398
40626
  } catch {
40399
40627
  consentEnabled = false;
40400
40628
  }
40401
- sessionId = randomBytes4(8).toString("hex");
40629
+ sessionId = randomBytes5(8).toString("hex");
40402
40630
  claudishVersion = getVersion();
40403
40631
  installMethod = detectInstallMethod();
40404
40632
  }
@@ -40708,11 +40936,11 @@ function showMonthlyBanner() {
40708
40936
  if (isStatsDisabledByEnv())
40709
40937
  return;
40710
40938
  const profileConfig = loadConfig();
40711
- const consent = profileConfig.stats;
40939
+ const consent2 = profileConfig.stats;
40712
40940
  const now = Date.now();
40713
- const lastPrompt = consent?.lastMonthlyPrompt ? new Date(consent.lastMonthlyPrompt).getTime() : 0;
40941
+ const lastPrompt = consent2?.lastMonthlyPrompt ? new Date(consent2.lastMonthlyPrompt).getTime() : 0;
40714
40942
  const timeSincePrompt = now - lastPrompt;
40715
- const isFirstRun = !consent?.lastMonthlyPrompt;
40943
+ const isFirstRun = !consent2?.lastMonthlyPrompt;
40716
40944
  const isMonthlyInterval = timeSincePrompt >= MONTHLY_INTERVAL_MS;
40717
40945
  if (!isFirstRun && !isMonthlyInterval)
40718
40946
  return;
@@ -40721,7 +40949,7 @@ function showMonthlyBanner() {
40721
40949
  ` + ` No prompts, API keys, or personal data \u2014 just model, latency, and token counts.
40722
40950
  ` + ` Enable: claudish stats on | Docs: claudish stats status
40723
40951
  `);
40724
- } else if (consent?.enabled) {
40952
+ } else if (consent2?.enabled) {
40725
40953
  process.stderr.write(`[claudish] Usage stats are ON \u2014 thank you for helping improve claudish!
40726
40954
  `);
40727
40955
  } else {
@@ -42376,9 +42604,9 @@ var init_openai_responses_sse = __esm(() => {
42376
42604
  });
42377
42605
 
42378
42606
  // src/handlers/shared/token-tracker.ts
42379
- import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
42380
- import { homedir as homedir22 } from "os";
42381
- import { dirname as dirname7, join as join22 } from "path";
42607
+ import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync10 } from "fs";
42608
+ import { homedir as homedir23 } from "os";
42609
+ import { dirname as dirname8, join as join23 } from "path";
42382
42610
  function stripProviderPrefix(name) {
42383
42611
  const at = name.indexOf("@");
42384
42612
  return at === -1 ? name : name.slice(at + 1);
@@ -42530,8 +42758,8 @@ class TokenTracker {
42530
42758
  data.quota_remaining = this.quotaRemaining;
42531
42759
  }
42532
42760
  const override = process.env.CLAUDISH_TOKEN_FILE;
42533
- const outPath = override || join22(homedir22(), ".claudish", `tokens-${this.port}.json`);
42534
- mkdirSync10(dirname7(outPath), { recursive: true });
42761
+ const outPath = override || join23(homedir23(), ".claudish", `tokens-${this.port}.json`);
42762
+ mkdirSync11(dirname8(outPath), { recursive: true });
42535
42763
  writeFileSync10(outPath, JSON.stringify(data), "utf-8");
42536
42764
  } catch (e) {
42537
42765
  log(`[TokenTracker] Error writing token file: ${e}`);
@@ -43047,6 +43275,9 @@ class ComposedHandler {
43047
43275
  invocation_mode: this.options.invocationMode ?? "auto-route"
43048
43276
  });
43049
43277
  } catch {}
43278
+ try {
43279
+ behaviorSession?.noteTurnComplete(this.tokenTracker.getInputTokens());
43280
+ } catch {}
43050
43281
  };
43051
43282
  return this.handleStream(c, response, adapter, claudeRequest, toolNameMap, onStreamComplete, (code, message) => {
43052
43283
  streamApiError = { code, message };
@@ -43399,7 +43630,7 @@ var init_fallback_handler = __esm(() => {
43399
43630
  });
43400
43631
 
43401
43632
  // src/handlers/native-handler-advisor.ts
43402
- import { appendFileSync as appendFileSync4 } from "fs";
43633
+ import { appendFileSync as appendFileSync5 } from "fs";
43403
43634
  function loadAdvisorSwapConfig(cliModels, cliCollector) {
43404
43635
  return {
43405
43636
  enabled: process.env.CLAUDISH_SWAP_ADVISOR === "1" || (cliModels?.length ?? 0) > 0,
@@ -43454,7 +43685,7 @@ function logAdvisorEvent(cfg, event) {
43454
43685
  const line = `${JSON.stringify({ ts: new Date().toISOString(), ...event })}
43455
43686
  `;
43456
43687
  try {
43457
- appendFileSync4(cfg.logPath, line);
43688
+ appendFileSync5(cfg.logPath, line);
43458
43689
  } catch {}
43459
43690
  }
43460
43691
  function recordAdvisorEventsFromChunk(cfg, chunkText) {
@@ -45211,10 +45442,10 @@ var init_ollama_api_format = __esm(() => {
45211
45442
 
45212
45443
  // src/providers/api-key-provenance.ts
45213
45444
  import { existsSync as existsSync16, readFileSync as readFileSync14 } from "fs";
45214
- import { homedir as homedir23 } from "os";
45215
- import { join as join23, resolve as resolve2 } from "path";
45445
+ import { homedir as homedir24 } from "os";
45446
+ import { join as join24, resolve as resolve2 } from "path";
45216
45447
  function activeConfigPath() {
45217
- return activeGlobalConfigFile(join23(homedir23(), ".claudish", "config.json"));
45448
+ return activeGlobalConfigFile(join24(homedir24(), ".claudish", "config.json"));
45218
45449
  }
45219
45450
  function configLayerLabel() {
45220
45451
  return getConfigFileOverride() ? activeConfigPath() : "~/.claudish/config.json";
@@ -46092,10 +46323,10 @@ class LocalModelQueue {
46092
46323
  return LocalModelQueue.instance;
46093
46324
  }
46094
46325
  static isEnabled() {
46095
- const enabled = process.env.CLAUDISH_LOCAL_QUEUE_ENABLED;
46096
- if (enabled === undefined || enabled === "")
46326
+ const enabled2 = process.env.CLAUDISH_LOCAL_QUEUE_ENABLED;
46327
+ if (enabled2 === undefined || enabled2 === "")
46097
46328
  return true;
46098
- return enabled !== "false" && enabled !== "0";
46329
+ return enabled2 !== "false" && enabled2 !== "0";
46099
46330
  }
46100
46331
  async enqueue(fetchFn, providerId, concurrencyOverride) {
46101
46332
  if (concurrencyOverride !== undefined) {
@@ -46782,8 +47013,8 @@ var init_poe = __esm(() => {
46782
47013
 
46783
47014
  // src/services/pricing-cache.ts
46784
47015
  import { existsSync as existsSync17, readFileSync as readFileSync15, statSync as statSync4 } from "fs";
46785
- import { homedir as homedir24 } from "os";
46786
- import { join as join24 } from "path";
47016
+ import { homedir as homedir25 } from "os";
47017
+ import { join as join25 } from "path";
46787
47018
  function prefixMatch(modelName) {
46788
47019
  for (const [key, pricing] of pricingMap) {
46789
47020
  if (modelName.startsWith(key))
@@ -46842,8 +47073,8 @@ var init_pricing_cache = __esm(() => {
46842
47073
  init_logger();
46843
47074
  init_catalog_query();
46844
47075
  pricingMap = new Map;
46845
- CACHE_DIR = join24(homedir24(), ".claudish");
46846
- CACHE_FILE = join24(CACHE_DIR, "pricing-cache.json");
47076
+ CACHE_DIR = join25(homedir25(), ".claudish");
47077
+ CACHE_FILE = join25(CACHE_DIR, "pricing-cache.json");
46847
47078
  CACHE_TTL_MS3 = 24 * 60 * 60 * 1000;
46848
47079
  });
46849
47080
 
@@ -47339,12 +47570,12 @@ var init_redact = __esm(() => {
47339
47570
 
47340
47571
  // src/team-stats.ts
47341
47572
  import { existsSync as existsSync18, readFileSync as readFileSync16, writeFileSync as writeFileSync11 } from "fs";
47342
- import { join as join25 } from "path";
47573
+ import { join as join26 } from "path";
47343
47574
  function statsDir(sessionPath) {
47344
- return join25(sessionPath, "stats");
47575
+ return join26(sessionPath, "stats");
47345
47576
  }
47346
47577
  function tokenFileFor(sessionPath, anonId) {
47347
- return join25(statsDir(sessionPath), `${anonId}.json`);
47578
+ return join26(statsDir(sessionPath), `${anonId}.json`);
47348
47579
  }
47349
47580
  function readTokenStats(sessionPath, anonId) {
47350
47581
  const path = tokenFileFor(sessionPath, anonId);
@@ -47499,7 +47730,7 @@ ${segs.join(" \xB7 ")}`;
47499
47730
  }
47500
47731
  function writeStatusFile(sessionPath, manifest, status, opts) {
47501
47732
  try {
47502
- writeFileSync11(join25(sessionPath, "status.txt"), `${renderTeamStats(sessionPath, manifest, status, opts)}
47733
+ writeFileSync11(join26(sessionPath, "status.txt"), `${renderTeamStats(sessionPath, manifest, status, opts)}
47503
47734
  `, "utf-8");
47504
47735
  } catch {}
47505
47736
  }
@@ -47526,12 +47757,12 @@ import { spawn as spawn2 } from "child_process";
47526
47757
  import {
47527
47758
  createWriteStream as createWriteStream2,
47528
47759
  existsSync as existsSync19,
47529
- mkdirSync as mkdirSync11,
47760
+ mkdirSync as mkdirSync12,
47530
47761
  readFileSync as readFileSync17,
47531
47762
  readdirSync as readdirSync3,
47532
47763
  writeFileSync as writeFileSync12
47533
47764
  } from "fs";
47534
- import { join as join26, resolve as resolve3 } from "path";
47765
+ import { join as join27, resolve as resolve3 } from "path";
47535
47766
  function classifyRunOutput(opts) {
47536
47767
  const { outputSize, stdoutTail, stderr, minOutputBytes } = opts;
47537
47768
  const apiError = API_ERROR_RE.exec(stdoutTail);
@@ -47592,18 +47823,18 @@ function setupSession(sessionPath, models, input) {
47592
47823
  if (models.length === 0) {
47593
47824
  throw new Error("At least one model is required");
47594
47825
  }
47595
- if (existsSync19(join26(sessionPath, "manifest.json"))) {
47826
+ if (existsSync19(join27(sessionPath, "manifest.json"))) {
47596
47827
  throw new Error(`Session already exists at ${sessionPath}. Use a new directory path or delete the existing session first.`);
47597
47828
  }
47598
47829
  const sentinels = models.filter(isSentinelModel);
47599
47830
  if (sentinels.length > 0) {
47600
47831
  throw new Error(`Invalid model(s) for team run: ${sentinels.join(", ")}. These are Claude Code agent selectors, not external model IDs. Use real external models (e.g., "gemini-2.0-flash", "gpt-4o", "or@deepseek/deepseek-r1"). For Claude models, use a Task agent instead of the team tool.`);
47601
47832
  }
47602
- mkdirSync11(join26(sessionPath, "work"), { recursive: true });
47603
- mkdirSync11(join26(sessionPath, "errors"), { recursive: true });
47833
+ mkdirSync12(join27(sessionPath, "work"), { recursive: true });
47834
+ mkdirSync12(join27(sessionPath, "errors"), { recursive: true });
47604
47835
  if (input !== undefined) {
47605
- writeFileSync12(join26(sessionPath, "input.md"), input, "utf-8");
47606
- } else if (!existsSync19(join26(sessionPath, "input.md"))) {
47836
+ writeFileSync12(join27(sessionPath, "input.md"), input, "utf-8");
47837
+ } else if (!existsSync19(join27(sessionPath, "input.md"))) {
47607
47838
  throw new Error(`No input.md found at ${sessionPath} and no input provided`);
47608
47839
  }
47609
47840
  const ids = models.map((_, i) => String(i + 1).padStart(2, "0"));
@@ -47620,9 +47851,9 @@ function setupSession(sessionPath, models, input) {
47620
47851
  model: models[i],
47621
47852
  assignedAt: now
47622
47853
  };
47623
- mkdirSync11(join26(sessionPath, "work", anonId), { recursive: true });
47854
+ mkdirSync12(join27(sessionPath, "work", anonId), { recursive: true });
47624
47855
  }
47625
- writeFileSync12(join26(sessionPath, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
47856
+ writeFileSync12(join27(sessionPath, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
47626
47857
  const status = {
47627
47858
  startedAt: now,
47628
47859
  models: Object.fromEntries(Object.keys(manifest.models).map((id) => [
@@ -47636,14 +47867,14 @@ function setupSession(sessionPath, models, input) {
47636
47867
  }
47637
47868
  ]))
47638
47869
  };
47639
- writeFileSync12(join26(sessionPath, "status.json"), JSON.stringify(status, null, 2), "utf-8");
47870
+ writeFileSync12(join27(sessionPath, "status.json"), JSON.stringify(status, null, 2), "utf-8");
47640
47871
  return manifest;
47641
47872
  }
47642
47873
  async function runModels(sessionPath, opts = {}) {
47643
47874
  const timeoutMs = (opts.timeout ?? 300) * 1000;
47644
- const manifest = JSON.parse(readFileSync17(join26(sessionPath, "manifest.json"), "utf-8"));
47645
- const statusPath = join26(sessionPath, "status.json");
47646
- const inputPath = join26(sessionPath, "input.md");
47875
+ const manifest = JSON.parse(readFileSync17(join27(sessionPath, "manifest.json"), "utf-8"));
47876
+ const statusPath = join27(sessionPath, "status.json");
47877
+ const inputPath = join27(sessionPath, "input.md");
47647
47878
  const inputContent = readFileSync17(inputPath, "utf-8");
47648
47879
  await prehydrateCredentialsForSpawn(Object.values(manifest.models).map((m) => m.model));
47649
47880
  const statusCache = JSON.parse(readFileSync17(statusPath, "utf-8"));
@@ -47652,7 +47883,7 @@ async function runModels(sessionPath, opts = {}) {
47652
47883
  writeFileSync12(statusPath, JSON.stringify(statusCache, null, 2), "utf-8");
47653
47884
  }
47654
47885
  const minOutputBytes = opts.minOutputBytes ?? DEFAULT_MIN_OUTPUT_BYTES;
47655
- mkdirSync11(statsDir(sessionPath), { recursive: true });
47886
+ mkdirSync12(statsDir(sessionPath), { recursive: true });
47656
47887
  const processes = new Map;
47657
47888
  const runtimes = new Map;
47658
47889
  const sigintHandler = () => {
@@ -47665,8 +47896,8 @@ async function runModels(sessionPath, opts = {}) {
47665
47896
  process.on("SIGINT", sigintHandler);
47666
47897
  const completionPromises = [];
47667
47898
  for (const [anonId, entry] of Object.entries(manifest.models)) {
47668
- const outputPath = join26(sessionPath, `response-${anonId}.md`);
47669
- const errorLogPath = join26(sessionPath, "errors", `${anonId}.log`);
47899
+ const outputPath = join27(sessionPath, `response-${anonId}.md`);
47900
+ const errorLogPath = join27(sessionPath, "errors", `${anonId}.log`);
47670
47901
  const args = ["--model", entry.model, "-y", "--stdin", "--quiet", ...opts.claudeFlags ?? []];
47671
47902
  updateModelStatus(anonId, {
47672
47903
  state: "RUNNING",
@@ -47855,23 +48086,23 @@ async function judgeResponses(sessionPath, opts = {}) {
47855
48086
  const responses = {};
47856
48087
  for (const file2 of responseFiles) {
47857
48088
  const id = file2.replace(/^response-/, "").replace(/\.md$/, "");
47858
- responses[id] = readFileSync17(join26(sessionPath, file2), "utf-8");
48089
+ responses[id] = readFileSync17(join27(sessionPath, file2), "utf-8");
47859
48090
  }
47860
- const input = readFileSync17(join26(sessionPath, "input.md"), "utf-8");
48091
+ const input = readFileSync17(join27(sessionPath, "input.md"), "utf-8");
47861
48092
  const judgePrompt = buildJudgePrompt(input, responses);
47862
- writeFileSync12(join26(sessionPath, "judge-prompt.md"), judgePrompt, "utf-8");
48093
+ writeFileSync12(join27(sessionPath, "judge-prompt.md"), judgePrompt, "utf-8");
47863
48094
  const judgeModels = opts.judges ?? getDefaultJudgeModels(sessionPath);
47864
- const judgePath = join26(sessionPath, "judging");
47865
- mkdirSync11(judgePath, { recursive: true });
48095
+ const judgePath = join27(sessionPath, "judging");
48096
+ mkdirSync12(judgePath, { recursive: true });
47866
48097
  setupSession(judgePath, judgeModels, judgePrompt);
47867
48098
  await runModels(judgePath, { claudeFlags: opts.claudeFlags });
47868
48099
  const votes = parseJudgeVotes(judgePath, Object.keys(responses));
47869
48100
  const verdict = aggregateVerdict(votes, Object.keys(responses));
47870
- writeFileSync12(join26(sessionPath, "verdict.md"), formatVerdict(verdict, sessionPath), "utf-8");
48101
+ writeFileSync12(join27(sessionPath, "verdict.md"), formatVerdict(verdict, sessionPath), "utf-8");
47871
48102
  return verdict;
47872
48103
  }
47873
48104
  function getStatus(sessionPath) {
47874
- return JSON.parse(readFileSync17(join26(sessionPath, "status.json"), "utf-8"));
48105
+ return JSON.parse(readFileSync17(join27(sessionPath, "status.json"), "utf-8"));
47875
48106
  }
47876
48107
  function fisherYatesShuffle(arr) {
47877
48108
  for (let i = arr.length - 1;i > 0; i--) {
@@ -47881,7 +48112,7 @@ function fisherYatesShuffle(arr) {
47881
48112
  return arr;
47882
48113
  }
47883
48114
  function getDefaultJudgeModels(sessionPath) {
47884
- const manifest = JSON.parse(readFileSync17(join26(sessionPath, "manifest.json"), "utf-8"));
48115
+ const manifest = JSON.parse(readFileSync17(join27(sessionPath, "manifest.json"), "utf-8"));
47885
48116
  return Object.values(manifest.models).map((e) => e.model);
47886
48117
  }
47887
48118
  function buildJudgePrompt(input, responses) {
@@ -47944,7 +48175,7 @@ function parseJudgeVotes(judgePath, responseIds) {
47944
48175
  const judgeId = file2.replace(/^response-/, "").replace(/\.md$/, "");
47945
48176
  let content;
47946
48177
  try {
47947
- content = readFileSync17(join26(judgePath, file2), "utf-8");
48178
+ content = readFileSync17(join27(judgePath, file2), "utf-8");
47948
48179
  } catch {
47949
48180
  continue;
47950
48181
  }
@@ -47996,7 +48227,7 @@ function aggregateVerdict(votes, responseIds) {
47996
48227
  function formatVerdict(verdict, sessionPath) {
47997
48228
  let manifest = null;
47998
48229
  try {
47999
- manifest = JSON.parse(readFileSync17(join26(sessionPath, "manifest.json"), "utf-8"));
48230
+ manifest = JSON.parse(readFileSync17(join27(sessionPath, "manifest.json"), "utf-8"));
48000
48231
  } catch {}
48001
48232
  let output = `# Team Verdict
48002
48233
 
@@ -48051,9 +48282,9 @@ __export(exports_mcp_server, {
48051
48282
  parseAnthropicSse: () => parseAnthropicSse,
48052
48283
  formatTeamResult: () => formatTeamResult
48053
48284
  });
48054
- import { existsSync as existsSync20, mkdirSync as mkdirSync12, readFileSync as readFileSync18, readdirSync as readdirSync4, writeFileSync as writeFileSync13 } from "fs";
48055
- import { homedir as homedir25 } from "os";
48056
- import { dirname as dirname8, join as join27 } from "path";
48285
+ import { existsSync as existsSync20, mkdirSync as mkdirSync13, readFileSync as readFileSync18, readdirSync as readdirSync4, writeFileSync as writeFileSync13 } from "fs";
48286
+ import { homedir as homedir26 } from "os";
48287
+ import { dirname as dirname9, join as join28 } from "path";
48057
48288
  import { fileURLToPath } from "url";
48058
48289
  async function loadAllModels(forceRefresh = false) {
48059
48290
  if (!forceRefresh && existsSync20(ALL_MODELS_CACHE_PATH2)) {
@@ -48072,7 +48303,7 @@ async function loadAllModels(forceRefresh = false) {
48072
48303
  throw new Error(`API returned ${response.status}`);
48073
48304
  const data = await response.json();
48074
48305
  const models = data.data || [];
48075
- mkdirSync12(CLAUDISH_CACHE_DIR, { recursive: true });
48306
+ mkdirSync13(CLAUDISH_CACHE_DIR, { recursive: true });
48076
48307
  writeFileSync13(ALL_MODELS_CACHE_PATH2, JSON.stringify({ lastUpdated: new Date().toISOString(), models }), "utf-8");
48077
48308
  return models;
48078
48309
  } catch {
@@ -48667,16 +48898,16 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
48667
48898
  const sp = session_path;
48668
48899
  for (const file2 of ["status.json", "manifest.json", "input.md"]) {
48669
48900
  try {
48670
- sessionData[file2] = readFileSync18(join27(sp, file2), "utf-8");
48901
+ sessionData[file2] = readFileSync18(join28(sp, file2), "utf-8");
48671
48902
  } catch {}
48672
48903
  }
48673
48904
  try {
48674
- const errorDir = join27(sp, "errors");
48905
+ const errorDir = join28(sp, "errors");
48675
48906
  if (existsSync20(errorDir)) {
48676
48907
  for (const f of readdirSync4(errorDir)) {
48677
48908
  if (f.endsWith(".log")) {
48678
48909
  try {
48679
- sessionData[`errors/${f}`] = readFileSync18(join27(errorDir, f), "utf-8");
48910
+ sessionData[`errors/${f}`] = readFileSync18(join28(errorDir, f), "utf-8");
48680
48911
  } catch {}
48681
48912
  }
48682
48913
  }
@@ -48686,7 +48917,7 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
48686
48917
  for (const f of readdirSync4(sp)) {
48687
48918
  if (f.startsWith("response-") && f.endsWith(".md")) {
48688
48919
  try {
48689
- const content = readFileSync18(join27(sp, f), "utf-8");
48920
+ const content = readFileSync18(join28(sp, f), "utf-8");
48690
48921
  sessionData[f] = content.slice(0, 200) + (content.length > 200 ? "... (truncated)" : "");
48691
48922
  } catch {}
48692
48923
  }
@@ -48695,7 +48926,7 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
48695
48926
  }
48696
48927
  let version2 = "unknown";
48697
48928
  try {
48698
- const pkgPath = join27(__dirname2, "../package.json");
48929
+ const pkgPath = join28(__dirname2, "../package.json");
48699
48930
  if (existsSync20(pkgPath)) {
48700
48931
  version2 = JSON.parse(readFileSync18(pkgPath, "utf-8")).version;
48701
48932
  }
@@ -48924,9 +49155,9 @@ Report manually at https://github.com/anthropics/claudish/issues${autoSendHint}`
48924
49155
  },
48925
49156
  group: "channel",
48926
49157
  handler: async (args) => {
48927
- const sessions = sessionManager.listSessions(args.include_completed);
49158
+ const sessions2 = sessionManager.listSessions(args.include_completed);
48928
49159
  return {
48929
- content: [{ type: "text", text: JSON.stringify({ sessions }) }]
49160
+ content: [{ type: "text", text: JSON.stringify({ sessions: sessions2 }) }]
48930
49161
  };
48931
49162
  }
48932
49163
  });
@@ -49095,9 +49326,9 @@ var init_mcp_server = __esm(() => {
49095
49326
  import_dotenv2 = __toESM(require_main(), 1);
49096
49327
  import_dotenv2.config({ quiet: true });
49097
49328
  __filename2 = fileURLToPath(import.meta.url);
49098
- __dirname2 = dirname8(__filename2);
49099
- CLAUDISH_CACHE_DIR = join27(homedir25(), ".claudish");
49100
- ALL_MODELS_CACHE_PATH2 = join27(CLAUDISH_CACHE_DIR, "all-models.json");
49329
+ __dirname2 = dirname9(__filename2);
49330
+ CLAUDISH_CACHE_DIR = join28(homedir26(), ".claudish");
49331
+ ALL_MODELS_CACHE_PATH2 = join28(CLAUDISH_CACHE_DIR, "all-models.json");
49101
49332
  NEXT_STEP = {
49102
49333
  nonzero_exit: "read the evidence log, then retry or drop the model",
49103
49334
  timeout: "raise `timeout`, or pick a faster model",
@@ -49223,6 +49454,7 @@ var exports_behavior_command = {};
49223
49454
  __export(exports_behavior_command, {
49224
49455
  behaviorCommand: () => behaviorCommand
49225
49456
  });
49457
+ import { existsSync as existsSync22, readFileSync as readFileSync20, writeFileSync as writeFileSync14 } from "fs";
49226
49458
  function severityColor(sev) {
49227
49459
  if (sev === "fix")
49228
49460
  return green(sev);
@@ -49316,6 +49548,67 @@ Behavior divergence corpus
49316
49548
  `));
49317
49549
  }
49318
49550
  }
49551
+ function setTelemetryEnabled(value) {
49552
+ const path = getConfigPath();
49553
+ let cfg = {};
49554
+ try {
49555
+ if (existsSync22(path)) {
49556
+ const parsed = JSON.parse(readFileSync20(path, "utf-8"));
49557
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
49558
+ cfg = parsed;
49559
+ }
49560
+ }
49561
+ } catch {}
49562
+ const behavior = cfg.behavior && typeof cfg.behavior === "object" && !Array.isArray(cfg.behavior) ? { ...cfg.behavior } : {};
49563
+ behavior.telemetry = { enabled: value };
49564
+ cfg.behavior = behavior;
49565
+ writeFileSync14(path, `${JSON.stringify(cfg, null, 2)}
49566
+ `, "utf-8");
49567
+ }
49568
+ function showTelemetry(action, json2) {
49569
+ if (action !== "status") {
49570
+ setTelemetryEnabled(action === "enable");
49571
+ }
49572
+ const config3 = parseBehaviorConfig(loadConfig().behavior);
49573
+ const on = config3.telemetry?.enabled === true;
49574
+ let pending = 0;
49575
+ try {
49576
+ const path = outboxPath();
49577
+ if (existsSync22(path)) {
49578
+ pending = readFileSync20(path, "utf8").split(`
49579
+ `).filter(Boolean).length;
49580
+ }
49581
+ } catch {}
49582
+ if (json2) {
49583
+ console.log(JSON.stringify({ enabled: on, pendingReports: pending }, null, 2));
49584
+ return;
49585
+ }
49586
+ console.log(bold2(`
49587
+ Behavior telemetry
49588
+ `));
49589
+ console.log(` status : ${on ? green("enabled") : dim2("disabled")}`);
49590
+ console.log(` pending : ${pending} session report(s) awaiting delivery
49591
+ `);
49592
+ if (!on) {
49593
+ console.log(" Opting in shares which models violate Claude Code conventions,");
49594
+ console.log(` so rules can be written for models we cannot test ourselves.
49595
+ `);
49596
+ console.log(dim2(" Sent : model, provider, rule id, tool name, decision counts,"));
49597
+ console.log(dim2(" a coarse context bucket, and categorical path relations"));
49598
+ console.log(dim2(" Never : file paths, argument values, prompts, code, model output,"));
49599
+ console.log(dim2(" credentials, or repo/branch/project names"));
49600
+ console.log(dim2(" Session : identified by a salted hash, unlinkable across sessions"));
49601
+ console.log(dim2(` Kept : 12 months, then non-identifying weekly aggregates only
49602
+ `));
49603
+ console.log(` Enable with ${bold2("claudish behavior telemetry --enable")}
49604
+ `);
49605
+ return;
49606
+ }
49607
+ console.log(dim2(` Local journalling is always on and unaffected by this setting.
49608
+ `));
49609
+ console.log(` Disable with ${bold2("claudish behavior telemetry --disable")}
49610
+ `);
49611
+ }
49319
49612
  async function behaviorCommand(argv) {
49320
49613
  const json2 = argv.includes("--json");
49321
49614
  const write = argv.includes("--write");
@@ -49327,12 +49620,16 @@ async function behaviorCommand(argv) {
49327
49620
  case "corpus":
49328
49621
  showCorpus(write, json2);
49329
49622
  return;
49623
+ case "telemetry":
49624
+ showTelemetry(argv.includes("--enable") ? "enable" : argv.includes("--disable") ? "disable" : "status", json2);
49625
+ return;
49330
49626
  default:
49331
49627
  console.error(`Unknown action "${action}".
49332
49628
 
49333
49629
  Usage:
49334
- claudish behavior rules [--json]
49335
- claudish behavior corpus [--write] [--json]
49630
+ claudish behavior rules [--json]
49631
+ claudish behavior corpus [--write] [--json]
49632
+ claudish behavior telemetry [--enable | --disable] [--json]
49336
49633
  `);
49337
49634
  process.exit(1);
49338
49635
  }
@@ -60747,7 +61044,7 @@ var init_RemoveFileError = __esm(() => {
60747
61044
 
60748
61045
  // ../../node_modules/.bun/@inquirer+external-editor@2.0.1+04f2146be16c61ef/node_modules/@inquirer/external-editor/dist/index.js
60749
61046
  import { spawn as spawn3, spawnSync as spawnSync2 } from "child_process";
60750
- import { readFileSync as readFileSync20, unlinkSync as unlinkSync6, writeFileSync as writeFileSync14 } from "fs";
61047
+ import { readFileSync as readFileSync21, unlinkSync as unlinkSync6, writeFileSync as writeFileSync15 } from "fs";
60751
61048
  import path from "path";
60752
61049
  import os from "os";
60753
61050
  import { randomUUID as randomUUID6 } from "crypto";
@@ -60856,14 +61153,14 @@ class ExternalEditor {
60856
61153
  if (Object.prototype.hasOwnProperty.call(this.fileOptions, "mode")) {
60857
61154
  opt.mode = this.fileOptions.mode;
60858
61155
  }
60859
- writeFileSync14(this.tempFile, this.text, opt);
61156
+ writeFileSync15(this.tempFile, this.text, opt);
60860
61157
  } catch (createFileError) {
60861
61158
  throw new CreateFileError(createFileError);
60862
61159
  }
60863
61160
  }
60864
61161
  readTemporaryFile() {
60865
61162
  try {
60866
- const tempFileBuffer = readFileSync20(this.tempFile);
61163
+ const tempFileBuffer = readFileSync21(this.tempFile);
60867
61164
  if (tempFileBuffer.length === 0) {
60868
61165
  this.text = "";
60869
61166
  } else {
@@ -61842,6 +62139,163 @@ var init_dist16 = __esm(() => {
61842
62139
  init_dist15();
61843
62140
  });
61844
62141
 
62142
+ // src/auth/antigravity-oauth.ts
62143
+ import { spawnSync as spawnSync3 } from "child_process";
62144
+ import { existsSync as existsSync23, unlinkSync as unlinkSync7 } from "fs";
62145
+ import { homedir as homedir27 } from "os";
62146
+ import { join as join29 } from "path";
62147
+ async function defaultSuggestModel() {
62148
+ try {
62149
+ const tok = readSharedAntigravityToken();
62150
+ if (!tok)
62151
+ return "<model>";
62152
+ const { projectId } = await setupAntigravityUser(tok.access_token);
62153
+ const { servedIds, defaultId } = await getServedAntigravityModels(tok.access_token, projectId);
62154
+ return defaultId || servedIds[0] || "<model>";
62155
+ } catch {
62156
+ return "<model>";
62157
+ }
62158
+ }
62159
+ function printManualInstall() {
62160
+ console.log("\nInstall the Antigravity CLI, then retry `claudish login antigravity`:");
62161
+ console.log(` ${INSTALL_CMD}`);
62162
+ console.log(` Docs: ${INSTALL_DOCS}`);
62163
+ }
62164
+ async function defaultConfirmInstall() {
62165
+ const { confirm } = await Promise.resolve().then(() => (init_dist16(), exports_dist));
62166
+ return confirm({
62167
+ message: `Install the Antigravity CLI now? (runs: ${INSTALL_CMD})`,
62168
+ default: true
62169
+ });
62170
+ }
62171
+ function defaultRunInstall() {
62172
+ const res = spawnSync3("bash", ["-c", INSTALL_CMD], { stdio: "inherit" });
62173
+ return !res.error && res.status === 0;
62174
+ }
62175
+ function defaultRunAgyAuth(agyPath, interactive) {
62176
+ if (interactive) {
62177
+ spawnSync3(agyPath, [], { stdio: "inherit" });
62178
+ } else {
62179
+ spawnSync3(agyPath, ["-p", "hello", "--print-timeout", "3m"], { stdio: "inherit" });
62180
+ }
62181
+ }
62182
+ async function pollForToken(deps) {
62183
+ const deadline = deps.now() + deps.timing.graceMs;
62184
+ for (;; ) {
62185
+ const tok = deps.readToken();
62186
+ if (tok)
62187
+ return tok;
62188
+ if (deps.now() >= deadline)
62189
+ return null;
62190
+ const remaining = deadline - deps.now();
62191
+ await deps.sleep(Math.min(deps.timing.intervalMs, Math.max(0, remaining)));
62192
+ }
62193
+ }
62194
+
62195
+ class AntigravityOAuth {
62196
+ static instance = null;
62197
+ static getInstance() {
62198
+ if (!AntigravityOAuth.instance) {
62199
+ AntigravityOAuth.instance = new AntigravityOAuth;
62200
+ }
62201
+ return AntigravityOAuth.instance;
62202
+ }
62203
+ constructor() {}
62204
+ async login(depsOverride = {}) {
62205
+ const deps = { ...defaultLoginDeps, ...depsOverride };
62206
+ log("[AntigravityOAuth] Starting agy-delegated login");
62207
+ if (deps.hasToken()) {
62208
+ console.log(`\u2705 Already authenticated with Antigravity. Use: claudish --model ag@${await (deps.suggestModel ?? defaultSuggestModel)()}`);
62209
+ return deps.exit(0);
62210
+ }
62211
+ let agyPath = deps.locateAgy();
62212
+ if (!agyPath) {
62213
+ console.log("\nThe Antigravity CLI (`agy`) is required to sign in to Antigravity.");
62214
+ console.log(`claudish delegates Antigravity sign-in to agy \u2014 agy holds the current OAuth secret
62215
+ ` + "and writes the session to the shared keychain store that claudish reads.");
62216
+ if (!deps.isInteractive()) {
62217
+ printManualInstall();
62218
+ return deps.exit(0);
62219
+ }
62220
+ const proceed = await deps.confirmInstall();
62221
+ if (!proceed) {
62222
+ printManualInstall();
62223
+ return deps.exit(0);
62224
+ }
62225
+ console.log(`
62226
+ Installing the Antigravity CLI\u2026
62227
+ `);
62228
+ if (!deps.runInstall()) {
62229
+ console.log(`
62230
+ \u274C Antigravity CLI installation failed.`);
62231
+ printManualInstall();
62232
+ return deps.exit(0);
62233
+ }
62234
+ agyPath = deps.locateAgy();
62235
+ if (!agyPath) {
62236
+ console.log(`
62237
+ \u274C Antigravity CLI still not found after install.`);
62238
+ printManualInstall();
62239
+ return deps.exit(0);
62240
+ }
62241
+ }
62242
+ console.log(`
62243
+ Launching the Antigravity CLI to sign in \u2014 complete the sign-in in your browser.
62244
+ ` + `claudish will detect the session automatically.
62245
+ `);
62246
+ deps.runAgyAuth(agyPath, false);
62247
+ let token = await pollForToken(deps);
62248
+ if (!token) {
62249
+ console.log(`
62250
+ No session detected yet. Starting the Antigravity CLI interactively \u2014
62251
+ ` + "sign in, then exit agy (its `/quit` command or Ctrl-C) to return here.\n");
62252
+ deps.runAgyAuth(agyPath, true);
62253
+ token = await pollForToken(deps);
62254
+ }
62255
+ if (token) {
62256
+ deps.onAuthenticated();
62257
+ console.log(`
62258
+ \u2705 Authenticated with Antigravity. Use: claudish --model ag@${await (deps.suggestModel ?? defaultSuggestModel)()}`);
62259
+ return deps.exit(0);
62260
+ }
62261
+ console.log("\nNo Antigravity session detected. Run `agy` and sign in, then retry `claudish login antigravity`.");
62262
+ return deps.exit(0);
62263
+ }
62264
+ async logout(deps) {
62265
+ deleteSharedAntigravityToken(deps);
62266
+ try {
62267
+ const tokenFile = join29(homedir27(), ".gemini", "antigravity-cli", "antigravity-oauth-token");
62268
+ if (existsSync23(tokenFile))
62269
+ unlinkSync7(tokenFile);
62270
+ } catch {}
62271
+ log("[AntigravityOAuth] Antigravity session cleared (keychain + agy token file)");
62272
+ }
62273
+ }
62274
+ var INSTALL_CMD = "curl -fsSL https://antigravity.google/cli/install.sh | bash", INSTALL_DOCS = "https://antigravity.google/docs/cli/install", defaultLoginDeps;
62275
+ var init_antigravity_oauth = __esm(() => {
62276
+ init_logger();
62277
+ init_antigravity_token();
62278
+ init_gemini_oauth();
62279
+ defaultLoginDeps = {
62280
+ locateAgy: locateAgyBinary,
62281
+ hasToken: () => readSharedAntigravityToken() != null,
62282
+ readToken: () => {
62283
+ _resetAntigravityTokenState();
62284
+ return readSharedAntigravityToken();
62285
+ },
62286
+ suggestModel: defaultSuggestModel,
62287
+ confirmInstall: defaultConfirmInstall,
62288
+ runInstall: defaultRunInstall,
62289
+ runAgyAuth: defaultRunAgyAuth,
62290
+ onAuthenticated: () => _resetAntigravityTokenState(),
62291
+ isInteractive: () => Boolean(process.stdin.isTTY),
62292
+ now: () => Date.now(),
62293
+ sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
62294
+ exit: (code) => process.exit(code),
62295
+ timing: { graceMs: 1e4, intervalMs: 500 }
62296
+ };
62297
+ });
62298
+
61845
62299
  // src/auth/auth-commands.ts
61846
62300
  var exports_auth_commands = {};
61847
62301
  __export(exports_auth_commands, {
@@ -61849,7 +62303,7 @@ __export(exports_auth_commands, {
61849
62303
  loginCommand: () => loginCommand
61850
62304
  });
61851
62305
  function getAuthStatus(provider) {
61852
- const hasCredentials = provider.registryKeys.some((k) => hasOAuthCredentials(k));
62306
+ const hasCredentials = provider.registryKeys.some((k) => hasOAuthCredentials(k)) || provider.name === "antigravity" && hasSharedAntigravityToken();
61853
62307
  return hasCredentials ? "logged in" : "not logged in";
61854
62308
  }
61855
62309
  async function selectProvider(action) {
@@ -61906,11 +62360,20 @@ async function logoutCommand(providerArg) {
61906
62360
  var AUTH_PROVIDERS;
61907
62361
  var init_auth_commands = __esm(() => {
61908
62362
  init_dist16();
62363
+ init_antigravity_oauth();
62364
+ init_antigravity_token();
61909
62365
  init_codex_oauth();
61910
62366
  init_gemini_oauth();
61911
62367
  init_kimi_oauth();
61912
62368
  init_oauth_registry();
61913
62369
  AUTH_PROVIDERS = [
62370
+ {
62371
+ name: "antigravity",
62372
+ displayName: "Antigravity",
62373
+ prefix: "ag@, antigravity@",
62374
+ getInstance: () => AntigravityOAuth.getInstance(),
62375
+ registryKeys: ["antigravity"]
62376
+ },
61914
62377
  {
61915
62378
  name: "gemini",
61916
62379
  displayName: "Gemini Code Assist",
@@ -62059,15 +62522,15 @@ async function geminiQuotaHandler() {
62059
62522
  }
62060
62523
  }
62061
62524
  async function codexQuotaHandler() {
62062
- const { readFileSync: readFileSync21, existsSync: existsSync22 } = await import("fs");
62063
- const { join: join28 } = await import("path");
62064
- const { homedir: homedir26 } = await import("os");
62065
- const credPath = join28(homedir26(), ".claudish", "codex-oauth.json");
62066
- if (!existsSync22(credPath)) {
62525
+ const { readFileSync: readFileSync22, existsSync: existsSync24 } = await import("fs");
62526
+ const { join: join30 } = await import("path");
62527
+ const { homedir: homedir28 } = await import("os");
62528
+ const credPath = join30(homedir28(), ".claudish", "codex-oauth.json");
62529
+ if (!existsSync24(credPath)) {
62067
62530
  console.error(`${RED}No Codex credentials found.${R} Run: ${B}claudish login codex${R}`);
62068
62531
  process.exit(1);
62069
62532
  }
62070
- const creds = JSON.parse(readFileSync21(credPath, "utf-8"));
62533
+ const creds = JSON.parse(readFileSync22(credPath, "utf-8"));
62071
62534
  let email3 = "";
62072
62535
  try {
62073
62536
  const parts = creds.access_token.split(".");
@@ -62119,9 +62582,9 @@ async function codexQuotaHandler() {
62119
62582
  }
62120
62583
  let modelSlugs = [];
62121
62584
  try {
62122
- const modelsPath = join28(homedir26(), ".codex", "models_cache.json");
62123
- if (existsSync22(modelsPath)) {
62124
- const cache2 = JSON.parse(readFileSync21(modelsPath, "utf-8"));
62585
+ const modelsPath = join30(homedir28(), ".codex", "models_cache.json");
62586
+ if (existsSync24(modelsPath)) {
62587
+ const cache2 = JSON.parse(readFileSync22(modelsPath, "utf-8"));
62125
62588
  modelSlugs = (cache2.models || []).map((m) => m.slug || m.id).filter(Boolean);
62126
62589
  }
62127
62590
  } catch {}
@@ -63407,7 +63870,7 @@ function annotateOAuthHint(result, provider, isOAuth) {
63407
63870
  return result;
63408
63871
  if (result.state === "live")
63409
63872
  return result;
63410
- const loginCommand2 = provider === "gemini-codeassist" ? "claudish login gemini" : provider === "vertex" ? "gcloud auth application-default login" : undefined;
63873
+ const loginCommand2 = provider === "gemini-codeassist" ? "claudish login gemini" : provider === "antigravity" ? "claudish login antigravity" : provider === "vertex" ? "gcloud auth application-default login" : undefined;
63411
63874
  if (!loginCommand2)
63412
63875
  return result;
63413
63876
  if (result.httpStatus === 403)
@@ -63873,7 +64336,7 @@ var init_theme2 = __esm(() => {
63873
64336
  bold3 = createTextAttributes({ bold: true });
63874
64337
  A = {
63875
64338
  bold: bold3,
63876
- boldIf: (enabled) => enabled ? bold3 : undefined
64339
+ boldIf: (enabled2) => enabled2 ? bold3 : undefined
63877
64340
  };
63878
64341
  LATENCY_BUCKETS = [
63879
64342
  { maxMs: 500, hex: "#1f8f3b" },
@@ -66009,22 +66472,22 @@ __export(exports_cli, {
66009
66472
  });
66010
66473
  import {
66011
66474
  copyFileSync as copyFileSync2,
66012
- existsSync as existsSync22,
66013
- mkdirSync as mkdirSync13,
66014
- readFileSync as readFileSync21,
66475
+ existsSync as existsSync24,
66476
+ mkdirSync as mkdirSync14,
66477
+ readFileSync as readFileSync22,
66015
66478
  readdirSync as readdirSync5,
66016
- unlinkSync as unlinkSync7,
66017
- writeFileSync as writeFileSync15
66479
+ unlinkSync as unlinkSync8,
66480
+ writeFileSync as writeFileSync16
66018
66481
  } from "fs";
66019
- import { homedir as homedir26 } from "os";
66020
- import { dirname as dirname9, join as join28 } from "path";
66482
+ import { homedir as homedir28 } from "os";
66483
+ import { dirname as dirname10, join as join30 } from "path";
66021
66484
  import { fileURLToPath as fileURLToPath2 } from "url";
66022
66485
  function getVersion3() {
66023
66486
  return VERSION;
66024
66487
  }
66025
66488
  function clearAllModelCaches() {
66026
- const cacheDir = join28(homedir26(), ".claudish");
66027
- if (!existsSync22(cacheDir))
66489
+ const cacheDir = join30(homedir28(), ".claudish");
66490
+ if (!existsSync24(cacheDir))
66028
66491
  return;
66029
66492
  const cachePatterns = ["pricing-cache.json", "recommended-models-cache.json"];
66030
66493
  let cleared = 0;
@@ -66032,7 +66495,7 @@ function clearAllModelCaches() {
66032
66495
  const files = readdirSync5(cacheDir);
66033
66496
  for (const file2 of files) {
66034
66497
  if (cachePatterns.includes(file2)) {
66035
- unlinkSync7(join28(cacheDir, file2));
66498
+ unlinkSync8(join30(cacheDir, file2));
66036
66499
  cleared++;
66037
66500
  }
66038
66501
  }
@@ -66442,15 +66905,15 @@ Usage: claudish --models --provider <slug>`);
66442
66905
  });
66443
66906
  config3.resolvedDefaultProvider = resolved;
66444
66907
  if (resolved.legacyAutoPromoted && !config3.quiet) {
66445
- const markerFile = join28(homedir26(), ".claudish", ".legacy-litellm-hint-shown");
66446
- if (!existsSync22(markerFile)) {
66908
+ const markerFile = join30(homedir28(), ".claudish", ".legacy-litellm-hint-shown");
66909
+ if (!existsSync24(markerFile)) {
66447
66910
  const hint = buildLegacyHint(resolved);
66448
66911
  if (hint) {
66449
66912
  console.error(hint);
66450
66913
  }
66451
66914
  try {
66452
- mkdirSync13(dirname9(markerFile), { recursive: true });
66453
- writeFileSync15(markerFile, new Date().toISOString(), "utf-8");
66915
+ mkdirSync14(dirname10(markerFile), { recursive: true });
66916
+ writeFileSync16(markerFile, new Date().toISOString(), "utf-8");
66454
66917
  } catch {}
66455
66918
  }
66456
66919
  }
@@ -67517,8 +67980,8 @@ ${h("MORE INFO")}
67517
67980
  }
67518
67981
  function printAIAgentGuide() {
67519
67982
  try {
67520
- const guidePath = join28(__dirname3, "../AI_AGENT_GUIDE.md");
67521
- const guideContent = readFileSync21(guidePath, "utf-8");
67983
+ const guidePath = join30(__dirname3, "../AI_AGENT_GUIDE.md");
67984
+ const guideContent = readFileSync22(guidePath, "utf-8");
67522
67985
  console.log(guideContent);
67523
67986
  } catch (error46) {
67524
67987
  console.error("Error reading AI Agent Guide:");
@@ -67534,19 +67997,19 @@ async function initializeClaudishSkill() {
67534
67997
  console.log(`\uD83D\uDD27 Initializing Claudish skill in current project...
67535
67998
  `);
67536
67999
  const cwd = process.cwd();
67537
- const claudeDir = join28(cwd, ".claude");
67538
- const skillsDir = join28(claudeDir, "skills");
67539
- const claudishSkillDir = join28(skillsDir, "claudish-usage");
67540
- const skillFile = join28(claudishSkillDir, "SKILL.md");
67541
- if (existsSync22(skillFile)) {
68000
+ const claudeDir = join30(cwd, ".claude");
68001
+ const skillsDir = join30(claudeDir, "skills");
68002
+ const claudishSkillDir = join30(skillsDir, "claudish-usage");
68003
+ const skillFile = join30(claudishSkillDir, "SKILL.md");
68004
+ if (existsSync24(skillFile)) {
67542
68005
  console.log("\u2705 Claudish skill already installed at:");
67543
68006
  console.log(` ${skillFile}
67544
68007
  `);
67545
68008
  console.log("\uD83D\uDCA1 To reinstall, delete the file and run 'claudish --init' again.");
67546
68009
  return;
67547
68010
  }
67548
- const sourceSkillPath = join28(__dirname3, "../skills/claudish-usage/SKILL.md");
67549
- if (!existsSync22(sourceSkillPath)) {
68011
+ const sourceSkillPath = join30(__dirname3, "../skills/claudish-usage/SKILL.md");
68012
+ if (!existsSync24(sourceSkillPath)) {
67550
68013
  console.error("\u274C Error: Claudish skill file not found in installation.");
67551
68014
  console.error(` Expected at: ${sourceSkillPath}`);
67552
68015
  console.error(`
@@ -67555,16 +68018,16 @@ async function initializeClaudishSkill() {
67555
68018
  process.exit(1);
67556
68019
  }
67557
68020
  try {
67558
- if (!existsSync22(claudeDir)) {
67559
- mkdirSync13(claudeDir, { recursive: true });
68021
+ if (!existsSync24(claudeDir)) {
68022
+ mkdirSync14(claudeDir, { recursive: true });
67560
68023
  console.log("\uD83D\uDCC1 Created .claude/ directory");
67561
68024
  }
67562
- if (!existsSync22(skillsDir)) {
67563
- mkdirSync13(skillsDir, { recursive: true });
68025
+ if (!existsSync24(skillsDir)) {
68026
+ mkdirSync14(skillsDir, { recursive: true });
67564
68027
  console.log("\uD83D\uDCC1 Created .claude/skills/ directory");
67565
68028
  }
67566
- if (!existsSync22(claudishSkillDir)) {
67567
- mkdirSync13(claudishSkillDir, { recursive: true });
68029
+ if (!existsSync24(claudishSkillDir)) {
68030
+ mkdirSync14(claudishSkillDir, { recursive: true });
67568
68031
  console.log("\uD83D\uDCC1 Created .claude/skills/claudish-usage/ directory");
67569
68032
  }
67570
68033
  copyFileSync2(sourceSkillPath, skillFile);
@@ -67636,7 +68099,7 @@ var init_cli = __esm(() => {
67636
68099
  init_routing_rules();
67637
68100
  init_provider_resolver();
67638
68101
  __filename3 = fileURLToPath2(import.meta.url);
67639
- __dirname3 = dirname9(__filename3);
68102
+ __dirname3 = dirname10(__filename3);
67640
68103
  });
67641
68104
 
67642
68105
  // src/update-checker.ts
@@ -67648,33 +68111,33 @@ __export(exports_update_checker, {
67648
68111
  clearCache: () => clearCache,
67649
68112
  checkForUpdates: () => checkForUpdates
67650
68113
  });
67651
- import { existsSync as existsSync23, mkdirSync as mkdirSync14, readFileSync as readFileSync22, unlinkSync as unlinkSync8, writeFileSync as writeFileSync16 } from "fs";
67652
- import { homedir as homedir27, platform as platform2, tmpdir } from "os";
67653
- import { join as join29 } from "path";
68114
+ import { existsSync as existsSync25, mkdirSync as mkdirSync15, readFileSync as readFileSync23, unlinkSync as unlinkSync9, writeFileSync as writeFileSync17 } from "fs";
68115
+ import { homedir as homedir29, platform as platform2, tmpdir } from "os";
68116
+ import { join as join31 } from "path";
67654
68117
  function getCacheFilePath() {
67655
68118
  let cacheDir;
67656
68119
  if (isWindows) {
67657
- const localAppData = process.env.LOCALAPPDATA || join29(homedir27(), "AppData", "Local");
67658
- cacheDir = join29(localAppData, "claudish");
68120
+ const localAppData = process.env.LOCALAPPDATA || join31(homedir29(), "AppData", "Local");
68121
+ cacheDir = join31(localAppData, "claudish");
67659
68122
  } else {
67660
- cacheDir = join29(homedir27(), ".cache", "claudish");
68123
+ cacheDir = join31(homedir29(), ".cache", "claudish");
67661
68124
  }
67662
68125
  try {
67663
- if (!existsSync23(cacheDir)) {
67664
- mkdirSync14(cacheDir, { recursive: true });
68126
+ if (!existsSync25(cacheDir)) {
68127
+ mkdirSync15(cacheDir, { recursive: true });
67665
68128
  }
67666
- return join29(cacheDir, "update-check.json");
68129
+ return join31(cacheDir, "update-check.json");
67667
68130
  } catch {
67668
- return join29(tmpdir(), "claudish-update-check.json");
68131
+ return join31(tmpdir(), "claudish-update-check.json");
67669
68132
  }
67670
68133
  }
67671
68134
  function readCache() {
67672
68135
  try {
67673
68136
  const cachePath = getCacheFilePath();
67674
- if (!existsSync23(cachePath)) {
68137
+ if (!existsSync25(cachePath)) {
67675
68138
  return null;
67676
68139
  }
67677
- const data = JSON.parse(readFileSync22(cachePath, "utf-8"));
68140
+ const data = JSON.parse(readFileSync23(cachePath, "utf-8"));
67678
68141
  return data;
67679
68142
  } catch {
67680
68143
  return null;
@@ -67687,7 +68150,7 @@ function writeCache(latestVersion) {
67687
68150
  lastCheck: Date.now(),
67688
68151
  latestVersion
67689
68152
  };
67690
- writeFileSync16(cachePath, JSON.stringify(data), "utf-8");
68153
+ writeFileSync17(cachePath, JSON.stringify(data), "utf-8");
67691
68154
  } catch {}
67692
68155
  }
67693
68156
  function isCacheValid(cache2) {
@@ -67697,8 +68160,8 @@ function isCacheValid(cache2) {
67697
68160
  function clearCache() {
67698
68161
  try {
67699
68162
  const cachePath = getCacheFilePath();
67700
- if (existsSync23(cachePath)) {
67701
- unlinkSync8(cachePath);
68163
+ if (existsSync25(cachePath)) {
68164
+ unlinkSync9(cachePath);
67702
68165
  }
67703
68166
  } catch {}
67704
68167
  }
@@ -68582,15 +69045,15 @@ var init_local_liveness = __esm(() => {
68582
69045
  });
68583
69046
 
68584
69047
  // src/providers/probe-catalog.ts
68585
- import { existsSync as existsSync24, mkdirSync as mkdirSync15, readFileSync as readFileSync23, writeFileSync as writeFileSync17 } from "fs";
68586
- import { homedir as homedir28 } from "os";
68587
- import { dirname as dirname10, join as join30 } from "path";
69048
+ import { existsSync as existsSync26, mkdirSync as mkdirSync16, readFileSync as readFileSync24, writeFileSync as writeFileSync18 } from "fs";
69049
+ import { homedir as homedir30 } from "os";
69050
+ import { dirname as dirname11, join as join32 } from "path";
68588
69051
  function readProbeModelsCache(path2 = PROBE_MODELS_CACHE_PATH) {
68589
- if (!existsSync24(path2))
69052
+ if (!existsSync26(path2))
68590
69053
  return null;
68591
69054
  let raw2;
68592
69055
  try {
68593
- raw2 = JSON.parse(readFileSync23(path2, "utf-8"));
69056
+ raw2 = JSON.parse(readFileSync24(path2, "utf-8"));
68594
69057
  } catch {
68595
69058
  return null;
68596
69059
  }
@@ -68599,8 +69062,8 @@ function readProbeModelsCache(path2 = PROBE_MODELS_CACHE_PATH) {
68599
69062
  return raw2;
68600
69063
  }
68601
69064
  function writeProbeModelsCache(data, path2 = PROBE_MODELS_CACHE_PATH) {
68602
- mkdirSync15(dirname10(path2), { recursive: true });
68603
- writeFileSync17(path2, JSON.stringify(data), "utf-8");
69065
+ mkdirSync16(dirname11(path2), { recursive: true });
69066
+ writeFileSync18(path2, JSON.stringify(data), "utf-8");
68604
69067
  }
68605
69068
  function isCacheFresh(data, ttlMs = CACHE_TTL_MS4) {
68606
69069
  if (!data?.generatedAt)
@@ -68719,7 +69182,7 @@ function isValidResponse(raw2) {
68719
69182
  var PROBE_MODELS_URL = "https://us-central1-claudish-6da10.cloudfunctions.net/probeModels", CACHE_TTL_MS4, FETCH_TIMEOUT_MS3 = 15000, PROBE_MODELS_CACHE_PATH, _inFlight = null;
68720
69183
  var init_probe_catalog = __esm(() => {
68721
69184
  CACHE_TTL_MS4 = 60 * 60 * 1000;
68722
- PROBE_MODELS_CACHE_PATH = join30(homedir28(), ".claudish", "probe-models.json");
69185
+ PROBE_MODELS_CACHE_PATH = join32(homedir30(), ".claudish", "probe-models.json");
68723
69186
  });
68724
69187
 
68725
69188
  // src/tui/constants.ts
@@ -71407,8 +71870,8 @@ function ProvidersContent({
71407
71870
  let statusText = p.isLocal ? isReady ? "enabled" : "disabled" : isReady ? "ready" : "not set";
71408
71871
  if (p.isLocal) {
71409
71872
  const live = localLiveness[p.catalogName];
71410
- const enabled = providerAuthSource(p, config3) !== null;
71411
- if (enabled) {
71873
+ const enabled2 = providerAuthSource(p, config3) !== null;
71874
+ if (enabled2) {
71412
71875
  if (live === "running") {
71413
71876
  statusFg = C.green;
71414
71877
  statusText = "running";
@@ -74917,13 +75380,15 @@ var exports_tui = {};
74917
75380
  __export(exports_tui, {
74918
75381
  startConfigTui: () => startConfigTui
74919
75382
  });
74920
- import { spawnSync as spawnSync3 } from "child_process";
75383
+ import { spawnSync as spawnSync4 } from "child_process";
74921
75384
  import { createCliRenderer as createCliRenderer2 } from "@opentui/core";
74922
75385
  import { createRoot as createRoot2 } from "@opentui/react";
74923
75386
  import { jsxDEV as jsxDEV17 } from "@opentui/react/jsx-dev-runtime";
74924
75387
  async function startConfigTui() {
74925
75388
  setStderrQuiet(true);
74926
- const loginRequest = { slug: null };
75389
+ const loginRequest = {
75390
+ slug: null
75391
+ };
74927
75392
  const requestLogin = (slug) => {
74928
75393
  loginRequest.slug = slug;
74929
75394
  };
@@ -74943,7 +75408,7 @@ async function startConfigTui() {
74943
75408
  console.log(`
74944
75409
  Launching: claudish login ${slug}
74945
75410
  `);
74946
- const result = spawnSync3(process.argv[0], [process.argv[1], "login", slug], {
75411
+ const result = spawnSync4(process.argv[0], [process.argv[1], "login", slug], {
74947
75412
  stdio: "inherit"
74948
75413
  });
74949
75414
  if (result.error) {
@@ -74955,7 +75420,10 @@ Launching: claudish login ${slug}
74955
75420
  \u274C Login exited with status ${result.status}
74956
75421
  `);
74957
75422
  } else {
74958
- if (slug === "gemini") {
75423
+ if (slug === "antigravity") {
75424
+ _resetAntigravityTokenState();
75425
+ invalidateProbeProxyHandlers("antigravity");
75426
+ } else if (slug === "gemini") {
74959
75427
  reloadGeminiCredentials();
74960
75428
  invalidateProbeProxyHandlers("google");
74961
75429
  invalidateProbeProxyHandlers("gemini-codeassist");
@@ -74976,6 +75444,7 @@ Returning to config\u2026
74976
75444
  }
74977
75445
  var isDirectRun = false;
74978
75446
  var init_tui = __esm(() => {
75447
+ init_antigravity_token();
74979
75448
  init_codex_oauth();
74980
75449
  init_gemini_oauth();
74981
75450
  init_kimi_oauth();
@@ -75064,17 +75533,17 @@ __export(exports_claude_runner, {
75064
75533
  import { spawn as spawn4 } from "child_process";
75065
75534
  import {
75066
75535
  closeSync as closeSync5,
75067
- existsSync as existsSync25,
75068
- mkdirSync as mkdirSync16,
75536
+ existsSync as existsSync27,
75537
+ mkdirSync as mkdirSync17,
75069
75538
  openSync as openSync5,
75070
- readFileSync as readFileSync24,
75539
+ readFileSync as readFileSync25,
75071
75540
  readdirSync as readdirSync6,
75072
75541
  statSync as statSync5,
75073
- unlinkSync as unlinkSync9,
75074
- writeFileSync as writeFileSync18
75542
+ unlinkSync as unlinkSync10,
75543
+ writeFileSync as writeFileSync19
75075
75544
  } from "fs";
75076
- import { homedir as homedir29, tmpdir as tmpdir2 } from "os";
75077
- import { dirname as dirname11, join as join31 } from "path";
75545
+ import { homedir as homedir31, tmpdir as tmpdir2 } from "os";
75546
+ import { dirname as dirname12, join as join33 } from "path";
75078
75547
  import { isatty } from "tty";
75079
75548
  function releaseTerminalIsolation() {
75080
75549
  if (!restoreTerminal)
@@ -75109,16 +75578,16 @@ function isProxyAuthMode(config3) {
75109
75578
  }
75110
75579
  function managedSettingsPath() {
75111
75580
  if (isWindows2()) {
75112
- return join31(process.env.PROGRAMDATA || "C:\\ProgramData", "ClaudeCode", "managed-settings.json");
75581
+ return join33(process.env.PROGRAMDATA || "C:\\ProgramData", "ClaudeCode", "managed-settings.json");
75113
75582
  }
75114
75583
  if (process.platform === "darwin") {
75115
75584
  return "/Library/Application Support/ClaudeCode/managed-settings.json";
75116
75585
  }
75117
75586
  return "/etc/claude-code/managed-settings.json";
75118
75587
  }
75119
- function managedSettingsForcesClaudeAi(readFile2 = readFileSync24) {
75588
+ function managedSettingsForcesClaudeAi(readFile3 = readFileSync25) {
75120
75589
  try {
75121
- const raw2 = readFile2(managedSettingsPath(), "utf-8");
75590
+ const raw2 = readFile3(managedSettingsPath(), "utf-8");
75122
75591
  const parsed = JSON.parse(raw2);
75123
75592
  return parsed.forceLoginMethod === "claudeai";
75124
75593
  } catch {
@@ -75130,9 +75599,9 @@ function isWindows2() {
75130
75599
  }
75131
75600
  function createStatusLineScript(tokenFilePath) {
75132
75601
  const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
75133
- const claudishDir = join31(homeDir, ".claudish");
75602
+ const claudishDir = join33(homeDir, ".claudish");
75134
75603
  const timestamp = Date.now();
75135
- const scriptPath = join31(claudishDir, `status-${timestamp}.js`);
75604
+ const scriptPath = join33(claudishDir, `status-${timestamp}.js`);
75136
75605
  const escapedTokenPath = tokenFilePath.replace(/\\/g, "\\\\");
75137
75606
  const script = `
75138
75607
  const fs = require('fs');
@@ -75250,13 +75719,13 @@ process.stdin.on('end', () => {
75250
75719
  }
75251
75720
  });
75252
75721
  `;
75253
- writeFileSync18(scriptPath, script, "utf-8");
75722
+ writeFileSync19(scriptPath, script, "utf-8");
75254
75723
  return scriptPath;
75255
75724
  }
75256
75725
  function initializeTokenFile(tokenFilePath) {
75257
75726
  try {
75258
- mkdirSync16(dirname11(tokenFilePath), { recursive: true });
75259
- writeFileSync18(tokenFilePath, JSON.stringify({
75727
+ mkdirSync17(dirname12(tokenFilePath), { recursive: true });
75728
+ writeFileSync19(tokenFilePath, JSON.stringify({
75260
75729
  input_tokens: 0,
75261
75730
  output_tokens: 0,
75262
75731
  total_tokens: 0,
@@ -75287,11 +75756,11 @@ function cleanupStaleTokenFiles(dir, now = Date.now(), maxAgeMs = STALE_TOKEN_FI
75287
75756
  if (!name.startsWith("tokens-") || !name.endsWith(".json"))
75288
75757
  continue;
75289
75758
  scanned++;
75290
- const full = join31(dir, name);
75759
+ const full = join33(dir, name);
75291
75760
  try {
75292
75761
  if (statSync5(full).mtimeMs >= cutoff)
75293
75762
  continue;
75294
- unlinkSync9(full);
75763
+ unlinkSync10(full);
75295
75764
  removed++;
75296
75765
  } catch {}
75297
75766
  }
@@ -75304,7 +75773,7 @@ function parseSettingsArg(value) {
75304
75773
  if (value.trimStart().startsWith("{")) {
75305
75774
  return JSON.parse(value);
75306
75775
  }
75307
- return JSON.parse(readFileSync24(value, "utf-8"));
75776
+ return JSON.parse(readFileSync25(value, "utf-8"));
75308
75777
  }
75309
75778
  function parseSettingsArgSafe(value) {
75310
75779
  try {
@@ -75316,13 +75785,13 @@ function parseSettingsArgSafe(value) {
75316
75785
  }
75317
75786
  function userSettingsFileCandidates(cwd) {
75318
75787
  return [
75319
- join31(homedir29(), ".claude", "settings.json"),
75320
- join31(cwd, ".claude", "settings.json"),
75321
- join31(cwd, ".claude", "settings.local.json")
75788
+ join33(homedir31(), ".claude", "settings.json"),
75789
+ join33(cwd, ".claude", "settings.json"),
75790
+ join33(cwd, ".claude", "settings.local.json")
75322
75791
  ];
75323
75792
  }
75324
75793
  function discoverUserStatusLineCommand(claudeArgs = [], cwd = process.cwd()) {
75325
- const sources = userSettingsFileCandidates(cwd).filter((file2) => existsSync25(file2));
75794
+ const sources = userSettingsFileCandidates(cwd).filter((file2) => existsSync27(file2));
75326
75795
  const idx = claudeArgs.indexOf("--settings");
75327
75796
  const settingsArg = idx === -1 ? undefined : claudeArgs[idx + 1];
75328
75797
  if (settingsArg)
@@ -75359,13 +75828,13 @@ function buildChainedStatusCommand(userCommand, claudishBody, claudishSegment) {
75359
75828
  }
75360
75829
  function createTempSettingsFile(_modelDisplay, port, proxyAuthMode, userStatusLineCommand) {
75361
75830
  const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
75362
- const claudishDir = join31(homeDir, ".claudish");
75831
+ const claudishDir = join33(homeDir, ".claudish");
75363
75832
  try {
75364
- mkdirSync16(claudishDir, { recursive: true });
75833
+ mkdirSync17(claudishDir, { recursive: true });
75365
75834
  } catch {}
75366
75835
  const timestamp = Date.now();
75367
- const tempPath = join31(claudishDir, `settings-${timestamp}.json`);
75368
- const tokenFilePath = join31(claudishDir, `tokens-${port}.json`);
75836
+ const tempPath = join33(claudishDir, `settings-${timestamp}.json`);
75837
+ const tokenFilePath = join33(claudishDir, `tokens-${port}.json`);
75369
75838
  cleanupStaleTokenFiles(claudishDir);
75370
75839
  initializeTokenFile(tokenFilePath);
75371
75840
  let statusCommand;
@@ -75396,7 +75865,7 @@ function createTempSettingsFile(_modelDisplay, port, proxyAuthMode, userStatusLi
75396
75865
  padding: 0
75397
75866
  };
75398
75867
  const settings = buildClaudishSettingsOverlay(statusLine, proxyAuthMode);
75399
- writeFileSync18(tempPath, JSON.stringify(settings, null, 2), "utf-8");
75868
+ writeFileSync19(tempPath, JSON.stringify(settings, null, 2), "utf-8");
75400
75869
  return { path: tempPath, statusLine, tokenFilePath };
75401
75870
  }
75402
75871
  function buildClaudishSettingsOverlay(statusLine, proxyAuthMode) {
@@ -75421,7 +75890,7 @@ function mergeUserSettingsIfPresent(config3, tempSettingsPath, statusLine, proxy
75421
75890
  if (proxyAuthMode && !("forceLoginMethod" in userSettings)) {
75422
75891
  userSettings.forceLoginMethod = "console";
75423
75892
  }
75424
- writeFileSync18(tempSettingsPath, JSON.stringify(userSettings, null, 2), "utf-8");
75893
+ writeFileSync19(tempSettingsPath, JSON.stringify(userSettings, null, 2), "utf-8");
75425
75894
  } catch {
75426
75895
  if (!config3.quiet) {
75427
75896
  console.warn(`[claudish] Warning: could not merge user settings: ${userSettingsValue}`);
@@ -75632,8 +76101,8 @@ async function runClaudeWithProxy(config3, proxyUrl, onCleanup) {
75632
76101
  console.error("Install it from: https://claude.com/claude-code");
75633
76102
  console.error(`
75634
76103
  Or set CLAUDE_PATH to your custom installation:`);
75635
- const home = homedir29();
75636
- const localPath = isWindows2() ? join31(home, ".claude", "local", "claude.exe") : join31(home, ".claude", "local", "claude");
76104
+ const home = homedir31();
76105
+ const localPath = isWindows2() ? join33(home, ".claude", "local", "claude.exe") : join33(home, ".claude", "local", "claude");
75637
76106
  console.error(` export CLAUDE_PATH=${localPath}`);
75638
76107
  process.exit(1);
75639
76108
  }
@@ -75684,7 +76153,7 @@ Or set CLAUDE_PATH to your custom installation:`);
75684
76153
  });
75685
76154
  releaseTerminalIsolation();
75686
76155
  try {
75687
- unlinkSync9(tempSettingsPath);
76156
+ unlinkSync10(tempSettingsPath);
75688
76157
  } catch {}
75689
76158
  return exitCode;
75690
76159
  }
@@ -75704,7 +76173,7 @@ function setupSignalHandlers(proc, tempSettingsPath, quiet, onCleanup) {
75704
76173
  } catch {}
75705
76174
  }
75706
76175
  try {
75707
- unlinkSync9(tempSettingsPath);
76176
+ unlinkSync10(tempSettingsPath);
75708
76177
  } catch {}
75709
76178
  process.exit(0);
75710
76179
  });
@@ -75713,23 +76182,23 @@ function setupSignalHandlers(proc, tempSettingsPath, quiet, onCleanup) {
75713
76182
  async function findClaudeBinary() {
75714
76183
  const isWindows3 = process.platform === "win32";
75715
76184
  if (process.env.CLAUDE_PATH) {
75716
- if (existsSync25(process.env.CLAUDE_PATH)) {
76185
+ if (existsSync27(process.env.CLAUDE_PATH)) {
75717
76186
  return process.env.CLAUDE_PATH;
75718
76187
  }
75719
76188
  }
75720
- const home = homedir29();
75721
- const localPath = isWindows3 ? join31(home, ".claude", "local", "claude.exe") : join31(home, ".claude", "local", "claude");
75722
- if (existsSync25(localPath)) {
76189
+ const home = homedir31();
76190
+ const localPath = isWindows3 ? join33(home, ".claude", "local", "claude.exe") : join33(home, ".claude", "local", "claude");
76191
+ if (existsSync27(localPath)) {
75723
76192
  return localPath;
75724
76193
  }
75725
76194
  if (isWindows3) {
75726
76195
  const windowsPaths = [
75727
- join31(home, "AppData", "Roaming", "npm", "claude.cmd"),
75728
- join31(home, ".npm-global", "claude.cmd"),
75729
- join31(home, "node_modules", ".bin", "claude.cmd")
76196
+ join33(home, "AppData", "Roaming", "npm", "claude.cmd"),
76197
+ join33(home, ".npm-global", "claude.cmd"),
76198
+ join33(home, "node_modules", ".bin", "claude.cmd")
75730
76199
  ];
75731
76200
  for (const path2 of windowsPaths) {
75732
- if (existsSync25(path2)) {
76201
+ if (existsSync27(path2)) {
75733
76202
  return path2;
75734
76203
  }
75735
76204
  }
@@ -75737,14 +76206,14 @@ async function findClaudeBinary() {
75737
76206
  const commonPaths = [
75738
76207
  "/usr/local/bin/claude",
75739
76208
  "/opt/homebrew/bin/claude",
75740
- join31(home, ".npm-global/bin/claude"),
75741
- join31(home, ".local/bin/claude"),
75742
- join31(home, "node_modules/.bin/claude"),
76209
+ join33(home, ".npm-global/bin/claude"),
76210
+ join33(home, ".local/bin/claude"),
76211
+ join33(home, "node_modules/.bin/claude"),
75743
76212
  "/data/data/com.termux/files/usr/bin/claude",
75744
- join31(home, "../usr/bin/claude")
76213
+ join33(home, "../usr/bin/claude")
75745
76214
  ];
75746
76215
  for (const path2 of commonPaths) {
75747
- if (existsSync25(path2)) {
76216
+ if (existsSync27(path2)) {
75748
76217
  return path2;
75749
76218
  }
75750
76219
  }
@@ -75804,18 +76273,18 @@ __export(exports_diag_output, {
75804
76273
  NullDiagOutput: () => NullDiagOutput,
75805
76274
  LogFileDiagOutput: () => LogFileDiagOutput
75806
76275
  });
75807
- import { createWriteStream as createWriteStream3, mkdirSync as mkdirSync17, unlinkSync as unlinkSync10, writeFileSync as writeFileSync19 } from "fs";
75808
- import { homedir as homedir30 } from "os";
75809
- import { join as join32 } from "path";
76276
+ import { createWriteStream as createWriteStream3, mkdirSync as mkdirSync18, unlinkSync as unlinkSync11, writeFileSync as writeFileSync20 } from "fs";
76277
+ import { homedir as homedir32 } from "os";
76278
+ import { join as join34 } from "path";
75810
76279
  function getClaudishDir() {
75811
- const dir = join32(homedir30(), ".claudish");
76280
+ const dir = join34(homedir32(), ".claudish");
75812
76281
  try {
75813
- mkdirSync17(dir, { recursive: true });
76282
+ mkdirSync18(dir, { recursive: true });
75814
76283
  } catch {}
75815
76284
  return dir;
75816
76285
  }
75817
76286
  function getDiagLogPath() {
75818
- return join32(getClaudishDir(), `diag-${process.pid}.log`);
76287
+ return join34(getClaudishDir(), `diag-${process.pid}.log`);
75819
76288
  }
75820
76289
 
75821
76290
  class LogFileDiagOutput {
@@ -75824,7 +76293,7 @@ class LogFileDiagOutput {
75824
76293
  constructor() {
75825
76294
  this.logPath = getDiagLogPath();
75826
76295
  try {
75827
- writeFileSync19(this.logPath, `--- claudish diag session ${new Date().toISOString()} ---
76296
+ writeFileSync20(this.logPath, `--- claudish diag session ${new Date().toISOString()} ---
75828
76297
  `);
75829
76298
  } catch {}
75830
76299
  this.stream = createWriteStream3(this.logPath, { flags: "a" });
@@ -75843,7 +76312,7 @@ class LogFileDiagOutput {
75843
76312
  this.stream.end();
75844
76313
  } catch {}
75845
76314
  try {
75846
- unlinkSync10(this.logPath);
76315
+ unlinkSync11(this.logPath);
75847
76316
  } catch {}
75848
76317
  }
75849
76318
  getLogPath() {
@@ -76026,9 +76495,9 @@ __export(exports_team_grid, {
76026
76495
  });
76027
76496
  import { spawn as spawn5 } from "child_process";
76028
76497
  import { execSync as execSync2 } from "child_process";
76029
- import { existsSync as existsSync26, readFileSync as readFileSync25, writeFileSync as writeFileSync20 } from "fs";
76498
+ import { existsSync as existsSync28, readFileSync as readFileSync26, writeFileSync as writeFileSync21 } from "fs";
76030
76499
  import { connect as netConnect } from "net";
76031
- import { dirname as dirname12, join as join33 } from "path";
76500
+ import { dirname as dirname13, join as join35 } from "path";
76032
76501
  import { setTimeout as wait } from "timers/promises";
76033
76502
  import { fileURLToPath as fileURLToPath3 } from "url";
76034
76503
  function resolveRouteInfo(modelId) {
@@ -76121,21 +76590,21 @@ function buildPaneHeader(model, prompt, bg) {
76121
76590
  }
76122
76591
  function findMagmuxBinary() {
76123
76592
  const thisFile = fileURLToPath3(import.meta.url);
76124
- const thisDir = dirname12(thisFile);
76125
- const pkgRoot = join33(thisDir, "..");
76593
+ const thisDir = dirname13(thisFile);
76594
+ const pkgRoot = join35(thisDir, "..");
76126
76595
  const platform3 = process.platform;
76127
76596
  const arch = process.arch;
76128
- const bundledMagmux = join33(pkgRoot, "native", `magmux-${platform3}-${arch}`);
76129
- if (existsSync26(bundledMagmux))
76597
+ const bundledMagmux = join35(pkgRoot, "native", `magmux-${platform3}-${arch}`);
76598
+ if (existsSync28(bundledMagmux))
76130
76599
  return bundledMagmux;
76131
76600
  try {
76132
76601
  const pkgName = `@claudish/magmux-${platform3}-${arch}`;
76133
76602
  let searchDir = pkgRoot;
76134
76603
  for (let i = 0;i < 5; i++) {
76135
- const candidate = join33(searchDir, "node_modules", pkgName, "bin", "magmux");
76136
- if (existsSync26(candidate))
76604
+ const candidate = join35(searchDir, "node_modules", pkgName, "bin", "magmux");
76605
+ if (existsSync28(candidate))
76137
76606
  return candidate;
76138
- const parent = dirname12(searchDir);
76607
+ const parent = dirname13(searchDir);
76139
76608
  if (parent === searchDir)
76140
76609
  break;
76141
76610
  searchDir = parent;
@@ -76152,7 +76621,7 @@ function findMagmuxBinary() {
76152
76621
  async function subscribeToMagmux(sockPath, onEvent) {
76153
76622
  let client = null;
76154
76623
  for (let attempt = 0;attempt < 40; attempt++) {
76155
- if (existsSync26(sockPath)) {
76624
+ if (existsSync28(sockPath)) {
76156
76625
  try {
76157
76626
  client = await new Promise((resolve4, reject) => {
76158
76627
  const s = netConnect(sockPath);
@@ -76239,9 +76708,9 @@ async function runWithGrid(sessionPath, models, input, opts) {
76239
76708
  const keep = opts?.keep ?? false;
76240
76709
  const manifest = setupSession(sessionPath, models, input);
76241
76710
  const startedAt = new Date().toISOString();
76242
- const gridfilePath = join33(sessionPath, "gridfile.txt");
76243
- const prompt = readFileSync25(join33(sessionPath, "input.md"), "utf-8").replace(/'/g, "'\\''").replace(/\n/g, " ");
76244
- const rawPrompt = readFileSync25(join33(sessionPath, "input.md"), "utf-8");
76711
+ const gridfilePath = join35(sessionPath, "gridfile.txt");
76712
+ const prompt = readFileSync26(join35(sessionPath, "input.md"), "utf-8").replace(/'/g, "'\\''").replace(/\n/g, " ");
76713
+ const rawPrompt = readFileSync26(join35(sessionPath, "input.md"), "utf-8");
76245
76714
  const usedBannerColors = new Set;
76246
76715
  const gridLines = Object.entries(manifest.models).map(([anonId]) => {
76247
76716
  const model = manifest.models[anonId].model;
@@ -76252,7 +76721,7 @@ async function runWithGrid(sessionPath, models, input, opts) {
76252
76721
  const header = buildPaneHeader(model, rawPrompt, bg);
76253
76722
  return `${header} claudish --model ${model} -y --quiet '${prompt}'`;
76254
76723
  });
76255
- writeFileSync20(gridfilePath, `${gridLines.join(`
76724
+ writeFileSync21(gridfilePath, `${gridLines.join(`
76256
76725
  `)}
76257
76726
  `, "utf-8");
76258
76727
  const magmuxPath = findMagmuxBinary();
@@ -76272,8 +76741,8 @@ async function runWithGrid(sessionPath, models, input, opts) {
76272
76741
  });
76273
76742
  const [{ results: results2 }] = await Promise.all([subscription, procExit]);
76274
76743
  const status = buildTeamStatus(manifest, startedAt, results2?.panes ?? null);
76275
- const statusPath = join33(sessionPath, "status.json");
76276
- writeFileSync20(statusPath, JSON.stringify(status, null, 2), "utf-8");
76744
+ const statusPath = join35(sessionPath, "status.json");
76745
+ writeFileSync21(statusPath, JSON.stringify(status, null, 2), "utf-8");
76277
76746
  return status;
76278
76747
  }
76279
76748
  var BANNER_BG_COLORS;
@@ -76296,8 +76765,8 @@ var init_team_grid = __esm(() => {
76296
76765
  init_op_source();
76297
76766
  init_startup_trace();
76298
76767
  var import_dotenv3 = __toESM(require_main(), 1);
76299
- import { existsSync as existsSync27, readFileSync as readFileSync26 } from "fs";
76300
- import { join as join34, resolve as resolve4 } from "path";
76768
+ import { existsSync as existsSync29, readFileSync as readFileSync27 } from "fs";
76769
+ import { join as join36, resolve as resolve4 } from "path";
76301
76770
  import_dotenv3.config({ quiet: true });
76302
76771
  function classifyStartupKind() {
76303
76772
  const argv = process.argv.slice(2);
@@ -76396,7 +76865,7 @@ async function applyConfigOverride() {
76396
76865
  const { planConfigOverride: planConfigOverride2, setConfigFileOverride: setConfigFileOverride2 } = await Promise.resolve().then(() => exports_config_override);
76397
76866
  const plan = planConfigOverride2(process.argv.slice(2), process.env, {
76398
76867
  resolve: resolve4,
76399
- exists: existsSync27
76868
+ exists: existsSync29
76400
76869
  });
76401
76870
  if (plan.kind === "none")
76402
76871
  return;
@@ -76544,14 +77013,14 @@ async function runCli() {
76544
77013
  if (cliConfig.team && cliConfig.team.length > 0) {
76545
77014
  let prompt = cliConfig.claudeArgs.join(" ");
76546
77015
  if (cliConfig.inputFile) {
76547
- prompt = readFileSync26(cliConfig.inputFile, "utf-8");
77016
+ prompt = readFileSync27(cliConfig.inputFile, "utf-8");
76548
77017
  }
76549
77018
  if (!prompt.trim()) {
76550
77019
  console.error("Error: --team requires a prompt (positional args or -f <file>)");
76551
77020
  process.exit(1);
76552
77021
  }
76553
77022
  const mode = cliConfig.teamMode ?? "default";
76554
- const sessionPath = join34(process.cwd(), `.claudish-team-${Date.now()}`);
77023
+ const sessionPath = join36(process.cwd(), `.claudish-team-${Date.now()}`);
76555
77024
  if (mode === "json") {
76556
77025
  const { setupSession: setupSession2, runModels: runModels2 } = await Promise.resolve().then(() => (init_team_orchestrator(), exports_team_orchestrator));
76557
77026
  setupSession2(sessionPath, cliConfig.team, prompt);
@@ -76561,9 +77030,9 @@ async function runCli() {
76561
77030
  });
76562
77031
  const result = { ...status2, responses: {} };
76563
77032
  for (const anonId of Object.keys(status2.models)) {
76564
- const responsePath = join34(sessionPath, `response-${anonId}.md`);
77033
+ const responsePath = join36(sessionPath, `response-${anonId}.md`);
76565
77034
  try {
76566
- const raw2 = readFileSync26(responsePath, "utf-8").trim();
77035
+ const raw2 = readFileSync27(responsePath, "utf-8").trim();
76567
77036
  try {
76568
77037
  result.responses[anonId] = JSON.parse(raw2);
76569
77038
  } catch {