claudish 7.20.1 → 7.21.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 +325 -159
  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.20.1";
654
+ var VERSION = "7.21.0";
655
655
 
656
656
  // src/logger.ts
657
657
  var exports_logger = {};
@@ -3654,7 +3654,10 @@ var require_sdk = __commonJS((exports) => {
3654
3654
  var exports_onepassword = {};
3655
3655
  __export(exports_onepassword, {
3656
3656
  withSdkRetry: () => withSdkRetry,
3657
+ wasOpAuthorizationDenied: () => wasOpAuthorizationDenied,
3657
3658
  valueTail: () => valueTail,
3659
+ setScreenLockProbe: () => setScreenLockProbe,
3660
+ setLockRetryTiming: () => setLockRetryTiming,
3658
3661
  resolveSecretsPartial: () => resolveSecretsPartial,
3659
3662
  resolveSecrets: () => resolveSecrets,
3660
3663
  resolveSdkAuth: () => resolveSdkAuth,
@@ -3663,7 +3666,10 @@ __export(exports_onepassword, {
3663
3666
  resolveGlobImport: () => resolveGlobImport,
3664
3667
  resolveDesktopAccount: () => resolveDesktopAccount,
3665
3668
  resetSdkClientCache: () => resetSdkClientCache,
3669
+ resetOpFailures: () => resetOpFailures,
3670
+ renderOpFailureNotice: () => renderOpFailureNotice,
3666
3671
  recordOpHydratedVars: () => recordOpHydratedVars,
3672
+ recordOpFailure: () => recordOpFailure,
3667
3673
  readEnvironment: () => readEnvironment,
3668
3674
  parseOpFlag: () => parseOpFlag,
3669
3675
  parseGlobImport: () => parseGlobImport,
@@ -3671,16 +3677,20 @@ __export(exports_onepassword, {
3671
3677
  listVaults: () => listVaults,
3672
3678
  listItems: () => listItems,
3673
3679
  isTransientSdkError: () => isTransientSdkError,
3680
+ isScreenLocked: () => isScreenLocked,
3674
3681
  isOpReference: () => isOpReference,
3675
3682
  isOpHydratedVar: () => isOpHydratedVar,
3683
+ isLockedDenial: () => isLockedDenial,
3676
3684
  isGlobImport: () => isGlobImport,
3677
3685
  globToRegExp: () => globToRegExp,
3686
+ getOpFailures: () => getOpFailures,
3678
3687
  filterGlobFields: () => filterGlobFields,
3679
3688
  envNameFromOpRef: () => envNameFromOpRef,
3680
3689
  discoverItemFieldsById: () => discoverItemFieldsById,
3681
3690
  discoverItemFields: () => discoverItemFields,
3682
3691
  detectSdkAuth: () => detectSdkAuth,
3683
3692
  defaultSdkClientFactory: () => defaultSdkClientFactory,
3693
+ defaultScreenLockProbe: () => defaultScreenLockProbe,
3684
3694
  defaultOpAccountLister: () => defaultOpAccountLister,
3685
3695
  collectConfigImports: () => collectConfigImports,
3686
3696
  buildAuthError: () => buildAuthError,
@@ -3700,6 +3710,43 @@ function recordOpHydratedVars(names) {
3700
3710
  function isOpHydratedVar(name) {
3701
3711
  return !!name && opHydratedVars.has(name);
3702
3712
  }
3713
+ function recordOpFailure(failure) {
3714
+ const dup = opSourceFailures.some((f) => f.kind === failure.kind && f.source === failure.source && f.message === failure.message);
3715
+ if (!dup)
3716
+ opSourceFailures.push(failure);
3717
+ }
3718
+ function getOpFailures() {
3719
+ return opSourceFailures;
3720
+ }
3721
+ function resetOpFailures() {
3722
+ opSourceFailures.length = 0;
3723
+ }
3724
+ function wasOpAuthorizationDenied() {
3725
+ return opSourceFailures.some((f) => /denied authorization/i.test(f.message));
3726
+ }
3727
+ function renderOpFailureNotice(envVar) {
3728
+ if (opSourceFailures.length === 0)
3729
+ return [];
3730
+ const lines = [`1Password was consulted for ${envVar} this run and failed:`];
3731
+ for (const f of opSourceFailures) {
3732
+ const where = f.source ? `${f.kind} ${f.source}` : f.kind;
3733
+ lines.push(` ${where} \u2014 ${f.message.split(`
3734
+ `)[0]}`);
3735
+ }
3736
+ lines.push("");
3737
+ if (wasOpAuthorizationDenied()) {
3738
+ lines.push(" The 1Password desktop app declined to release secrets. This happens when");
3739
+ lines.push(" the approval prompt was dismissed, or when your Mac is locked and the");
3740
+ lines.push(" prompt cannot be shown at all.");
3741
+ lines.push("");
3742
+ lines.push(" Fix: unlock the Mac, approve the 1Password prompt, and re-run.");
3743
+ lines.push(" Headless (no desktop app): export OP_SERVICE_ACCOUNT_TOKEN='ops_...'");
3744
+ } else {
3745
+ lines.push(" Fix: check the reference resolves \u2014 claudish config \u2192 1Password tab.");
3746
+ lines.push(" Headless (no desktop app): export OP_SERVICE_ACCOUNT_TOKEN='ops_...'");
3747
+ }
3748
+ return lines;
3749
+ }
3703
3750
  function buildAuthError(detail) {
3704
3751
  return new Error(`${detail}
3705
3752
  Set OP_SERVICE_ACCOUNT_TOKEN (service account, headless) or OP_ACCOUNT (your 1Password account URL, e.g. my-team.1password.com) for the desktop app \u2014 or set \`onepasswordAccount\` in ~/.claudish/config.json.`);
@@ -4035,7 +4082,97 @@ function runSdkExclusive(op, label = "op:sdk-op", meta) {
4035
4082
  function sdkSleep(ms) {
4036
4083
  return new Promise((resolve) => setTimeout(resolve, ms));
4037
4084
  }
4085
+ function setLockRetryTiming(opts) {
4086
+ lockRetrySeconds = opts?.seconds ?? LOCK_RETRY_SECONDS;
4087
+ lockTickMs = opts?.tickMs ?? 1000;
4088
+ }
4089
+ function setScreenLockProbe(probe) {
4090
+ screenLockProbe = probe ?? defaultScreenLockProbe;
4091
+ }
4092
+ function isScreenLocked() {
4093
+ return screenLockProbe();
4094
+ }
4095
+ function isLockedDenial(err, env = process.env) {
4096
+ const msg = (err instanceof Error ? err.message : String(err)).toLowerCase();
4097
+ if (!msg.includes("denied authorization"))
4098
+ return false;
4099
+ if (env.OP_SERVICE_ACCOUNT_TOKEN)
4100
+ return false;
4101
+ return isScreenLocked();
4102
+ }
4103
+ async function countdownForUnlock(round, rounds) {
4104
+ const ttyOut = process.stderr.isTTY === true;
4105
+ const ttyIn = process.stdin.isTTY === true;
4106
+ let cancelled = false;
4107
+ if (round === 1) {
4108
+ process.stderr.write(`
4109
+ ${bold("\uD83D\uDD10 1Password needs your OK \u2014 but your Mac is locked, so it can't ask.")}
4110
+ Unlock your Mac and approve the popup. Claudish picks it up from there.
4111
+
4112
+ `);
4113
+ }
4114
+ let restoreInput = () => {};
4115
+ if (ttyIn) {
4116
+ const onKey = (buf) => {
4117
+ const k = buf.toString();
4118
+ if (k === "\x1B" || k === "q" || k === "\x03")
4119
+ cancelled = true;
4120
+ };
4121
+ const wasRaw = process.stdin.isRaw === true;
4122
+ try {
4123
+ process.stdin.setRawMode(true);
4124
+ process.stdin.resume();
4125
+ process.stdin.on("data", onKey);
4126
+ restoreInput = () => {
4127
+ process.stdin.off("data", onKey);
4128
+ process.stdin.setRawMode(wasRaw);
4129
+ process.stdin.pause();
4130
+ };
4131
+ } catch {
4132
+ restoreInput = () => {};
4133
+ }
4134
+ }
4135
+ const stop = ttyIn ? "Esc to stop waiting" : "Ctrl-C to stop waiting";
4136
+ const line = (secs) => dim(` waiting ${secs}s \xB7 try ${round} of ${rounds} \xB7 ${stop}`);
4137
+ if (!ttyOut)
4138
+ process.stderr.write(`${line(lockRetrySeconds)}
4139
+ `);
4140
+ try {
4141
+ for (let remaining = lockRetrySeconds;remaining > 0; remaining--) {
4142
+ if (cancelled)
4143
+ break;
4144
+ if (!isScreenLocked())
4145
+ break;
4146
+ if (ttyOut)
4147
+ process.stderr.write(`\r\x1B[2K${line(remaining)}`);
4148
+ await sdkSleep(lockTickMs);
4149
+ }
4150
+ } finally {
4151
+ restoreInput();
4152
+ if (ttyOut)
4153
+ process.stderr.write("\r\x1B[2K");
4154
+ }
4155
+ if (cancelled) {
4156
+ process.stderr.write(` OK, not waiting. You can unlock and re-run any time.
4157
+ `);
4158
+ return "cancel";
4159
+ }
4160
+ return "retry";
4161
+ }
4038
4162
  async function withSdkRetry(op, label = "op:sdk-op") {
4163
+ for (let round = 1;; round++) {
4164
+ try {
4165
+ return await withSdkTransientRetry(op, label);
4166
+ } catch (err) {
4167
+ if (round > LOCK_RETRY_ROUNDS || !isLockedDenial(err))
4168
+ throw err;
4169
+ if (await countdownForUnlock(round, LOCK_RETRY_ROUNDS) === "cancel")
4170
+ throw err;
4171
+ resetSdkClientCache();
4172
+ }
4173
+ }
4174
+ }
4175
+ async function withSdkTransientRetry(op, label) {
4039
4176
  const MAX_ATTEMPTS = 3;
4040
4177
  let lastErr;
4041
4178
  for (let attempt = 1;attempt <= MAX_ATTEMPTS; attempt++) {
@@ -4211,7 +4348,7 @@ async function readEnvironment(environmentId, opts = {}) {
4211
4348
  }
4212
4349
  return out;
4213
4350
  }
4214
- var OP_REF_RE, opHydratedVars, ENV_VAR_NAME_RE, sdkClientCache, defaultSdkClientFactory = async (auth) => {
4351
+ var OP_REF_RE, opHydratedVars, opSourceFailures, ENV_VAR_NAME_RE, sdkClientCache, defaultSdkClientFactory = async (auth) => {
4215
4352
  const key = sdkAuthCacheKey(auth);
4216
4353
  const cached = sdkClientCache.get(key);
4217
4354
  if (cached)
@@ -4232,7 +4369,21 @@ var OP_REF_RE, opHydratedVars, ENV_VAR_NAME_RE, sdkClientCache, defaultSdkClient
4232
4369
  sdkClientCache.set(key, build);
4233
4370
  build.catch(() => sdkClientCache.delete(key));
4234
4371
  return build;
4235
- }, sdkQueue, defaultOpAccountLister = () => {
4372
+ }, sdkQueue, LOCK_RETRY_ROUNDS = 3, LOCK_RETRY_SECONDS = 10, lockRetrySeconds, lockTickMs = 1000, styled = (code, s) => process.stderr.isTTY === true ? `\x1B[${code}m${s}\x1B[0m` : s, bold = (s) => styled("1", s), dim = (s) => styled("2", s), defaultScreenLockProbe = () => {
4373
+ if (process.platform !== "darwin")
4374
+ return false;
4375
+ try {
4376
+ const res = spawnSync("ioreg", ["-n", "Root", "-d1", "-a"], {
4377
+ encoding: "utf-8",
4378
+ timeout: 2000
4379
+ });
4380
+ if (res.status !== 0 || typeof res.stdout !== "string")
4381
+ return false;
4382
+ return /CGSSessionScreenIsLocked<\/key>\s*(?:<true\/>|<integer>1<\/integer>)/.test(res.stdout);
4383
+ } catch {
4384
+ return false;
4385
+ }
4386
+ }, screenLockProbe, defaultOpAccountLister = () => {
4236
4387
  try {
4237
4388
  const res = spawnSync("op", ["account", "list", "--format=json"], { encoding: "utf-8" });
4238
4389
  if (res.error || res.status !== 0)
@@ -4263,9 +4414,12 @@ var init_onepassword = __esm(() => {
4263
4414
  init_startup_trace();
4264
4415
  OP_REF_RE = /^op:\/\/[^\s]+$/;
4265
4416
  opHydratedVars = new Set;
4417
+ opSourceFailures = [];
4266
4418
  ENV_VAR_NAME_RE = /^[A-Z_][A-Z0-9_]*$/;
4267
4419
  sdkClientCache = new Map;
4268
4420
  sdkQueue = Promise.resolve();
4421
+ lockRetrySeconds = LOCK_RETRY_SECONDS;
4422
+ screenLockProbe = defaultScreenLockProbe;
4269
4423
  });
4270
4424
 
4271
4425
  // src/auth/credentials/op-source.ts
@@ -4571,12 +4725,14 @@ async function resolveOpKeyForEnvVarsInner(wanted, opts = {}, span) {
4571
4725
  } catch (err) {
4572
4726
  if (err instanceof OpAuthError && onAuthFailure === "skip") {
4573
4727
  console.error(`[claudish] 1Password auth unavailable, skipping op:// keys: ${err.message}`);
4728
+ const { recordOpFailure: recordOpFailure3 } = await Promise.resolve().then(() => (init_onepassword(), exports_onepassword));
4729
+ recordOpFailure3({ kind: "auth", message: err.message });
4574
4730
  return {};
4575
4731
  }
4576
4732
  throw err;
4577
4733
  }
4578
4734
  }
4579
- const { collectConfigImports: collectConfigImports2, resolveSecrets: resolveSecrets2, recordOpHydratedVars: recordOpHydratedVars2 } = await Promise.resolve().then(() => (init_onepassword(), exports_onepassword));
4735
+ const { collectConfigImports: collectConfigImports2, resolveSecrets: resolveSecrets2, recordOpHydratedVars: recordOpHydratedVars2, recordOpFailure: recordOpFailure2 } = await Promise.resolve().then(() => (init_onepassword(), exports_onepassword));
4580
4736
  const cfg = readConfigRaw();
4581
4737
  const out = {};
4582
4738
  try {
@@ -4613,6 +4769,7 @@ async function resolveOpKeyForEnvVarsInner(wanted, opts = {}, span) {
4613
4769
  } catch (globErr) {
4614
4770
  const m = globErr instanceof Error ? globErr.message : String(globErr);
4615
4771
  console.error(`[claudish] 1Password import skipped: ${m}`);
4772
+ recordOpFailure2({ kind: "import", source: globPath, message: m });
4616
4773
  }
4617
4774
  }
4618
4775
  if (cfg.customEndpoints && typeof cfg.customEndpoints === "object") {
@@ -4654,16 +4811,19 @@ async function resolveOpKeyForEnvVarsInner(wanted, opts = {}, span) {
4654
4811
  } catch (envErr) {
4655
4812
  const m = envErr instanceof Error ? envErr.message : String(envErr);
4656
4813
  console.error(`[claudish] 1Password environment skipped: ${m}`);
4814
+ recordOpFailure2({ kind: "environment", source: envId, message: m });
4657
4815
  }
4658
4816
  }
4659
4817
  }
4660
4818
  } catch (err) {
4661
4819
  if (err instanceof OpAuthError && onAuthFailure === "skip") {
4662
4820
  console.error(`[claudish] 1Password resolution skipped: ${err.message}`);
4821
+ recordOpFailure2({ kind: "auth", message: err.message });
4663
4822
  return out;
4664
4823
  }
4665
4824
  const message = err instanceof Error ? err.message : String(err);
4666
4825
  console.error(`[claudish] 1Password secret resolution failed: ${message}`);
4826
+ recordOpFailure2({ kind: "reference", message });
4667
4827
  if (onAuthFailure === "throw")
4668
4828
  throw err;
4669
4829
  }
@@ -42454,7 +42614,12 @@ function getMissingKeyError(resolution) {
42454
42614
  const lines = [];
42455
42615
  lines.push(`Error: ${resolution.apiKeyDescription} is required for model "${resolution.fullModelId}"`);
42456
42616
  lines.push("");
42457
- lines.push("Set it with:");
42617
+ const opNotice = renderOpFailureNotice(resolution.requiredApiKeyEnvVar);
42618
+ if (opNotice.length > 0) {
42619
+ lines.push(...opNotice);
42620
+ lines.push("");
42621
+ }
42622
+ lines.push(opNotice.length > 0 ? "Or set the key directly:" : "Set it with:");
42458
42623
  lines.push(` export ${resolution.requiredApiKeyEnvVar}='your-key-here'`);
42459
42624
  if (resolution.apiKeyUrl) {
42460
42625
  lines.push("");
@@ -42533,6 +42698,7 @@ var init_provider_resolver = __esm(() => {
42533
42698
  init_provider_definitions();
42534
42699
  init_provider_registry();
42535
42700
  init_remote_provider_registry();
42701
+ init_onepassword();
42536
42702
  init_routing_hints();
42537
42703
  API_KEY_INFO = new Proxy({}, {
42538
42704
  get(_target, prop) {
@@ -60138,7 +60304,7 @@ function tokBarCells(tokensPerSec, maxTokPerSec, tokWidth) {
60138
60304
  const raw2 = Math.round(tokWidth * Math.max(0, tokensPerSec) / denom);
60139
60305
  return Math.min(tokWidth, Math.max(0, raw2));
60140
60306
  }
60141
- var C, bold, A, LATENCY_BUCKETS, latencyFg = "#ffffff", LATENCY_FG_ANSI = "\x1B[38;2;255;255;255m", ANSI_RESET = "\x1B[0m", STAGE_BG, STAGE_FG, STAGE_BG_ANSI;
60307
+ var C, bold2, A, LATENCY_BUCKETS, latencyFg = "#ffffff", LATENCY_FG_ANSI = "\x1B[38;2;255;255;255m", ANSI_RESET = "\x1B[0m", STAGE_BG, STAGE_FG, STAGE_BG_ANSI;
60142
60308
  var init_theme2 = __esm(() => {
60143
60309
  C = {
60144
60310
  bg: "#000000",
@@ -60169,10 +60335,10 @@ var init_theme2 = __esm(() => {
60169
60335
  chipKeyBg: "#3a3a3a",
60170
60336
  chipLabelBg: "#222222"
60171
60337
  };
60172
- bold = createTextAttributes({ bold: true });
60338
+ bold2 = createTextAttributes({ bold: true });
60173
60339
  A = {
60174
- bold,
60175
- boldIf: (enabled) => enabled ? bold : undefined
60340
+ bold: bold2,
60341
+ boldIf: (enabled) => enabled ? bold2 : undefined
60176
60342
  };
60177
60343
  LATENCY_BUCKETS = [
60178
60344
  { maxMs: 500, hex: "#1f8f3b" },
@@ -63508,99 +63674,99 @@ async function probeModelRouting(models, jsonOutput, options = { live: true, tim
63508
63674
  function printHelp() {
63509
63675
  const useColor = !!process.stdout.isTTY && !process.env.NO_COLOR;
63510
63676
  const c = (code) => (s) => useColor ? `\x1B[${code}m${s}\x1B[0m` : s;
63511
- const bold2 = c("1");
63512
- const dim = c("2");
63677
+ const bold3 = c("1");
63678
+ const dim2 = c("2");
63513
63679
  const cyan = c("36");
63514
63680
  const green = c("32");
63515
63681
  const yellow = c("33");
63516
63682
  const magenta = c("35");
63517
63683
  const blue = c("34");
63518
- const h = (title) => bold2(cyan(`\u258C ${title}`));
63684
+ const h = (title) => bold3(cyan(`\u258C ${title}`));
63519
63685
  console.log(`
63520
- ${bold2("claudish")} ${dim("\xB7")} Run Claude Code with any AI model
63521
- ${dim("OpenRouter \xB7 Gemini \xB7 OpenAI \xB7 xAI \xB7 MiniMax \xB7 Kimi \xB7 GLM \xB7 Z.AI \xB7 Sakana \xB7 Poe \xB7 LiteLLM \xB7 Local")}
63686
+ ${bold3("claudish")} ${dim2("\xB7")} Run Claude Code with any AI model
63687
+ ${dim2("OpenRouter \xB7 Gemini \xB7 OpenAI \xB7 xAI \xB7 MiniMax \xB7 Kimi \xB7 GLM \xB7 Z.AI \xB7 Sakana \xB7 Poe \xB7 LiteLLM \xB7 Local")}
63522
63688
 
63523
63689
  ${h("USAGE")}
63524
- ${green("claudish")} ${dim("# Interactive mode (default, model selector)")}
63525
- ${green("claudish")} ${yellow("[OPTIONS] <claude-args...>")} ${dim("# Single-shot mode (requires --model)")}
63526
- ${green("claudish")} ${green("--team")} ${yellow("a,b,c")} ${yellow('"prompt"')} ${dim("# Run models in parallel (magmux grid)")}
63527
- ${green("claudish")} ${green("--team")} ${yellow("a,b,c")} ${green("-f")} ${yellow("input.md")} ${dim("# Team mode with file input")}
63690
+ ${green("claudish")} ${dim2("# Interactive mode (default, model selector)")}
63691
+ ${green("claudish")} ${yellow("[OPTIONS] <claude-args...>")} ${dim2("# Single-shot mode (requires --model)")}
63692
+ ${green("claudish")} ${green("--team")} ${yellow("a,b,c")} ${yellow('"prompt"')} ${dim2("# Run models in parallel (magmux grid)")}
63693
+ ${green("claudish")} ${green("--team")} ${yellow("a,b,c")} ${green("-f")} ${yellow("input.md")} ${dim2("# Team mode with file input")}
63528
63694
 
63529
63695
  ${h("MODEL ROUTING")}
63530
- ${bold2("New syntax:")} ${yellow("provider@model[:concurrency]")}
63531
- ${magenta("google@gemini-3-pro")} ${dim("Direct Google API (explicit)")}
63532
- ${magenta("openrouter@google/gemini-3-pro")} ${dim("OpenRouter (explicit)")}
63533
- ${magenta("oai@gpt-5.3")} ${dim("Direct OpenAI API (shortcut)")}
63534
- ${magenta("ollama@llama3.2:3")} ${dim("Local Ollama, 3 concurrent requests")}
63535
- ${magenta("ollama@llama3.2:0")} ${dim("Local Ollama, no limits")}
63536
-
63537
- ${bold2("Provider shortcuts:")}
63538
- ${magenta("g, gemini")} ${dim("->")} Google Gemini ${dim("google@gemini-3-pro")}
63539
- ${magenta("oai")} ${dim("->")} OpenAI Direct ${dim("oai@gpt-5.3")}
63540
- ${magenta("cx, codex")} ${dim("->")} OpenAI Codex ${dim("cx@gpt-5.3 (Responses API)")}
63541
- ${magenta("or")} ${dim("->")} OpenRouter ${dim("or@openai/gpt-5.3")}
63542
- ${magenta("x-ai, xai, grok")} ${dim("->")} xAI / Grok ${dim("x-ai@grok-3")}
63543
- ${magenta("mm, mmax")} ${dim("->")} MiniMax Direct ${dim("mm@MiniMax-M2.1")}
63544
- ${magenta("mmc")} ${dim("->")} MiniMax Coding ${dim("mmc@MiniMax-M2.1")}
63545
- ${magenta("kimi, moon")} ${dim("->")} Kimi Direct ${dim("kimi@kimi-k2-thinking-turbo")}
63546
- ${magenta("kc")} ${dim("->")} Kimi Coding ${dim("kc@kimi-k2-thinking-turbo")}
63547
- ${magenta("glm, zhipu")} ${dim("->")} GLM Direct ${dim("glm@glm-4.7")}
63548
- ${magenta("gc")} ${dim("->")} GLM Coding ${dim("gc@glm-4.7")}
63549
- ${magenta("z-ai, zai")} ${dim("->")} Z.AI Direct ${dim("z-ai@glm-4.7")}
63550
- ${magenta("oc, llama, lc, meta")} ${dim("->")} OllamaCloud ${dim("oc@llama-3.1")}
63551
- ${magenta("zen")} ${dim("->")} OpenCode Zen ${dim("zen@grok-code")}
63552
- ${magenta("zengo, zgo")} ${dim("->")} OpenCode Zen Go ${dim("zengo@grok-code")}
63553
- ${magenta("v, vertex")} ${dim("->")} Vertex AI ${dim("v@gemini-2.5-flash")}
63554
- ${magenta("go")} ${dim("->")} Gemini Code Assist ${dim("go@gemini-2.5-flash")}
63555
- ${magenta("poe")} ${dim("->")} Poe ${dim("poe@GPT-4o")}
63556
- ${magenta("litellm, ll")} ${dim("->")} LiteLLM ${dim("ll@gpt-4o (needs LITELLM_BASE_URL)")}
63557
- ${magenta("ds")} ${dim("->")} DeepSeek ${dim("ds@deepseek-chat")}
63558
- ${magenta("sakana, fugu")} ${dim("->")} Sakana Fugu ${dim("fugu@fugu-ultra")}
63559
- ${magenta("sc")} ${dim("->")} Sakana Subscription ${dim("sc@fugu-ultra")}
63560
- ${magenta("ollama")} ${dim("->")} Ollama (local) ${dim("ollama@llama3.2")}
63561
- ${magenta("lms, lmstudio")} ${dim("->")} LM Studio (local) ${dim("lms@qwen")}
63562
- ${magenta("vllm")} ${dim("->")} vLLM (local) ${dim("vllm@model")}
63563
- ${magenta("mlx")} ${dim("->")} MLX (local) ${dim("mlx@model")}
63564
-
63565
- ${bold2("Native auto-detection")} ${dim("(when no provider specified):")}
63566
- ${yellow("google/*, gemini-*")} ${dim("->")} Google API
63567
- ${yellow("openai/*, gpt-*, o1-*")} ${dim("->")} OpenAI API
63568
- ${yellow("x-ai/*, grok-*")} ${dim("->")} xAI
63569
- ${yellow("meta-llama/*, llama-*")} ${dim("->")} OllamaCloud
63570
- ${yellow("minimax/*, abab-*")} ${dim("->")} MiniMax API
63571
- ${yellow("moonshot/*, kimi-*")} ${dim("->")} Kimi API
63572
- ${yellow("zhipu/*, glm-*")} ${dim("->")} GLM API
63573
- ${yellow("sakana/*, fugu-*")} ${dim("->")} Sakana Fugu
63574
- ${yellow("poe:*")} ${dim("->")} Poe
63575
- ${yellow("anthropic/*, claude-*")} ${dim("->")} Native Anthropic
63576
- ${yellow("(unknown vendor/)")} ${dim("->")} Error (use openrouter@vendor/model)
63577
-
63578
- ${dim("A defaultProvider (config / --default-provider) catches bare names that match no rule.")}
63696
+ ${bold3("New syntax:")} ${yellow("provider@model[:concurrency]")}
63697
+ ${magenta("google@gemini-3-pro")} ${dim2("Direct Google API (explicit)")}
63698
+ ${magenta("openrouter@google/gemini-3-pro")} ${dim2("OpenRouter (explicit)")}
63699
+ ${magenta("oai@gpt-5.3")} ${dim2("Direct OpenAI API (shortcut)")}
63700
+ ${magenta("ollama@llama3.2:3")} ${dim2("Local Ollama, 3 concurrent requests")}
63701
+ ${magenta("ollama@llama3.2:0")} ${dim2("Local Ollama, no limits")}
63702
+
63703
+ ${bold3("Provider shortcuts:")}
63704
+ ${magenta("g, gemini")} ${dim2("->")} Google Gemini ${dim2("google@gemini-3-pro")}
63705
+ ${magenta("oai")} ${dim2("->")} OpenAI Direct ${dim2("oai@gpt-5.3")}
63706
+ ${magenta("cx, codex")} ${dim2("->")} OpenAI Codex ${dim2("cx@gpt-5.3 (Responses API)")}
63707
+ ${magenta("or")} ${dim2("->")} OpenRouter ${dim2("or@openai/gpt-5.3")}
63708
+ ${magenta("x-ai, xai, grok")} ${dim2("->")} xAI / Grok ${dim2("x-ai@grok-3")}
63709
+ ${magenta("mm, mmax")} ${dim2("->")} MiniMax Direct ${dim2("mm@MiniMax-M2.1")}
63710
+ ${magenta("mmc")} ${dim2("->")} MiniMax Coding ${dim2("mmc@MiniMax-M2.1")}
63711
+ ${magenta("kimi, moon")} ${dim2("->")} Kimi Direct ${dim2("kimi@kimi-k2-thinking-turbo")}
63712
+ ${magenta("kc")} ${dim2("->")} Kimi Coding ${dim2("kc@kimi-k2-thinking-turbo")}
63713
+ ${magenta("glm, zhipu")} ${dim2("->")} GLM Direct ${dim2("glm@glm-4.7")}
63714
+ ${magenta("gc")} ${dim2("->")} GLM Coding ${dim2("gc@glm-4.7")}
63715
+ ${magenta("z-ai, zai")} ${dim2("->")} Z.AI Direct ${dim2("z-ai@glm-4.7")}
63716
+ ${magenta("oc, llama, lc, meta")} ${dim2("->")} OllamaCloud ${dim2("oc@llama-3.1")}
63717
+ ${magenta("zen")} ${dim2("->")} OpenCode Zen ${dim2("zen@grok-code")}
63718
+ ${magenta("zengo, zgo")} ${dim2("->")} OpenCode Zen Go ${dim2("zengo@grok-code")}
63719
+ ${magenta("v, vertex")} ${dim2("->")} Vertex AI ${dim2("v@gemini-2.5-flash")}
63720
+ ${magenta("go")} ${dim2("->")} Gemini Code Assist ${dim2("go@gemini-2.5-flash")}
63721
+ ${magenta("poe")} ${dim2("->")} Poe ${dim2("poe@GPT-4o")}
63722
+ ${magenta("litellm, ll")} ${dim2("->")} LiteLLM ${dim2("ll@gpt-4o (needs LITELLM_BASE_URL)")}
63723
+ ${magenta("ds")} ${dim2("->")} DeepSeek ${dim2("ds@deepseek-chat")}
63724
+ ${magenta("sakana, fugu")} ${dim2("->")} Sakana Fugu ${dim2("fugu@fugu-ultra")}
63725
+ ${magenta("sc")} ${dim2("->")} Sakana Subscription ${dim2("sc@fugu-ultra")}
63726
+ ${magenta("ollama")} ${dim2("->")} Ollama (local) ${dim2("ollama@llama3.2")}
63727
+ ${magenta("lms, lmstudio")} ${dim2("->")} LM Studio (local) ${dim2("lms@qwen")}
63728
+ ${magenta("vllm")} ${dim2("->")} vLLM (local) ${dim2("vllm@model")}
63729
+ ${magenta("mlx")} ${dim2("->")} MLX (local) ${dim2("mlx@model")}
63730
+
63731
+ ${bold3("Native auto-detection")} ${dim2("(when no provider specified):")}
63732
+ ${yellow("google/*, gemini-*")} ${dim2("->")} Google API
63733
+ ${yellow("openai/*, gpt-*, o1-*")} ${dim2("->")} OpenAI API
63734
+ ${yellow("x-ai/*, grok-*")} ${dim2("->")} xAI
63735
+ ${yellow("meta-llama/*, llama-*")} ${dim2("->")} OllamaCloud
63736
+ ${yellow("minimax/*, abab-*")} ${dim2("->")} MiniMax API
63737
+ ${yellow("moonshot/*, kimi-*")} ${dim2("->")} Kimi API
63738
+ ${yellow("zhipu/*, glm-*")} ${dim2("->")} GLM API
63739
+ ${yellow("sakana/*, fugu-*")} ${dim2("->")} Sakana Fugu
63740
+ ${yellow("poe:*")} ${dim2("->")} Poe
63741
+ ${yellow("anthropic/*, claude-*")} ${dim2("->")} Native Anthropic
63742
+ ${yellow("(unknown vendor/)")} ${dim2("->")} Error (use openrouter@vendor/model)
63743
+
63744
+ ${dim2("A defaultProvider (config / --default-provider) catches bare names that match no rule.")}
63579
63745
 
63580
63746
  ${h("OPTIONS")}
63581
63747
  ${green("-i, --interactive")} Run in interactive mode (default when no prompt given)
63582
63748
  ${green("-m, --model")} ${yellow("<model>")} Model to use (required for single-shot mode)
63583
63749
  ${green("--profile")} ${yellow("<name>")} Use named profile for model mapping (default profile if omitted)
63584
63750
  ${green("--default-provider")} ${yellow("<name>")} Fallback provider for bare model names (builtin or customEndpoints key)
63585
- ${dim("Precedence: this flag > CLAUDISH_DEFAULT_PROVIDER env > config.json")}
63751
+ ${dim2("Precedence: this flag > CLAUDISH_DEFAULT_PROVIDER env > config.json")}
63586
63752
  ${green("--anthropic-api-billing")} Use your real ANTHROPIC_API_KEY for native Claude models
63587
- ${dim("(metered API billing). Default: the key is hidden so Claude Code")}
63588
- ${dim("uses your claude.ai subscription. Env: CLAUDISH_ANTHROPIC_API_BILLING")}
63589
- ${dim("Config: anthropicApiBilling: true")}
63753
+ ${dim2("(metered API billing). Default: the key is hidden so Claude Code")}
63754
+ ${dim2("uses your claude.ai subscription. Env: CLAUDISH_ANTHROPIC_API_BILLING")}
63755
+ ${dim2("Config: anthropicApiBilling: true")}
63590
63756
  ${green("--config")} ${yellow("<file>")} Use THIS config file for the run, fully replacing the machine
63591
- ${dim("global (~/.claudish/config.json) AND project (.claudish.json).")}
63592
- ${dim("A file naming no op:// source never touches 1Password (no prompt).")}
63593
- ${dim("Env vars still resolve first. Env: CLAUDISH_CONFIG")}
63757
+ ${dim2("global (~/.claudish/config.json) AND project (.claudish.json).")}
63758
+ ${dim2("A file naming no op:// source never touches 1Password (no prompt).")}
63759
+ ${dim2("Env vars still resolve first. Env: CLAUDISH_CONFIG")}
63594
63760
  ${green("--op")} ${yellow("<op://glob>")} Load API keys from a 1Password item glob (SDK-based, no op CLI)
63595
63761
  ${green("--op")} ${yellow("<glob>")} ${green("--list")} Preview which fields the glob would import (names only, no values)
63596
63762
  ${green("--op-env")} ${yellow("<id>")} Load env vars from a 1Password Environment (highest priority)
63597
63763
  ${green("--port")} ${yellow("<port>")} Proxy server port (default: random)
63598
63764
  ${green("-d, --debug-claudish")} Enable claudish debug logging to file (logs/claudish_*.log)
63599
- ${dim('Always-on: CLAUDISH_DEBUG=1 env var or "debug": true in config.json')}
63765
+ ${dim2('Always-on: CLAUDISH_DEBUG=1 env var or "debug": true in config.json')}
63600
63766
  ${green("--no-debug-claudish")} Force debug logging off for this run (when globally enabled)
63601
63767
  ${green("--log-off")} Disable always-on structural logging (~/.claudish/logs/)
63602
63768
  ${green("--log-diag")} ${yellow("<mode>")} Diagnostic output: auto (default), logfile, off
63603
- ${dim('Also: CLAUDISH_DIAG_MODE env var or "diagMode" in config.json')}
63769
+ ${dim2('Also: CLAUDISH_DIAG_MODE env var or "diagMode" in config.json')}
63604
63770
  ${green("--log-level")} ${yellow("<level>")} Log verbosity: debug (full), info (truncated), minimal (labels)
63605
63771
  ${green("-q, --quiet")} Suppress [claudish] log messages (default in single-shot mode)
63606
63772
  ${green("-v, --verbose")} Show [claudish] log messages (default in interactive mode)
@@ -63624,13 +63790,13 @@ ${h("OPTIONS")}
63624
63790
  ${h("MODEL DISCOVERY")}
63625
63791
  ${green("--models")} Top 100 ranked (Firebase + local providers)
63626
63792
  ${green("--models --provider")} ${yellow("<slug>")} Filter the catalog to one provider
63627
- ${dim("e.g. --provider opencode-zen, anthropic, openai")}
63793
+ ${dim2("e.g. --provider opencode-zen, anthropic, openai")}
63628
63794
  ${green("--providers")} Every provider + active-model count
63629
63795
  ${green("-s, --models-search")} ${yellow("<query>")} Fuzzy search: id, brand synonyms (chatgpt,
63630
- ${dim("claude, grok), gateways (zen, oc, codex), caps")}
63796
+ ${dim2("claude, grok), gateways (zen, oc, codex), caps")}
63631
63797
  ${green("--models-top")} Curated recommended models (flagship + fast)
63632
63798
  ${green("--probe")} ${yellow("<models...>")} Probe each provider in the fallback chain with
63633
- ${dim("a real 1-token request (may incur tiny cost)")}
63799
+ ${dim2("a real 1-token request (may incur tiny cost)")}
63634
63800
  ${green("--no-probe")} Skip live requests, show static chain only
63635
63801
  ${green("--probe-timeout")} ${yellow("<secs>")} Per-link timeout for live probes (default: 40)
63636
63802
  ${green("--models-refresh")} Force refresh the slim model catalog from Firebase
@@ -63639,11 +63805,11 @@ ${h("MODEL DISCOVERY")}
63639
63805
 
63640
63806
  ${h("TEAM MODE")}
63641
63807
  ${green("--team")} ${yellow("<models>")} Run multiple models in parallel (comma-separated)
63642
- ${dim('Example: --team minimax-m2.5,kimi-k2.5 "prompt"')}
63808
+ ${dim2('Example: --team minimax-m2.5,kimi-k2.5 "prompt"')}
63643
63809
  ${green("--mode")} ${yellow("<mode>")} Team mode: default (grid), interactive, json
63644
63810
  ${green("-f, --file")} ${yellow("<path>")} Read prompt from file (use with --team or single-shot)
63645
63811
 
63646
- ${h("MODEL MAPPING")} ${dim("(per-role override)")}
63812
+ ${h("MODEL MAPPING")} ${dim2("(per-role override)")}
63647
63813
  ${green("--model-opus")} ${yellow("<model>")} Model for Opus role (planning, complex tasks)
63648
63814
  ${green("--model-sonnet")} ${yellow("<model>")} Model for Sonnet role (default coding)
63649
63815
  ${green("--model-haiku")} ${yellow("<model>")} Model for Haiku role (fast tasks, background)
@@ -63651,13 +63817,13 @@ ${h("MODEL MAPPING")} ${dim("(per-role override)")}
63651
63817
 
63652
63818
  ${h("SUBCOMMANDS")}
63653
63819
  ${green("claudish config")} Open the interactive config TUI (profiles,
63654
- ${dim("providers, routing, 1Password)")}
63820
+ ${dim2("providers, routing, 1Password)")}
63655
63821
  ${green("claudish providers")} ${yellow("[--json]")} Show provider credential status (no key material)
63656
63822
  ${green("claudish quota")} ${yellow("[provider]")} Show remaining quota/usage (alias: usage)
63657
63823
  ${green("claudish serve")} ${yellow("--port <n> --models <p>")} Run the Claude Desktop redirect gateway
63658
63824
  ${green("claudish update")} Check for updates and install the latest version
63659
63825
 
63660
- ${bold2("Profiles:")}
63826
+ ${bold3("Profiles:")}
63661
63827
  ${green("claudish init")} ${yellow("[--local|--global]")} Setup wizard - create config + first profile
63662
63828
  ${green("claudish profile list")} ${yellow("[scope]")} List all profiles (both scopes by default)
63663
63829
  ${green("claudish profile add")} ${yellow("[scope]")} Add a new profile
@@ -63665,104 +63831,104 @@ ${h("SUBCOMMANDS")}
63665
63831
  ${green("claudish profile use")} ${yellow("[name] [scope]")} Set default profile
63666
63832
  ${green("claudish profile show")} ${yellow("[name] [scope]")} Show profile details
63667
63833
  ${green("claudish profile edit")} ${yellow("[name] [scope]")} Edit a profile
63668
- ${dim("scope = --local (.claudish.json) | --global (~/.claudish/config.json) | (prompted)")}
63834
+ ${dim2("scope = --local (.claudish.json) | --global (~/.claudish/config.json) | (prompted)")}
63669
63835
 
63670
- ${bold2("Authentication:")}
63836
+ ${bold3("Authentication:")}
63671
63837
  ${green("claudish login")} ${yellow("[provider]")} Login to an OAuth provider (interactive if omitted)
63672
63838
  ${green("claudish logout")} ${yellow("[provider]")} Clear OAuth credentials
63673
- ${dim("Providers: gemini, kimi")}
63839
+ ${dim2("Providers: gemini, kimi")}
63674
63840
 
63675
- ${h("1PASSWORD")} ${dim("(SDK-based \u2014 no op CLI needed for secrets)")}
63676
- ${dim("Auth via OP_SERVICE_ACCOUNT_TOKEN, or OP_ACCOUNT / onepasswordAccount config (DesktopAuth).")}
63841
+ ${h("1PASSWORD")} ${dim2("(SDK-based \u2014 no op CLI needed for secrets)")}
63842
+ ${dim2("Auth via OP_SERVICE_ACCOUNT_TOKEN, or OP_ACCOUNT / onepasswordAccount config (DesktopAuth).")}
63677
63843
  ${green("--op")} ${yellow("<glob> --list")} Preview which fields a glob would import (names only)
63678
63844
  ${green("--op")} ${yellow("<glob>")} ${yellow("[...args]")} Resolve a glob into env vars, then run a session
63679
- ${dim("Inline op import requires a GLOB (self-names via field labels)")}
63680
- ${dim('Example: claudish --op "op://Jack/Keys/**" --model gpt-4o "task"')}
63845
+ ${dim2("Inline op import requires a GLOB (self-names via field labels)")}
63846
+ ${dim2('Example: claudish --op "op://Jack/Keys/**" --model gpt-4o "task"')}
63681
63847
  ${green("--op-env")} ${yellow("<id>")} Load a 1Password Environment (highest-priority source)
63682
- ${dim("Persistent setup (single refs, sets, environments, account): claudish config -> 1Password tab")}
63848
+ ${dim2("Persistent setup (single refs, sets, environments, account): claudish config -> 1Password tab")}
63683
63849
 
63684
63850
  ${h("CLAUDE CODE FLAG PASSTHROUGH")}
63685
- ${dim("Any unrecognized flag is forwarded to Claude Code. Claudish flags can appear in any order.")}
63686
- ${green("claudish")} --model grok ${yellow("--agent test")} ${yellow('"task"')} ${dim("# --agent passes through")}
63687
- ${green("claudish")} --model grok ${yellow("--effort high")} --stdin ${yellow('"task"')} ${dim("# --effort passes, --stdin stays")}
63688
- ${green("claudish")} --model grok ${yellow("--permission-mode plan")} -i ${dim("# works in interactive too")}
63689
- ${dim("Use -- when a Claude Code flag value starts with '-':")}
63851
+ ${dim2("Any unrecognized flag is forwarded to Claude Code. Claudish flags can appear in any order.")}
63852
+ ${green("claudish")} --model grok ${yellow("--agent test")} ${yellow('"task"')} ${dim2("# --agent passes through")}
63853
+ ${green("claudish")} --model grok ${yellow("--effort high")} --stdin ${yellow('"task"')} ${dim2("# --effort passes, --stdin stays")}
63854
+ ${green("claudish")} --model grok ${yellow("--permission-mode plan")} -i ${dim2("# works in interactive too")}
63855
+ ${dim2("Use -- when a Claude Code flag value starts with '-':")}
63690
63856
  ${green("claudish")} --model grok ${green("--")} ${yellow('--system-prompt "-verbose mode" "task"')}
63691
63857
 
63692
63858
  ${h("CUSTOM MODELS & ENDPOINTS")}
63693
- ${dim("Claudish accepts ANY valid model ID from the Firebase catalog, even if not in --models:")}
63859
+ ${dim2("Claudish accepts ANY valid model ID from the Firebase catalog, even if not in --models:")}
63694
63860
  ${green("claudish")} --model ${yellow("openrouter@your_provider/custom-model-123")} ${yellow('"task"')}
63695
- ${dim("Named custom endpoints live in ~/.claudish/config.json under 'customEndpoints' and route via @:")}
63861
+ ${dim2("Named custom endpoints live in ~/.claudish/config.json under 'customEndpoints' and route via @:")}
63696
63862
  ${green("claudish")} --model ${yellow("my-vllm@llama3.1-70b")} ${yellow('"task"')}
63697
63863
 
63698
63864
  ${h("MODES")}
63699
- ${green("\u2022")} ${bold2("Interactive")} ${dim("(default):")} shows model selector, starts a persistent session
63700
- ${green("\u2022")} ${bold2("Single-shot")} ${dim("(--model):")} runs one task headless and exits
63865
+ ${green("\u2022")} ${bold3("Interactive")} ${dim2("(default):")} shows model selector, starts a persistent session
63866
+ ${green("\u2022")} ${bold3("Single-shot")} ${dim2("(--model):")} runs one task headless and exits
63701
63867
 
63702
63868
  ${h("NOTES")}
63703
- ${yellow("\u2022")} Permission prompts are ${bold2("ENABLED")} by default (normal Claude Code behavior)
63869
+ ${yellow("\u2022")} Permission prompts are ${bold3("ENABLED")} by default (normal Claude Code behavior)
63704
63870
  ${yellow("\u2022")} Use ${green("-y")} / ${green("--auto-approve")} to skip permission prompts
63705
63871
  ${yellow("\u2022")} Model selector appears ONLY in interactive mode when ${green("--model")} not specified
63706
63872
  ${yellow("\u2022")} ${green("--dangerous")} disables the sandbox \u2014 use with extreme caution
63707
63873
 
63708
63874
  ${h("ENVIRONMENT VARIABLES")}
63709
- ${dim("Claudish auto-loads a .env file from the current directory.")}
63875
+ ${dim2("Claudish auto-loads a .env file from the current directory.")}
63710
63876
 
63711
- ${bold2("Claude Code installation:")}
63877
+ ${bold3("Claude Code installation:")}
63712
63878
  ${blue("CLAUDE_PATH")} Custom path to Claude Code binary
63713
- ${dim("Search: CLAUDE_PATH -> ~/.claude/local/claude -> PATH")}
63879
+ ${dim2("Search: CLAUDE_PATH -> ~/.claude/local/claude -> PATH")}
63714
63880
 
63715
- ${bold2("API keys")} ${dim("(at least one required for cloud models):")}
63881
+ ${bold3("API keys")} ${dim2("(at least one required for cloud models):")}
63716
63882
  ${blue("OPENROUTER_API_KEY")} OpenRouter (default backend)
63717
- ${blue("GEMINI_API_KEY")} Google Gemini ${dim("(g@, gemini@; alias GOOGLE_API_KEY)")}
63718
- ${blue("OPENAI_API_KEY")} OpenAI ${dim("(oai@)")}
63719
- ${blue("OPENAI_CODEX_API_KEY")} OpenAI Codex / Responses API ${dim("(cx@, codex@)")}
63720
- ${blue("XAI_API_KEY")} xAI / Grok ${dim("(x-ai@, grok@)")}
63721
- ${blue("MINIMAX_API_KEY")} MiniMax ${dim("(mm@, mmax@)")}
63722
- ${blue("MINIMAX_CODING_API_KEY")} MiniMax Coding Plan ${dim("(mmc@)")}
63723
- ${blue("MOONSHOT_API_KEY")} Kimi / Moonshot ${dim("(kimi@, moon@; alias KIMI_API_KEY)")}
63724
- ${blue("KIMI_CODING_API_KEY")} Kimi Coding Plan ${dim("(kc@)")}
63725
- ${blue("ZHIPU_API_KEY")} GLM / Zhipu ${dim("(glm@, zhipu@; alias GLM_API_KEY)")}
63726
- ${blue("GLM_CODING_API_KEY")} GLM Coding Plan ${dim("(gc@; alias ZAI_CODING_API_KEY)")}
63727
- ${blue("ZAI_API_KEY")} Z.AI ${dim("(z-ai@, zai@)")}
63728
- ${blue("DEEPSEEK_API_KEY")} DeepSeek ${dim("(ds@)")}
63729
- ${blue("SAKANA_API_KEY")} Sakana Fugu ${dim("(sakana@, fugu@)")}
63730
- ${blue("SAKANA_SUBSCRIPTION_API_KEY")} Sakana Fugu Subscription ${dim("(sc@; separate subscription key)")}
63731
- ${blue("OLLAMA_API_KEY")} OllamaCloud ${dim("(oc@, llama@)")}
63732
- ${blue("OPENCODE_API_KEY")} OpenCode Zen ${dim("(zen@; optional - free models work without it)")}
63733
- ${blue("POE_API_KEY")} Poe ${dim("(poe@)")}
63734
- ${blue("LITELLM_API_KEY")} LiteLLM ${dim("(litellm@, ll@; needs LITELLM_BASE_URL)")}
63735
- ${blue("VERTEX_API_KEY")} Vertex AI Express ${dim("(v@)")}
63736
- ${blue("VERTEX_PROJECT")} Vertex AI project ID ${dim("(OAuth mode, v@)")}
63737
- ${blue("VERTEX_LOCATION")} Vertex AI region ${dim("(default: us-central1)")}
63883
+ ${blue("GEMINI_API_KEY")} Google Gemini ${dim2("(g@, gemini@; alias GOOGLE_API_KEY)")}
63884
+ ${blue("OPENAI_API_KEY")} OpenAI ${dim2("(oai@)")}
63885
+ ${blue("OPENAI_CODEX_API_KEY")} OpenAI Codex / Responses API ${dim2("(cx@, codex@)")}
63886
+ ${blue("XAI_API_KEY")} xAI / Grok ${dim2("(x-ai@, grok@)")}
63887
+ ${blue("MINIMAX_API_KEY")} MiniMax ${dim2("(mm@, mmax@)")}
63888
+ ${blue("MINIMAX_CODING_API_KEY")} MiniMax Coding Plan ${dim2("(mmc@)")}
63889
+ ${blue("MOONSHOT_API_KEY")} Kimi / Moonshot ${dim2("(kimi@, moon@; alias KIMI_API_KEY)")}
63890
+ ${blue("KIMI_CODING_API_KEY")} Kimi Coding Plan ${dim2("(kc@)")}
63891
+ ${blue("ZHIPU_API_KEY")} GLM / Zhipu ${dim2("(glm@, zhipu@; alias GLM_API_KEY)")}
63892
+ ${blue("GLM_CODING_API_KEY")} GLM Coding Plan ${dim2("(gc@; alias ZAI_CODING_API_KEY)")}
63893
+ ${blue("ZAI_API_KEY")} Z.AI ${dim2("(z-ai@, zai@)")}
63894
+ ${blue("DEEPSEEK_API_KEY")} DeepSeek ${dim2("(ds@)")}
63895
+ ${blue("SAKANA_API_KEY")} Sakana Fugu ${dim2("(sakana@, fugu@)")}
63896
+ ${blue("SAKANA_SUBSCRIPTION_API_KEY")} Sakana Fugu Subscription ${dim2("(sc@; separate subscription key)")}
63897
+ ${blue("OLLAMA_API_KEY")} OllamaCloud ${dim2("(oc@, llama@)")}
63898
+ ${blue("OPENCODE_API_KEY")} OpenCode Zen ${dim2("(zen@; optional - free models work without it)")}
63899
+ ${blue("POE_API_KEY")} Poe ${dim2("(poe@)")}
63900
+ ${blue("LITELLM_API_KEY")} LiteLLM ${dim2("(litellm@, ll@; needs LITELLM_BASE_URL)")}
63901
+ ${blue("VERTEX_API_KEY")} Vertex AI Express ${dim2("(v@)")}
63902
+ ${blue("VERTEX_PROJECT")} Vertex AI project ID ${dim2("(OAuth mode, v@)")}
63903
+ ${blue("VERTEX_LOCATION")} Vertex AI region ${dim2("(default: us-central1)")}
63738
63904
  ${blue("ANTHROPIC_API_KEY")} Placeholder (prevents Claude Code dialog)
63739
63905
  ${blue("ANTHROPIC_AUTH_TOKEN")} Placeholder (prevents Claude Code login screen)
63740
63906
 
63741
- ${bold2("Custom / base-URL overrides:")}
63907
+ ${bold3("Custom / base-URL overrides:")}
63742
63908
  ${blue("GEMINI_BASE_URL")} Custom Gemini endpoint
63743
63909
  ${blue("OPENAI_BASE_URL")} Custom OpenAI / Azure endpoint
63744
63910
  ${blue("MINIMAX_BASE_URL")} Custom MiniMax endpoint
63745
- ${blue("MOONSHOT_BASE_URL")} Custom Kimi / Moonshot endpoint ${dim("(alias KIMI_BASE_URL)")}
63746
- ${blue("ZHIPU_BASE_URL")} Custom GLM / Zhipu endpoint ${dim("(alias GLM_BASE_URL)")}
63747
- ${blue("SAKANA_BASE_URL")} Custom Sakana endpoint ${dim("(default: https://api.sakana.ai)")}
63748
- ${blue("LITELLM_BASE_URL")} LiteLLM gateway base URL ${dim("(required for ll@)")}
63749
- ${blue("OLLAMACLOUD_BASE_URL")} OllamaCloud ${dim("(default: https://ollama.com)")}
63750
- ${blue("OPENCODE_BASE_URL")} OpenCode Zen ${dim("(default: https://opencode.ai/zen)")}
63751
-
63752
- ${bold2("Local providers:")}
63753
- ${blue("OLLAMA_BASE_URL")} Ollama server ${dim("(default: http://localhost:11434; alias OLLAMA_HOST)")}
63754
- ${blue("LMSTUDIO_BASE_URL")} LM Studio server ${dim("(default: http://localhost:1234)")}
63755
- ${blue("VLLM_BASE_URL")} vLLM server ${dim("(default: http://localhost:8000)")}
63756
- ${blue("MLX_BASE_URL")} MLX server ${dim("(default: http://127.0.0.1:8080)")}
63757
-
63758
- ${bold2("Claudish settings:")}
63759
- ${blue("CLAUDISH_MODEL")} Default model ${dim("(default: openai/gpt-5.3)")}
63760
- ${blue("CLAUDISH_DEFAULT_PROVIDER")} Fallback provider for bare names ${dim("(see --default-provider)")}
63911
+ ${blue("MOONSHOT_BASE_URL")} Custom Kimi / Moonshot endpoint ${dim2("(alias KIMI_BASE_URL)")}
63912
+ ${blue("ZHIPU_BASE_URL")} Custom GLM / Zhipu endpoint ${dim2("(alias GLM_BASE_URL)")}
63913
+ ${blue("SAKANA_BASE_URL")} Custom Sakana endpoint ${dim2("(default: https://api.sakana.ai)")}
63914
+ ${blue("LITELLM_BASE_URL")} LiteLLM gateway base URL ${dim2("(required for ll@)")}
63915
+ ${blue("OLLAMACLOUD_BASE_URL")} OllamaCloud ${dim2("(default: https://ollama.com)")}
63916
+ ${blue("OPENCODE_BASE_URL")} OpenCode Zen ${dim2("(default: https://opencode.ai/zen)")}
63917
+
63918
+ ${bold3("Local providers:")}
63919
+ ${blue("OLLAMA_BASE_URL")} Ollama server ${dim2("(default: http://localhost:11434; alias OLLAMA_HOST)")}
63920
+ ${blue("LMSTUDIO_BASE_URL")} LM Studio server ${dim2("(default: http://localhost:1234)")}
63921
+ ${blue("VLLM_BASE_URL")} vLLM server ${dim2("(default: http://localhost:8000)")}
63922
+ ${blue("MLX_BASE_URL")} MLX server ${dim2("(default: http://127.0.0.1:8080)")}
63923
+
63924
+ ${bold3("Claudish settings:")}
63925
+ ${blue("CLAUDISH_MODEL")} Default model ${dim2("(default: openai/gpt-5.3)")}
63926
+ ${blue("CLAUDISH_DEFAULT_PROVIDER")} Fallback provider for bare names ${dim2("(see --default-provider)")}
63761
63927
  ${blue("CLAUDISH_PORT")} Default proxy port
63762
63928
  ${blue("CLAUDISH_CONTEXT_WINDOW")} Override context window size
63763
63929
  ${blue("CLAUDISH_DIAG_MODE")} Diagnostic output: auto / logfile / off
63764
- ${blue("CLAUDISH_DEBUG")} Always enable debug logging: 1 / true ${dim("(same as -d)")}
63765
- ${blue("CLAUDISH_ANTHROPIC_API_BILLING")} Bill native Claude to your API key ${dim("(see --anthropic-api-billing)")}
63930
+ ${blue("CLAUDISH_DEBUG")} Always enable debug logging: 1 / true ${dim2("(same as -d)")}
63931
+ ${blue("CLAUDISH_ANTHROPIC_API_BILLING")} Bill native Claude to your API key ${dim2("(see --anthropic-api-billing)")}
63766
63932
  ${blue("CLAUDISH_MCP_TOOLS")} MCP tool gating: all / low-level / agentic / channel
63767
63933
  ${blue("CLAUDISH_MODEL_OPUS")} Override model for Opus role
63768
63934
  ${blue("CLAUDISH_MODEL_SONNET")} Override model for Sonnet role
@@ -63770,41 +63936,41 @@ ${h("ENVIRONMENT VARIABLES")}
63770
63936
  ${blue("CLAUDISH_MODEL_SUBAGENT")} Override model for sub-agents
63771
63937
  ${blue("NO_COLOR")} Set to disable colored output
63772
63938
 
63773
- ${bold2("1Password auth:")}
63939
+ ${bold3("1Password auth:")}
63774
63940
  ${blue("OP_SERVICE_ACCOUNT_TOKEN")} Service-account token (preferred for headless)
63775
- ${blue("OP_ACCOUNT")} Account URL for DesktopAuth ${dim("(e.g. my-team.1password.com)")}
63941
+ ${blue("OP_ACCOUNT")} Account URL for DesktopAuth ${dim2("(e.g. my-team.1password.com)")}
63776
63942
 
63777
63943
  ${h("EXAMPLES")}
63778
- ${dim("# Interactive (default) - model selector")}
63944
+ ${dim2("# Interactive (default) - model selector")}
63779
63945
  ${green("claudish")}
63780
- ${green("claudish")} --free ${dim("# only FREE models")}
63946
+ ${green("claudish")} --free ${dim2("# only FREE models")}
63781
63947
 
63782
- ${dim("# Explicit provider routing")}
63948
+ ${dim2("# Explicit provider routing")}
63783
63949
  ${green("claudish")} --model ${magenta("google@gemini-3-pro")} ${yellow('"implement auth"')}
63784
63950
  ${green("claudish")} --model ${magenta("oai@gpt-5.3")} ${yellow('"add tests for login"')}
63785
63951
  ${green("claudish")} --model ${magenta("openrouter@deepseek/deepseek-r1")} ${yellow('"unknown vendor"')}
63786
63952
 
63787
- ${dim("# Native auto-detection (provider inferred from model name)")}
63953
+ ${dim2("# Native auto-detection (provider inferred from model name)")}
63788
63954
  ${green("claudish")} --model ${yellow("gpt-4o")} ${yellow('"routes to OpenAI"')}
63789
63955
  ${green("claudish")} --model ${yellow("gemini-2.5-pro")} ${yellow('"routes to Google"')}
63790
63956
 
63791
- ${dim("# Per-role model mapping")}
63957
+ ${dim2("# Per-role model mapping")}
63792
63958
  ${green("claudish")} --model-opus ${magenta("oai@gpt-5.3")} --model-sonnet ${magenta("google@gemini-3-pro")}
63793
63959
 
63794
- ${dim("# stdin for large prompts (diffs, code review)")}
63795
- ${dim("git diff |")} ${green("claudish")} --stdin --model ${magenta("oai@gpt-5.3")} ${yellow('"Review these changes"')}
63960
+ ${dim2("# stdin for large prompts (diffs, code review)")}
63961
+ ${dim2("git diff |")} ${green("claudish")} --stdin --model ${magenta("oai@gpt-5.3")} ${yellow('"Review these changes"')}
63796
63962
 
63797
- ${dim("# Local models with concurrency control")}
63963
+ ${dim2("# Local models with concurrency control")}
63798
63964
  ${green("claudish")} --model ${magenta("ollama@llama3.2:3")} ${yellow('"3 concurrent requests"')}
63799
63965
  ${green("claudish")} --model ${magenta("lms@qwen2.5-coder")} ${yellow('"LM Studio shortcut"')}
63800
63966
  ${green("claudish")} --model ${yellow('"http://localhost:8000/mistral"')} ${yellow('"any OpenAI-compatible URL"')}
63801
63967
 
63802
- ${dim("# Autonomous (no prompts, no sandbox) \u2014 use with caution")}
63968
+ ${dim2("# Autonomous (no prompts, no sandbox) \u2014 use with caution")}
63803
63969
  ${green("claudish")} -y --dangerous ${yellow('"refactor entire codebase"')}
63804
63970
 
63805
63971
  ${h("MORE INFO")}
63806
- ${dim("GitHub:")} ${blue("https://github.com/MadAppGang/claude-code")}
63807
- ${dim("OpenRouter:")} ${blue("https://openrouter.ai")}
63972
+ ${dim2("GitHub:")} ${blue("https://github.com/MadAppGang/claude-code")}
63973
+ ${dim2("OpenRouter:")} ${blue("https://openrouter.ai")}
63808
63974
  `);
63809
63975
  }
63810
63976
  function printAIAgentGuide() {
@@ -71859,8 +72025,8 @@ var init_claude_runner = __esm(() => {
71859
72025
  init_model_catalog();
71860
72026
  init_config();
71861
72027
  init_logger();
71862
- init_model_discovery();
71863
72028
  init_profile_config();
72029
+ init_model_discovery();
71864
72030
  init_model_parser();
71865
72031
  init_routing_rules();
71866
72032
  init_telemetry();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "7.20.1",
3
+ "version": "7.21.0",
4
4
  "description": "Run Claude Code with any model - OpenRouter, Ollama, LM Studio & local models",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -60,10 +60,10 @@
60
60
  "ai"
61
61
  ],
62
62
  "optionalDependencies": {
63
- "@claudish/magmux-darwin-arm64": "7.20.1",
64
- "@claudish/magmux-darwin-x64": "7.20.1",
65
- "@claudish/magmux-linux-arm64": "7.20.1",
66
- "@claudish/magmux-linux-x64": "7.20.1"
63
+ "@claudish/magmux-darwin-arm64": "7.21.0",
64
+ "@claudish/magmux-darwin-x64": "7.21.0",
65
+ "@claudish/magmux-linux-arm64": "7.21.0",
66
+ "@claudish/magmux-linux-x64": "7.21.0"
67
67
  },
68
68
  "author": "Jack Rudenko <i@madappgang.com>",
69
69
  "license": "MIT",