claudish 6.6.3 → 6.7.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.
package/dist/index.js CHANGED
@@ -23252,6 +23252,21 @@ var init_provider_definitions = __esm(() => {
23252
23252
  isLocal: true,
23253
23253
  description: "Local MLX (mlx@)"
23254
23254
  },
23255
+ {
23256
+ name: "deepseek",
23257
+ displayName: "DeepSeek",
23258
+ transport: "openai",
23259
+ baseUrl: "",
23260
+ apiPath: "",
23261
+ apiKeyEnvVar: "",
23262
+ apiKeyDescription: "DeepSeek (auto-routed via OpenRouter)",
23263
+ apiKeyUrl: "",
23264
+ shortcuts: ["ds"],
23265
+ shortestPrefix: "ds",
23266
+ legacyPrefixes: [],
23267
+ nativeModelPatterns: [{ pattern: /^deepseek\//i }, { pattern: /^deepseek-/i }],
23268
+ description: "DeepSeek (auto-routed via OpenRouter)"
23269
+ },
23255
23270
  {
23256
23271
  name: "qwen",
23257
23272
  displayName: "Qwen",
@@ -24806,75 +24821,156 @@ var init_static_fallback = __esm(() => {
24806
24821
  minimax: "minimax",
24807
24822
  openrouter: "openrouter",
24808
24823
  ollamacloud: "meta-llama",
24809
- qwen: "qwen"
24824
+ qwen: "qwen",
24825
+ deepseek: "deepseek",
24826
+ grok: "x-ai"
24810
24827
  };
24811
24828
  });
24812
24829
 
24813
24830
  // src/providers/catalog-resolvers/openrouter.ts
24814
- import { readFileSync as readFileSync6, existsSync as existsSync8 } from "fs";
24831
+ import { readFileSync as readFileSync6, existsSync as existsSync8, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8 } from "fs";
24815
24832
  import { join as join10 } from "path";
24816
24833
  import { homedir as homedir9 } from "os";
24817
24834
 
24818
24835
  class OpenRouterCatalogResolver {
24819
24836
  provider = "openrouter";
24820
24837
  resolveSync(userInput) {
24838
+ const entries = this._getEntries();
24821
24839
  if (userInput.includes("/")) {
24822
- const models2 = this._getModels();
24823
- if (models2) {
24824
- const exactMatch = models2.find((m) => m.id === userInput);
24825
- return exactMatch ? exactMatch.id : userInput;
24840
+ if (entries) {
24841
+ for (const entry of entries) {
24842
+ for (const src of Object.values(entry.sources)) {
24843
+ if (src.externalId === userInput)
24844
+ return userInput;
24845
+ }
24846
+ }
24826
24847
  }
24827
24848
  return userInput;
24828
24849
  }
24829
- const models = this._getModels();
24830
- if (models) {
24850
+ if (entries) {
24851
+ const byModelId = entries.find((e) => e.modelId === userInput);
24852
+ if (byModelId) {
24853
+ const orId = this._getOpenRouterExternalId(byModelId);
24854
+ if (orId)
24855
+ return orId;
24856
+ }
24857
+ const byAlias = entries.find((e) => e.aliases.includes(userInput));
24858
+ if (byAlias) {
24859
+ const orId = this._getOpenRouterExternalId(byAlias);
24860
+ if (orId)
24861
+ return orId;
24862
+ }
24863
+ for (const entry of entries) {
24864
+ for (const src of Object.values(entry.sources)) {
24865
+ if (src.externalId === userInput) {
24866
+ const orId = this._getOpenRouterExternalId(entry);
24867
+ if (orId)
24868
+ return orId;
24869
+ }
24870
+ }
24871
+ }
24831
24872
  const suffix = `/${userInput}`;
24832
- const match2 = models.find((m) => m.id.endsWith(suffix));
24833
- if (match2)
24834
- return match2.id;
24873
+ for (const entry of entries) {
24874
+ const orId = this._getOpenRouterExternalId(entry);
24875
+ if (orId && orId.endsWith(suffix))
24876
+ return orId;
24877
+ }
24835
24878
  const lowerSuffix = `/${userInput.toLowerCase()}`;
24836
- const ciMatch = models.find((m) => m.id.toLowerCase().endsWith(lowerSuffix));
24837
- if (ciMatch)
24838
- return ciMatch.id;
24879
+ for (const entry of entries) {
24880
+ const orId = this._getOpenRouterExternalId(entry);
24881
+ if (orId && orId.toLowerCase().endsWith(lowerSuffix))
24882
+ return orId;
24883
+ }
24839
24884
  }
24840
24885
  return staticOpenRouterFallback(userInput);
24841
24886
  }
24842
24887
  async warmCache() {
24843
- try {
24844
- const existing = getCachedOpenRouterModels();
24845
- if (existing && existing.length > 0) {
24846
- _memCache = existing;
24847
- return;
24848
- }
24849
- const models = await ensureOpenRouterModelsLoaded();
24850
- if (models.length > 0) {
24851
- _memCache = models;
24852
- }
24853
- } catch {}
24888
+ if (!_warmPromise) {
24889
+ _warmPromise = this._fetchAndCache();
24890
+ }
24891
+ await _warmPromise;
24854
24892
  }
24855
24893
  isCacheWarm() {
24856
24894
  return _memCache !== null && _memCache.length > 0;
24857
24895
  }
24858
- _getModels() {
24896
+ async ensureReady(timeoutMs) {
24897
+ if (this.isCacheWarm())
24898
+ return;
24899
+ if (!_warmPromise) {
24900
+ _warmPromise = this._fetchAndCache();
24901
+ }
24902
+ await Promise.race([
24903
+ _warmPromise,
24904
+ new Promise((resolve2) => setTimeout(resolve2, timeoutMs))
24905
+ ]);
24906
+ }
24907
+ _getOpenRouterExternalId(entry) {
24908
+ const orSource = entry.sources["openrouter-api"];
24909
+ if (orSource?.externalId)
24910
+ return orSource.externalId;
24911
+ for (const src of Object.values(entry.sources)) {
24912
+ if (src.externalId.includes("/"))
24913
+ return src.externalId;
24914
+ }
24915
+ return null;
24916
+ }
24917
+ _getEntries() {
24859
24918
  if (_memCache)
24860
24919
  return _memCache;
24861
- const diskPath = join10(homedir9(), ".claudish", "all-models.json");
24862
- if (existsSync8(diskPath)) {
24920
+ if (existsSync8(DISK_CACHE_PATH)) {
24863
24921
  try {
24864
- const data = JSON.parse(readFileSync6(diskPath, "utf-8"));
24922
+ const data = JSON.parse(readFileSync6(DISK_CACHE_PATH, "utf-8"));
24923
+ if (data.version === 2 && Array.isArray(data.entries) && data.entries.length > 0) {
24924
+ _memCache = data.entries;
24925
+ return _memCache;
24926
+ }
24865
24927
  if (Array.isArray(data.models) && data.models.length > 0) {
24866
- _memCache = data.models;
24928
+ _memCache = data.models.map((m) => ({
24929
+ modelId: m.id.includes("/") ? m.id.split("/").slice(1).join("/") : m.id,
24930
+ aliases: [],
24931
+ sources: { "openrouter-api": { externalId: m.id } }
24932
+ }));
24867
24933
  return _memCache;
24868
24934
  }
24869
24935
  } catch {}
24870
24936
  }
24871
24937
  return null;
24872
24938
  }
24939
+ async _fetchAndCache() {
24940
+ try {
24941
+ const response = await fetch(FIREBASE_CATALOG_URL, {
24942
+ signal: AbortSignal.timeout(8000)
24943
+ });
24944
+ if (!response.ok) {
24945
+ throw new Error(`Firebase catalog returned ${response.status}`);
24946
+ }
24947
+ const data = await response.json();
24948
+ if (!Array.isArray(data.models) || data.models.length === 0)
24949
+ return;
24950
+ _memCache = data.models;
24951
+ const backwardCompatModels = [];
24952
+ for (const entry of data.models) {
24953
+ const orSource = entry.sources["openrouter-api"];
24954
+ if (orSource?.externalId) {
24955
+ backwardCompatModels.push({ id: orSource.externalId });
24956
+ }
24957
+ }
24958
+ const cacheDir = join10(homedir9(), ".claudish");
24959
+ mkdirSync8(cacheDir, { recursive: true });
24960
+ const diskData = {
24961
+ version: 2,
24962
+ lastUpdated: new Date().toISOString(),
24963
+ entries: data.models,
24964
+ models: backwardCompatModels
24965
+ };
24966
+ writeFileSync8(DISK_CACHE_PATH, JSON.stringify(diskData), "utf-8");
24967
+ } catch {}
24968
+ }
24873
24969
  }
24874
- var _memCache = null;
24970
+ var FIREBASE_CATALOG_URL = "https://us-central1-claudish-6da10.cloudfunctions.net/queryModels?status=active&catalog=slim&limit=1000", DISK_CACHE_PATH, _memCache = null, _warmPromise = null;
24875
24971
  var init_openrouter2 = __esm(() => {
24876
- init_model_loader();
24877
24972
  init_static_fallback();
24973
+ DISK_CACHE_PATH = join10(homedir9(), ".claudish", "all-models.json");
24878
24974
  });
24879
24975
 
24880
24976
  // src/providers/catalog-resolvers/litellm.ts
@@ -24927,6 +25023,10 @@ class LiteLLMCatalogResolver {
24927
25023
  isCacheWarm() {
24928
25024
  return _memCache2 !== null && _memCache2.length > 0;
24929
25025
  }
25026
+ async ensureReady(_timeoutMs) {
25027
+ if (!this.isCacheWarm())
25028
+ await this.warmCache();
25029
+ }
24930
25030
  _getModelIds() {
24931
25031
  if (_memCache2)
24932
25032
  return _memCache2;
@@ -24977,6 +25077,12 @@ function logResolution(userInput, result, quiet = false) {
24977
25077
  `);
24978
25078
  }
24979
25079
  }
25080
+ async function ensureCatalogReady(provider, timeoutMs = 5000) {
25081
+ const resolver = getResolver(provider);
25082
+ if (!resolver || resolver.isCacheWarm())
25083
+ return;
25084
+ await resolver.ensureReady(timeoutMs);
25085
+ }
24980
25086
  async function warmAllCatalogs(providers) {
24981
25087
  const targets = providers ? [...RESOLVER_REGISTRY.entries()].filter(([k]) => providers.includes(k)) : [...RESOLVER_REGISTRY.entries()];
24982
25088
  await Promise.allSettled(targets.map(([, r]) => r.warmCache()));
@@ -25125,8 +25231,8 @@ async function warmZenModelCache() {
25125
25231
  if (models.length === 0)
25126
25232
  return;
25127
25233
  const cacheDir = join12(homedir11(), ".claudish");
25128
- const { mkdirSync: mkdirSync8, writeFileSync: writeSync } = await import("fs");
25129
- mkdirSync8(cacheDir, { recursive: true });
25234
+ const { mkdirSync: mkdirSync9, writeFileSync: writeSync } = await import("fs");
25235
+ mkdirSync9(cacheDir, { recursive: true });
25130
25236
  writeSync(join12(cacheDir, "zen-models.json"), JSON.stringify({ models, fetchedAt: new Date().toISOString() }));
25131
25237
  }
25132
25238
  function readZenGoModelCacheSync() {
@@ -25162,8 +25268,8 @@ async function warmZenGoModelCache() {
25162
25268
  if (models.length === 0)
25163
25269
  return;
25164
25270
  const cacheDir = join12(homedir11(), ".claudish");
25165
- const { mkdirSync: mkdirSync8, writeFileSync: writeSync } = await import("fs");
25166
- mkdirSync8(cacheDir, { recursive: true });
25271
+ const { mkdirSync: mkdirSync9, writeFileSync: writeSync } = await import("fs");
25272
+ mkdirSync9(cacheDir, { recursive: true });
25167
25273
  writeSync(join12(cacheDir, "zen-go-models.json"), JSON.stringify({ models, fetchedAt: new Date().toISOString() }));
25168
25274
  }
25169
25275
  function hasProviderCredentials(provider) {
@@ -25200,7 +25306,7 @@ function getFallbackChain(modelName, nativeProvider) {
25200
25306
  displayName: sub.displayName
25201
25307
  });
25202
25308
  }
25203
- if (nativeProvider !== "unknown" && nativeProvider !== "qwen" && nativeProvider !== "native-anthropic") {
25309
+ if (nativeProvider !== "unknown" && nativeProvider !== "qwen" && nativeProvider !== "deepseek" && nativeProvider !== "native-anthropic") {
25204
25310
  if (hasProviderCredentials(nativeProvider)) {
25205
25311
  const prefix = PROVIDER_TO_PREFIX[nativeProvider] || nativeProvider;
25206
25312
  routes.push({
@@ -25639,7 +25745,7 @@ var init_provider_resolver = __esm(() => {
25639
25745
  });
25640
25746
 
25641
25747
  // src/services/pricing-cache.ts
25642
- import { readFileSync as readFileSync9, writeFileSync as writeFileSync8, existsSync as existsSync12, mkdirSync as mkdirSync8, statSync as statSync2 } from "fs";
25748
+ import { readFileSync as readFileSync9, writeFileSync as writeFileSync9, existsSync as existsSync12, mkdirSync as mkdirSync9, statSync as statSync2 } from "fs";
25643
25749
  import { homedir as homedir13 } from "os";
25644
25750
  import { join as join14 } from "path";
25645
25751
  function getDynamicPricingSync(provider, modelName) {
@@ -25723,12 +25829,12 @@ function loadDiskCache() {
25723
25829
  }
25724
25830
  function saveDiskCache() {
25725
25831
  try {
25726
- mkdirSync8(CACHE_DIR, { recursive: true });
25832
+ mkdirSync9(CACHE_DIR, { recursive: true });
25727
25833
  const data = {};
25728
25834
  for (const [key, pricing] of pricingMap) {
25729
25835
  data[key] = pricing;
25730
25836
  }
25731
- writeFileSync8(CACHE_FILE, JSON.stringify(data), "utf-8");
25837
+ writeFileSync9(CACHE_FILE, JSON.stringify(data), "utf-8");
25732
25838
  } catch (error2) {
25733
25839
  log(`[PricingCache] Error saving disk cache: ${error2}`);
25734
25840
  }
@@ -26305,8 +26411,8 @@ Details: ${e.message}`);
26305
26411
  const credPath = this.getCredentialsPath();
26306
26412
  const claudishDir = join15(homedir14(), ".claudish");
26307
26413
  if (!existsSync13(claudishDir)) {
26308
- const { mkdirSync: mkdirSync9 } = __require("fs");
26309
- mkdirSync9(claudishDir, { recursive: true });
26414
+ const { mkdirSync: mkdirSync10 } = __require("fs");
26415
+ mkdirSync10(claudishDir, { recursive: true });
26310
26416
  }
26311
26417
  const fd = openSync(credPath, "w", 384);
26312
26418
  try {
@@ -27163,8 +27269,8 @@ Details: ${e.message}`);
27163
27269
  const credPath = this.getCredentialsPath();
27164
27270
  const claudishDir = join16(homedir15(), ".claudish");
27165
27271
  if (!existsSync14(claudishDir)) {
27166
- const { mkdirSync: mkdirSync9 } = __require("fs");
27167
- mkdirSync9(claudishDir, { recursive: true });
27272
+ const { mkdirSync: mkdirSync10 } = __require("fs");
27273
+ mkdirSync10(claudishDir, { recursive: true });
27168
27274
  }
27169
27275
  const fd = openSync2(credPath, "w", 384);
27170
27276
  try {
@@ -27480,8 +27586,8 @@ class KimiOAuth {
27480
27586
  const deviceIdPath = this.getDeviceIdPath();
27481
27587
  const claudishDir = join18(homedir17(), ".claudish");
27482
27588
  if (!existsSync16(claudishDir)) {
27483
- const { mkdirSync: mkdirSync9 } = __require("fs");
27484
- mkdirSync9(claudishDir, { recursive: true });
27589
+ const { mkdirSync: mkdirSync10 } = __require("fs");
27590
+ mkdirSync10(claudishDir, { recursive: true });
27485
27591
  }
27486
27592
  if (existsSync16(deviceIdPath)) {
27487
27593
  try {
@@ -27764,8 +27870,8 @@ Waiting for authorization...`);
27764
27870
  const credPath = this.getCredentialsPath();
27765
27871
  const claudishDir = join18(homedir17(), ".claudish");
27766
27872
  if (!existsSync16(claudishDir)) {
27767
- const { mkdirSync: mkdirSync9 } = __require("fs");
27768
- mkdirSync9(claudishDir, { recursive: true });
27873
+ const { mkdirSync: mkdirSync10 } = __require("fs");
27874
+ mkdirSync10(claudishDir, { recursive: true });
27769
27875
  }
27770
27876
  const fd = openSync3(credPath, "w", 384);
27771
27877
  try {
@@ -29001,7 +29107,7 @@ async function createProxyServer(port, openrouterApiKey, model, monitorMode = fa
29001
29107
  }
29002
29108
  return "auto-route";
29003
29109
  };
29004
- const getHandlerForRequest = (requestedModel) => {
29110
+ const getHandlerForRequest = async (requestedModel) => {
29005
29111
  if (monitorMode)
29006
29112
  return nativeHandler;
29007
29113
  let target = requestedModel;
@@ -29026,6 +29132,7 @@ async function createProxyServer(port, openrouterApiKey, model, monitorMode = fa
29026
29132
  {
29027
29133
  const parsedTarget = parseModelSpec(target);
29028
29134
  if (parsedTarget.provider === "openrouter" || parsedTarget.provider === "litellm") {
29135
+ await ensureCatalogReady(parsedTarget.provider, 5000);
29029
29136
  const resolution = resolveModelNameSync(parsedTarget.model, parsedTarget.provider);
29030
29137
  logResolution(parsedTarget.model, resolution, options.quiet);
29031
29138
  if (resolution.wasResolved) {
@@ -29040,6 +29147,7 @@ async function createProxyServer(port, openrouterApiKey, model, monitorMode = fa
29040
29147
  if (fallbackHandlerCache.has(cacheKey2)) {
29041
29148
  return fallbackHandlerCache.get(cacheKey2);
29042
29149
  }
29150
+ await ensureCatalogReady("openrouter", 5000);
29043
29151
  const matchedEntries = customRoutingRules ? matchRoutingRule(parsedForFallback.model, customRoutingRules) : null;
29044
29152
  const chain = matchedEntries ? buildRoutingChain(matchedEntries, parsedForFallback.model) : getFallbackChain(parsedForFallback.model, parsedForFallback.provider);
29045
29153
  if (chain.length > 0) {
@@ -29099,7 +29207,7 @@ async function createProxyServer(port, openrouterApiKey, model, monitorMode = fa
29099
29207
  try {
29100
29208
  const body = await c.req.json();
29101
29209
  const reqModel = body.model || "claude-3-opus-20240229";
29102
- const handler = getHandlerForRequest(reqModel);
29210
+ const handler = await getHandlerForRequest(reqModel);
29103
29211
  if (handler instanceof NativeHandler) {
29104
29212
  const headers = { "Content-Type": "application/json" };
29105
29213
  if (anthropicApiKey)
@@ -29121,7 +29229,7 @@ async function createProxyServer(port, openrouterApiKey, model, monitorMode = fa
29121
29229
  app.post("/v1/messages", async (c) => {
29122
29230
  try {
29123
29231
  const body = await c.req.json();
29124
- const handler = getHandlerForRequest(body.model);
29232
+ const handler = await getHandlerForRequest(body.model);
29125
29233
  return handler.handle(c, body);
29126
29234
  } catch (e) {
29127
29235
  log(`[Proxy] Error: ${e}`);
@@ -29210,7 +29318,7 @@ var exports_mcp_server = {};
29210
29318
  __export(exports_mcp_server, {
29211
29319
  startMcpServer: () => startMcpServer
29212
29320
  });
29213
- import { readFileSync as readFileSync17, existsSync as existsSync20, writeFileSync as writeFileSync9, mkdirSync as mkdirSync9, readdirSync as readdirSync3 } from "fs";
29321
+ import { readFileSync as readFileSync17, existsSync as existsSync20, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10, readdirSync as readdirSync3 } from "fs";
29214
29322
  import { join as join22, dirname as dirname2 } from "path";
29215
29323
  import { homedir as homedir21 } from "os";
29216
29324
  import { fileURLToPath as fileURLToPath2 } from "url";
@@ -29242,8 +29350,8 @@ async function loadAllModels(forceRefresh = false) {
29242
29350
  throw new Error(`API returned ${response.status}`);
29243
29351
  const data = await response.json();
29244
29352
  const models = data.data || [];
29245
- mkdirSync9(CLAUDISH_CACHE_DIR, { recursive: true });
29246
- writeFileSync9(ALL_MODELS_CACHE_PATH, JSON.stringify({ lastUpdated: new Date().toISOString(), models }), "utf-8");
29353
+ mkdirSync10(CLAUDISH_CACHE_DIR, { recursive: true });
29354
+ writeFileSync10(ALL_MODELS_CACHE_PATH, JSON.stringify({ lastUpdated: new Date().toISOString(), models }), "utf-8");
29247
29355
  return models;
29248
29356
  } catch {
29249
29357
  if (existsSync20(ALL_MODELS_CACHE_PATH)) {
@@ -32719,9 +32827,9 @@ __export(exports_cli, {
32719
32827
  });
32720
32828
  import {
32721
32829
  readFileSync as readFileSync18,
32722
- writeFileSync as writeFileSync10,
32830
+ writeFileSync as writeFileSync11,
32723
32831
  existsSync as existsSync21,
32724
- mkdirSync as mkdirSync10,
32832
+ mkdirSync as mkdirSync11,
32725
32833
  copyFileSync,
32726
32834
  readdirSync as readdirSync4,
32727
32835
  unlinkSync as unlinkSync6
@@ -33071,8 +33179,8 @@ async function searchAndPrintModels(query, forceUpdate) {
33071
33179
  throw new Error(`API returned ${response.status}`);
33072
33180
  const data = await response.json();
33073
33181
  models = data.data;
33074
- mkdirSync10(CLAUDISH_CACHE_DIR2, { recursive: true });
33075
- writeFileSync10(ALL_MODELS_JSON_PATH, JSON.stringify({
33182
+ mkdirSync11(CLAUDISH_CACHE_DIR2, { recursive: true });
33183
+ writeFileSync11(ALL_MODELS_JSON_PATH, JSON.stringify({
33076
33184
  lastUpdated: new Date().toISOString(),
33077
33185
  models
33078
33186
  }), "utf-8");
@@ -33244,8 +33352,8 @@ async function printAllModels(jsonOutput, forceUpdate) {
33244
33352
  throw new Error(`API returned ${response.status}`);
33245
33353
  const data = await response.json();
33246
33354
  models = data.data;
33247
- mkdirSync10(CLAUDISH_CACHE_DIR2, { recursive: true });
33248
- writeFileSync10(ALL_MODELS_JSON_PATH, JSON.stringify({
33355
+ mkdirSync11(CLAUDISH_CACHE_DIR2, { recursive: true });
33356
+ writeFileSync11(ALL_MODELS_JSON_PATH, JSON.stringify({
33249
33357
  lastUpdated: new Date().toISOString(),
33250
33358
  models
33251
33359
  }), "utf-8");
@@ -33522,8 +33630,8 @@ async function updateModelsFromOpenRouter() {
33522
33630
  source: "https://openrouter.ai/models?categories=programming&fmt=cards&order=top-weekly",
33523
33631
  models: recommendations
33524
33632
  };
33525
- mkdirSync10(CLAUDISH_CACHE_DIR2, { recursive: true });
33526
- writeFileSync10(CACHED_MODELS_PATH, JSON.stringify(updatedData, null, 2), "utf-8");
33633
+ mkdirSync11(CLAUDISH_CACHE_DIR2, { recursive: true });
33634
+ writeFileSync11(CACHED_MODELS_PATH, JSON.stringify(updatedData, null, 2), "utf-8");
33527
33635
  console.error(`\u2705 Updated ${recommendations.length} models (last updated: ${updatedData.lastUpdated})`);
33528
33636
  } catch (error2) {
33529
33637
  console.error(`\u274C Failed to update models: ${error2 instanceof Error ? error2.message : String(error2)}`);
@@ -34173,15 +34281,15 @@ async function initializeClaudishSkill() {
34173
34281
  }
34174
34282
  try {
34175
34283
  if (!existsSync21(claudeDir)) {
34176
- mkdirSync10(claudeDir, { recursive: true });
34284
+ mkdirSync11(claudeDir, { recursive: true });
34177
34285
  console.log("\uD83D\uDCC1 Created .claude/ directory");
34178
34286
  }
34179
34287
  if (!existsSync21(skillsDir)) {
34180
- mkdirSync10(skillsDir, { recursive: true });
34288
+ mkdirSync11(skillsDir, { recursive: true });
34181
34289
  console.log("\uD83D\uDCC1 Created .claude/skills/ directory");
34182
34290
  }
34183
34291
  if (!existsSync21(claudishSkillDir)) {
34184
- mkdirSync10(claudishSkillDir, { recursive: true });
34292
+ mkdirSync11(claudishSkillDir, { recursive: true });
34185
34293
  console.log("\uD83D\uDCC1 Created .claude/skills/claudish-usage/ directory");
34186
34294
  }
34187
34295
  copyFileSync(sourceSkillPath, skillFile);
@@ -34361,7 +34469,7 @@ async function fetchGLMCodingModels() {
34361
34469
  return [];
34362
34470
  }
34363
34471
  }
34364
- var __filename4, __dirname4, VERSION = "6.6.3", CACHE_MAX_AGE_DAYS2 = 2, CLAUDISH_CACHE_DIR2, BUNDLED_MODELS_PATH, CACHED_MODELS_PATH, ALL_MODELS_JSON_PATH;
34472
+ var __filename4, __dirname4, VERSION = "6.7.0", CACHE_MAX_AGE_DAYS2 = 2, CLAUDISH_CACHE_DIR2, BUNDLED_MODELS_PATH, CACHED_MODELS_PATH, ALL_MODELS_JSON_PATH;
34365
34473
  var init_cli = __esm(() => {
34366
34474
  init_config();
34367
34475
  init_model_loader();
@@ -34392,7 +34500,7 @@ __export(exports_update_checker, {
34392
34500
  checkForUpdates: () => checkForUpdates
34393
34501
  });
34394
34502
  import { execSync } from "child_process";
34395
- import { existsSync as existsSync22, mkdirSync as mkdirSync11, readFileSync as readFileSync19, unlinkSync as unlinkSync7, writeFileSync as writeFileSync11 } from "fs";
34503
+ import { existsSync as existsSync22, mkdirSync as mkdirSync12, readFileSync as readFileSync19, unlinkSync as unlinkSync7, writeFileSync as writeFileSync12 } from "fs";
34396
34504
  import { homedir as homedir23, platform as platform2, tmpdir } from "os";
34397
34505
  import { join as join24 } from "path";
34398
34506
  import { createInterface as createInterface2 } from "readline";
@@ -34413,7 +34521,7 @@ function getCacheFilePath() {
34413
34521
  }
34414
34522
  try {
34415
34523
  if (!existsSync22(cacheDir)) {
34416
- mkdirSync11(cacheDir, { recursive: true });
34524
+ mkdirSync12(cacheDir, { recursive: true });
34417
34525
  }
34418
34526
  return join24(cacheDir, "update-check.json");
34419
34527
  } catch {
@@ -34439,7 +34547,7 @@ function writeCache(latestVersion) {
34439
34547
  lastCheck: Date.now(),
34440
34548
  latestVersion
34441
34549
  };
34442
- writeFileSync11(cachePath, JSON.stringify(data), "utf-8");
34550
+ writeFileSync12(cachePath, JSON.stringify(data), "utf-8");
34443
34551
  } catch {}
34444
34552
  }
34445
34553
  function isCacheValid(cache) {
@@ -34715,7 +34823,7 @@ __export(exports_model_selector, {
34715
34823
  promptForApiKey: () => promptForApiKey,
34716
34824
  confirmAction: () => confirmAction
34717
34825
  });
34718
- import { readFileSync as readFileSync20, writeFileSync as writeFileSync12, existsSync as existsSync23, mkdirSync as mkdirSync12 } from "fs";
34826
+ import { readFileSync as readFileSync20, writeFileSync as writeFileSync13, existsSync as existsSync23, mkdirSync as mkdirSync13 } from "fs";
34719
34827
  import { join as join25, dirname as dirname4 } from "path";
34720
34828
  import { homedir as homedir24 } from "os";
34721
34829
  import { fileURLToPath as fileURLToPath4 } from "url";
@@ -34753,8 +34861,8 @@ async function fetchAllModels(forceUpdate = false) {
34753
34861
  throw new Error(`API returned ${response.status}`);
34754
34862
  const data = await response.json();
34755
34863
  const models = data.data;
34756
- mkdirSync12(CLAUDISH_CACHE_DIR3, { recursive: true });
34757
- writeFileSync12(ALL_MODELS_JSON_PATH2, JSON.stringify({
34864
+ mkdirSync13(CLAUDISH_CACHE_DIR3, { recursive: true });
34865
+ writeFileSync13(ALL_MODELS_JSON_PATH2, JSON.stringify({
34758
34866
  lastUpdated: new Date().toISOString(),
34759
34867
  models
34760
34868
  }), "utf-8");
@@ -36634,7 +36742,7 @@ import os from "os";
36634
36742
  import path from "path";
36635
36743
  import { EventEmitter as EventEmitter3 } from "events";
36636
36744
  import { dlopen, toArrayBuffer as toArrayBuffer4, JSCallback, ptr as ptr4 } from "bun:ffi";
36637
- import { existsSync as existsSync25, writeFileSync as writeFileSync13 } from "fs";
36745
+ import { existsSync as existsSync25, writeFileSync as writeFileSync14 } from "fs";
36638
36746
  import { EventEmitter as EventEmitter4 } from "events";
36639
36747
  import { toArrayBuffer, ptr } from "bun:ffi";
36640
36748
  import { ptr as ptr2, toArrayBuffer as toArrayBuffer2 } from "bun:ffi";
@@ -41980,7 +42088,7 @@ function convertToDebugSymbols(symbols) {
41980
42088
  if (env.OTUI_DEBUG_FFI && globalFFILogPath) {
41981
42089
  const logPath = globalFFILogPath;
41982
42090
  const writeSync4 = (msg) => {
41983
- writeFileSync13(logPath, msg + `
42091
+ writeFileSync14(logPath, msg + `
41984
42092
  `, { flag: "a" });
41985
42093
  };
41986
42094
  Object.entries(symbols).forEach(([key, value]) => {
@@ -95546,10 +95654,10 @@ import { spawn as spawn3 } from "child_process";
95546
95654
  import {
95547
95655
  appendFileSync,
95548
95656
  existsSync as existsSync26,
95549
- mkdirSync as mkdirSync13,
95657
+ mkdirSync as mkdirSync14,
95550
95658
  readFileSync as readFileSync21,
95551
95659
  unlinkSync as unlinkSync8,
95552
- writeFileSync as writeFileSync14
95660
+ writeFileSync as writeFileSync15
95553
95661
  } from "fs";
95554
95662
  import { dirname as dirname6, join as join27 } from "path";
95555
95663
  import { fileURLToPath as fileURLToPath6 } from "url";
@@ -95562,7 +95670,7 @@ function formatElapsed(ms) {
95562
95670
  const rem = s % 60;
95563
95671
  return `${m2}m ${rem}s`;
95564
95672
  }
95565
- function findMultiplexerBinary() {
95673
+ function findMagmuxBinary() {
95566
95674
  const thisFile = fileURLToPath6(import.meta.url);
95567
95675
  const thisDir = dirname6(thisFile);
95568
95676
  const pkgRoot = join27(thisDir, "..");
@@ -95570,40 +95678,17 @@ function findMultiplexerBinary() {
95570
95678
  const arch = process.arch;
95571
95679
  const builtMagmux = join27(pkgRoot, "native", "magmux", "magmux");
95572
95680
  if (existsSync26(builtMagmux))
95573
- return { path: builtMagmux, kind: "magmux" };
95681
+ return builtMagmux;
95574
95682
  const bundledMagmux = join27(pkgRoot, "native", "magmux", `magmux-${platform3}-${arch}`);
95575
95683
  if (existsSync26(bundledMagmux))
95576
- return { path: bundledMagmux, kind: "magmux" };
95684
+ return bundledMagmux;
95577
95685
  try {
95578
95686
  const result = execSync3("which magmux", { encoding: "utf-8" }).trim();
95579
95687
  if (result)
95580
- return { path: result, kind: "magmux" };
95581
- } catch {}
95582
- const builtMtm = join27(pkgRoot, "native", "mtm", "mtm");
95583
- if (existsSync26(builtMtm))
95584
- return { path: builtMtm, kind: "mtm" };
95585
- const bundledMtm = join27(pkgRoot, "native", "mtm", `mtm-${platform3}-${arch}`);
95586
- if (existsSync26(bundledMtm))
95587
- return { path: bundledMtm, kind: "mtm" };
95588
- try {
95589
- const result = execSync3("which mtm", { encoding: "utf-8" }).trim();
95590
- if (result && isMtmForkWithGrid(result))
95591
- return { path: result, kind: "mtm" };
95688
+ return result;
95592
95689
  } catch {}
95593
- throw new Error(`No terminal multiplexer found. Install magmux (recommended) or build mtm:
95594
- ` + ` brew install MadAppGang/tap/magmux
95595
- ` + " # or: cd packages/cli/native/mtm && make");
95596
- }
95597
- function isMtmForkWithGrid(binPath) {
95598
- try {
95599
- const output = execSync3(`"${binPath}" --help 2>&1 || true`, {
95600
- encoding: "utf-8",
95601
- timeout: 2000
95602
- });
95603
- return output.includes("-g ");
95604
- } catch {
95605
- return false;
95606
- }
95690
+ throw new Error(`magmux not found. Install it:
95691
+ brew install MadAppGang/tap/magmux`);
95607
95692
  }
95608
95693
  function renderGridStatusBar(counts) {
95609
95694
  const elapsed = formatElapsed(counts.elapsedMs);
@@ -95671,7 +95756,7 @@ function pollStatus(state) {
95671
95756
  else
95672
95757
  failed++;
95673
95758
  } else {
95674
- if (elapsedMs > timeoutMs) {
95759
+ if (!state.interactive && elapsedMs > timeoutMs) {
95675
95760
  const newState = {
95676
95761
  ...current,
95677
95762
  state: "TIMEOUT",
@@ -95696,7 +95781,7 @@ function pollStatus(state) {
95696
95781
  }
95697
95782
  }
95698
95783
  if (changed) {
95699
- writeFileSync14(statusPath, JSON.stringify(statusCache, null, 2), "utf-8");
95784
+ writeFileSync15(statusPath, JSON.stringify(statusCache, null, 2), "utf-8");
95700
95785
  }
95701
95786
  const total = anonIds.length;
95702
95787
  const allDone = done + failed >= total;
@@ -95717,8 +95802,9 @@ function pollStatus(state) {
95717
95802
  }
95718
95803
  async function runWithGrid(sessionPath, models, input, opts) {
95719
95804
  const timeoutMs = (opts?.timeout ?? 300) * 1000;
95805
+ const interactive = opts?.interactive ?? false;
95720
95806
  const manifest = setupSession(sessionPath, models, input);
95721
- mkdirSync13(join27(sessionPath, "errors"), { recursive: true });
95807
+ mkdirSync14(join27(sessionPath, "errors"), { recursive: true });
95722
95808
  for (const anonId of Object.keys(manifest.models)) {
95723
95809
  const stale = join27(sessionPath, "work", anonId, ".exit-code");
95724
95810
  try {
@@ -95732,6 +95818,9 @@ async function runWithGrid(sessionPath, models, input, opts) {
95732
95818
  const exitCodeFile = join27(sessionPath, "work", anonId, ".exit-code");
95733
95819
  const model = manifest.models[anonId].model;
95734
95820
  const paneIndex = Object.keys(manifest.models).indexOf(anonId);
95821
+ if (interactive) {
95822
+ return `claudish --model ${model} --dangerously-skip-permissions '${prompt}'`;
95823
+ }
95735
95824
  return [
95736
95825
  `claudish --model ${model} -y -v '${prompt}' 2>${errorLog};`,
95737
95826
  `_ec=$?; echo $_ec > ${exitCodeFile};`,
@@ -95747,10 +95836,10 @@ async function runWithGrid(sessionPath, models, input, opts) {
95747
95836
  `exec sleep 86400`
95748
95837
  ].join(" ");
95749
95838
  });
95750
- writeFileSync14(gridfilePath, gridLines.join(`
95839
+ writeFileSync15(gridfilePath, gridLines.join(`
95751
95840
  `) + `
95752
95841
  `, "utf-8");
95753
- const mux = findMultiplexerBinary();
95842
+ const magmuxPath = findMagmuxBinary();
95754
95843
  const statusbarPath = join27(sessionPath, "statusbar.txt");
95755
95844
  const statusPath = join27(sessionPath, "status.json");
95756
95845
  const statusCache = JSON.parse(readFileSync21(statusPath, "utf-8"));
@@ -95773,18 +95862,17 @@ async function runWithGrid(sessionPath, models, input, opts) {
95773
95862
  startTime,
95774
95863
  timeoutMs,
95775
95864
  statusbarPath,
95776
- completedAtMs: null
95865
+ completedAtMs: null,
95866
+ interactive
95777
95867
  };
95778
95868
  const pollInterval = setInterval(() => {
95779
95869
  pollStatus(pollState);
95780
95870
  }, 500);
95781
95871
  const spawnArgs = ["-g", gridfilePath, "-S", statusbarPath];
95782
- if (mux.kind === "mtm") {
95783
- spawnArgs.push("-t", "xterm-256color");
95784
- } else {
95872
+ if (!interactive) {
95785
95873
  spawnArgs.push("-w");
95786
95874
  }
95787
- const proc = spawn3(mux.path, spawnArgs, {
95875
+ const proc = spawn3(magmuxPath, spawnArgs, {
95788
95876
  stdio: "inherit",
95789
95877
  env: { ...process.env }
95790
95878
  });
@@ -95844,7 +95932,7 @@ Options (run / run-and-judge):
95844
95932
  --models <a,b,...> Comma-separated model IDs to run
95845
95933
  --input <text> Task prompt (or create input.md in --path beforehand)
95846
95934
  --timeout <secs> Timeout per model in seconds (default: 300)
95847
- --grid Show all models in an mtm grid with live output + status bar
95935
+ --grid Show all models in a magmux grid with live output + status bar
95848
95936
 
95849
95937
  Options (judge / run-and-judge):
95850
95938
  --judges <a,b,...> Comma-separated judge model IDs (default: same as runners)
@@ -95861,11 +95949,13 @@ Examples:
95861
95949
  `);
95862
95950
  }
95863
95951
  async function teamCommand(args) {
95864
- const subcommand = args[0];
95865
- if (!subcommand || hasFlag(args, "--help") || hasFlag(args, "-h")) {
95952
+ if (hasFlag(args, "--help") || hasFlag(args, "-h")) {
95866
95953
  printHelp2();
95867
95954
  process.exit(0);
95868
95955
  }
95956
+ const firstArg = args[0] ?? "";
95957
+ const legacySubs = ["run", "judge", "run-and-judge", "status"];
95958
+ const subcommand = legacySubs.includes(firstArg) ? firstArg : "run";
95869
95959
  const rawSessionPath = getFlag(args, "--path") ?? ".";
95870
95960
  let sessionPath;
95871
95961
  try {
@@ -95876,22 +95966,36 @@ async function teamCommand(args) {
95876
95966
  }
95877
95967
  const modelsRaw = getFlag(args, "--models");
95878
95968
  const judgesRaw = getFlag(args, "--judges");
95879
- const input = getFlag(args, "--input");
95969
+ const mode = getFlag(args, "--mode") ?? "default";
95880
95970
  const timeoutStr = getFlag(args, "--timeout");
95881
95971
  const timeout = timeoutStr ? parseInt(timeoutStr, 10) : 300;
95972
+ let input = getFlag(args, "--input");
95973
+ if (!input) {
95974
+ const flagsWithValues = ["--models", "--judges", "--mode", "--path", "--timeout", "--input"];
95975
+ const positionals = args.filter((a, i) => {
95976
+ if (legacySubs.includes(a) && i === 0)
95977
+ return false;
95978
+ if (a.startsWith("--"))
95979
+ return false;
95980
+ const prev = args[i - 1];
95981
+ if (prev && flagsWithValues.includes(prev))
95982
+ return false;
95983
+ return true;
95984
+ });
95985
+ if (positionals.length > 0)
95986
+ input = positionals.join(" ");
95987
+ }
95882
95988
  const models = modelsRaw ? modelsRaw.split(",").map((m2) => m2.trim()).filter(Boolean) : [];
95883
95989
  const judges = judgesRaw ? judgesRaw.split(",").map((m2) => m2.trim()).filter(Boolean) : undefined;
95990
+ const effectiveMode = hasFlag(args, "--interactive") ? "interactive" : hasFlag(args, "--grid") ? "default" : mode;
95884
95991
  switch (subcommand) {
95885
95992
  case "run": {
95886
95993
  if (models.length === 0) {
95887
- console.error("Error: --models is required for 'run'");
95994
+ console.error("Error: --models is required");
95995
+ printHelp2();
95888
95996
  process.exit(1);
95889
95997
  }
95890
- if (hasFlag(args, "--grid")) {
95891
- const { runWithGrid: runWithGrid2 } = await Promise.resolve().then(() => (init_team_grid(), exports_team_grid));
95892
- const gridStatus = await runWithGrid2(sessionPath, models, input ?? "", { timeout });
95893
- printStatus(gridStatus);
95894
- } else {
95998
+ if (effectiveMode === "json") {
95895
95999
  setupSession(sessionPath, models, input);
95896
96000
  const runStatus = await runModels(sessionPath, {
95897
96001
  timeout,
@@ -95901,17 +96005,22 @@ async function teamCommand(args) {
95901
96005
  }
95902
96006
  });
95903
96007
  printStatus(runStatus);
96008
+ } else {
96009
+ const { runWithGrid: runWithGrid2 } = await Promise.resolve().then(() => (init_team_grid(), exports_team_grid));
96010
+ const interactive = effectiveMode === "interactive";
96011
+ const gridStatus = await runWithGrid2(sessionPath, models, input ?? "", { timeout, interactive });
96012
+ printStatus(gridStatus);
95904
96013
  }
95905
96014
  break;
95906
96015
  }
95907
96016
  case "judge": {
95908
- const verdict = await judgeResponses(sessionPath, { judges });
96017
+ await judgeResponses(sessionPath, { judges });
95909
96018
  console.log(readFileSync22(join28(sessionPath, "verdict.md"), "utf-8"));
95910
96019
  break;
95911
96020
  }
95912
96021
  case "run-and-judge": {
95913
96022
  if (models.length === 0) {
95914
- console.error("Error: --models is required for 'run-and-judge'");
96023
+ console.error("Error: --models is required");
95915
96024
  process.exit(1);
95916
96025
  }
95917
96026
  setupSession(sessionPath, models, input);
@@ -95928,15 +96037,10 @@ async function teamCommand(args) {
95928
96037
  break;
95929
96038
  }
95930
96039
  case "status": {
95931
- const status = getStatus(sessionPath);
95932
- printStatus(status);
96040
+ const statusResult = getStatus(sessionPath);
96041
+ printStatus(statusResult);
95933
96042
  break;
95934
96043
  }
95935
- default: {
95936
- console.error(`Unknown team subcommand: ${subcommand}`);
95937
- printHelp2();
95938
- process.exit(1);
95939
- }
95940
96044
  }
95941
96045
  }
95942
96046
  var init_team_cli = __esm(() => {
@@ -95950,7 +96054,7 @@ __export(exports_claude_runner, {
95950
96054
  checkClaudeInstalled: () => checkClaudeInstalled
95951
96055
  });
95952
96056
  import { spawn as spawn4 } from "child_process";
95953
- import { writeFileSync as writeFileSync15, unlinkSync as unlinkSync9, mkdirSync as mkdirSync14, existsSync as existsSync28, readFileSync as readFileSync23 } from "fs";
96057
+ import { writeFileSync as writeFileSync16, unlinkSync as unlinkSync9, mkdirSync as mkdirSync15, existsSync as existsSync28, readFileSync as readFileSync23 } from "fs";
95954
96058
  import { tmpdir as tmpdir2, homedir as homedir25 } from "os";
95955
96059
  import { join as join29 } from "path";
95956
96060
  function hasNativeAnthropicMapping(config3) {
@@ -96059,14 +96163,14 @@ process.stdin.on('end', () => {
96059
96163
  }
96060
96164
  });
96061
96165
  `;
96062
- writeFileSync15(scriptPath, script, "utf-8");
96166
+ writeFileSync16(scriptPath, script, "utf-8");
96063
96167
  return scriptPath;
96064
96168
  }
96065
96169
  function createTempSettingsFile(modelDisplay, port) {
96066
96170
  const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
96067
96171
  const claudishDir = join29(homeDir, ".claudish");
96068
96172
  try {
96069
- mkdirSync14(claudishDir, { recursive: true });
96173
+ mkdirSync15(claudishDir, { recursive: true });
96070
96174
  } catch {}
96071
96175
  const timestamp = Date.now();
96072
96176
  const tempPath = join29(claudishDir, `settings-${timestamp}.json`);
@@ -96092,7 +96196,7 @@ function createTempSettingsFile(modelDisplay, port) {
96092
96196
  padding: 0
96093
96197
  };
96094
96198
  const settings = { statusLine };
96095
- writeFileSync15(tempPath, JSON.stringify(settings, null, 2), "utf-8");
96199
+ writeFileSync16(tempPath, JSON.stringify(settings, null, 2), "utf-8");
96096
96200
  return { path: tempPath, statusLine };
96097
96201
  }
96098
96202
  function mergeUserSettingsIfPresent(config3, tempSettingsPath, statusLine) {
@@ -96110,7 +96214,7 @@ function mergeUserSettingsIfPresent(config3, tempSettingsPath, statusLine) {
96110
96214
  userSettings = JSON.parse(rawUserSettings);
96111
96215
  }
96112
96216
  userSettings.statusLine = statusLine;
96113
- writeFileSync15(tempSettingsPath, JSON.stringify(userSettings, null, 2), "utf-8");
96217
+ writeFileSync16(tempSettingsPath, JSON.stringify(userSettings, null, 2), "utf-8");
96114
96218
  } catch {
96115
96219
  if (!config3.quiet) {
96116
96220
  console.warn(`[claudish] Warning: could not merge user settings: ${userSettingsValue}`);
@@ -96118,7 +96222,7 @@ function mergeUserSettingsIfPresent(config3, tempSettingsPath, statusLine) {
96118
96222
  }
96119
96223
  config3.claudeArgs.splice(idx, 2);
96120
96224
  }
96121
- async function runClaudeWithProxy(config3, proxyUrl, onCleanup, ptyDiagRunner) {
96225
+ async function runClaudeWithProxy(config3, proxyUrl, onCleanup) {
96122
96226
  const hasProfileMappings = config3.modelOpus || config3.modelSonnet || config3.modelHaiku || config3.modelSubagent;
96123
96227
  const modelId = config3.model || (hasProfileMappings || config3.monitor ? undefined : "unknown");
96124
96228
  const portMatch = proxyUrl.match(/:(\d+)/);
@@ -96205,28 +96309,20 @@ Or set CLAUDE_PATH to your custom installation:`);
96205
96309
  }
96206
96310
  const needsShell = isWindows2() && claudeBinary.endsWith(".cmd");
96207
96311
  const spawnCommand = needsShell ? `"${claudeBinary}"` : claudeBinary;
96208
- let exitCode;
96209
- if (config3.interactive && ptyDiagRunner) {
96210
- exitCode = await ptyDiagRunner.run(spawnCommand, claudeArgs, env2);
96211
- try {
96212
- unlinkSync9(tempSettingsPath);
96213
- } catch {}
96214
- } else {
96215
- const proc = spawn4(spawnCommand, claudeArgs, {
96216
- env: env2,
96217
- stdio: "inherit",
96218
- shell: needsShell
96219
- });
96220
- setupSignalHandlers(proc, tempSettingsPath, config3.quiet, onCleanup);
96221
- exitCode = await new Promise((resolve4) => {
96222
- proc.on("exit", (code) => {
96223
- resolve4(code ?? 1);
96224
- });
96312
+ const proc = spawn4(spawnCommand, claudeArgs, {
96313
+ env: env2,
96314
+ stdio: "inherit",
96315
+ shell: needsShell
96316
+ });
96317
+ setupSignalHandlers(proc, tempSettingsPath, config3.quiet, onCleanup);
96318
+ const exitCode = await new Promise((resolve4) => {
96319
+ proc.on("exit", (code) => {
96320
+ resolve4(code ?? 1);
96225
96321
  });
96226
- try {
96227
- unlinkSync9(tempSettingsPath);
96228
- } catch {}
96229
- }
96322
+ });
96323
+ try {
96324
+ unlinkSync9(tempSettingsPath);
96325
+ } catch {}
96230
96326
  return exitCode;
96231
96327
  }
96232
96328
  function setupSignalHandlers(proc, tempSettingsPath, quiet, onCleanup) {
@@ -96330,20 +96426,16 @@ var init_claude_runner = __esm(() => {
96330
96426
  var exports_diag_output = {};
96331
96427
  __export(exports_diag_output, {
96332
96428
  createDiagOutput: () => createDiagOutput,
96333
- TmuxDiagOutput: () => TmuxDiagOutput,
96334
- OpentUiDiagOutput: () => OpentUiDiagOutput,
96335
96429
  NullDiagOutput: () => NullDiagOutput,
96336
- MtmDiagOutput: () => MtmDiagOutput,
96337
96430
  LogFileDiagOutput: () => LogFileDiagOutput
96338
96431
  });
96339
- import { createWriteStream as createWriteStream3, mkdirSync as mkdirSync15, writeFileSync as writeFileSync16, unlinkSync as unlinkSync10 } from "fs";
96340
- import { execFileSync } from "child_process";
96432
+ import { createWriteStream as createWriteStream3, mkdirSync as mkdirSync16, writeFileSync as writeFileSync17, unlinkSync as unlinkSync10 } from "fs";
96341
96433
  import { homedir as homedir26 } from "os";
96342
96434
  import { join as join30 } from "path";
96343
96435
  function getClaudishDir() {
96344
96436
  const dir = join30(homedir26(), ".claudish");
96345
96437
  try {
96346
- mkdirSync15(dir, { recursive: true });
96438
+ mkdirSync16(dir, { recursive: true });
96347
96439
  } catch {}
96348
96440
  return dir;
96349
96441
  }
@@ -96357,7 +96449,7 @@ class LogFileDiagOutput {
96357
96449
  constructor() {
96358
96450
  this.logPath = getDiagLogPath();
96359
96451
  try {
96360
- writeFileSync16(this.logPath, `--- claudish diag session ${new Date().toISOString()} ---
96452
+ writeFileSync17(this.logPath, `--- claudish diag session ${new Date().toISOString()} ---
96361
96453
  `);
96362
96454
  } catch {}
96363
96455
  this.stream = createWriteStream3(this.logPath, { flags: "a" });
@@ -96384,30 +96476,6 @@ class LogFileDiagOutput {
96384
96476
  }
96385
96477
  }
96386
96478
 
96387
- class MtmDiagOutput {
96388
- runner;
96389
- constructor(runner) {
96390
- this.runner = runner;
96391
- }
96392
- write(msg) {
96393
- this.runner.write(msg);
96394
- }
96395
- cleanup() {}
96396
- }
96397
-
96398
- class OpentUiDiagOutput {
96399
- inner;
96400
- constructor(runner) {
96401
- this.inner = new MtmDiagOutput(runner);
96402
- }
96403
- write(msg) {
96404
- this.inner.write(msg);
96405
- }
96406
- cleanup() {
96407
- this.inner.cleanup();
96408
- }
96409
- }
96410
-
96411
96479
  class NullDiagOutput {
96412
96480
  write(_msg) {}
96413
96481
  cleanup() {}
@@ -96420,389 +96488,22 @@ function createDiagOutput(options) {
96420
96488
  if (mode === "off") {
96421
96489
  return new NullDiagOutput;
96422
96490
  }
96423
- const mtmRunner = options.mtmRunner ?? options.ptyRunner ?? null;
96424
- if (mode === "pty" || mode === "auto") {
96425
- if (mtmRunner) {
96426
- return new MtmDiagOutput(mtmRunner);
96427
- }
96428
- if (mode === "pty") {
96429
- return new LogFileDiagOutput;
96430
- }
96431
- }
96432
- if (mode === "tmux" || mode === "auto") {
96433
- if (process.env.TMUX) {
96434
- return new TmuxDiagOutput;
96435
- }
96436
- if (mode === "tmux") {
96437
- return new LogFileDiagOutput;
96438
- }
96439
- }
96440
96491
  return new LogFileDiagOutput;
96441
96492
  }
96442
- var TmuxDiagOutput;
96443
- var init_diag_output = __esm(() => {
96444
- TmuxDiagOutput = class TmuxDiagOutput extends LogFileDiagOutput {
96445
- paneId = null;
96446
- constructor() {
96447
- super();
96448
- this.openTmuxPane();
96449
- }
96450
- openTmuxPane() {
96451
- try {
96452
- const targetPane = process.env.TMUX_PANE || "";
96453
- const args = ["split-window", "-v", "-l", "5", "-d", "-P", "-F", "#{pane_id}"];
96454
- if (targetPane) {
96455
- args.push("-t", targetPane);
96456
- }
96457
- args.push("tail", "-f", this.logPath);
96458
- const output = execFileSync("tmux", args, {
96459
- encoding: "utf-8",
96460
- stdio: ["pipe", "pipe", "pipe"]
96461
- });
96462
- this.paneId = output.trim();
96463
- } catch {
96464
- this.paneId = null;
96465
- }
96466
- }
96467
- cleanup() {
96468
- if (this.paneId) {
96469
- try {
96470
- execFileSync("tmux", ["kill-pane", "-t", this.paneId], {
96471
- stdio: ["pipe", "pipe", "pipe"]
96472
- });
96473
- } catch {}
96474
- this.paneId = null;
96475
- }
96476
- super.cleanup();
96477
- }
96478
- };
96479
- });
96480
-
96481
- // src/pty-diag-runner.ts
96482
- var exports_pty_diag_runner = {};
96483
- __export(exports_pty_diag_runner, {
96484
- tryCreatePtyRunner: () => tryCreatePtyRunner,
96485
- tryCreateMtmRunner: () => tryCreateMtmRunner,
96486
- PtyDiagRunner: () => MtmDiagRunner,
96487
- MtmDiagRunner: () => MtmDiagRunner
96488
- });
96489
- import { spawn as spawn5 } from "child_process";
96490
- import {
96491
- appendFileSync as appendFileSync2,
96492
- createWriteStream as createWriteStream4,
96493
- existsSync as existsSync29,
96494
- mkdirSync as mkdirSync16,
96495
- readFileSync as readFileSync24,
96496
- unlinkSync as unlinkSync11
96497
- } from "fs";
96498
- import { homedir as homedir27 } from "os";
96499
- import { dirname as dirname7, join as join31 } from "path";
96500
- import { execSync as execSync4 } from "child_process";
96501
- import { fileURLToPath as fileURLToPath7 } from "url";
96502
-
96503
- class MtmDiagRunner {
96504
- mtmProc = null;
96505
- logPath;
96506
- statusPath;
96507
- logStream = null;
96508
- constructor() {
96509
- const dir = join31(homedir27(), ".claudish");
96510
- try {
96511
- mkdirSync16(dir, { recursive: true });
96512
- } catch {}
96513
- this.logPath = join31(dir, `diag-${process.pid}.log`);
96514
- this.statusPath = join31(dir, `status-${process.pid}.txt`);
96515
- this.logStream = createWriteStream4(this.logPath, { flags: "w" });
96516
- this.logStream.on("error", () => {});
96517
- }
96518
- async run(claudeCommand, claudeArgs, env2) {
96519
- const mtmBin = this.findMtmBinary();
96520
- const quotedArgs = claudeArgs.map((a) => shellQuote(a)).join(" ");
96521
- const claudeCmd = `${shellQuote(claudeCommand)} ${quotedArgs}`;
96522
- const mergedEnv = { ...process.env, ...env2 };
96523
- this.mtmProc = spawn5(mtmBin, ["-t", "xterm-256color", "-e", claudeCmd, "-S", this.statusPath, "-L", this.logPath], {
96524
- stdio: "inherit",
96525
- env: mergedEnv
96526
- });
96527
- const exitCode = await new Promise((resolve4) => {
96528
- this.mtmProc.on("exit", (code) => {
96529
- resolve4(code ?? 1);
96530
- });
96531
- this.mtmProc.on("error", (err) => {
96532
- if (this.logStream) {
96533
- try {
96534
- this.logStream.write(`[mtm] spawn error: ${err.message}
96535
- `);
96536
- } catch {}
96537
- }
96538
- resolve4(1);
96539
- });
96540
- });
96541
- this.cleanup();
96542
- return exitCode;
96543
- }
96544
- write(msg) {
96545
- if (!this.logStream)
96546
- return;
96547
- const timestamp = new Date().toISOString();
96548
- try {
96549
- this.logStream.write(`[${timestamp}] ${msg}
96550
- `);
96551
- } catch {}
96552
- const parsed = parseLogMessage(msg);
96553
- if (parsed.isError) {
96554
- this.errorCount++;
96555
- this.lastError = parsed.short;
96556
- if (parsed.provider)
96557
- this.provider = parsed.provider;
96558
- }
96559
- if (msg.includes("HANDLER STARTED") || msg.includes("=== Request")) {
96560
- this.requestCount++;
96561
- }
96562
- const rtMatch = msg.match(/(\d+)ms\b/);
96563
- if (rtMatch && msg.includes("Response")) {
96564
- const ms = parseInt(rtMatch[1], 10);
96565
- this.roundtripSamples.push(ms);
96566
- if (this.roundtripSamples.length > 20)
96567
- this.roundtripSamples.shift();
96568
- this.avgRoundtripMs = Math.round(this.roundtripSamples.reduce((a, b2) => a + b2, 0) / this.roundtripSamples.length);
96569
- }
96570
- if (msg.includes("Format:") || msg.includes("Transport:") || msg.includes("Translator:")) {
96571
- const parts = msg.split(":").slice(1).join(":").trim();
96572
- if (parts)
96573
- this.adapters = parts;
96574
- }
96575
- if (msg.includes("Auth refreshed") && msg.includes("tier:")) {
96576
- const tierMatch = msg.match(/tier:\s*(.+)$/);
96577
- if (tierMatch)
96578
- this.provider = tierMatch[1].trim();
96579
- }
96580
- if (msg.includes("[Fallback]") && msg.includes("succeeded")) {
96581
- const fbMatch = msg.match(/\[Fallback\]\s+(\S+)\s+succeeded/);
96582
- if (fbMatch)
96583
- this.provider = fbMatch[1];
96584
- }
96585
- if (msg.includes("Rate limited") && msg.includes("retrying")) {
96586
- this.lastError = msg.replace(/.*\]\s*/, "").substring(0, 60);
96587
- }
96588
- this.refreshStatusBar();
96589
- }
96590
- modelName = "";
96591
- provider = "";
96592
- port = "";
96593
- quotaRemaining;
96594
- tokenPollTimer = null;
96595
- lastError = "";
96596
- errorCount = 0;
96597
- requestCount = 0;
96598
- totalCost = 0;
96599
- avgRoundtripMs = 0;
96600
- roundtripSamples = [];
96601
- adapters = "";
96602
- setPort(port) {
96603
- this.port = String(port);
96604
- this.tokenPollTimer = setInterval(() => {
96605
- const changed = this.readTokenFile();
96606
- if (changed)
96607
- this.refreshStatusBar();
96608
- }, 3000);
96609
- }
96610
- setModel(name) {
96611
- this.modelName = name.includes("/") ? name.split("/").pop() : name;
96612
- if (name.includes("@")) {
96613
- this.provider = name.split("@")[0];
96614
- } else if (name.includes("/")) {
96615
- this.provider = name.split("/")[0];
96616
- }
96617
- }
96618
- readTokenFile() {
96619
- if (!this.port)
96620
- return false;
96621
- try {
96622
- const tokPath = join31(homedir27(), ".claudish", `tokens-${this.port}.json`);
96623
- const tok = JSON.parse(readFileSync24(tokPath, "utf-8"));
96624
- let changed = false;
96625
- if (typeof tok.quota_remaining === "number" && tok.quota_remaining !== this.quotaRemaining) {
96626
- this.quotaRemaining = tok.quota_remaining;
96627
- changed = true;
96628
- }
96629
- if (tok.provider_name && tok.provider_name !== this.provider) {
96630
- this.provider = tok.provider_name;
96631
- changed = true;
96632
- }
96633
- return changed;
96634
- } catch {
96635
- return false;
96636
- }
96637
- }
96638
- refreshStatusBar() {
96639
- this.readTokenFile();
96640
- const bar = renderStatusBar({
96641
- model: this.modelName,
96642
- provider: this.provider,
96643
- errorCount: this.errorCount,
96644
- lastError: this.lastError,
96645
- requestCount: this.requestCount,
96646
- avgRoundtripMs: this.avgRoundtripMs,
96647
- quotaRemaining: this.quotaRemaining
96648
- });
96649
- try {
96650
- appendFileSync2(this.statusPath, bar + `
96651
- `);
96652
- } catch {}
96653
- }
96654
- getLogPath() {
96655
- return this.logPath;
96656
- }
96657
- cleanup() {
96658
- if (this.tokenPollTimer) {
96659
- clearInterval(this.tokenPollTimer);
96660
- this.tokenPollTimer = null;
96661
- }
96662
- if (this.logStream) {
96663
- try {
96664
- this.logStream.end();
96665
- } catch {}
96666
- this.logStream = null;
96667
- }
96668
- try {
96669
- unlinkSync11(this.logPath);
96670
- } catch {}
96671
- try {
96672
- unlinkSync11(this.statusPath);
96673
- } catch {}
96674
- if (this.mtmProc) {
96675
- try {
96676
- this.mtmProc.kill();
96677
- } catch {}
96678
- this.mtmProc = null;
96679
- }
96680
- }
96681
- findMtmBinary() {
96682
- const thisFile = fileURLToPath7(import.meta.url);
96683
- const thisDir = dirname7(thisFile);
96684
- const platform3 = process.platform;
96685
- const arch = process.arch;
96686
- const pkgRoot = join31(thisDir, "..");
96687
- const bundledPlatform = join31(pkgRoot, "native", "mtm", `mtm-${platform3}-${arch}`);
96688
- if (existsSync29(bundledPlatform))
96689
- return bundledPlatform;
96690
- const builtDev = join31(pkgRoot, "native", "mtm", "mtm");
96691
- if (existsSync29(builtDev))
96692
- return builtDev;
96693
- try {
96694
- const result = execSync4("which mtm", { encoding: "utf-8" }).trim();
96695
- if (result && this.isMtmFork(result))
96696
- return result;
96697
- } catch {}
96698
- throw new Error("mtm binary not found. Build it with: cd packages/cli/native/mtm && make");
96699
- }
96700
- isMtmFork(binPath) {
96701
- try {
96702
- const output = execSync4(`"${binPath}" --help 2>&1 || true`, {
96703
- encoding: "utf-8",
96704
- timeout: 2000
96705
- });
96706
- return output.includes("-e ");
96707
- } catch {
96708
- return false;
96709
- }
96710
- }
96711
- }
96712
- function shellQuote(s) {
96713
- return "'" + s.replace(/'/g, "'\\''") + "'";
96714
- }
96715
- function renderStatusBar(state) {
96716
- const { model, provider, errorCount, lastError, quotaRemaining } = state;
96717
- const parts = [];
96718
- parts.push("M: claudish ");
96719
- if (model)
96720
- parts.push(`C: ${model} `);
96721
- if (provider)
96722
- parts.push(`D: ${provider}`);
96723
- if (errorCount > 0) {
96724
- const errLabel = errorCount === 1 ? "\u26A0 1 error" : `\u26A0 ${errorCount} errors`;
96725
- parts.push(`R: ${errLabel} `);
96726
- if (lastError)
96727
- parts.push(`D: ${lastError}`);
96728
- }
96729
- if (typeof quotaRemaining === "number") {
96730
- const usedPct = Math.round((1 - quotaRemaining) * 100);
96731
- const barWidth = 8;
96732
- const usedCols = Math.max(usedPct > 0 ? 1 : 0, Math.round(usedPct / 100 * barWidth));
96733
- const freeCols = barWidth - usedCols;
96734
- const bar = "\u2588".repeat(usedCols) + "\u2591".repeat(freeCols);
96735
- const color = usedPct < 50 ? "g" : usedPct < 80 ? "y" : "r";
96736
- parts.push(`${color}: ${bar} ${usedPct}%`);
96737
- }
96738
- return parts.join("\t");
96739
- }
96740
- function parseLogMessage(msg) {
96741
- const providerMatch = msg.match(/\[(?!Fallback|Streaming|Auto-route|SSE)([^\]]+)\]/);
96742
- const provider = providerMatch?.[1];
96743
- if (msg.includes("All") && msg.includes("failed")) {
96744
- const countMatch = msg.match(/All (\d+)/);
96745
- return { isError: true, short: `all ${countMatch?.[1] || ""} providers failed`, provider };
96746
- }
96747
- if (msg.includes("[Fallback]")) {
96748
- if (msg.includes("succeeded")) {
96749
- const n = msg.match(/after (\d+)/)?.[1] || "?";
96750
- return { isError: false, short: `succeeded after ${n} retries`, provider };
96751
- }
96752
- const failMatch = msg.match(/\]\s*(.+?)\s+failed/);
96753
- return {
96754
- isError: false,
96755
- short: failMatch ? `${failMatch[1]} failed, retrying` : "fallback",
96756
- provider
96757
- };
96758
- }
96759
- const httpMatch = msg.match(/HTTP (\d{3})/);
96760
- if (httpMatch) {
96761
- const jsonMatch = msg.match(/"message"\s*:\s*"([^"]+)"/);
96762
- if (jsonMatch?.[1]) {
96763
- const detail = jsonMatch[1].replace(/is not a valid model ID/, "invalid model").replace(/Provider returned error/, "provider error");
96764
- return { isError: true, short: detail, provider };
96765
- }
96766
- const hintMatch = msg.match(/HTTP \d{3}\.\s*(.+?)\.?\s*$/);
96767
- if (hintMatch?.[1]) {
96768
- return { isError: true, short: hintMatch[1], provider };
96769
- }
96770
- return { isError: true, short: `HTTP ${httpMatch[1]}`, provider };
96771
- }
96772
- if (msg.toLowerCase().includes("error")) {
96773
- const short = msg.replace(/^Error\s*\[[^\]]+\]:\s*/, "").replace(/\.\s*$/, "");
96774
- return { isError: true, short: short.length > 80 ? short.slice(0, 79) + "\u2026" : short, provider };
96775
- }
96776
- return { isError: false, short: msg.length > 80 ? msg.slice(0, 79) + "\u2026" : msg };
96777
- }
96778
- async function tryCreateMtmRunner() {
96779
- if (process.env.MTM)
96780
- return null;
96781
- try {
96782
- const runner = new MtmDiagRunner;
96783
- runner.findMtmBinary();
96784
- return runner;
96785
- } catch {
96786
- return null;
96787
- }
96788
- }
96789
- var tryCreatePtyRunner;
96790
- var init_pty_diag_runner = __esm(() => {
96791
- tryCreatePtyRunner = tryCreateMtmRunner;
96792
- });
96493
+ var init_diag_output = () => {};
96793
96494
 
96794
96495
  // src/index.ts
96795
96496
  var import_dotenv3 = __toESM(require_main(), 1);
96796
- import { existsSync as existsSync30, readFileSync as readFileSync25 } from "fs";
96797
- import { homedir as homedir28 } from "os";
96798
- import { join as join32 } from "path";
96497
+ import { existsSync as existsSync29, readFileSync as readFileSync24 } from "fs";
96498
+ import { homedir as homedir27 } from "os";
96499
+ import { join as join31 } from "path";
96799
96500
  import_dotenv3.config({ quiet: true });
96800
96501
  function loadStoredApiKeys() {
96801
96502
  try {
96802
- const configPath = join32(homedir28(), ".claudish", "config.json");
96803
- if (!existsSync30(configPath))
96503
+ const configPath = join31(homedir27(), ".claudish", "config.json");
96504
+ if (!existsSync29(configPath))
96804
96505
  return;
96805
- const raw2 = readFileSync25(configPath, "utf-8");
96506
+ const raw2 = readFileSync24(configPath, "utf-8");
96806
96507
  const cfg = JSON.parse(raw2);
96807
96508
  if (cfg.apiKeys) {
96808
96509
  for (const [envVar, value] of Object.entries(cfg.apiKeys)) {
@@ -96903,8 +96604,7 @@ async function runCli() {
96903
96604
  getMissingKeysError: getMissingKeysError2
96904
96605
  } = await Promise.resolve().then(() => (init_provider_resolver(), exports_provider_resolver));
96905
96606
  const { initLogger: initLogger2, getLogFilePath: getLogFilePath2, getAlwaysOnLogPath: getAlwaysOnLogPath2, setDiagOutput: setDiagOutput2 } = await Promise.resolve().then(() => (init_logger(), exports_logger));
96906
- const { createDiagOutput: createDiagOutput2, LogFileDiagOutput: LogFileDiagOutput2 } = await Promise.resolve().then(() => (init_diag_output(), exports_diag_output));
96907
- const { tryCreateMtmRunner: tryCreateMtmRunner2 } = await Promise.resolve().then(() => (init_pty_diag_runner(), exports_pty_diag_runner));
96607
+ const { createDiagOutput: createDiagOutput2 } = await Promise.resolve().then(() => (init_diag_output(), exports_diag_output));
96908
96608
  const { findAvailablePort: findAvailablePort2 } = await Promise.resolve().then(() => (init_port_manager(), exports_port_manager));
96909
96609
  const { createProxyServer: createProxyServer2 } = await Promise.resolve().then(() => (init_proxy_server(), exports_proxy_server));
96910
96610
  const { checkForUpdates: checkForUpdates2 } = await Promise.resolve().then(() => (init_update_checker(), exports_update_checker));
@@ -97059,27 +96759,16 @@ async function runCli() {
97059
96759
  quiet: cliConfig.quiet,
97060
96760
  isInteractive: cliConfig.interactive
97061
96761
  });
97062
- const needsMtm = cliConfig.interactive && (cliConfig.diagMode === "auto" || cliConfig.diagMode === "pty");
97063
- const mtmRunner = needsMtm ? await tryCreateMtmRunner2() : null;
97064
- if (mtmRunner) {
97065
- if (explicitModel)
97066
- mtmRunner.setModel(explicitModel);
97067
- mtmRunner.setPort(port);
97068
- }
97069
96762
  const diag = createDiagOutput2({
97070
96763
  interactive: cliConfig.interactive,
97071
- mtmRunner,
97072
96764
  diagMode: cliConfig.diagMode
97073
96765
  });
97074
96766
  if (cliConfig.interactive) {
97075
96767
  setDiagOutput2(diag);
97076
- if (!mtmRunner && !process.env.TMUX && !cliConfig.quiet && diag instanceof LogFileDiagOutput2) {
97077
- console.log(`[claudish] Diagnostic log: ${diag.getLogPath()}`);
97078
- }
97079
96768
  }
97080
96769
  let exitCode = 0;
97081
96770
  try {
97082
- exitCode = await runClaudeWithProxy2(cliConfig, proxy.url, () => diag.cleanup(), mtmRunner);
96771
+ exitCode = await runClaudeWithProxy2(cliConfig, proxy.url, () => diag.cleanup());
97083
96772
  } finally {
97084
96773
  setDiagOutput2(null);
97085
96774
  diag.cleanup();