claudish 5.2.0 → 5.3.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/AI_AGENT_GUIDE.md CHANGED
@@ -256,6 +256,26 @@ for (const model of models) {
256
256
  | `--debug` / `-d` | Debug logging to file | Disabled |
257
257
  | `--no-auto-approve` | Require prompts | Auto-approve enabled |
258
258
 
259
+ ### Claude Code Flag Passthrough
260
+
261
+ Any Claude Code flag that claudish doesn't recognize is automatically forwarded. This means you can use:
262
+
263
+ ```bash
264
+ # Agent selection
265
+ claudish --model grok --agent code-review --stdin --quiet < prompt.md
266
+
267
+ # Effort and budget control
268
+ claudish --model grok --effort high --max-budget-usd 0.50 --stdin --quiet < prompt.md
269
+
270
+ # Permission mode
271
+ claudish --model grok --permission-mode plan --stdin --quiet < prompt.md
272
+ ```
273
+
274
+ Use `--` separator when flag values start with `-`:
275
+ ```bash
276
+ claudish --model grok -- --system-prompt "-v mode" --stdin --quiet < prompt.md
277
+ ```
278
+
259
279
  ## Common Workflows
260
280
 
261
281
  ### Workflow 1: Quick Code Fix (Grok)
package/dist/index.js CHANGED
@@ -6,39 +6,60 @@ var __defProp = Object.defineProperty;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
8
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ function __accessProp(key) {
10
+ return this[key];
11
+ }
12
+ var __toESMCache_node;
13
+ var __toESMCache_esm;
9
14
  var __toESM = (mod, isNodeMode, target) => {
15
+ var canCache = mod != null && typeof mod === "object";
16
+ if (canCache) {
17
+ var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
18
+ var cached = cache.get(mod);
19
+ if (cached)
20
+ return cached;
21
+ }
10
22
  target = mod != null ? __create(__getProtoOf(mod)) : {};
11
23
  const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
12
24
  for (let key of __getOwnPropNames(mod))
13
25
  if (!__hasOwnProp.call(to, key))
14
26
  __defProp(to, key, {
15
- get: () => mod[key],
27
+ get: __accessProp.bind(mod, key),
16
28
  enumerable: true
17
29
  });
30
+ if (canCache)
31
+ cache.set(mod, to);
18
32
  return to;
19
33
  };
20
- var __moduleCache = /* @__PURE__ */ new WeakMap;
21
34
  var __toCommonJS = (from) => {
22
- var entry = __moduleCache.get(from), desc;
35
+ var entry = (__moduleCache ??= new WeakMap).get(from), desc;
23
36
  if (entry)
24
37
  return entry;
25
38
  entry = __defProp({}, "__esModule", { value: true });
26
- if (from && typeof from === "object" || typeof from === "function")
27
- __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
28
- get: () => from[key],
29
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
30
- }));
39
+ if (from && typeof from === "object" || typeof from === "function") {
40
+ for (var key of __getOwnPropNames(from))
41
+ if (!__hasOwnProp.call(entry, key))
42
+ __defProp(entry, key, {
43
+ get: __accessProp.bind(from, key),
44
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
45
+ });
46
+ }
31
47
  __moduleCache.set(from, entry);
32
48
  return entry;
33
49
  };
50
+ var __moduleCache;
34
51
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
52
+ var __returnValue = (v) => v;
53
+ function __exportSetter(name, newValue) {
54
+ this[name] = __returnValue.bind(null, newValue);
55
+ }
35
56
  var __export = (target, all) => {
36
57
  for (var name in all)
37
58
  __defProp(target, name, {
38
59
  get: all[name],
39
60
  enumerable: true,
40
61
  configurable: true,
41
- set: (newValue) => all[name] = () => newValue
62
+ set: __exportSetter.bind(all, name)
42
63
  });
43
64
  };
44
65
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
@@ -34209,9 +34230,16 @@ async function parseArgs(args) {
34209
34230
  process.exit(0);
34210
34231
  } else if (arg === "--summarize-tools") {
34211
34232
  config3.summarizeTools = true;
34212
- } else {
34213
- config3.claudeArgs = args.slice(i);
34233
+ } else if (arg === "--") {
34234
+ config3.claudeArgs.push(...args.slice(i + 1));
34214
34235
  break;
34236
+ } else if (arg.startsWith("-")) {
34237
+ config3.claudeArgs.push(arg);
34238
+ if (i + 1 < args.length && !args[i + 1].startsWith("-")) {
34239
+ config3.claudeArgs.push(args[++i]);
34240
+ }
34241
+ } else {
34242
+ config3.claudeArgs.push(arg);
34215
34243
  }
34216
34244
  i++;
34217
34245
  }
@@ -34895,6 +34923,19 @@ OPTIONS:
34895
34923
  -h, --help Show this help message
34896
34924
  --help-ai Show AI agent usage guide (file-based patterns, sub-agents)
34897
34925
  --init Install Claudish skill in current project (.claude/skills/)
34926
+ -- Separator: everything after passes directly to Claude Code
34927
+
34928
+ CLAUDE CODE FLAG PASSTHROUGH:
34929
+ Any unrecognized flag is automatically forwarded to Claude Code.
34930
+ Claudish flags (--model, --stdin, --quiet, etc.) can appear in any order.
34931
+
34932
+ Examples:
34933
+ claudish --model grok --agent test "task" # --agent passes to Claude Code
34934
+ claudish --model grok --effort high --stdin "task" # --effort passes, --stdin stays
34935
+ claudish --model grok --permission-mode plan -i # Works in interactive mode too
34936
+
34937
+ Use -- when a Claude Code flag value starts with '-':
34938
+ claudish --model grok -- --system-prompt "-verbose mode" "task"
34898
34939
 
34899
34940
  PROFILE MANAGEMENT:
34900
34941
  claudish init [--local|--global] Setup wizard - create config and first profile
@@ -35346,7 +35387,7 @@ async function fetchGLMCodingModels2() {
35346
35387
  return [];
35347
35388
  }
35348
35389
  }
35349
- var __filename5, __dirname5, VERSION = "5.2.0", CACHE_MAX_AGE_DAYS3 = 2, MODELS_JSON_PATH, CLAUDISH_CACHE_DIR3, ALL_MODELS_JSON_PATH2;
35390
+ var __filename5, __dirname5, VERSION = "5.3.0", CACHE_MAX_AGE_DAYS3 = 2, MODELS_JSON_PATH, CLAUDISH_CACHE_DIR3, ALL_MODELS_JSON_PATH2;
35350
35391
  var init_cli = __esm(() => {
35351
35392
  init_config();
35352
35393
  init_model_loader();
@@ -35370,7 +35411,7 @@ __export(exports_claude_runner, {
35370
35411
  checkClaudeInstalled: () => checkClaudeInstalled
35371
35412
  });
35372
35413
  import { spawn } from "node:child_process";
35373
- import { writeFileSync as writeFileSync7, unlinkSync as unlinkSync4, mkdirSync as mkdirSync7, existsSync as existsSync12 } from "node:fs";
35414
+ import { writeFileSync as writeFileSync7, unlinkSync as unlinkSync4, mkdirSync as mkdirSync7, existsSync as existsSync12, readFileSync as readFileSync10 } from "node:fs";
35374
35415
  import { tmpdir, homedir as homedir11 } from "node:os";
35375
35416
  import { join as join12 } from "node:path";
35376
35417
  function isWindows() {
@@ -35487,22 +35528,45 @@ function createTempSettingsFile(modelDisplay, port) {
35487
35528
  const formatTokensBash = `fmt_tok() { local n=\${1:-0}; if [ "$n" -ge 1000000 ]; then echo "$((n/1000000))M"; elif [ "$n" -ge 1000 ]; then echo "$((n/1000))k"; else echo "$n"; fi; }`;
35488
35529
  statusCommand = `JSON=$(cat) && DIR=$(basename "$(pwd)") && [ \${#DIR} -gt 15 ] && DIR="\${DIR:0:12}..." || true && CTX=100 && COST="0" && IS_FREE="false" && IS_EST="false" && PROVIDER="" && TOKEN_MODEL="" && IN_TOK=0 && CTX_WIN=0 && ${formatTokensBash} && if [ -f "${tokenFilePath}" ]; then TOKENS=$(cat "${tokenFilePath}" 2>/dev/null | tr -d ' \\n') && REAL_CTX=$(echo "$TOKENS" | grep -o '"context_left_percent":[0-9]*' | grep -o '[0-9]*') && if [ ! -z "$REAL_CTX" ]; then CTX="$REAL_CTX"; fi && REAL_COST=$(echo "$TOKENS" | grep -o '"total_cost":[0-9.]*' | cut -d: -f2) && if [ ! -z "$REAL_COST" ]; then COST="$REAL_COST"; fi && IN_TOK=$(echo "$TOKENS" | grep -o '"input_tokens":[0-9]*' | grep -o '[0-9]*') && CTX_WIN=$(echo "$TOKENS" | grep -o '"context_window":[0-9]*' | grep -o '[0-9]*') && IS_FREE=$(echo "$TOKENS" | grep -o '"is_free":[a-z]*' | cut -d: -f2) && IS_EST=$(echo "$TOKENS" | grep -o '"is_estimated":[a-z]*' | cut -d: -f2) && PROVIDER=$(echo "$TOKENS" | grep -o '"provider_name":"[^"]*"' | cut -d'"' -f4) && TOKEN_MODEL=$(echo "$TOKENS" | grep -o '"model_name":"[^"]*"' | cut -d'"' -f4); fi && if [ "$CLAUDISH_IS_LOCAL" = "true" ]; then COST_DISPLAY="LOCAL"; elif [ "$IS_FREE" = "true" ]; then COST_DISPLAY="FREE"; elif [ "$IS_EST" = "true" ]; then COST_DISPLAY=$(printf "~\\$%.3f" "$COST"); else COST_DISPLAY=$(printf "\\$%.3f" "$COST"); fi && MODEL_DISPLAY="\${TOKEN_MODEL:-$CLAUDISH_ACTIVE_MODEL_NAME}" && if [ ! -z "$PROVIDER" ]; then MODEL_DISPLAY="$PROVIDER $MODEL_DISPLAY"; fi && if [ "$IN_TOK" -gt 0 ] 2>/dev/null && [ "$CTX_WIN" -gt 0 ] 2>/dev/null; then CTX_DISPLAY="$CTX% ($(fmt_tok $IN_TOK)/$(fmt_tok $CTX_WIN))"; else CTX_DISPLAY="$CTX%"; fi && printf "${CYAN2}${BOLD2}%s${RESET2} ${DIM2}•${RESET2} ${YELLOW2}%s${RESET2} ${DIM2}•${RESET2} ${GREEN2}%s${RESET2} ${DIM2}•${RESET2} ${MAGENTA2}%s${RESET2}\\n" "$DIR" "$MODEL_DISPLAY" "$COST_DISPLAY" "$CTX_DISPLAY"`;
35489
35530
  }
35490
- const settings = {
35491
- statusLine: {
35492
- type: "command",
35493
- command: statusCommand,
35494
- padding: 0
35495
- }
35531
+ const statusLine = {
35532
+ type: "command",
35533
+ command: statusCommand,
35534
+ padding: 0
35496
35535
  };
35536
+ const settings = { statusLine };
35497
35537
  writeFileSync7(tempPath, JSON.stringify(settings, null, 2), "utf-8");
35498
- return tempPath;
35538
+ return { path: tempPath, statusLine };
35539
+ }
35540
+ function mergeUserSettingsIfPresent(config3, tempSettingsPath, statusLine) {
35541
+ const idx = config3.claudeArgs.indexOf("--settings");
35542
+ if (idx === -1 || !config3.claudeArgs[idx + 1]) {
35543
+ return;
35544
+ }
35545
+ const userSettingsValue = config3.claudeArgs[idx + 1];
35546
+ try {
35547
+ let userSettings;
35548
+ if (userSettingsValue.trimStart().startsWith("{")) {
35549
+ userSettings = JSON.parse(userSettingsValue);
35550
+ } else {
35551
+ const rawUserSettings = readFileSync10(userSettingsValue, "utf-8");
35552
+ userSettings = JSON.parse(rawUserSettings);
35553
+ }
35554
+ userSettings.statusLine = statusLine;
35555
+ writeFileSync7(tempSettingsPath, JSON.stringify(userSettings, null, 2), "utf-8");
35556
+ } catch {
35557
+ if (!config3.quiet) {
35558
+ console.warn(`[claudish] Warning: could not merge user settings: ${userSettingsValue}`);
35559
+ }
35560
+ }
35561
+ config3.claudeArgs.splice(idx, 2);
35499
35562
  }
35500
35563
  async function runClaudeWithProxy(config3, proxyUrl) {
35501
35564
  const hasProfileMappings = config3.modelOpus || config3.modelSonnet || config3.modelHaiku || config3.modelSubagent;
35502
35565
  const modelId = config3.model || (hasProfileMappings ? undefined : "unknown");
35503
35566
  const portMatch = proxyUrl.match(/:(\d+)/);
35504
35567
  const port = portMatch ? portMatch[1] : "unknown";
35505
- const tempSettingsPath = createTempSettingsFile(modelId, port);
35568
+ const { path: tempSettingsPath, statusLine } = createTempSettingsFile(modelId, port);
35569
+ mergeUserSettingsIfPresent(config3, tempSettingsPath, statusLine);
35506
35570
  const claudeArgs = [];
35507
35571
  claudeArgs.push("--settings", tempSettingsPath);
35508
35572
  if (config3.interactive) {
@@ -35512,6 +35576,7 @@ async function runClaudeWithProxy(config3, proxyUrl) {
35512
35576
  if (config3.dangerous) {
35513
35577
  claudeArgs.push("--dangerouslyDisableSandbox");
35514
35578
  }
35579
+ claudeArgs.push(...config3.claudeArgs);
35515
35580
  } else {
35516
35581
  claudeArgs.push("-p");
35517
35582
  if (config3.autoApprove) {
@@ -35523,14 +35588,7 @@ async function runClaudeWithProxy(config3, proxyUrl) {
35523
35588
  if (config3.jsonOutput) {
35524
35589
  claudeArgs.push("--output-format", "json");
35525
35590
  }
35526
- if (config3.agent && config3.claudeArgs.length > 0) {
35527
- const modifiedArgs = [...config3.claudeArgs];
35528
- const agentId = config3.agent.startsWith("@agent-") ? config3.agent : `@agent-${config3.agent}`;
35529
- modifiedArgs[0] = `Use the ${agentId} agent to: ${modifiedArgs[0]}`;
35530
- claudeArgs.push(...modifiedArgs);
35531
- } else {
35532
- claudeArgs.push(...config3.claudeArgs);
35533
- }
35591
+ claudeArgs.push(...config3.claudeArgs);
35534
35592
  }
35535
35593
  const isLocalModel2 = modelId ? modelId.startsWith("ollama/") || modelId.startsWith("ollama:") || modelId.startsWith("lmstudio/") || modelId.startsWith("lmstudio:") || modelId.startsWith("vllm/") || modelId.startsWith("vllm:") || modelId.startsWith("mlx/") || modelId.startsWith("mlx:") || modelId.startsWith("http://") || modelId.startsWith("https://") : false;
35536
35594
  const modelDisplayName = modelId || config3.profile || "default";
@@ -63368,7 +63426,7 @@ var init_litellm = __esm(() => {
63368
63426
  });
63369
63427
 
63370
63428
  // src/adapters/litellm-adapter.ts
63371
- import { existsSync as existsSync14, readFileSync as readFileSync11 } from "node:fs";
63429
+ import { existsSync as existsSync14, readFileSync as readFileSync12 } from "node:fs";
63372
63430
  import { createHash as createHash4 } from "node:crypto";
63373
63431
  import { homedir as homedir14 } from "node:os";
63374
63432
  import { join as join15 } from "node:path";
@@ -63470,7 +63528,7 @@ var init_litellm_adapter = __esm(() => {
63470
63528
  const cachePath = join15(homedir14(), ".claudish", `litellm-models-${hash2}.json`);
63471
63529
  if (!existsSync14(cachePath))
63472
63530
  return true;
63473
- const cacheData = JSON.parse(readFileSync11(cachePath, "utf-8"));
63531
+ const cacheData = JSON.parse(readFileSync12(cachePath, "utf-8"));
63474
63532
  const model = cacheData.models?.find((m) => m.name === this.modelId);
63475
63533
  if (model && model.supportsVision === false) {
63476
63534
  log(`[LiteLLMAdapter] Model ${this.modelId} does not support vision`);
@@ -63588,12 +63646,12 @@ class AnthropicCompatProvider {
63588
63646
  }
63589
63647
  if (this.provider.name === "kimi-coding" && !this.apiKey) {
63590
63648
  try {
63591
- const { existsSync: existsSync15, readFileSync: readFileSync12 } = await import("node:fs");
63649
+ const { existsSync: existsSync15, readFileSync: readFileSync13 } = await import("node:fs");
63592
63650
  const { join: join16 } = await import("node:path");
63593
63651
  const { homedir: homedir15 } = await import("node:os");
63594
63652
  const credPath = join16(homedir15(), ".claudish", "kimi-oauth.json");
63595
63653
  if (existsSync15(credPath)) {
63596
- const data = JSON.parse(readFileSync12(credPath, "utf-8"));
63654
+ const data = JSON.parse(readFileSync13(credPath, "utf-8"));
63597
63655
  if (data.access_token && data.refresh_token) {
63598
63656
  const { KimiOAuth: KimiOAuth2 } = await Promise.resolve().then(() => (init_kimi_oauth(), exports_kimi_oauth));
63599
63657
  const oauth = KimiOAuth2.getInstance();
@@ -63815,7 +63873,7 @@ var init_ollamacloud_adapter = __esm(() => {
63815
63873
  });
63816
63874
 
63817
63875
  // src/services/pricing-cache.ts
63818
- import { readFileSync as readFileSync12, writeFileSync as writeFileSync9, existsSync as existsSync15, mkdirSync as mkdirSync9, statSync } from "node:fs";
63876
+ import { readFileSync as readFileSync13, writeFileSync as writeFileSync9, existsSync as existsSync15, mkdirSync as mkdirSync9, statSync } from "node:fs";
63819
63877
  import { homedir as homedir15 } from "node:os";
63820
63878
  import { join as join16 } from "node:path";
63821
63879
  function getDynamicPricingSync(provider, modelName) {
@@ -63887,7 +63945,7 @@ function loadDiskCache() {
63887
63945
  const stat = statSync(CACHE_FILE);
63888
63946
  const age = Date.now() - stat.mtimeMs;
63889
63947
  const isFresh = age < CACHE_TTL_MS;
63890
- const raw2 = readFileSync12(CACHE_FILE, "utf-8");
63948
+ const raw2 = readFileSync13(CACHE_FILE, "utf-8");
63891
63949
  const data = JSON.parse(raw2);
63892
63950
  for (const [key, pricing] of Object.entries(data)) {
63893
63951
  pricingMap.set(key, pricing);
@@ -64312,7 +64370,7 @@ __export(exports_update_checker, {
64312
64370
  checkForUpdates: () => checkForUpdates
64313
64371
  });
64314
64372
  import { execSync } from "node:child_process";
64315
- import { existsSync as existsSync16, mkdirSync as mkdirSync10, readFileSync as readFileSync13, unlinkSync as unlinkSync5, writeFileSync as writeFileSync10 } from "node:fs";
64373
+ import { existsSync as existsSync16, mkdirSync as mkdirSync10, readFileSync as readFileSync14, unlinkSync as unlinkSync5, writeFileSync as writeFileSync10 } from "node:fs";
64316
64374
  import { homedir as homedir16, platform as platform2, tmpdir as tmpdir2 } from "node:os";
64317
64375
  import { join as join17 } from "node:path";
64318
64376
  import { createInterface as createInterface2 } from "node:readline";
@@ -64346,7 +64404,7 @@ function readCache() {
64346
64404
  if (!existsSync16(cachePath)) {
64347
64405
  return null;
64348
64406
  }
64349
- const data = JSON.parse(readFileSync13(cachePath, "utf-8"));
64407
+ const data = JSON.parse(readFileSync14(cachePath, "utf-8"));
64350
64408
  return data;
64351
64409
  } catch {
64352
64410
  return null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "5.2.0",
3
+ "version": "5.3.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",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": "1.2.0",
3
- "lastUpdated": "2026-02-26",
3
+ "lastUpdated": "2026-03-02",
4
4
  "source": "https://openrouter.ai/models?categories=programming&fmt=cards&order=top-weekly",
5
5
  "models": [
6
6
  {