claudish 3.3.11 → 3.4.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 +430 -286
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -58176,229 +58176,15 @@ var init_dist11 = __esm(() => {
58176
58176
  init_config();
58177
58177
  });
58178
58178
 
58179
- // src/claude-runner.ts
58180
- var exports_claude_runner = {};
58181
- __export(exports_claude_runner, {
58182
- runClaudeWithProxy: () => runClaudeWithProxy,
58183
- checkClaudeInstalled: () => checkClaudeInstalled
58184
- });
58185
- import { spawn } from "node:child_process";
58186
- import { writeFileSync as writeFileSync10, unlinkSync, mkdirSync as mkdirSync8 } from "node:fs";
58187
- import { tmpdir } from "node:os";
58188
- import { join as join11 } from "node:path";
58189
- function isWindows() {
58190
- return process.platform === "win32";
58191
- }
58192
- function createStatusLineScript(tokenFilePath) {
58193
- const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir();
58194
- const claudishDir = join11(homeDir, ".claudish");
58195
- const timestamp = Date.now();
58196
- const scriptPath = join11(claudishDir, `status-${timestamp}.js`);
58197
- const escapedTokenPath = tokenFilePath.replace(/\\/g, "\\\\");
58198
- const script = `
58199
- const fs = require('fs');
58200
- const path = require('path');
58201
-
58202
- const CYAN = "\\x1b[96m";
58203
- const YELLOW = "\\x1b[93m";
58204
- const GREEN = "\\x1b[92m";
58205
- const MAGENTA = "\\x1b[95m";
58206
- const DIM = "\\x1b[2m";
58207
- const RESET = "\\x1b[0m";
58208
- const BOLD = "\\x1b[1m";
58209
-
58210
- let input = '';
58211
- process.stdin.setEncoding('utf8');
58212
- process.stdin.on('data', chunk => input += chunk);
58213
- process.stdin.on('end', () => {
58214
- try {
58215
- let dir = path.basename(process.cwd());
58216
- if (dir.length > 15) dir = dir.substring(0, 12) + '...';
58217
-
58218
- let ctx = 100, cost = 0;
58219
- const model = process.env.CLAUDISH_ACTIVE_MODEL_NAME || 'unknown';
58220
- const isLocal = process.env.CLAUDISH_IS_LOCAL === 'true';
58221
-
58222
- try {
58223
- const tokens = JSON.parse(fs.readFileSync('${escapedTokenPath}', 'utf-8'));
58224
- cost = tokens.total_cost || 0;
58225
- ctx = tokens.context_left_percent || 100;
58226
- } catch (e) {
58227
- try {
58228
- const json = JSON.parse(input);
58229
- cost = json.total_cost_usd || 0;
58230
- } catch {}
58231
- }
58232
-
58233
- const costDisplay = isLocal ? 'LOCAL' : ('$' + cost.toFixed(3));
58234
- console.log(\`\${CYAN}\${BOLD}\${dir}\${RESET} \${DIM}•\${RESET} \${YELLOW}\${model}\${RESET} \${DIM}•\${RESET} \${GREEN}\${costDisplay}\${RESET} \${DIM}•\${RESET} \${MAGENTA}\${ctx}%\${RESET}\`);
58235
- } catch (e) {
58236
- console.log('claudish');
58237
- }
58238
- });
58239
- `;
58240
- writeFileSync10(scriptPath, script, "utf-8");
58241
- return scriptPath;
58242
- }
58243
- function createTempSettingsFile(modelDisplay, port) {
58244
- const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir();
58245
- const claudishDir = join11(homeDir, ".claudish");
58246
- try {
58247
- mkdirSync8(claudishDir, { recursive: true });
58248
- } catch {}
58249
- const timestamp = Date.now();
58250
- const tempPath = join11(claudishDir, `settings-${timestamp}.json`);
58251
- const tokenFilePath = join11(claudishDir, `tokens-${port}.json`);
58252
- let statusCommand;
58253
- if (isWindows()) {
58254
- const scriptPath = createStatusLineScript(tokenFilePath);
58255
- statusCommand = `node "${scriptPath}"`;
58256
- } else {
58257
- const CYAN2 = "\\033[96m";
58258
- const YELLOW2 = "\\033[93m";
58259
- const GREEN2 = "\\033[92m";
58260
- const MAGENTA = "\\033[95m";
58261
- const DIM2 = "\\033[2m";
58262
- const RESET2 = "\\033[0m";
58263
- const BOLD2 = "\\033[1m";
58264
- statusCommand = `JSON=$(cat) && DIR=$(basename "$(pwd)") && [ \${#DIR} -gt 15 ] && DIR="\${DIR:0:12}..." || true && CTX=100 && COST="0" && if [ -f "${tokenFilePath}" ]; then TOKENS=$(cat "${tokenFilePath}" 2>/dev/null) && 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; fi && if [ "$CLAUDISH_IS_LOCAL" = "true" ]; then COST_DISPLAY="LOCAL"; else COST_DISPLAY=$(printf "\\$%.3f" "$COST"); fi && printf "${CYAN2}${BOLD2}%s${RESET2} ${DIM2}•${RESET2} ${YELLOW2}%s${RESET2} ${DIM2}•${RESET2} ${GREEN2}%s${RESET2} ${DIM2}•${RESET2} ${MAGENTA}%s%%${RESET2}\\n" "$DIR" "$CLAUDISH_ACTIVE_MODEL_NAME" "$COST_DISPLAY" "$CTX"`;
58265
- }
58266
- const settings = {
58267
- statusLine: {
58268
- type: "command",
58269
- command: statusCommand,
58270
- padding: 0
58271
- }
58272
- };
58273
- writeFileSync10(tempPath, JSON.stringify(settings, null, 2), "utf-8");
58274
- return tempPath;
58275
- }
58276
- async function runClaudeWithProxy(config3, proxyUrl) {
58277
- const modelId = config3.model || "unknown";
58278
- const portMatch = proxyUrl.match(/:(\d+)/);
58279
- const port = portMatch ? portMatch[1] : "unknown";
58280
- const tempSettingsPath = createTempSettingsFile(modelId, port);
58281
- const claudeArgs = [];
58282
- claudeArgs.push("--settings", tempSettingsPath);
58283
- if (config3.interactive) {
58284
- if (config3.autoApprove) {
58285
- claudeArgs.push("--dangerously-skip-permissions");
58286
- }
58287
- if (config3.dangerous) {
58288
- claudeArgs.push("--dangerouslyDisableSandbox");
58289
- }
58290
- } else {
58291
- claudeArgs.push("-p");
58292
- if (config3.autoApprove) {
58293
- claudeArgs.push("--dangerously-skip-permissions");
58294
- }
58295
- if (config3.dangerous) {
58296
- claudeArgs.push("--dangerouslyDisableSandbox");
58297
- }
58298
- if (config3.jsonOutput) {
58299
- claudeArgs.push("--output-format", "json");
58300
- }
58301
- if (config3.agent && config3.claudeArgs.length > 0) {
58302
- const modifiedArgs = [...config3.claudeArgs];
58303
- const agentId = config3.agent.startsWith("@agent-") ? config3.agent : `@agent-${config3.agent}`;
58304
- modifiedArgs[0] = `Use the ${agentId} agent to: ${modifiedArgs[0]}`;
58305
- claudeArgs.push(...modifiedArgs);
58306
- } else {
58307
- claudeArgs.push(...config3.claudeArgs);
58308
- }
58309
- }
58310
- const isLocalModel = 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://");
58311
- const env = {
58312
- ...process.env,
58313
- ANTHROPIC_BASE_URL: proxyUrl,
58314
- [ENV.CLAUDISH_ACTIVE_MODEL_NAME]: modelId,
58315
- CLAUDISH_IS_LOCAL: isLocalModel ? "true" : "false",
58316
- [ENV.ANTHROPIC_MODEL]: modelId,
58317
- [ENV.ANTHROPIC_SMALL_FAST_MODEL]: modelId
58318
- };
58319
- if (config3.monitor) {
58320
- delete env.ANTHROPIC_API_KEY;
58321
- } else {
58322
- env.ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || "sk-ant-api03-placeholder-not-used-proxy-handles-auth-with-openrouter-key-xxxxxxxxxxxxxxxxxxxxx";
58323
- }
58324
- const log2 = (message) => {
58325
- if (!config3.quiet) {
58326
- console.log(message);
58327
- }
58328
- };
58329
- if (config3.interactive) {
58330
- log2(`
58331
- [claudish] Model: ${modelId}
58332
- `);
58333
- } else {
58334
- log2(`
58335
- [claudish] Model: ${modelId}`);
58336
- log2(`[claudish] Arguments: ${claudeArgs.join(" ")}
58337
- `);
58338
- }
58339
- const proc = spawn("claude", claudeArgs, {
58340
- env,
58341
- stdio: "inherit",
58342
- shell: isWindows()
58343
- });
58344
- setupSignalHandlers(proc, tempSettingsPath, config3.quiet);
58345
- const exitCode = await new Promise((resolve) => {
58346
- proc.on("exit", (code) => {
58347
- resolve(code ?? 1);
58348
- });
58349
- });
58350
- try {
58351
- unlinkSync(tempSettingsPath);
58352
- } catch (error46) {}
58353
- return exitCode;
58354
- }
58355
- function setupSignalHandlers(proc, tempSettingsPath, quiet) {
58356
- const signals2 = isWindows() ? ["SIGINT", "SIGTERM"] : ["SIGINT", "SIGTERM", "SIGHUP"];
58357
- for (const signal of signals2) {
58358
- process.on(signal, () => {
58359
- if (!quiet) {
58360
- console.log(`
58361
- [claudish] Received ${signal}, shutting down...`);
58362
- }
58363
- proc.kill();
58364
- try {
58365
- unlinkSync(tempSettingsPath);
58366
- } catch {}
58367
- process.exit(0);
58368
- });
58369
- }
58370
- }
58371
- async function checkClaudeInstalled() {
58372
- try {
58373
- const isWindows2 = process.platform === "win32";
58374
- const command = isWindows2 ? "where" : "which";
58375
- const proc = spawn(command, ["claude"], {
58376
- stdio: "ignore",
58377
- shell: isWindows2
58378
- });
58379
- const exitCode = await new Promise((resolve) => {
58380
- proc.on("exit", (code) => {
58381
- resolve(code ?? 1);
58382
- });
58383
- });
58384
- return exitCode === 0;
58385
- } catch {
58386
- return false;
58387
- }
58388
- }
58389
- var init_claude_runner = __esm(() => {
58390
- init_dist11();
58391
- });
58392
-
58393
58179
  // src/model-loader.ts
58394
58180
  import { readFileSync as readFileSync5, existsSync as existsSync6 } from "node:fs";
58395
- import { join as join12, dirname as dirname4 } from "node:path";
58181
+ import { join as join11, dirname as dirname4 } from "node:path";
58396
58182
  import { fileURLToPath as fileURLToPath4 } from "node:url";
58397
58183
  function loadModelInfo2() {
58398
58184
  if (_cachedModelInfo2) {
58399
58185
  return _cachedModelInfo2;
58400
58186
  }
58401
- const jsonPath = join12(__dirname5, "../recommended-models.json");
58187
+ const jsonPath = join11(__dirname5, "../recommended-models.json");
58402
58188
  if (existsSync6(jsonPath)) {
58403
58189
  try {
58404
58190
  const jsonContent = readFileSync5(jsonPath, "utf-8");
@@ -58431,7 +58217,7 @@ function getAvailableModels() {
58431
58217
  if (_cachedModelIds) {
58432
58218
  return _cachedModelIds;
58433
58219
  }
58434
- const jsonPath = join12(__dirname5, "../recommended-models.json");
58220
+ const jsonPath = join11(__dirname5, "../recommended-models.json");
58435
58221
  if (existsSync6(jsonPath)) {
58436
58222
  try {
58437
58223
  const jsonContent = readFileSync5(jsonPath, "utf-8");
@@ -58494,9 +58280,9 @@ __export(exports_cli, {
58494
58280
  parseArgs: () => parseArgs,
58495
58281
  getVersion: () => getVersion
58496
58282
  });
58497
- import { readFileSync as readFileSync6, writeFileSync as writeFileSync11, existsSync as existsSync7, mkdirSync as mkdirSync9, copyFileSync } from "node:fs";
58283
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync10, existsSync as existsSync7, mkdirSync as mkdirSync8, copyFileSync } from "node:fs";
58498
58284
  import { fileURLToPath as fileURLToPath5 } from "node:url";
58499
- import { dirname as dirname5, join as join13 } from "node:path";
58285
+ import { dirname as dirname5, join as join12 } from "node:path";
58500
58286
  function getVersion() {
58501
58287
  return VERSION;
58502
58288
  }
@@ -58788,7 +58574,7 @@ async function searchAndPrintModels(query, forceUpdate) {
58788
58574
  throw new Error(`API returned ${response.status}`);
58789
58575
  const data = await response.json();
58790
58576
  models = data.data;
58791
- writeFileSync11(ALL_MODELS_JSON_PATH2, JSON.stringify({
58577
+ writeFileSync10(ALL_MODELS_JSON_PATH2, JSON.stringify({
58792
58578
  lastUpdated: new Date().toISOString(),
58793
58579
  models
58794
58580
  }), "utf-8");
@@ -58889,7 +58675,7 @@ async function printAllModels(jsonOutput, forceUpdate) {
58889
58675
  throw new Error(`API returned ${response.status}`);
58890
58676
  const data = await response.json();
58891
58677
  models = data.data;
58892
- writeFileSync11(ALL_MODELS_JSON_PATH2, JSON.stringify({
58678
+ writeFileSync10(ALL_MODELS_JSON_PATH2, JSON.stringify({
58893
58679
  lastUpdated: new Date().toISOString(),
58894
58680
  models
58895
58681
  }), "utf-8");
@@ -59110,7 +58896,7 @@ async function updateModelsFromOpenRouter() {
59110
58896
  source: "https://openrouter.ai/models?categories=programming&fmt=cards&order=top-weekly",
59111
58897
  models: recommendations
59112
58898
  };
59113
- writeFileSync11(MODELS_JSON_PATH, JSON.stringify(updatedData, null, 2), "utf-8");
58899
+ writeFileSync10(MODELS_JSON_PATH, JSON.stringify(updatedData, null, 2), "utf-8");
59114
58900
  console.error(`✅ Updated ${recommendations.length} models (last updated: ${updatedData.lastUpdated})`);
59115
58901
  } catch (error46) {
59116
58902
  console.error(`❌ Failed to update models: ${error46 instanceof Error ? error46.message : String(error46)}`);
@@ -59194,6 +58980,9 @@ PROFILE MANAGEMENT:
59194
58980
  claudish profile show Show profile details (default profile or claudish profile show <name>)
59195
58981
  claudish profile edit Edit a profile (interactive or claudish profile edit <name>)
59196
58982
 
58983
+ UPDATE:
58984
+ claudish update Check for updates and install latest version
58985
+
59197
58986
  MODEL MAPPING (per-role override):
59198
58987
  --model-opus <model> Model for Opus role (planning, complex tasks)
59199
58988
  --model-sonnet <model> Model for Sonnet role (default coding)
@@ -59353,7 +59142,7 @@ MORE INFO:
59353
59142
  }
59354
59143
  function printAIAgentGuide() {
59355
59144
  try {
59356
- const guidePath = join13(__dirname6, "../AI_AGENT_GUIDE.md");
59145
+ const guidePath = join12(__dirname6, "../AI_AGENT_GUIDE.md");
59357
59146
  const guideContent = readFileSync6(guidePath, "utf-8");
59358
59147
  console.log(guideContent);
59359
59148
  } catch (error46) {
@@ -59370,10 +59159,10 @@ async function initializeClaudishSkill() {
59370
59159
  console.log(`\uD83D\uDD27 Initializing Claudish skill in current project...
59371
59160
  `);
59372
59161
  const cwd = process.cwd();
59373
- const claudeDir = join13(cwd, ".claude");
59374
- const skillsDir = join13(claudeDir, "skills");
59375
- const claudishSkillDir = join13(skillsDir, "claudish-usage");
59376
- const skillFile = join13(claudishSkillDir, "SKILL.md");
59162
+ const claudeDir = join12(cwd, ".claude");
59163
+ const skillsDir = join12(claudeDir, "skills");
59164
+ const claudishSkillDir = join12(skillsDir, "claudish-usage");
59165
+ const skillFile = join12(claudishSkillDir, "SKILL.md");
59377
59166
  if (existsSync7(skillFile)) {
59378
59167
  console.log("✅ Claudish skill already installed at:");
59379
59168
  console.log(` ${skillFile}
@@ -59381,7 +59170,7 @@ async function initializeClaudishSkill() {
59381
59170
  console.log("\uD83D\uDCA1 To reinstall, delete the file and run 'claudish --init' again.");
59382
59171
  return;
59383
59172
  }
59384
- const sourceSkillPath = join13(__dirname6, "../skills/claudish-usage/SKILL.md");
59173
+ const sourceSkillPath = join12(__dirname6, "../skills/claudish-usage/SKILL.md");
59385
59174
  if (!existsSync7(sourceSkillPath)) {
59386
59175
  console.error("❌ Error: Claudish skill file not found in installation.");
59387
59176
  console.error(` Expected at: ${sourceSkillPath}`);
@@ -59392,15 +59181,15 @@ async function initializeClaudishSkill() {
59392
59181
  }
59393
59182
  try {
59394
59183
  if (!existsSync7(claudeDir)) {
59395
- mkdirSync9(claudeDir, { recursive: true });
59184
+ mkdirSync8(claudeDir, { recursive: true });
59396
59185
  console.log("\uD83D\uDCC1 Created .claude/ directory");
59397
59186
  }
59398
59187
  if (!existsSync7(skillsDir)) {
59399
- mkdirSync9(skillsDir, { recursive: true });
59188
+ mkdirSync8(skillsDir, { recursive: true });
59400
59189
  console.log("\uD83D\uDCC1 Created .claude/skills/ directory");
59401
59190
  }
59402
59191
  if (!existsSync7(claudishSkillDir)) {
59403
- mkdirSync9(claudishSkillDir, { recursive: true });
59192
+ mkdirSync8(claudishSkillDir, { recursive: true });
59404
59193
  console.log("\uD83D\uDCC1 Created .claude/skills/claudish-usage/ directory");
59405
59194
  }
59406
59195
  copyFileSync(sourceSkillPath, skillFile);
@@ -59494,7 +59283,7 @@ Force update: claudish --list-models --force-update
59494
59283
  `);
59495
59284
  }
59496
59285
  function printAvailableModelsJSON() {
59497
- const jsonPath = join13(__dirname6, "../recommended-models.json");
59286
+ const jsonPath = join12(__dirname6, "../recommended-models.json");
59498
59287
  try {
59499
59288
  const jsonContent = readFileSync6(jsonPath, "utf-8");
59500
59289
  const data = JSON.parse(jsonContent);
@@ -59528,72 +59317,41 @@ var init_cli = __esm(() => {
59528
59317
  __filename6 = fileURLToPath5(import.meta.url);
59529
59318
  __dirname6 = dirname5(__filename6);
59530
59319
  try {
59531
- const packageJson = JSON.parse(readFileSync6(join13(__dirname6, "../package.json"), "utf-8"));
59320
+ const packageJson = JSON.parse(readFileSync6(join12(__dirname6, "../package.json"), "utf-8"));
59532
59321
  VERSION = packageJson.version;
59533
59322
  } catch {}
59534
- MODELS_JSON_PATH = join13(__dirname6, "../recommended-models.json");
59535
- ALL_MODELS_JSON_PATH2 = join13(__dirname6, "../all-models.json");
59536
- });
59537
-
59538
- // src/port-manager.ts
59539
- var exports_port_manager = {};
59540
- __export(exports_port_manager, {
59541
- isPortAvailable: () => isPortAvailable,
59542
- findAvailablePort: () => findAvailablePort
59323
+ MODELS_JSON_PATH = join12(__dirname6, "../recommended-models.json");
59324
+ ALL_MODELS_JSON_PATH2 = join12(__dirname6, "../all-models.json");
59543
59325
  });
59544
- import { createServer } from "node:net";
59545
- async function findAvailablePort(startPort = 3000, endPort = 9000) {
59546
- const randomPort = Math.floor(Math.random() * (endPort - startPort + 1)) + startPort;
59547
- if (await isPortAvailable(randomPort)) {
59548
- return randomPort;
59549
- }
59550
- for (let port = startPort;port <= endPort; port++) {
59551
- if (await isPortAvailable(port)) {
59552
- return port;
59553
- }
59554
- }
59555
- throw new Error(`No available ports found in range ${startPort}-${endPort}`);
59556
- }
59557
- async function isPortAvailable(port) {
59558
- return new Promise((resolve) => {
59559
- const server = createServer();
59560
- server.once("error", (err) => {
59561
- resolve(err.code !== "EADDRINUSE");
59562
- });
59563
- server.once("listening", () => {
59564
- server.close();
59565
- resolve(true);
59566
- });
59567
- server.listen(port, "127.0.0.1");
59568
- });
59569
- }
59570
- var init_port_manager = () => {};
59571
59326
 
59572
59327
  // src/update-checker.ts
59573
59328
  var exports_update_checker = {};
59574
59329
  __export(exports_update_checker, {
59330
+ fetchLatestVersion: () => fetchLatestVersion,
59331
+ compareVersions: () => compareVersions,
59332
+ clearCache: () => clearCache,
59575
59333
  checkForUpdates: () => checkForUpdates
59576
59334
  });
59577
59335
  import { execSync } from "node:child_process";
59336
+ import { existsSync as existsSync8, mkdirSync as mkdirSync9, readFileSync as readFileSync7, unlinkSync, writeFileSync as writeFileSync11 } from "node:fs";
59337
+ import { homedir as homedir7, platform, tmpdir } from "node:os";
59338
+ import { join as join13 } from "node:path";
59578
59339
  import { createInterface as createInterface2 } from "node:readline";
59579
- import { existsSync as existsSync8, readFileSync as readFileSync7, writeFileSync as writeFileSync12, mkdirSync as mkdirSync10, unlinkSync as unlinkSync2 } from "node:fs";
59580
- import { join as join14 } from "node:path";
59581
- import { tmpdir as tmpdir2, homedir as homedir7, platform } from "node:os";
59582
59340
  function getCacheFilePath() {
59583
59341
  let cacheDir;
59584
- if (isWindows2) {
59585
- const localAppData = process.env.LOCALAPPDATA || join14(homedir7(), "AppData", "Local");
59586
- cacheDir = join14(localAppData, "claudish");
59342
+ if (isWindows) {
59343
+ const localAppData = process.env.LOCALAPPDATA || join13(homedir7(), "AppData", "Local");
59344
+ cacheDir = join13(localAppData, "claudish");
59587
59345
  } else {
59588
- cacheDir = join14(homedir7(), ".cache", "claudish");
59346
+ cacheDir = join13(homedir7(), ".cache", "claudish");
59589
59347
  }
59590
59348
  try {
59591
59349
  if (!existsSync8(cacheDir)) {
59592
- mkdirSync10(cacheDir, { recursive: true });
59350
+ mkdirSync9(cacheDir, { recursive: true });
59593
59351
  }
59594
- return join14(cacheDir, "update-check.json");
59352
+ return join13(cacheDir, "update-check.json");
59595
59353
  } catch {
59596
- return join14(tmpdir2(), "claudish-update-check.json");
59354
+ return join13(tmpdir(), "claudish-update-check.json");
59597
59355
  }
59598
59356
  }
59599
59357
  function readCache() {
@@ -59615,7 +59373,7 @@ function writeCache(latestVersion) {
59615
59373
  lastCheck: Date.now(),
59616
59374
  latestVersion
59617
59375
  };
59618
- writeFileSync12(cachePath, JSON.stringify(data), "utf-8");
59376
+ writeFileSync11(cachePath, JSON.stringify(data), "utf-8");
59619
59377
  } catch {}
59620
59378
  }
59621
59379
  function isCacheValid(cache) {
@@ -59626,7 +59384,7 @@ function clearCache() {
59626
59384
  try {
59627
59385
  const cachePath = getCacheFilePath();
59628
59386
  if (existsSync8(cachePath)) {
59629
- unlinkSync2(cachePath);
59387
+ unlinkSync(cachePath);
59630
59388
  }
59631
59389
  } catch {}
59632
59390
  }
@@ -59679,10 +59437,9 @@ function runUpdate() {
59679
59437
  console.error(`
59680
59438
  [claudish] Updating...
59681
59439
  `);
59682
- const result = execSync("npm install -g claudish@latest", {
59440
+ execSync("npm install -g claudish@latest", {
59683
59441
  stdio: "inherit",
59684
- encoding: "utf-8",
59685
- shell: true
59442
+ shell: process.platform === "win32" ? "cmd.exe" : "/bin/sh"
59686
59443
  });
59687
59444
  console.error(`
59688
59445
  [claudish] Update complete! Please restart claudish.
@@ -59742,12 +59499,397 @@ async function checkForUpdates(currentVersion, options = {}) {
59742
59499
  }
59743
59500
  return false;
59744
59501
  }
59745
- var isWindows2, NPM_REGISTRY_URL = "https://registry.npmjs.org/claudish/latest", CACHE_MAX_AGE_MS;
59502
+ var isWindows, NPM_REGISTRY_URL = "https://registry.npmjs.org/claudish/latest", CACHE_MAX_AGE_MS;
59746
59503
  var init_update_checker = __esm(() => {
59747
- isWindows2 = platform() === "win32";
59504
+ isWindows = platform() === "win32";
59748
59505
  CACHE_MAX_AGE_MS = 24 * 60 * 60 * 1000;
59749
59506
  });
59750
59507
 
59508
+ // src/update-command.ts
59509
+ var exports_update_command = {};
59510
+ __export(exports_update_command, {
59511
+ updateCommand: () => updateCommand
59512
+ });
59513
+ import { execSync as execSync2 } from "node:child_process";
59514
+ import { createInterface as createInterface3 } from "node:readline";
59515
+ function detectInstallationMethod() {
59516
+ const scriptPath = process.argv[1] || "";
59517
+ if (scriptPath.includes("/opt/homebrew/") || scriptPath.includes("/usr/local/Cellar/")) {
59518
+ return { method: "brew", path: scriptPath };
59519
+ }
59520
+ if (scriptPath.includes("/.bun/")) {
59521
+ return { method: "bun", path: scriptPath };
59522
+ }
59523
+ if (scriptPath.includes("/node_modules/") || scriptPath.includes("/nvm/") || scriptPath.includes("/npm/")) {
59524
+ return { method: "npm", path: scriptPath };
59525
+ }
59526
+ return { method: "unknown", path: scriptPath };
59527
+ }
59528
+ function getUpdateCommand(method) {
59529
+ switch (method) {
59530
+ case "npm":
59531
+ return "npm install -g claudish@latest";
59532
+ case "bun":
59533
+ return "bun update -g claudish";
59534
+ case "brew":
59535
+ return "brew upgrade claudish";
59536
+ case "unknown":
59537
+ return "";
59538
+ }
59539
+ }
59540
+ function promptUser2(question) {
59541
+ return new Promise((resolve) => {
59542
+ const rl = createInterface3({
59543
+ input: process.stdin,
59544
+ output: process.stdout
59545
+ });
59546
+ rl.question(question, (answer) => {
59547
+ rl.close();
59548
+ const normalized = answer.toLowerCase().trim();
59549
+ resolve(normalized === "y" || normalized === "yes" || normalized === "");
59550
+ });
59551
+ });
59552
+ }
59553
+ async function executeUpdate(command) {
59554
+ try {
59555
+ console.log(`
59556
+ ${BOLD2}Updating...${RESET2}
59557
+ `);
59558
+ execSync2(command, {
59559
+ stdio: "inherit",
59560
+ shell: process.platform === "win32" ? "cmd.exe" : "/bin/sh"
59561
+ });
59562
+ console.log(`
59563
+ ${GREEN2}✓${RESET2} ${BOLD2}Update complete!${RESET2}`);
59564
+ console.log(`${CYAN2}Please restart any running claudish sessions.${RESET2}
59565
+ `);
59566
+ return true;
59567
+ } catch (error46) {
59568
+ console.error(`
59569
+ ${RED}✗${RESET2} ${BOLD2}Update failed.${RESET2}`);
59570
+ console.error(`${YELLOW2}Try manually:${RESET2}`);
59571
+ console.error(` ${command}
59572
+ `);
59573
+ return false;
59574
+ }
59575
+ }
59576
+ function printManualInstructions() {
59577
+ console.log(`
59578
+ ${BOLD2}Unable to detect installation method.${RESET2}`);
59579
+ console.log(`${YELLOW2}Please update manually:${RESET2}
59580
+ `);
59581
+ console.log(` ${CYAN2}npm:${RESET2} npm install -g claudish@latest`);
59582
+ console.log(` ${CYAN2}bun:${RESET2} bun install -g claudish@latest`);
59583
+ console.log(` ${CYAN2}brew:${RESET2} brew upgrade claudish ${RED}(not yet available)${RESET2}
59584
+ `);
59585
+ }
59586
+ async function updateCommand() {
59587
+ console.log(`
59588
+ ${BOLD2}Checking for updates...${RESET2}
59589
+ `);
59590
+ const currentVersion = getVersion();
59591
+ const latestVersion = await fetchLatestVersion();
59592
+ if (!latestVersion) {
59593
+ console.error(`${RED}✗${RESET2} Unable to fetch latest version from npm registry.`);
59594
+ console.error(`${YELLOW2}Please check your internet connection and try again.${RESET2}
59595
+ `);
59596
+ process.exit(1);
59597
+ }
59598
+ const comparison = compareVersions(latestVersion, currentVersion);
59599
+ if (comparison <= 0) {
59600
+ console.log(`${GREEN2}✓${RESET2} ${BOLD2}Already up-to-date!${RESET2}`);
59601
+ console.log(`${CYAN2}Current version: ${currentVersion}${RESET2}
59602
+ `);
59603
+ process.exit(0);
59604
+ }
59605
+ console.log(`${BOLD2}Current version:${RESET2} ${YELLOW2}${currentVersion}${RESET2}`);
59606
+ console.log(`${BOLD2}Latest version:${RESET2} ${GREEN2}${latestVersion}${RESET2}
59607
+ `);
59608
+ const installInfo = detectInstallationMethod();
59609
+ if (installInfo.method === "unknown") {
59610
+ printManualInstructions();
59611
+ process.exit(1);
59612
+ }
59613
+ console.log(`${BOLD2}Detected installation method:${RESET2} ${CYAN2}${installInfo.method}${RESET2}`);
59614
+ const command = getUpdateCommand(installInfo.method);
59615
+ if (installInfo.method === "brew") {
59616
+ console.log(`${RED}Note: Homebrew formula not yet published.${RESET2}
59617
+ `);
59618
+ printManualInstructions();
59619
+ process.exit(1);
59620
+ }
59621
+ console.log(`${BOLD2}Update command:${RESET2} ${command}
59622
+ `);
59623
+ const shouldUpdate = await promptUser2(`${BOLD2}Proceed with update? [Y/n]${RESET2} `);
59624
+ if (!shouldUpdate) {
59625
+ console.log(`
59626
+ ${YELLOW2}Update cancelled.${RESET2}`);
59627
+ console.log(`${CYAN2}Update later with: ${command}${RESET2}
59628
+ `);
59629
+ process.exit(0);
59630
+ }
59631
+ const success2 = await executeUpdate(command);
59632
+ if (success2) {
59633
+ clearCache();
59634
+ process.exit(0);
59635
+ } else {
59636
+ process.exit(1);
59637
+ }
59638
+ }
59639
+ var RESET2 = "\x1B[0m", BOLD2 = "\x1B[1m", GREEN2 = "\x1B[32m", YELLOW2 = "\x1B[33m", CYAN2 = "\x1B[36m", RED = "\x1B[31m";
59640
+ var init_update_command = __esm(() => {
59641
+ init_cli();
59642
+ init_update_checker();
59643
+ });
59644
+
59645
+ // src/claude-runner.ts
59646
+ var exports_claude_runner = {};
59647
+ __export(exports_claude_runner, {
59648
+ runClaudeWithProxy: () => runClaudeWithProxy,
59649
+ checkClaudeInstalled: () => checkClaudeInstalled
59650
+ });
59651
+ import { spawn } from "node:child_process";
59652
+ import { writeFileSync as writeFileSync12, unlinkSync as unlinkSync2, mkdirSync as mkdirSync10 } from "node:fs";
59653
+ import { tmpdir as tmpdir2 } from "node:os";
59654
+ import { join as join14 } from "node:path";
59655
+ function isWindows2() {
59656
+ return process.platform === "win32";
59657
+ }
59658
+ function createStatusLineScript(tokenFilePath) {
59659
+ const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
59660
+ const claudishDir = join14(homeDir, ".claudish");
59661
+ const timestamp = Date.now();
59662
+ const scriptPath = join14(claudishDir, `status-${timestamp}.js`);
59663
+ const escapedTokenPath = tokenFilePath.replace(/\\/g, "\\\\");
59664
+ const script = `
59665
+ const fs = require('fs');
59666
+ const path = require('path');
59667
+
59668
+ const CYAN = "\\x1b[96m";
59669
+ const YELLOW = "\\x1b[93m";
59670
+ const GREEN = "\\x1b[92m";
59671
+ const MAGENTA = "\\x1b[95m";
59672
+ const DIM = "\\x1b[2m";
59673
+ const RESET = "\\x1b[0m";
59674
+ const BOLD = "\\x1b[1m";
59675
+
59676
+ let input = '';
59677
+ process.stdin.setEncoding('utf8');
59678
+ process.stdin.on('data', chunk => input += chunk);
59679
+ process.stdin.on('end', () => {
59680
+ try {
59681
+ let dir = path.basename(process.cwd());
59682
+ if (dir.length > 15) dir = dir.substring(0, 12) + '...';
59683
+
59684
+ let ctx = 100, cost = 0;
59685
+ const model = process.env.CLAUDISH_ACTIVE_MODEL_NAME || 'unknown';
59686
+ const isLocal = process.env.CLAUDISH_IS_LOCAL === 'true';
59687
+
59688
+ try {
59689
+ const tokens = JSON.parse(fs.readFileSync('${escapedTokenPath}', 'utf-8'));
59690
+ cost = tokens.total_cost || 0;
59691
+ ctx = tokens.context_left_percent || 100;
59692
+ } catch (e) {
59693
+ try {
59694
+ const json = JSON.parse(input);
59695
+ cost = json.total_cost_usd || 0;
59696
+ } catch {}
59697
+ }
59698
+
59699
+ const costDisplay = isLocal ? 'LOCAL' : ('$' + cost.toFixed(3));
59700
+ console.log(\`\${CYAN}\${BOLD}\${dir}\${RESET} \${DIM}•\${RESET} \${YELLOW}\${model}\${RESET} \${DIM}•\${RESET} \${GREEN}\${costDisplay}\${RESET} \${DIM}•\${RESET} \${MAGENTA}\${ctx}%\${RESET}\`);
59701
+ } catch (e) {
59702
+ console.log('claudish');
59703
+ }
59704
+ });
59705
+ `;
59706
+ writeFileSync12(scriptPath, script, "utf-8");
59707
+ return scriptPath;
59708
+ }
59709
+ function createTempSettingsFile(modelDisplay, port) {
59710
+ const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
59711
+ const claudishDir = join14(homeDir, ".claudish");
59712
+ try {
59713
+ mkdirSync10(claudishDir, { recursive: true });
59714
+ } catch {}
59715
+ const timestamp = Date.now();
59716
+ const tempPath = join14(claudishDir, `settings-${timestamp}.json`);
59717
+ const tokenFilePath = join14(claudishDir, `tokens-${port}.json`);
59718
+ let statusCommand;
59719
+ if (isWindows2()) {
59720
+ const scriptPath = createStatusLineScript(tokenFilePath);
59721
+ statusCommand = `node "${scriptPath}"`;
59722
+ } else {
59723
+ const CYAN3 = "\\033[96m";
59724
+ const YELLOW3 = "\\033[93m";
59725
+ const GREEN3 = "\\033[92m";
59726
+ const MAGENTA = "\\033[95m";
59727
+ const DIM2 = "\\033[2m";
59728
+ const RESET3 = "\\033[0m";
59729
+ const BOLD3 = "\\033[1m";
59730
+ statusCommand = `JSON=$(cat) && DIR=$(basename "$(pwd)") && [ \${#DIR} -gt 15 ] && DIR="\${DIR:0:12}..." || true && CTX=100 && COST="0" && if [ -f "${tokenFilePath}" ]; then TOKENS=$(cat "${tokenFilePath}" 2>/dev/null) && 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; fi && if [ "$CLAUDISH_IS_LOCAL" = "true" ]; then COST_DISPLAY="LOCAL"; else COST_DISPLAY=$(printf "\\$%.3f" "$COST"); fi && printf "${CYAN3}${BOLD3}%s${RESET3} ${DIM2}•${RESET3} ${YELLOW3}%s${RESET3} ${DIM2}•${RESET3} ${GREEN3}%s${RESET3} ${DIM2}•${RESET3} ${MAGENTA}%s%%${RESET3}\\n" "$DIR" "$CLAUDISH_ACTIVE_MODEL_NAME" "$COST_DISPLAY" "$CTX"`;
59731
+ }
59732
+ const settings = {
59733
+ statusLine: {
59734
+ type: "command",
59735
+ command: statusCommand,
59736
+ padding: 0
59737
+ }
59738
+ };
59739
+ writeFileSync12(tempPath, JSON.stringify(settings, null, 2), "utf-8");
59740
+ return tempPath;
59741
+ }
59742
+ async function runClaudeWithProxy(config3, proxyUrl) {
59743
+ const modelId = config3.model || "unknown";
59744
+ const portMatch = proxyUrl.match(/:(\d+)/);
59745
+ const port = portMatch ? portMatch[1] : "unknown";
59746
+ const tempSettingsPath = createTempSettingsFile(modelId, port);
59747
+ const claudeArgs = [];
59748
+ claudeArgs.push("--settings", tempSettingsPath);
59749
+ if (config3.interactive) {
59750
+ if (config3.autoApprove) {
59751
+ claudeArgs.push("--dangerously-skip-permissions");
59752
+ }
59753
+ if (config3.dangerous) {
59754
+ claudeArgs.push("--dangerouslyDisableSandbox");
59755
+ }
59756
+ } else {
59757
+ claudeArgs.push("-p");
59758
+ if (config3.autoApprove) {
59759
+ claudeArgs.push("--dangerously-skip-permissions");
59760
+ }
59761
+ if (config3.dangerous) {
59762
+ claudeArgs.push("--dangerouslyDisableSandbox");
59763
+ }
59764
+ if (config3.jsonOutput) {
59765
+ claudeArgs.push("--output-format", "json");
59766
+ }
59767
+ if (config3.agent && config3.claudeArgs.length > 0) {
59768
+ const modifiedArgs = [...config3.claudeArgs];
59769
+ const agentId = config3.agent.startsWith("@agent-") ? config3.agent : `@agent-${config3.agent}`;
59770
+ modifiedArgs[0] = `Use the ${agentId} agent to: ${modifiedArgs[0]}`;
59771
+ claudeArgs.push(...modifiedArgs);
59772
+ } else {
59773
+ claudeArgs.push(...config3.claudeArgs);
59774
+ }
59775
+ }
59776
+ const isLocalModel = 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://");
59777
+ const env = {
59778
+ ...process.env,
59779
+ ANTHROPIC_BASE_URL: proxyUrl,
59780
+ [ENV.CLAUDISH_ACTIVE_MODEL_NAME]: modelId,
59781
+ CLAUDISH_IS_LOCAL: isLocalModel ? "true" : "false",
59782
+ [ENV.ANTHROPIC_MODEL]: modelId,
59783
+ [ENV.ANTHROPIC_SMALL_FAST_MODEL]: modelId
59784
+ };
59785
+ if (config3.monitor) {
59786
+ delete env.ANTHROPIC_API_KEY;
59787
+ } else {
59788
+ env.ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || "sk-ant-api03-placeholder-not-used-proxy-handles-auth-with-openrouter-key-xxxxxxxxxxxxxxxxxxxxx";
59789
+ }
59790
+ const log2 = (message) => {
59791
+ if (!config3.quiet) {
59792
+ console.log(message);
59793
+ }
59794
+ };
59795
+ if (config3.interactive) {
59796
+ log2(`
59797
+ [claudish] Model: ${modelId}
59798
+ `);
59799
+ } else {
59800
+ log2(`
59801
+ [claudish] Model: ${modelId}`);
59802
+ log2(`[claudish] Arguments: ${claudeArgs.join(" ")}
59803
+ `);
59804
+ }
59805
+ const proc = spawn("claude", claudeArgs, {
59806
+ env,
59807
+ stdio: "inherit",
59808
+ shell: isWindows2()
59809
+ });
59810
+ setupSignalHandlers(proc, tempSettingsPath, config3.quiet);
59811
+ const exitCode = await new Promise((resolve) => {
59812
+ proc.on("exit", (code) => {
59813
+ resolve(code ?? 1);
59814
+ });
59815
+ });
59816
+ try {
59817
+ unlinkSync2(tempSettingsPath);
59818
+ } catch (error46) {}
59819
+ return exitCode;
59820
+ }
59821
+ function setupSignalHandlers(proc, tempSettingsPath, quiet) {
59822
+ const signals2 = isWindows2() ? ["SIGINT", "SIGTERM"] : ["SIGINT", "SIGTERM", "SIGHUP"];
59823
+ for (const signal of signals2) {
59824
+ process.on(signal, () => {
59825
+ if (!quiet) {
59826
+ console.log(`
59827
+ [claudish] Received ${signal}, shutting down...`);
59828
+ }
59829
+ proc.kill();
59830
+ try {
59831
+ unlinkSync2(tempSettingsPath);
59832
+ } catch {}
59833
+ process.exit(0);
59834
+ });
59835
+ }
59836
+ }
59837
+ async function checkClaudeInstalled() {
59838
+ try {
59839
+ const isWindows3 = process.platform === "win32";
59840
+ const command = isWindows3 ? "where" : "which";
59841
+ const proc = spawn(command, ["claude"], {
59842
+ stdio: "ignore",
59843
+ shell: isWindows3
59844
+ });
59845
+ const exitCode = await new Promise((resolve) => {
59846
+ proc.on("exit", (code) => {
59847
+ resolve(code ?? 1);
59848
+ });
59849
+ });
59850
+ return exitCode === 0;
59851
+ } catch {
59852
+ return false;
59853
+ }
59854
+ }
59855
+ var init_claude_runner = __esm(() => {
59856
+ init_dist11();
59857
+ });
59858
+
59859
+ // src/port-manager.ts
59860
+ var exports_port_manager = {};
59861
+ __export(exports_port_manager, {
59862
+ isPortAvailable: () => isPortAvailable,
59863
+ findAvailablePort: () => findAvailablePort
59864
+ });
59865
+ import { createServer } from "node:net";
59866
+ async function findAvailablePort(startPort = 3000, endPort = 9000) {
59867
+ const randomPort = Math.floor(Math.random() * (endPort - startPort + 1)) + startPort;
59868
+ if (await isPortAvailable(randomPort)) {
59869
+ return randomPort;
59870
+ }
59871
+ for (let port = startPort;port <= endPort; port++) {
59872
+ if (await isPortAvailable(port)) {
59873
+ return port;
59874
+ }
59875
+ }
59876
+ throw new Error(`No available ports found in range ${startPort}-${endPort}`);
59877
+ }
59878
+ async function isPortAvailable(port) {
59879
+ return new Promise((resolve) => {
59880
+ const server = createServer();
59881
+ server.once("error", (err) => {
59882
+ resolve(err.code !== "EADDRINUSE");
59883
+ });
59884
+ server.once("listening", () => {
59885
+ server.close();
59886
+ resolve(true);
59887
+ });
59888
+ server.listen(port, "127.0.0.1");
59889
+ });
59890
+ }
59891
+ var init_port_manager = () => {};
59892
+
59751
59893
  // src/index.ts
59752
59894
  var import_dotenv2 = __toESM(require_main(), 1);
59753
59895
  import_dotenv2.config({ quiet: true });
@@ -59760,6 +59902,8 @@ if (isMcpMode) {
59760
59902
  Promise.resolve().then(() => (init_profile_commands(), exports_profile_commands)).then((pc) => pc.initCommand());
59761
59903
  } else if (firstArg === "profile") {
59762
59904
  Promise.resolve().then(() => (init_profile_commands(), exports_profile_commands)).then((pc) => pc.profileCommand(args.slice(1)));
59905
+ } else if (firstArg === "update") {
59906
+ Promise.resolve().then(() => (init_update_command(), exports_update_command)).then((uc) => uc.updateCommand());
59763
59907
  } else {
59764
59908
  runCli();
59765
59909
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "3.3.11",
3
+ "version": "3.4.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",