claudish 7.34.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 +569 -231
  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.34.0";
654
+ var VERSION = "7.35.0";
655
655
 
656
656
  // src/logger.ts
657
657
  var exports_logger = {};
@@ -38401,6 +38401,145 @@ var init_journal = __esm(() => {
38401
38401
  PRUNE_TO_BYTES = Math.floor(MAX_JOURNAL_BYTES * 0.6);
38402
38402
  });
38403
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
+
38404
38543
  // src/behavior/observer/digest.ts
38405
38544
  var exports_digest = {};
38406
38545
  __export(exports_digest, {
@@ -38592,10 +38731,10 @@ __export(exports_live_log, {
38592
38731
  recordLiveDivergence: () => recordLiveDivergence
38593
38732
  });
38594
38733
  import { appendFile as appendFile3 } from "fs/promises";
38595
- import { homedir as homedir19 } from "os";
38596
- import { join as join19 } from "path";
38734
+ import { homedir as homedir20 } from "os";
38735
+ import { join as join20 } from "path";
38597
38736
  function defaultPath() {
38598
- return join19(homedir19(), ".claudish", "behavior-divergences.jsonl");
38737
+ return join20(homedir20(), ".claudish", "behavior-divergences.jsonl");
38599
38738
  }
38600
38739
  async function recordLiveDivergence(entry, path = defaultPath()) {
38601
38740
  try {
@@ -38609,6 +38748,109 @@ var init_live_log = __esm(() => {
38609
38748
  init_logger();
38610
38749
  });
38611
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
+
38612
38854
  // src/behavior/engine.ts
38613
38855
  class BehaviorSession {
38614
38856
  active;
@@ -38713,6 +38955,14 @@ class BehaviorSession {
38713
38955
  interceptsTool(toolName) {
38714
38956
  return this.bufferedTools.has(toolName);
38715
38957
  }
38958
+ noteTurnComplete(inputTokens) {
38959
+ recordTelemetryTurn({
38960
+ sessionId: this.sessionId,
38961
+ model: this.modelId,
38962
+ provider: this.providerName,
38963
+ inputTokens
38964
+ });
38965
+ }
38716
38966
  observeText(text, kind = "text") {
38717
38967
  if (!this.watchesOutput || !text)
38718
38968
  return;
@@ -38841,6 +39091,17 @@ class BehaviorSession {
38841
39091
  return changed ? JSON.stringify(args) : null;
38842
39092
  }
38843
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
+ });
38844
39105
  recordDecision({
38845
39106
  ts: new Date().toISOString(),
38846
39107
  model: this.modelId,
@@ -38850,7 +39111,7 @@ class BehaviorSession {
38850
39111
  ruleId: detail.ruleId,
38851
39112
  toolName: detail.toolName,
38852
39113
  argKeys: detail.argKeys,
38853
- pathRelation: classifyPath(detail.observedPath, detail.expectedPath),
39114
+ pathRelation,
38854
39115
  local: {
38855
39116
  observedPath: detail.observedPath,
38856
39117
  expectedPath: detail.expectedPath,
@@ -38944,6 +39205,11 @@ class BehaviorEngine {
38944
39205
  constructor(config2, rules) {
38945
39206
  this.config = config2;
38946
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
+ }
38947
39213
  }
38948
39214
  queueCorrection(key, text) {
38949
39215
  const list = this.corrections.get(key) ?? [];
@@ -38991,6 +39257,7 @@ var init_engine = __esm(() => {
38991
39257
  init_config();
38992
39258
  init_harness();
38993
39259
  init_journal();
39260
+ init_aggregate();
38994
39261
  MAX_OBSERVED_CHARS = 64 * 1024;
38995
39262
  });
38996
39263
 
@@ -39124,9 +39391,9 @@ var init_hooks = __esm(() => {
39124
39391
  });
39125
39392
 
39126
39393
  // src/behavior/observer/corpus.ts
39127
- import { appendFileSync as appendFileSync3, readFileSync as readFileSync12, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
39128
- import { homedir as homedir20 } from "os";
39129
- 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";
39130
39397
  function directoryOf2(filePath) {
39131
39398
  const slash = filePath.lastIndexOf("/");
39132
39399
  return slash > 0 ? filePath.slice(0, slash) : undefined;
@@ -39205,28 +39472,28 @@ function listTranscripts(root) {
39205
39472
  return files;
39206
39473
  }
39207
39474
  for (const project of projects) {
39208
- const dir = join20(root, project);
39475
+ const dir = join21(root, project);
39209
39476
  try {
39210
39477
  if (!statSync2(dir).isDirectory())
39211
39478
  continue;
39212
39479
  for (const f of readdirSync2(dir)) {
39213
39480
  if (f.endsWith(".jsonl"))
39214
- files.push(join20(dir, f));
39481
+ files.push(join21(dir, f));
39215
39482
  }
39216
39483
  } catch {}
39217
39484
  }
39218
39485
  return files;
39219
39486
  }
39220
39487
  function buildCorpus(options = {}) {
39221
- const root = options.projectsRoot ?? join20(homedir20(), ".claude", "projects");
39488
+ const root = options.projectsRoot ?? join21(homedir21(), ".claude", "projects");
39222
39489
  const files = listTranscripts(root);
39223
39490
  const records = [];
39224
39491
  for (const f of files)
39225
39492
  records.push(...replayTranscript(f));
39226
39493
  if (options.write && records.length > 0) {
39227
- const outputPath = options.outputPath ?? join20(homedir20(), ".claudish", "behavior-divergences.jsonl");
39494
+ const outputPath = options.outputPath ?? join21(homedir21(), ".claudish", "behavior-divergences.jsonl");
39228
39495
  try {
39229
- appendFileSync3(outputPath, `${records.map((r) => JSON.stringify(r)).join(`
39496
+ appendFileSync4(outputPath, `${records.map((r) => JSON.stringify(r)).join(`
39230
39497
  `)}
39231
39498
  `);
39232
39499
  return { scanned: files.length, records, outputPath };
@@ -39266,6 +39533,8 @@ var init_behavior = __esm(() => {
39266
39533
  init_digest();
39267
39534
  init_client();
39268
39535
  init_corpus();
39536
+ init_aggregate();
39537
+ init_upload();
39269
39538
  BUILTIN_RULES = [...PLAN_MODE_RULES];
39270
39539
  hookRules = [];
39271
39540
  });
@@ -39836,17 +40105,17 @@ var init_vision_proxy = __esm(() => {
39836
40105
  // src/stats-buffer.ts
39837
40106
  import {
39838
40107
  existsSync as existsSync15,
39839
- mkdirSync as mkdirSync9,
40108
+ mkdirSync as mkdirSync10,
39840
40109
  readFileSync as readFileSync13,
39841
40110
  renameSync,
39842
40111
  unlinkSync as unlinkSync5,
39843
40112
  writeFileSync as writeFileSync9
39844
40113
  } from "fs";
39845
- import { homedir as homedir21 } from "os";
39846
- import { join as join21 } from "path";
40114
+ import { homedir as homedir22 } from "os";
40115
+ import { join as join22 } from "path";
39847
40116
  function ensureDir() {
39848
40117
  if (!existsSync15(CLAUDISH_DIR)) {
39849
- mkdirSync9(CLAUDISH_DIR, { recursive: true });
40118
+ mkdirSync10(CLAUDISH_DIR, { recursive: true });
39850
40119
  }
39851
40120
  }
39852
40121
  function readFromDisk() {
@@ -39878,7 +40147,7 @@ function writeToDisk(events) {
39878
40147
  ensureDir();
39879
40148
  const trimmed = enforceSizeCap([...events]);
39880
40149
  const payload = { version: 1, events: trimmed };
39881
- const tmpFile = join21(CLAUDISH_DIR, `stats-buffer.tmp.${process.pid}.json`);
40150
+ const tmpFile = join22(CLAUDISH_DIR, `stats-buffer.tmp.${process.pid}.json`);
39882
40151
  writeFileSync9(tmpFile, JSON.stringify(payload, null, 2), "utf-8");
39883
40152
  renameSync(tmpFile, BUFFER_FILE);
39884
40153
  memoryCache = trimmed;
@@ -39951,8 +40220,8 @@ function syncFlushOnExit() {
39951
40220
  var BUFFER_MAX_BYTES, CLAUDISH_DIR, BUFFER_FILE, memoryCache = null, eventsSinceLastFlush = 0, flushScheduled = false;
39952
40221
  var init_stats_buffer = __esm(() => {
39953
40222
  BUFFER_MAX_BYTES = 64 * 1024;
39954
- CLAUDISH_DIR = join21(homedir21(), ".claudish");
39955
- BUFFER_FILE = join21(CLAUDISH_DIR, "stats-buffer.json");
40223
+ CLAUDISH_DIR = join22(homedir22(), ".claudish");
40224
+ BUFFER_FILE = join22(CLAUDISH_DIR, "stats-buffer.json");
39956
40225
  process.on("exit", syncFlushOnExit);
39957
40226
  process.on("SIGTERM", () => {
39958
40227
  try {
@@ -40089,7 +40358,7 @@ __export(exports_telemetry, {
40089
40358
  classifyError: () => classifyError,
40090
40359
  buildReport: () => buildReport
40091
40360
  });
40092
- import { randomBytes as randomBytes4 } from "crypto";
40361
+ import { randomBytes as randomBytes5 } from "crypto";
40093
40362
  function getVersion() {
40094
40363
  return VERSION;
40095
40364
  }
@@ -40357,7 +40626,7 @@ function initTelemetry(_config) {
40357
40626
  } catch {
40358
40627
  consentEnabled = false;
40359
40628
  }
40360
- sessionId = randomBytes4(8).toString("hex");
40629
+ sessionId = randomBytes5(8).toString("hex");
40361
40630
  claudishVersion = getVersion();
40362
40631
  installMethod = detectInstallMethod();
40363
40632
  }
@@ -40667,11 +40936,11 @@ function showMonthlyBanner() {
40667
40936
  if (isStatsDisabledByEnv())
40668
40937
  return;
40669
40938
  const profileConfig = loadConfig();
40670
- const consent = profileConfig.stats;
40939
+ const consent2 = profileConfig.stats;
40671
40940
  const now = Date.now();
40672
- const lastPrompt = consent?.lastMonthlyPrompt ? new Date(consent.lastMonthlyPrompt).getTime() : 0;
40941
+ const lastPrompt = consent2?.lastMonthlyPrompt ? new Date(consent2.lastMonthlyPrompt).getTime() : 0;
40673
40942
  const timeSincePrompt = now - lastPrompt;
40674
- const isFirstRun = !consent?.lastMonthlyPrompt;
40943
+ const isFirstRun = !consent2?.lastMonthlyPrompt;
40675
40944
  const isMonthlyInterval = timeSincePrompt >= MONTHLY_INTERVAL_MS;
40676
40945
  if (!isFirstRun && !isMonthlyInterval)
40677
40946
  return;
@@ -40680,7 +40949,7 @@ function showMonthlyBanner() {
40680
40949
  ` + ` No prompts, API keys, or personal data \u2014 just model, latency, and token counts.
40681
40950
  ` + ` Enable: claudish stats on | Docs: claudish stats status
40682
40951
  `);
40683
- } else if (consent?.enabled) {
40952
+ } else if (consent2?.enabled) {
40684
40953
  process.stderr.write(`[claudish] Usage stats are ON \u2014 thank you for helping improve claudish!
40685
40954
  `);
40686
40955
  } else {
@@ -42335,9 +42604,9 @@ var init_openai_responses_sse = __esm(() => {
42335
42604
  });
42336
42605
 
42337
42606
  // src/handlers/shared/token-tracker.ts
42338
- import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
42339
- import { homedir as homedir22 } from "os";
42340
- 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";
42341
42610
  function stripProviderPrefix(name) {
42342
42611
  const at = name.indexOf("@");
42343
42612
  return at === -1 ? name : name.slice(at + 1);
@@ -42489,8 +42758,8 @@ class TokenTracker {
42489
42758
  data.quota_remaining = this.quotaRemaining;
42490
42759
  }
42491
42760
  const override = process.env.CLAUDISH_TOKEN_FILE;
42492
- const outPath = override || join22(homedir22(), ".claudish", `tokens-${this.port}.json`);
42493
- mkdirSync10(dirname7(outPath), { recursive: true });
42761
+ const outPath = override || join23(homedir23(), ".claudish", `tokens-${this.port}.json`);
42762
+ mkdirSync11(dirname8(outPath), { recursive: true });
42494
42763
  writeFileSync10(outPath, JSON.stringify(data), "utf-8");
42495
42764
  } catch (e) {
42496
42765
  log(`[TokenTracker] Error writing token file: ${e}`);
@@ -43006,6 +43275,9 @@ class ComposedHandler {
43006
43275
  invocation_mode: this.options.invocationMode ?? "auto-route"
43007
43276
  });
43008
43277
  } catch {}
43278
+ try {
43279
+ behaviorSession?.noteTurnComplete(this.tokenTracker.getInputTokens());
43280
+ } catch {}
43009
43281
  };
43010
43282
  return this.handleStream(c, response, adapter, claudeRequest, toolNameMap, onStreamComplete, (code, message) => {
43011
43283
  streamApiError = { code, message };
@@ -43358,7 +43630,7 @@ var init_fallback_handler = __esm(() => {
43358
43630
  });
43359
43631
 
43360
43632
  // src/handlers/native-handler-advisor.ts
43361
- import { appendFileSync as appendFileSync4 } from "fs";
43633
+ import { appendFileSync as appendFileSync5 } from "fs";
43362
43634
  function loadAdvisorSwapConfig(cliModels, cliCollector) {
43363
43635
  return {
43364
43636
  enabled: process.env.CLAUDISH_SWAP_ADVISOR === "1" || (cliModels?.length ?? 0) > 0,
@@ -43413,7 +43685,7 @@ function logAdvisorEvent(cfg, event) {
43413
43685
  const line = `${JSON.stringify({ ts: new Date().toISOString(), ...event })}
43414
43686
  `;
43415
43687
  try {
43416
- appendFileSync4(cfg.logPath, line);
43688
+ appendFileSync5(cfg.logPath, line);
43417
43689
  } catch {}
43418
43690
  }
43419
43691
  function recordAdvisorEventsFromChunk(cfg, chunkText) {
@@ -45170,10 +45442,10 @@ var init_ollama_api_format = __esm(() => {
45170
45442
 
45171
45443
  // src/providers/api-key-provenance.ts
45172
45444
  import { existsSync as existsSync16, readFileSync as readFileSync14 } from "fs";
45173
- import { homedir as homedir23 } from "os";
45174
- 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";
45175
45447
  function activeConfigPath() {
45176
- return activeGlobalConfigFile(join23(homedir23(), ".claudish", "config.json"));
45448
+ return activeGlobalConfigFile(join24(homedir24(), ".claudish", "config.json"));
45177
45449
  }
45178
45450
  function configLayerLabel() {
45179
45451
  return getConfigFileOverride() ? activeConfigPath() : "~/.claudish/config.json";
@@ -46051,10 +46323,10 @@ class LocalModelQueue {
46051
46323
  return LocalModelQueue.instance;
46052
46324
  }
46053
46325
  static isEnabled() {
46054
- const enabled = process.env.CLAUDISH_LOCAL_QUEUE_ENABLED;
46055
- if (enabled === undefined || enabled === "")
46326
+ const enabled2 = process.env.CLAUDISH_LOCAL_QUEUE_ENABLED;
46327
+ if (enabled2 === undefined || enabled2 === "")
46056
46328
  return true;
46057
- return enabled !== "false" && enabled !== "0";
46329
+ return enabled2 !== "false" && enabled2 !== "0";
46058
46330
  }
46059
46331
  async enqueue(fetchFn, providerId, concurrencyOverride) {
46060
46332
  if (concurrencyOverride !== undefined) {
@@ -46741,8 +47013,8 @@ var init_poe = __esm(() => {
46741
47013
 
46742
47014
  // src/services/pricing-cache.ts
46743
47015
  import { existsSync as existsSync17, readFileSync as readFileSync15, statSync as statSync4 } from "fs";
46744
- import { homedir as homedir24 } from "os";
46745
- import { join as join24 } from "path";
47016
+ import { homedir as homedir25 } from "os";
47017
+ import { join as join25 } from "path";
46746
47018
  function prefixMatch(modelName) {
46747
47019
  for (const [key, pricing] of pricingMap) {
46748
47020
  if (modelName.startsWith(key))
@@ -46801,8 +47073,8 @@ var init_pricing_cache = __esm(() => {
46801
47073
  init_logger();
46802
47074
  init_catalog_query();
46803
47075
  pricingMap = new Map;
46804
- CACHE_DIR = join24(homedir24(), ".claudish");
46805
- CACHE_FILE = join24(CACHE_DIR, "pricing-cache.json");
47076
+ CACHE_DIR = join25(homedir25(), ".claudish");
47077
+ CACHE_FILE = join25(CACHE_DIR, "pricing-cache.json");
46806
47078
  CACHE_TTL_MS3 = 24 * 60 * 60 * 1000;
46807
47079
  });
46808
47080
 
@@ -47298,12 +47570,12 @@ var init_redact = __esm(() => {
47298
47570
 
47299
47571
  // src/team-stats.ts
47300
47572
  import { existsSync as existsSync18, readFileSync as readFileSync16, writeFileSync as writeFileSync11 } from "fs";
47301
- import { join as join25 } from "path";
47573
+ import { join as join26 } from "path";
47302
47574
  function statsDir(sessionPath) {
47303
- return join25(sessionPath, "stats");
47575
+ return join26(sessionPath, "stats");
47304
47576
  }
47305
47577
  function tokenFileFor(sessionPath, anonId) {
47306
- return join25(statsDir(sessionPath), `${anonId}.json`);
47578
+ return join26(statsDir(sessionPath), `${anonId}.json`);
47307
47579
  }
47308
47580
  function readTokenStats(sessionPath, anonId) {
47309
47581
  const path = tokenFileFor(sessionPath, anonId);
@@ -47458,7 +47730,7 @@ ${segs.join(" \xB7 ")}`;
47458
47730
  }
47459
47731
  function writeStatusFile(sessionPath, manifest, status, opts) {
47460
47732
  try {
47461
- writeFileSync11(join25(sessionPath, "status.txt"), `${renderTeamStats(sessionPath, manifest, status, opts)}
47733
+ writeFileSync11(join26(sessionPath, "status.txt"), `${renderTeamStats(sessionPath, manifest, status, opts)}
47462
47734
  `, "utf-8");
47463
47735
  } catch {}
47464
47736
  }
@@ -47485,12 +47757,12 @@ import { spawn as spawn2 } from "child_process";
47485
47757
  import {
47486
47758
  createWriteStream as createWriteStream2,
47487
47759
  existsSync as existsSync19,
47488
- mkdirSync as mkdirSync11,
47760
+ mkdirSync as mkdirSync12,
47489
47761
  readFileSync as readFileSync17,
47490
47762
  readdirSync as readdirSync3,
47491
47763
  writeFileSync as writeFileSync12
47492
47764
  } from "fs";
47493
- import { join as join26, resolve as resolve3 } from "path";
47765
+ import { join as join27, resolve as resolve3 } from "path";
47494
47766
  function classifyRunOutput(opts) {
47495
47767
  const { outputSize, stdoutTail, stderr, minOutputBytes } = opts;
47496
47768
  const apiError = API_ERROR_RE.exec(stdoutTail);
@@ -47551,18 +47823,18 @@ function setupSession(sessionPath, models, input) {
47551
47823
  if (models.length === 0) {
47552
47824
  throw new Error("At least one model is required");
47553
47825
  }
47554
- if (existsSync19(join26(sessionPath, "manifest.json"))) {
47826
+ if (existsSync19(join27(sessionPath, "manifest.json"))) {
47555
47827
  throw new Error(`Session already exists at ${sessionPath}. Use a new directory path or delete the existing session first.`);
47556
47828
  }
47557
47829
  const sentinels = models.filter(isSentinelModel);
47558
47830
  if (sentinels.length > 0) {
47559
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.`);
47560
47832
  }
47561
- mkdirSync11(join26(sessionPath, "work"), { recursive: true });
47562
- mkdirSync11(join26(sessionPath, "errors"), { recursive: true });
47833
+ mkdirSync12(join27(sessionPath, "work"), { recursive: true });
47834
+ mkdirSync12(join27(sessionPath, "errors"), { recursive: true });
47563
47835
  if (input !== undefined) {
47564
- writeFileSync12(join26(sessionPath, "input.md"), input, "utf-8");
47565
- } else if (!existsSync19(join26(sessionPath, "input.md"))) {
47836
+ writeFileSync12(join27(sessionPath, "input.md"), input, "utf-8");
47837
+ } else if (!existsSync19(join27(sessionPath, "input.md"))) {
47566
47838
  throw new Error(`No input.md found at ${sessionPath} and no input provided`);
47567
47839
  }
47568
47840
  const ids = models.map((_, i) => String(i + 1).padStart(2, "0"));
@@ -47579,9 +47851,9 @@ function setupSession(sessionPath, models, input) {
47579
47851
  model: models[i],
47580
47852
  assignedAt: now
47581
47853
  };
47582
- mkdirSync11(join26(sessionPath, "work", anonId), { recursive: true });
47854
+ mkdirSync12(join27(sessionPath, "work", anonId), { recursive: true });
47583
47855
  }
47584
- 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");
47585
47857
  const status = {
47586
47858
  startedAt: now,
47587
47859
  models: Object.fromEntries(Object.keys(manifest.models).map((id) => [
@@ -47595,14 +47867,14 @@ function setupSession(sessionPath, models, input) {
47595
47867
  }
47596
47868
  ]))
47597
47869
  };
47598
- 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");
47599
47871
  return manifest;
47600
47872
  }
47601
47873
  async function runModels(sessionPath, opts = {}) {
47602
47874
  const timeoutMs = (opts.timeout ?? 300) * 1000;
47603
- const manifest = JSON.parse(readFileSync17(join26(sessionPath, "manifest.json"), "utf-8"));
47604
- const statusPath = join26(sessionPath, "status.json");
47605
- 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");
47606
47878
  const inputContent = readFileSync17(inputPath, "utf-8");
47607
47879
  await prehydrateCredentialsForSpawn(Object.values(manifest.models).map((m) => m.model));
47608
47880
  const statusCache = JSON.parse(readFileSync17(statusPath, "utf-8"));
@@ -47611,7 +47883,7 @@ async function runModels(sessionPath, opts = {}) {
47611
47883
  writeFileSync12(statusPath, JSON.stringify(statusCache, null, 2), "utf-8");
47612
47884
  }
47613
47885
  const minOutputBytes = opts.minOutputBytes ?? DEFAULT_MIN_OUTPUT_BYTES;
47614
- mkdirSync11(statsDir(sessionPath), { recursive: true });
47886
+ mkdirSync12(statsDir(sessionPath), { recursive: true });
47615
47887
  const processes = new Map;
47616
47888
  const runtimes = new Map;
47617
47889
  const sigintHandler = () => {
@@ -47624,8 +47896,8 @@ async function runModels(sessionPath, opts = {}) {
47624
47896
  process.on("SIGINT", sigintHandler);
47625
47897
  const completionPromises = [];
47626
47898
  for (const [anonId, entry] of Object.entries(manifest.models)) {
47627
- const outputPath = join26(sessionPath, `response-${anonId}.md`);
47628
- const errorLogPath = join26(sessionPath, "errors", `${anonId}.log`);
47899
+ const outputPath = join27(sessionPath, `response-${anonId}.md`);
47900
+ const errorLogPath = join27(sessionPath, "errors", `${anonId}.log`);
47629
47901
  const args = ["--model", entry.model, "-y", "--stdin", "--quiet", ...opts.claudeFlags ?? []];
47630
47902
  updateModelStatus(anonId, {
47631
47903
  state: "RUNNING",
@@ -47814,23 +48086,23 @@ async function judgeResponses(sessionPath, opts = {}) {
47814
48086
  const responses = {};
47815
48087
  for (const file2 of responseFiles) {
47816
48088
  const id = file2.replace(/^response-/, "").replace(/\.md$/, "");
47817
- responses[id] = readFileSync17(join26(sessionPath, file2), "utf-8");
48089
+ responses[id] = readFileSync17(join27(sessionPath, file2), "utf-8");
47818
48090
  }
47819
- const input = readFileSync17(join26(sessionPath, "input.md"), "utf-8");
48091
+ const input = readFileSync17(join27(sessionPath, "input.md"), "utf-8");
47820
48092
  const judgePrompt = buildJudgePrompt(input, responses);
47821
- writeFileSync12(join26(sessionPath, "judge-prompt.md"), judgePrompt, "utf-8");
48093
+ writeFileSync12(join27(sessionPath, "judge-prompt.md"), judgePrompt, "utf-8");
47822
48094
  const judgeModels = opts.judges ?? getDefaultJudgeModels(sessionPath);
47823
- const judgePath = join26(sessionPath, "judging");
47824
- mkdirSync11(judgePath, { recursive: true });
48095
+ const judgePath = join27(sessionPath, "judging");
48096
+ mkdirSync12(judgePath, { recursive: true });
47825
48097
  setupSession(judgePath, judgeModels, judgePrompt);
47826
48098
  await runModels(judgePath, { claudeFlags: opts.claudeFlags });
47827
48099
  const votes = parseJudgeVotes(judgePath, Object.keys(responses));
47828
48100
  const verdict = aggregateVerdict(votes, Object.keys(responses));
47829
- writeFileSync12(join26(sessionPath, "verdict.md"), formatVerdict(verdict, sessionPath), "utf-8");
48101
+ writeFileSync12(join27(sessionPath, "verdict.md"), formatVerdict(verdict, sessionPath), "utf-8");
47830
48102
  return verdict;
47831
48103
  }
47832
48104
  function getStatus(sessionPath) {
47833
- return JSON.parse(readFileSync17(join26(sessionPath, "status.json"), "utf-8"));
48105
+ return JSON.parse(readFileSync17(join27(sessionPath, "status.json"), "utf-8"));
47834
48106
  }
47835
48107
  function fisherYatesShuffle(arr) {
47836
48108
  for (let i = arr.length - 1;i > 0; i--) {
@@ -47840,7 +48112,7 @@ function fisherYatesShuffle(arr) {
47840
48112
  return arr;
47841
48113
  }
47842
48114
  function getDefaultJudgeModels(sessionPath) {
47843
- const manifest = JSON.parse(readFileSync17(join26(sessionPath, "manifest.json"), "utf-8"));
48115
+ const manifest = JSON.parse(readFileSync17(join27(sessionPath, "manifest.json"), "utf-8"));
47844
48116
  return Object.values(manifest.models).map((e) => e.model);
47845
48117
  }
47846
48118
  function buildJudgePrompt(input, responses) {
@@ -47903,7 +48175,7 @@ function parseJudgeVotes(judgePath, responseIds) {
47903
48175
  const judgeId = file2.replace(/^response-/, "").replace(/\.md$/, "");
47904
48176
  let content;
47905
48177
  try {
47906
- content = readFileSync17(join26(judgePath, file2), "utf-8");
48178
+ content = readFileSync17(join27(judgePath, file2), "utf-8");
47907
48179
  } catch {
47908
48180
  continue;
47909
48181
  }
@@ -47955,7 +48227,7 @@ function aggregateVerdict(votes, responseIds) {
47955
48227
  function formatVerdict(verdict, sessionPath) {
47956
48228
  let manifest = null;
47957
48229
  try {
47958
- manifest = JSON.parse(readFileSync17(join26(sessionPath, "manifest.json"), "utf-8"));
48230
+ manifest = JSON.parse(readFileSync17(join27(sessionPath, "manifest.json"), "utf-8"));
47959
48231
  } catch {}
47960
48232
  let output = `# Team Verdict
47961
48233
 
@@ -48010,9 +48282,9 @@ __export(exports_mcp_server, {
48010
48282
  parseAnthropicSse: () => parseAnthropicSse,
48011
48283
  formatTeamResult: () => formatTeamResult
48012
48284
  });
48013
- import { existsSync as existsSync20, mkdirSync as mkdirSync12, readFileSync as readFileSync18, readdirSync as readdirSync4, writeFileSync as writeFileSync13 } from "fs";
48014
- import { homedir as homedir25 } from "os";
48015
- 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";
48016
48288
  import { fileURLToPath } from "url";
48017
48289
  async function loadAllModels(forceRefresh = false) {
48018
48290
  if (!forceRefresh && existsSync20(ALL_MODELS_CACHE_PATH2)) {
@@ -48031,7 +48303,7 @@ async function loadAllModels(forceRefresh = false) {
48031
48303
  throw new Error(`API returned ${response.status}`);
48032
48304
  const data = await response.json();
48033
48305
  const models = data.data || [];
48034
- mkdirSync12(CLAUDISH_CACHE_DIR, { recursive: true });
48306
+ mkdirSync13(CLAUDISH_CACHE_DIR, { recursive: true });
48035
48307
  writeFileSync13(ALL_MODELS_CACHE_PATH2, JSON.stringify({ lastUpdated: new Date().toISOString(), models }), "utf-8");
48036
48308
  return models;
48037
48309
  } catch {
@@ -48626,16 +48898,16 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
48626
48898
  const sp = session_path;
48627
48899
  for (const file2 of ["status.json", "manifest.json", "input.md"]) {
48628
48900
  try {
48629
- sessionData[file2] = readFileSync18(join27(sp, file2), "utf-8");
48901
+ sessionData[file2] = readFileSync18(join28(sp, file2), "utf-8");
48630
48902
  } catch {}
48631
48903
  }
48632
48904
  try {
48633
- const errorDir = join27(sp, "errors");
48905
+ const errorDir = join28(sp, "errors");
48634
48906
  if (existsSync20(errorDir)) {
48635
48907
  for (const f of readdirSync4(errorDir)) {
48636
48908
  if (f.endsWith(".log")) {
48637
48909
  try {
48638
- sessionData[`errors/${f}`] = readFileSync18(join27(errorDir, f), "utf-8");
48910
+ sessionData[`errors/${f}`] = readFileSync18(join28(errorDir, f), "utf-8");
48639
48911
  } catch {}
48640
48912
  }
48641
48913
  }
@@ -48645,7 +48917,7 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
48645
48917
  for (const f of readdirSync4(sp)) {
48646
48918
  if (f.startsWith("response-") && f.endsWith(".md")) {
48647
48919
  try {
48648
- const content = readFileSync18(join27(sp, f), "utf-8");
48920
+ const content = readFileSync18(join28(sp, f), "utf-8");
48649
48921
  sessionData[f] = content.slice(0, 200) + (content.length > 200 ? "... (truncated)" : "");
48650
48922
  } catch {}
48651
48923
  }
@@ -48654,7 +48926,7 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
48654
48926
  }
48655
48927
  let version2 = "unknown";
48656
48928
  try {
48657
- const pkgPath = join27(__dirname2, "../package.json");
48929
+ const pkgPath = join28(__dirname2, "../package.json");
48658
48930
  if (existsSync20(pkgPath)) {
48659
48931
  version2 = JSON.parse(readFileSync18(pkgPath, "utf-8")).version;
48660
48932
  }
@@ -48883,9 +49155,9 @@ Report manually at https://github.com/anthropics/claudish/issues${autoSendHint}`
48883
49155
  },
48884
49156
  group: "channel",
48885
49157
  handler: async (args) => {
48886
- const sessions = sessionManager.listSessions(args.include_completed);
49158
+ const sessions2 = sessionManager.listSessions(args.include_completed);
48887
49159
  return {
48888
- content: [{ type: "text", text: JSON.stringify({ sessions }) }]
49160
+ content: [{ type: "text", text: JSON.stringify({ sessions: sessions2 }) }]
48889
49161
  };
48890
49162
  }
48891
49163
  });
@@ -49054,9 +49326,9 @@ var init_mcp_server = __esm(() => {
49054
49326
  import_dotenv2 = __toESM(require_main(), 1);
49055
49327
  import_dotenv2.config({ quiet: true });
49056
49328
  __filename2 = fileURLToPath(import.meta.url);
49057
- __dirname2 = dirname8(__filename2);
49058
- CLAUDISH_CACHE_DIR = join27(homedir25(), ".claudish");
49059
- 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");
49060
49332
  NEXT_STEP = {
49061
49333
  nonzero_exit: "read the evidence log, then retry or drop the model",
49062
49334
  timeout: "raise `timeout`, or pick a faster model",
@@ -49182,6 +49454,7 @@ var exports_behavior_command = {};
49182
49454
  __export(exports_behavior_command, {
49183
49455
  behaviorCommand: () => behaviorCommand
49184
49456
  });
49457
+ import { existsSync as existsSync22, readFileSync as readFileSync20, writeFileSync as writeFileSync14 } from "fs";
49185
49458
  function severityColor(sev) {
49186
49459
  if (sev === "fix")
49187
49460
  return green(sev);
@@ -49275,6 +49548,67 @@ Behavior divergence corpus
49275
49548
  `));
49276
49549
  }
49277
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
+ }
49278
49612
  async function behaviorCommand(argv) {
49279
49613
  const json2 = argv.includes("--json");
49280
49614
  const write = argv.includes("--write");
@@ -49286,12 +49620,16 @@ async function behaviorCommand(argv) {
49286
49620
  case "corpus":
49287
49621
  showCorpus(write, json2);
49288
49622
  return;
49623
+ case "telemetry":
49624
+ showTelemetry(argv.includes("--enable") ? "enable" : argv.includes("--disable") ? "disable" : "status", json2);
49625
+ return;
49289
49626
  default:
49290
49627
  console.error(`Unknown action "${action}".
49291
49628
 
49292
49629
  Usage:
49293
- claudish behavior rules [--json]
49294
- claudish behavior corpus [--write] [--json]
49630
+ claudish behavior rules [--json]
49631
+ claudish behavior corpus [--write] [--json]
49632
+ claudish behavior telemetry [--enable | --disable] [--json]
49295
49633
  `);
49296
49634
  process.exit(1);
49297
49635
  }
@@ -60706,7 +61044,7 @@ var init_RemoveFileError = __esm(() => {
60706
61044
 
60707
61045
  // ../../node_modules/.bun/@inquirer+external-editor@2.0.1+04f2146be16c61ef/node_modules/@inquirer/external-editor/dist/index.js
60708
61046
  import { spawn as spawn3, spawnSync as spawnSync2 } from "child_process";
60709
- 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";
60710
61048
  import path from "path";
60711
61049
  import os from "os";
60712
61050
  import { randomUUID as randomUUID6 } from "crypto";
@@ -60815,14 +61153,14 @@ class ExternalEditor {
60815
61153
  if (Object.prototype.hasOwnProperty.call(this.fileOptions, "mode")) {
60816
61154
  opt.mode = this.fileOptions.mode;
60817
61155
  }
60818
- writeFileSync14(this.tempFile, this.text, opt);
61156
+ writeFileSync15(this.tempFile, this.text, opt);
60819
61157
  } catch (createFileError) {
60820
61158
  throw new CreateFileError(createFileError);
60821
61159
  }
60822
61160
  }
60823
61161
  readTemporaryFile() {
60824
61162
  try {
60825
- const tempFileBuffer = readFileSync20(this.tempFile);
61163
+ const tempFileBuffer = readFileSync21(this.tempFile);
60826
61164
  if (tempFileBuffer.length === 0) {
60827
61165
  this.text = "";
60828
61166
  } else {
@@ -61803,9 +62141,9 @@ var init_dist16 = __esm(() => {
61803
62141
 
61804
62142
  // src/auth/antigravity-oauth.ts
61805
62143
  import { spawnSync as spawnSync3 } from "child_process";
61806
- import { existsSync as existsSync22, unlinkSync as unlinkSync7 } from "fs";
61807
- import { homedir as homedir26 } from "os";
61808
- import { join as join28 } from "path";
62144
+ import { existsSync as existsSync23, unlinkSync as unlinkSync7 } from "fs";
62145
+ import { homedir as homedir27 } from "os";
62146
+ import { join as join29 } from "path";
61809
62147
  async function defaultSuggestModel() {
61810
62148
  try {
61811
62149
  const tok = readSharedAntigravityToken();
@@ -61926,8 +62264,8 @@ No session detected yet. Starting the Antigravity CLI interactively \u2014
61926
62264
  async logout(deps) {
61927
62265
  deleteSharedAntigravityToken(deps);
61928
62266
  try {
61929
- const tokenFile = join28(homedir26(), ".gemini", "antigravity-cli", "antigravity-oauth-token");
61930
- if (existsSync22(tokenFile))
62267
+ const tokenFile = join29(homedir27(), ".gemini", "antigravity-cli", "antigravity-oauth-token");
62268
+ if (existsSync23(tokenFile))
61931
62269
  unlinkSync7(tokenFile);
61932
62270
  } catch {}
61933
62271
  log("[AntigravityOAuth] Antigravity session cleared (keychain + agy token file)");
@@ -62184,15 +62522,15 @@ async function geminiQuotaHandler() {
62184
62522
  }
62185
62523
  }
62186
62524
  async function codexQuotaHandler() {
62187
- const { readFileSync: readFileSync21, existsSync: existsSync23 } = await import("fs");
62188
- const { join: join29 } = await import("path");
62189
- const { homedir: homedir27 } = await import("os");
62190
- const credPath = join29(homedir27(), ".claudish", "codex-oauth.json");
62191
- if (!existsSync23(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)) {
62192
62530
  console.error(`${RED}No Codex credentials found.${R} Run: ${B}claudish login codex${R}`);
62193
62531
  process.exit(1);
62194
62532
  }
62195
- const creds = JSON.parse(readFileSync21(credPath, "utf-8"));
62533
+ const creds = JSON.parse(readFileSync22(credPath, "utf-8"));
62196
62534
  let email3 = "";
62197
62535
  try {
62198
62536
  const parts = creds.access_token.split(".");
@@ -62244,9 +62582,9 @@ async function codexQuotaHandler() {
62244
62582
  }
62245
62583
  let modelSlugs = [];
62246
62584
  try {
62247
- const modelsPath = join29(homedir27(), ".codex", "models_cache.json");
62248
- if (existsSync23(modelsPath)) {
62249
- 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"));
62250
62588
  modelSlugs = (cache2.models || []).map((m) => m.slug || m.id).filter(Boolean);
62251
62589
  }
62252
62590
  } catch {}
@@ -63998,7 +64336,7 @@ var init_theme2 = __esm(() => {
63998
64336
  bold3 = createTextAttributes({ bold: true });
63999
64337
  A = {
64000
64338
  bold: bold3,
64001
- boldIf: (enabled) => enabled ? bold3 : undefined
64339
+ boldIf: (enabled2) => enabled2 ? bold3 : undefined
64002
64340
  };
64003
64341
  LATENCY_BUCKETS = [
64004
64342
  { maxMs: 500, hex: "#1f8f3b" },
@@ -66134,22 +66472,22 @@ __export(exports_cli, {
66134
66472
  });
66135
66473
  import {
66136
66474
  copyFileSync as copyFileSync2,
66137
- existsSync as existsSync23,
66138
- mkdirSync as mkdirSync13,
66139
- readFileSync as readFileSync21,
66475
+ existsSync as existsSync24,
66476
+ mkdirSync as mkdirSync14,
66477
+ readFileSync as readFileSync22,
66140
66478
  readdirSync as readdirSync5,
66141
66479
  unlinkSync as unlinkSync8,
66142
- writeFileSync as writeFileSync15
66480
+ writeFileSync as writeFileSync16
66143
66481
  } from "fs";
66144
- import { homedir as homedir27 } from "os";
66145
- import { dirname as dirname9, join as join29 } from "path";
66482
+ import { homedir as homedir28 } from "os";
66483
+ import { dirname as dirname10, join as join30 } from "path";
66146
66484
  import { fileURLToPath as fileURLToPath2 } from "url";
66147
66485
  function getVersion3() {
66148
66486
  return VERSION;
66149
66487
  }
66150
66488
  function clearAllModelCaches() {
66151
- const cacheDir = join29(homedir27(), ".claudish");
66152
- if (!existsSync23(cacheDir))
66489
+ const cacheDir = join30(homedir28(), ".claudish");
66490
+ if (!existsSync24(cacheDir))
66153
66491
  return;
66154
66492
  const cachePatterns = ["pricing-cache.json", "recommended-models-cache.json"];
66155
66493
  let cleared = 0;
@@ -66157,7 +66495,7 @@ function clearAllModelCaches() {
66157
66495
  const files = readdirSync5(cacheDir);
66158
66496
  for (const file2 of files) {
66159
66497
  if (cachePatterns.includes(file2)) {
66160
- unlinkSync8(join29(cacheDir, file2));
66498
+ unlinkSync8(join30(cacheDir, file2));
66161
66499
  cleared++;
66162
66500
  }
66163
66501
  }
@@ -66567,15 +66905,15 @@ Usage: claudish --models --provider <slug>`);
66567
66905
  });
66568
66906
  config3.resolvedDefaultProvider = resolved;
66569
66907
  if (resolved.legacyAutoPromoted && !config3.quiet) {
66570
- const markerFile = join29(homedir27(), ".claudish", ".legacy-litellm-hint-shown");
66571
- if (!existsSync23(markerFile)) {
66908
+ const markerFile = join30(homedir28(), ".claudish", ".legacy-litellm-hint-shown");
66909
+ if (!existsSync24(markerFile)) {
66572
66910
  const hint = buildLegacyHint(resolved);
66573
66911
  if (hint) {
66574
66912
  console.error(hint);
66575
66913
  }
66576
66914
  try {
66577
- mkdirSync13(dirname9(markerFile), { recursive: true });
66578
- writeFileSync15(markerFile, new Date().toISOString(), "utf-8");
66915
+ mkdirSync14(dirname10(markerFile), { recursive: true });
66916
+ writeFileSync16(markerFile, new Date().toISOString(), "utf-8");
66579
66917
  } catch {}
66580
66918
  }
66581
66919
  }
@@ -67642,8 +67980,8 @@ ${h("MORE INFO")}
67642
67980
  }
67643
67981
  function printAIAgentGuide() {
67644
67982
  try {
67645
- const guidePath = join29(__dirname3, "../AI_AGENT_GUIDE.md");
67646
- const guideContent = readFileSync21(guidePath, "utf-8");
67983
+ const guidePath = join30(__dirname3, "../AI_AGENT_GUIDE.md");
67984
+ const guideContent = readFileSync22(guidePath, "utf-8");
67647
67985
  console.log(guideContent);
67648
67986
  } catch (error46) {
67649
67987
  console.error("Error reading AI Agent Guide:");
@@ -67659,19 +67997,19 @@ async function initializeClaudishSkill() {
67659
67997
  console.log(`\uD83D\uDD27 Initializing Claudish skill in current project...
67660
67998
  `);
67661
67999
  const cwd = process.cwd();
67662
- const claudeDir = join29(cwd, ".claude");
67663
- const skillsDir = join29(claudeDir, "skills");
67664
- const claudishSkillDir = join29(skillsDir, "claudish-usage");
67665
- const skillFile = join29(claudishSkillDir, "SKILL.md");
67666
- if (existsSync23(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)) {
67667
68005
  console.log("\u2705 Claudish skill already installed at:");
67668
68006
  console.log(` ${skillFile}
67669
68007
  `);
67670
68008
  console.log("\uD83D\uDCA1 To reinstall, delete the file and run 'claudish --init' again.");
67671
68009
  return;
67672
68010
  }
67673
- const sourceSkillPath = join29(__dirname3, "../skills/claudish-usage/SKILL.md");
67674
- if (!existsSync23(sourceSkillPath)) {
68011
+ const sourceSkillPath = join30(__dirname3, "../skills/claudish-usage/SKILL.md");
68012
+ if (!existsSync24(sourceSkillPath)) {
67675
68013
  console.error("\u274C Error: Claudish skill file not found in installation.");
67676
68014
  console.error(` Expected at: ${sourceSkillPath}`);
67677
68015
  console.error(`
@@ -67680,16 +68018,16 @@ async function initializeClaudishSkill() {
67680
68018
  process.exit(1);
67681
68019
  }
67682
68020
  try {
67683
- if (!existsSync23(claudeDir)) {
67684
- mkdirSync13(claudeDir, { recursive: true });
68021
+ if (!existsSync24(claudeDir)) {
68022
+ mkdirSync14(claudeDir, { recursive: true });
67685
68023
  console.log("\uD83D\uDCC1 Created .claude/ directory");
67686
68024
  }
67687
- if (!existsSync23(skillsDir)) {
67688
- mkdirSync13(skillsDir, { recursive: true });
68025
+ if (!existsSync24(skillsDir)) {
68026
+ mkdirSync14(skillsDir, { recursive: true });
67689
68027
  console.log("\uD83D\uDCC1 Created .claude/skills/ directory");
67690
68028
  }
67691
- if (!existsSync23(claudishSkillDir)) {
67692
- mkdirSync13(claudishSkillDir, { recursive: true });
68029
+ if (!existsSync24(claudishSkillDir)) {
68030
+ mkdirSync14(claudishSkillDir, { recursive: true });
67693
68031
  console.log("\uD83D\uDCC1 Created .claude/skills/claudish-usage/ directory");
67694
68032
  }
67695
68033
  copyFileSync2(sourceSkillPath, skillFile);
@@ -67761,7 +68099,7 @@ var init_cli = __esm(() => {
67761
68099
  init_routing_rules();
67762
68100
  init_provider_resolver();
67763
68101
  __filename3 = fileURLToPath2(import.meta.url);
67764
- __dirname3 = dirname9(__filename3);
68102
+ __dirname3 = dirname10(__filename3);
67765
68103
  });
67766
68104
 
67767
68105
  // src/update-checker.ts
@@ -67773,33 +68111,33 @@ __export(exports_update_checker, {
67773
68111
  clearCache: () => clearCache,
67774
68112
  checkForUpdates: () => checkForUpdates
67775
68113
  });
67776
- import { existsSync as existsSync24, mkdirSync as mkdirSync14, readFileSync as readFileSync22, unlinkSync as unlinkSync9, writeFileSync as writeFileSync16 } from "fs";
67777
- import { homedir as homedir28, platform as platform2, tmpdir } from "os";
67778
- import { join as join30 } 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";
67779
68117
  function getCacheFilePath() {
67780
68118
  let cacheDir;
67781
68119
  if (isWindows) {
67782
- const localAppData = process.env.LOCALAPPDATA || join30(homedir28(), "AppData", "Local");
67783
- cacheDir = join30(localAppData, "claudish");
68120
+ const localAppData = process.env.LOCALAPPDATA || join31(homedir29(), "AppData", "Local");
68121
+ cacheDir = join31(localAppData, "claudish");
67784
68122
  } else {
67785
- cacheDir = join30(homedir28(), ".cache", "claudish");
68123
+ cacheDir = join31(homedir29(), ".cache", "claudish");
67786
68124
  }
67787
68125
  try {
67788
- if (!existsSync24(cacheDir)) {
67789
- mkdirSync14(cacheDir, { recursive: true });
68126
+ if (!existsSync25(cacheDir)) {
68127
+ mkdirSync15(cacheDir, { recursive: true });
67790
68128
  }
67791
- return join30(cacheDir, "update-check.json");
68129
+ return join31(cacheDir, "update-check.json");
67792
68130
  } catch {
67793
- return join30(tmpdir(), "claudish-update-check.json");
68131
+ return join31(tmpdir(), "claudish-update-check.json");
67794
68132
  }
67795
68133
  }
67796
68134
  function readCache() {
67797
68135
  try {
67798
68136
  const cachePath = getCacheFilePath();
67799
- if (!existsSync24(cachePath)) {
68137
+ if (!existsSync25(cachePath)) {
67800
68138
  return null;
67801
68139
  }
67802
- const data = JSON.parse(readFileSync22(cachePath, "utf-8"));
68140
+ const data = JSON.parse(readFileSync23(cachePath, "utf-8"));
67803
68141
  return data;
67804
68142
  } catch {
67805
68143
  return null;
@@ -67812,7 +68150,7 @@ function writeCache(latestVersion) {
67812
68150
  lastCheck: Date.now(),
67813
68151
  latestVersion
67814
68152
  };
67815
- writeFileSync16(cachePath, JSON.stringify(data), "utf-8");
68153
+ writeFileSync17(cachePath, JSON.stringify(data), "utf-8");
67816
68154
  } catch {}
67817
68155
  }
67818
68156
  function isCacheValid(cache2) {
@@ -67822,7 +68160,7 @@ function isCacheValid(cache2) {
67822
68160
  function clearCache() {
67823
68161
  try {
67824
68162
  const cachePath = getCacheFilePath();
67825
- if (existsSync24(cachePath)) {
68163
+ if (existsSync25(cachePath)) {
67826
68164
  unlinkSync9(cachePath);
67827
68165
  }
67828
68166
  } catch {}
@@ -68707,15 +69045,15 @@ var init_local_liveness = __esm(() => {
68707
69045
  });
68708
69046
 
68709
69047
  // src/providers/probe-catalog.ts
68710
- import { existsSync as existsSync25, mkdirSync as mkdirSync15, readFileSync as readFileSync23, writeFileSync as writeFileSync17 } from "fs";
68711
- import { homedir as homedir29 } from "os";
68712
- import { dirname as dirname10, join as join31 } 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";
68713
69051
  function readProbeModelsCache(path2 = PROBE_MODELS_CACHE_PATH) {
68714
- if (!existsSync25(path2))
69052
+ if (!existsSync26(path2))
68715
69053
  return null;
68716
69054
  let raw2;
68717
69055
  try {
68718
- raw2 = JSON.parse(readFileSync23(path2, "utf-8"));
69056
+ raw2 = JSON.parse(readFileSync24(path2, "utf-8"));
68719
69057
  } catch {
68720
69058
  return null;
68721
69059
  }
@@ -68724,8 +69062,8 @@ function readProbeModelsCache(path2 = PROBE_MODELS_CACHE_PATH) {
68724
69062
  return raw2;
68725
69063
  }
68726
69064
  function writeProbeModelsCache(data, path2 = PROBE_MODELS_CACHE_PATH) {
68727
- mkdirSync15(dirname10(path2), { recursive: true });
68728
- writeFileSync17(path2, JSON.stringify(data), "utf-8");
69065
+ mkdirSync16(dirname11(path2), { recursive: true });
69066
+ writeFileSync18(path2, JSON.stringify(data), "utf-8");
68729
69067
  }
68730
69068
  function isCacheFresh(data, ttlMs = CACHE_TTL_MS4) {
68731
69069
  if (!data?.generatedAt)
@@ -68844,7 +69182,7 @@ function isValidResponse(raw2) {
68844
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;
68845
69183
  var init_probe_catalog = __esm(() => {
68846
69184
  CACHE_TTL_MS4 = 60 * 60 * 1000;
68847
- PROBE_MODELS_CACHE_PATH = join31(homedir29(), ".claudish", "probe-models.json");
69185
+ PROBE_MODELS_CACHE_PATH = join32(homedir30(), ".claudish", "probe-models.json");
68848
69186
  });
68849
69187
 
68850
69188
  // src/tui/constants.ts
@@ -71532,8 +71870,8 @@ function ProvidersContent({
71532
71870
  let statusText = p.isLocal ? isReady ? "enabled" : "disabled" : isReady ? "ready" : "not set";
71533
71871
  if (p.isLocal) {
71534
71872
  const live = localLiveness[p.catalogName];
71535
- const enabled = providerAuthSource(p, config3) !== null;
71536
- if (enabled) {
71873
+ const enabled2 = providerAuthSource(p, config3) !== null;
71874
+ if (enabled2) {
71537
71875
  if (live === "running") {
71538
71876
  statusFg = C.green;
71539
71877
  statusText = "running";
@@ -75195,17 +75533,17 @@ __export(exports_claude_runner, {
75195
75533
  import { spawn as spawn4 } from "child_process";
75196
75534
  import {
75197
75535
  closeSync as closeSync5,
75198
- existsSync as existsSync26,
75199
- mkdirSync as mkdirSync16,
75536
+ existsSync as existsSync27,
75537
+ mkdirSync as mkdirSync17,
75200
75538
  openSync as openSync5,
75201
- readFileSync as readFileSync24,
75539
+ readFileSync as readFileSync25,
75202
75540
  readdirSync as readdirSync6,
75203
75541
  statSync as statSync5,
75204
75542
  unlinkSync as unlinkSync10,
75205
- writeFileSync as writeFileSync18
75543
+ writeFileSync as writeFileSync19
75206
75544
  } from "fs";
75207
- import { homedir as homedir30, tmpdir as tmpdir2 } from "os";
75208
- import { dirname as dirname11, join as join32 } from "path";
75545
+ import { homedir as homedir31, tmpdir as tmpdir2 } from "os";
75546
+ import { dirname as dirname12, join as join33 } from "path";
75209
75547
  import { isatty } from "tty";
75210
75548
  function releaseTerminalIsolation() {
75211
75549
  if (!restoreTerminal)
@@ -75240,16 +75578,16 @@ function isProxyAuthMode(config3) {
75240
75578
  }
75241
75579
  function managedSettingsPath() {
75242
75580
  if (isWindows2()) {
75243
- return join32(process.env.PROGRAMDATA || "C:\\ProgramData", "ClaudeCode", "managed-settings.json");
75581
+ return join33(process.env.PROGRAMDATA || "C:\\ProgramData", "ClaudeCode", "managed-settings.json");
75244
75582
  }
75245
75583
  if (process.platform === "darwin") {
75246
75584
  return "/Library/Application Support/ClaudeCode/managed-settings.json";
75247
75585
  }
75248
75586
  return "/etc/claude-code/managed-settings.json";
75249
75587
  }
75250
- function managedSettingsForcesClaudeAi(readFile2 = readFileSync24) {
75588
+ function managedSettingsForcesClaudeAi(readFile3 = readFileSync25) {
75251
75589
  try {
75252
- const raw2 = readFile2(managedSettingsPath(), "utf-8");
75590
+ const raw2 = readFile3(managedSettingsPath(), "utf-8");
75253
75591
  const parsed = JSON.parse(raw2);
75254
75592
  return parsed.forceLoginMethod === "claudeai";
75255
75593
  } catch {
@@ -75261,9 +75599,9 @@ function isWindows2() {
75261
75599
  }
75262
75600
  function createStatusLineScript(tokenFilePath) {
75263
75601
  const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
75264
- const claudishDir = join32(homeDir, ".claudish");
75602
+ const claudishDir = join33(homeDir, ".claudish");
75265
75603
  const timestamp = Date.now();
75266
- const scriptPath = join32(claudishDir, `status-${timestamp}.js`);
75604
+ const scriptPath = join33(claudishDir, `status-${timestamp}.js`);
75267
75605
  const escapedTokenPath = tokenFilePath.replace(/\\/g, "\\\\");
75268
75606
  const script = `
75269
75607
  const fs = require('fs');
@@ -75381,13 +75719,13 @@ process.stdin.on('end', () => {
75381
75719
  }
75382
75720
  });
75383
75721
  `;
75384
- writeFileSync18(scriptPath, script, "utf-8");
75722
+ writeFileSync19(scriptPath, script, "utf-8");
75385
75723
  return scriptPath;
75386
75724
  }
75387
75725
  function initializeTokenFile(tokenFilePath) {
75388
75726
  try {
75389
- mkdirSync16(dirname11(tokenFilePath), { recursive: true });
75390
- writeFileSync18(tokenFilePath, JSON.stringify({
75727
+ mkdirSync17(dirname12(tokenFilePath), { recursive: true });
75728
+ writeFileSync19(tokenFilePath, JSON.stringify({
75391
75729
  input_tokens: 0,
75392
75730
  output_tokens: 0,
75393
75731
  total_tokens: 0,
@@ -75418,7 +75756,7 @@ function cleanupStaleTokenFiles(dir, now = Date.now(), maxAgeMs = STALE_TOKEN_FI
75418
75756
  if (!name.startsWith("tokens-") || !name.endsWith(".json"))
75419
75757
  continue;
75420
75758
  scanned++;
75421
- const full = join32(dir, name);
75759
+ const full = join33(dir, name);
75422
75760
  try {
75423
75761
  if (statSync5(full).mtimeMs >= cutoff)
75424
75762
  continue;
@@ -75435,7 +75773,7 @@ function parseSettingsArg(value) {
75435
75773
  if (value.trimStart().startsWith("{")) {
75436
75774
  return JSON.parse(value);
75437
75775
  }
75438
- return JSON.parse(readFileSync24(value, "utf-8"));
75776
+ return JSON.parse(readFileSync25(value, "utf-8"));
75439
75777
  }
75440
75778
  function parseSettingsArgSafe(value) {
75441
75779
  try {
@@ -75447,13 +75785,13 @@ function parseSettingsArgSafe(value) {
75447
75785
  }
75448
75786
  function userSettingsFileCandidates(cwd) {
75449
75787
  return [
75450
- join32(homedir30(), ".claude", "settings.json"),
75451
- join32(cwd, ".claude", "settings.json"),
75452
- join32(cwd, ".claude", "settings.local.json")
75788
+ join33(homedir31(), ".claude", "settings.json"),
75789
+ join33(cwd, ".claude", "settings.json"),
75790
+ join33(cwd, ".claude", "settings.local.json")
75453
75791
  ];
75454
75792
  }
75455
75793
  function discoverUserStatusLineCommand(claudeArgs = [], cwd = process.cwd()) {
75456
- const sources = userSettingsFileCandidates(cwd).filter((file2) => existsSync26(file2));
75794
+ const sources = userSettingsFileCandidates(cwd).filter((file2) => existsSync27(file2));
75457
75795
  const idx = claudeArgs.indexOf("--settings");
75458
75796
  const settingsArg = idx === -1 ? undefined : claudeArgs[idx + 1];
75459
75797
  if (settingsArg)
@@ -75490,13 +75828,13 @@ function buildChainedStatusCommand(userCommand, claudishBody, claudishSegment) {
75490
75828
  }
75491
75829
  function createTempSettingsFile(_modelDisplay, port, proxyAuthMode, userStatusLineCommand) {
75492
75830
  const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
75493
- const claudishDir = join32(homeDir, ".claudish");
75831
+ const claudishDir = join33(homeDir, ".claudish");
75494
75832
  try {
75495
- mkdirSync16(claudishDir, { recursive: true });
75833
+ mkdirSync17(claudishDir, { recursive: true });
75496
75834
  } catch {}
75497
75835
  const timestamp = Date.now();
75498
- const tempPath = join32(claudishDir, `settings-${timestamp}.json`);
75499
- const tokenFilePath = join32(claudishDir, `tokens-${port}.json`);
75836
+ const tempPath = join33(claudishDir, `settings-${timestamp}.json`);
75837
+ const tokenFilePath = join33(claudishDir, `tokens-${port}.json`);
75500
75838
  cleanupStaleTokenFiles(claudishDir);
75501
75839
  initializeTokenFile(tokenFilePath);
75502
75840
  let statusCommand;
@@ -75527,7 +75865,7 @@ function createTempSettingsFile(_modelDisplay, port, proxyAuthMode, userStatusLi
75527
75865
  padding: 0
75528
75866
  };
75529
75867
  const settings = buildClaudishSettingsOverlay(statusLine, proxyAuthMode);
75530
- writeFileSync18(tempPath, JSON.stringify(settings, null, 2), "utf-8");
75868
+ writeFileSync19(tempPath, JSON.stringify(settings, null, 2), "utf-8");
75531
75869
  return { path: tempPath, statusLine, tokenFilePath };
75532
75870
  }
75533
75871
  function buildClaudishSettingsOverlay(statusLine, proxyAuthMode) {
@@ -75552,7 +75890,7 @@ function mergeUserSettingsIfPresent(config3, tempSettingsPath, statusLine, proxy
75552
75890
  if (proxyAuthMode && !("forceLoginMethod" in userSettings)) {
75553
75891
  userSettings.forceLoginMethod = "console";
75554
75892
  }
75555
- writeFileSync18(tempSettingsPath, JSON.stringify(userSettings, null, 2), "utf-8");
75893
+ writeFileSync19(tempSettingsPath, JSON.stringify(userSettings, null, 2), "utf-8");
75556
75894
  } catch {
75557
75895
  if (!config3.quiet) {
75558
75896
  console.warn(`[claudish] Warning: could not merge user settings: ${userSettingsValue}`);
@@ -75763,8 +76101,8 @@ async function runClaudeWithProxy(config3, proxyUrl, onCleanup) {
75763
76101
  console.error("Install it from: https://claude.com/claude-code");
75764
76102
  console.error(`
75765
76103
  Or set CLAUDE_PATH to your custom installation:`);
75766
- const home = homedir30();
75767
- const localPath = isWindows2() ? join32(home, ".claude", "local", "claude.exe") : join32(home, ".claude", "local", "claude");
76104
+ const home = homedir31();
76105
+ const localPath = isWindows2() ? join33(home, ".claude", "local", "claude.exe") : join33(home, ".claude", "local", "claude");
75768
76106
  console.error(` export CLAUDE_PATH=${localPath}`);
75769
76107
  process.exit(1);
75770
76108
  }
@@ -75844,23 +76182,23 @@ function setupSignalHandlers(proc, tempSettingsPath, quiet, onCleanup) {
75844
76182
  async function findClaudeBinary() {
75845
76183
  const isWindows3 = process.platform === "win32";
75846
76184
  if (process.env.CLAUDE_PATH) {
75847
- if (existsSync26(process.env.CLAUDE_PATH)) {
76185
+ if (existsSync27(process.env.CLAUDE_PATH)) {
75848
76186
  return process.env.CLAUDE_PATH;
75849
76187
  }
75850
76188
  }
75851
- const home = homedir30();
75852
- const localPath = isWindows3 ? join32(home, ".claude", "local", "claude.exe") : join32(home, ".claude", "local", "claude");
75853
- if (existsSync26(localPath)) {
76189
+ const home = homedir31();
76190
+ const localPath = isWindows3 ? join33(home, ".claude", "local", "claude.exe") : join33(home, ".claude", "local", "claude");
76191
+ if (existsSync27(localPath)) {
75854
76192
  return localPath;
75855
76193
  }
75856
76194
  if (isWindows3) {
75857
76195
  const windowsPaths = [
75858
- join32(home, "AppData", "Roaming", "npm", "claude.cmd"),
75859
- join32(home, ".npm-global", "claude.cmd"),
75860
- join32(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")
75861
76199
  ];
75862
76200
  for (const path2 of windowsPaths) {
75863
- if (existsSync26(path2)) {
76201
+ if (existsSync27(path2)) {
75864
76202
  return path2;
75865
76203
  }
75866
76204
  }
@@ -75868,14 +76206,14 @@ async function findClaudeBinary() {
75868
76206
  const commonPaths = [
75869
76207
  "/usr/local/bin/claude",
75870
76208
  "/opt/homebrew/bin/claude",
75871
- join32(home, ".npm-global/bin/claude"),
75872
- join32(home, ".local/bin/claude"),
75873
- join32(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"),
75874
76212
  "/data/data/com.termux/files/usr/bin/claude",
75875
- join32(home, "../usr/bin/claude")
76213
+ join33(home, "../usr/bin/claude")
75876
76214
  ];
75877
76215
  for (const path2 of commonPaths) {
75878
- if (existsSync26(path2)) {
76216
+ if (existsSync27(path2)) {
75879
76217
  return path2;
75880
76218
  }
75881
76219
  }
@@ -75935,18 +76273,18 @@ __export(exports_diag_output, {
75935
76273
  NullDiagOutput: () => NullDiagOutput,
75936
76274
  LogFileDiagOutput: () => LogFileDiagOutput
75937
76275
  });
75938
- import { createWriteStream as createWriteStream3, mkdirSync as mkdirSync17, unlinkSync as unlinkSync11, writeFileSync as writeFileSync19 } from "fs";
75939
- import { homedir as homedir31 } from "os";
75940
- import { join as join33 } 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";
75941
76279
  function getClaudishDir() {
75942
- const dir = join33(homedir31(), ".claudish");
76280
+ const dir = join34(homedir32(), ".claudish");
75943
76281
  try {
75944
- mkdirSync17(dir, { recursive: true });
76282
+ mkdirSync18(dir, { recursive: true });
75945
76283
  } catch {}
75946
76284
  return dir;
75947
76285
  }
75948
76286
  function getDiagLogPath() {
75949
- return join33(getClaudishDir(), `diag-${process.pid}.log`);
76287
+ return join34(getClaudishDir(), `diag-${process.pid}.log`);
75950
76288
  }
75951
76289
 
75952
76290
  class LogFileDiagOutput {
@@ -75955,7 +76293,7 @@ class LogFileDiagOutput {
75955
76293
  constructor() {
75956
76294
  this.logPath = getDiagLogPath();
75957
76295
  try {
75958
- writeFileSync19(this.logPath, `--- claudish diag session ${new Date().toISOString()} ---
76296
+ writeFileSync20(this.logPath, `--- claudish diag session ${new Date().toISOString()} ---
75959
76297
  `);
75960
76298
  } catch {}
75961
76299
  this.stream = createWriteStream3(this.logPath, { flags: "a" });
@@ -76157,9 +76495,9 @@ __export(exports_team_grid, {
76157
76495
  });
76158
76496
  import { spawn as spawn5 } from "child_process";
76159
76497
  import { execSync as execSync2 } from "child_process";
76160
- import { existsSync as existsSync27, readFileSync as readFileSync25, writeFileSync as writeFileSync20 } from "fs";
76498
+ import { existsSync as existsSync28, readFileSync as readFileSync26, writeFileSync as writeFileSync21 } from "fs";
76161
76499
  import { connect as netConnect } from "net";
76162
- import { dirname as dirname12, join as join34 } from "path";
76500
+ import { dirname as dirname13, join as join35 } from "path";
76163
76501
  import { setTimeout as wait } from "timers/promises";
76164
76502
  import { fileURLToPath as fileURLToPath3 } from "url";
76165
76503
  function resolveRouteInfo(modelId) {
@@ -76252,21 +76590,21 @@ function buildPaneHeader(model, prompt, bg) {
76252
76590
  }
76253
76591
  function findMagmuxBinary() {
76254
76592
  const thisFile = fileURLToPath3(import.meta.url);
76255
- const thisDir = dirname12(thisFile);
76256
- const pkgRoot = join34(thisDir, "..");
76593
+ const thisDir = dirname13(thisFile);
76594
+ const pkgRoot = join35(thisDir, "..");
76257
76595
  const platform3 = process.platform;
76258
76596
  const arch = process.arch;
76259
- const bundledMagmux = join34(pkgRoot, "native", `magmux-${platform3}-${arch}`);
76260
- if (existsSync27(bundledMagmux))
76597
+ const bundledMagmux = join35(pkgRoot, "native", `magmux-${platform3}-${arch}`);
76598
+ if (existsSync28(bundledMagmux))
76261
76599
  return bundledMagmux;
76262
76600
  try {
76263
76601
  const pkgName = `@claudish/magmux-${platform3}-${arch}`;
76264
76602
  let searchDir = pkgRoot;
76265
76603
  for (let i = 0;i < 5; i++) {
76266
- const candidate = join34(searchDir, "node_modules", pkgName, "bin", "magmux");
76267
- if (existsSync27(candidate))
76604
+ const candidate = join35(searchDir, "node_modules", pkgName, "bin", "magmux");
76605
+ if (existsSync28(candidate))
76268
76606
  return candidate;
76269
- const parent = dirname12(searchDir);
76607
+ const parent = dirname13(searchDir);
76270
76608
  if (parent === searchDir)
76271
76609
  break;
76272
76610
  searchDir = parent;
@@ -76283,7 +76621,7 @@ function findMagmuxBinary() {
76283
76621
  async function subscribeToMagmux(sockPath, onEvent) {
76284
76622
  let client = null;
76285
76623
  for (let attempt = 0;attempt < 40; attempt++) {
76286
- if (existsSync27(sockPath)) {
76624
+ if (existsSync28(sockPath)) {
76287
76625
  try {
76288
76626
  client = await new Promise((resolve4, reject) => {
76289
76627
  const s = netConnect(sockPath);
@@ -76370,9 +76708,9 @@ async function runWithGrid(sessionPath, models, input, opts) {
76370
76708
  const keep = opts?.keep ?? false;
76371
76709
  const manifest = setupSession(sessionPath, models, input);
76372
76710
  const startedAt = new Date().toISOString();
76373
- const gridfilePath = join34(sessionPath, "gridfile.txt");
76374
- const prompt = readFileSync25(join34(sessionPath, "input.md"), "utf-8").replace(/'/g, "'\\''").replace(/\n/g, " ");
76375
- const rawPrompt = readFileSync25(join34(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");
76376
76714
  const usedBannerColors = new Set;
76377
76715
  const gridLines = Object.entries(manifest.models).map(([anonId]) => {
76378
76716
  const model = manifest.models[anonId].model;
@@ -76383,7 +76721,7 @@ async function runWithGrid(sessionPath, models, input, opts) {
76383
76721
  const header = buildPaneHeader(model, rawPrompt, bg);
76384
76722
  return `${header} claudish --model ${model} -y --quiet '${prompt}'`;
76385
76723
  });
76386
- writeFileSync20(gridfilePath, `${gridLines.join(`
76724
+ writeFileSync21(gridfilePath, `${gridLines.join(`
76387
76725
  `)}
76388
76726
  `, "utf-8");
76389
76727
  const magmuxPath = findMagmuxBinary();
@@ -76403,8 +76741,8 @@ async function runWithGrid(sessionPath, models, input, opts) {
76403
76741
  });
76404
76742
  const [{ results: results2 }] = await Promise.all([subscription, procExit]);
76405
76743
  const status = buildTeamStatus(manifest, startedAt, results2?.panes ?? null);
76406
- const statusPath = join34(sessionPath, "status.json");
76407
- 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");
76408
76746
  return status;
76409
76747
  }
76410
76748
  var BANNER_BG_COLORS;
@@ -76427,8 +76765,8 @@ var init_team_grid = __esm(() => {
76427
76765
  init_op_source();
76428
76766
  init_startup_trace();
76429
76767
  var import_dotenv3 = __toESM(require_main(), 1);
76430
- import { existsSync as existsSync28, readFileSync as readFileSync26 } from "fs";
76431
- import { join as join35, 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";
76432
76770
  import_dotenv3.config({ quiet: true });
76433
76771
  function classifyStartupKind() {
76434
76772
  const argv = process.argv.slice(2);
@@ -76527,7 +76865,7 @@ async function applyConfigOverride() {
76527
76865
  const { planConfigOverride: planConfigOverride2, setConfigFileOverride: setConfigFileOverride2 } = await Promise.resolve().then(() => exports_config_override);
76528
76866
  const plan = planConfigOverride2(process.argv.slice(2), process.env, {
76529
76867
  resolve: resolve4,
76530
- exists: existsSync28
76868
+ exists: existsSync29
76531
76869
  });
76532
76870
  if (plan.kind === "none")
76533
76871
  return;
@@ -76675,14 +77013,14 @@ async function runCli() {
76675
77013
  if (cliConfig.team && cliConfig.team.length > 0) {
76676
77014
  let prompt = cliConfig.claudeArgs.join(" ");
76677
77015
  if (cliConfig.inputFile) {
76678
- prompt = readFileSync26(cliConfig.inputFile, "utf-8");
77016
+ prompt = readFileSync27(cliConfig.inputFile, "utf-8");
76679
77017
  }
76680
77018
  if (!prompt.trim()) {
76681
77019
  console.error("Error: --team requires a prompt (positional args or -f <file>)");
76682
77020
  process.exit(1);
76683
77021
  }
76684
77022
  const mode = cliConfig.teamMode ?? "default";
76685
- const sessionPath = join35(process.cwd(), `.claudish-team-${Date.now()}`);
77023
+ const sessionPath = join36(process.cwd(), `.claudish-team-${Date.now()}`);
76686
77024
  if (mode === "json") {
76687
77025
  const { setupSession: setupSession2, runModels: runModels2 } = await Promise.resolve().then(() => (init_team_orchestrator(), exports_team_orchestrator));
76688
77026
  setupSession2(sessionPath, cliConfig.team, prompt);
@@ -76692,9 +77030,9 @@ async function runCli() {
76692
77030
  });
76693
77031
  const result = { ...status2, responses: {} };
76694
77032
  for (const anonId of Object.keys(status2.models)) {
76695
- const responsePath = join35(sessionPath, `response-${anonId}.md`);
77033
+ const responsePath = join36(sessionPath, `response-${anonId}.md`);
76696
77034
  try {
76697
- const raw2 = readFileSync26(responsePath, "utf-8").trim();
77035
+ const raw2 = readFileSync27(responsePath, "utf-8").trim();
76698
77036
  try {
76699
77037
  result.responses[anonId] = JSON.parse(raw2);
76700
77038
  } catch {