claudish 1.8.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -331,14 +331,14 @@ function getAvailableModels() {
331
331
  }
332
332
 
333
333
  // src/cli.ts
334
- import { readFileSync as readFileSync2 } from "node:fs";
334
+ import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync as existsSync2, mkdirSync, copyFileSync } from "node:fs";
335
335
  import { fileURLToPath as fileURLToPath2 } from "node:url";
336
336
  import { dirname as dirname2, join as join3 } from "node:path";
337
337
  var __filename3 = fileURLToPath2(import.meta.url);
338
338
  var __dirname3 = dirname2(__filename3);
339
339
  var packageJson = JSON.parse(readFileSync2(join3(__dirname3, "../package.json"), "utf-8"));
340
340
  var VERSION = packageJson.version;
341
- function parseArgs(args) {
341
+ async function parseArgs(args) {
342
342
  const config = {
343
343
  model: undefined,
344
344
  autoApprove: true,
@@ -429,8 +429,16 @@ function parseArgs(args) {
429
429
  } else if (arg === "--help" || arg === "-h") {
430
430
  printHelp();
431
431
  process.exit(0);
432
+ } else if (arg === "--help-ai") {
433
+ printAIAgentGuide();
434
+ process.exit(0);
435
+ } else if (arg === "--init") {
436
+ await initializeClaudishSkill();
437
+ process.exit(0);
432
438
  } else if (arg === "--list-models") {
433
439
  const hasJsonFlag = args.includes("--json");
440
+ const forceUpdate = args.includes("--force-update");
441
+ await checkAndUpdateModelsCache(forceUpdate);
434
442
  if (hasJsonFlag) {
435
443
  printAvailableModelsJSON();
436
444
  } else {
@@ -483,6 +491,164 @@ function parseArgs(args) {
483
491
  }
484
492
  return config;
485
493
  }
494
+ var CACHE_MAX_AGE_DAYS = 2;
495
+ var MODELS_JSON_PATH = join3(__dirname3, "../recommended-models.json");
496
+ function isCacheStale() {
497
+ if (!existsSync2(MODELS_JSON_PATH)) {
498
+ return true;
499
+ }
500
+ try {
501
+ const jsonContent = readFileSync2(MODELS_JSON_PATH, "utf-8");
502
+ const data = JSON.parse(jsonContent);
503
+ if (!data.lastUpdated) {
504
+ return true;
505
+ }
506
+ const lastUpdated = new Date(data.lastUpdated);
507
+ const now = new Date;
508
+ const ageInDays = (now.getTime() - lastUpdated.getTime()) / (1000 * 60 * 60 * 24);
509
+ return ageInDays > CACHE_MAX_AGE_DAYS;
510
+ } catch (error) {
511
+ return true;
512
+ }
513
+ }
514
+ async function updateModelsFromOpenRouter() {
515
+ console.error("\uD83D\uDD04 Updating model recommendations from OpenRouter...");
516
+ try {
517
+ const topWeeklyProgrammingModels = [
518
+ "x-ai/grok-code-fast-1",
519
+ "anthropic/claude-sonnet-4.5",
520
+ "google/gemini-2.5-flash",
521
+ "minimax/minimax-m2",
522
+ "anthropic/claude-sonnet-4",
523
+ "z-ai/glm-4.6",
524
+ "anthropic/claude-haiku-4.5",
525
+ "openai/gpt-5",
526
+ "qwen/qwen3-vl-235b-a22b-instruct",
527
+ "openrouter/polaris-alpha"
528
+ ];
529
+ const apiResponse = await fetch("https://openrouter.ai/api/v1/models");
530
+ if (!apiResponse.ok) {
531
+ throw new Error(`OpenRouter API returned ${apiResponse.status}`);
532
+ }
533
+ const openrouterData = await apiResponse.json();
534
+ const allModels = openrouterData.data;
535
+ const modelMap = new Map;
536
+ for (const model of allModels) {
537
+ modelMap.set(model.id, model);
538
+ }
539
+ const recommendations = [];
540
+ const providers = new Set;
541
+ for (const modelId of topWeeklyProgrammingModels) {
542
+ const provider = modelId.split("/")[0];
543
+ if (provider === "anthropic") {
544
+ continue;
545
+ }
546
+ if (providers.has(provider)) {
547
+ continue;
548
+ }
549
+ const model = modelMap.get(modelId);
550
+ if (!model) {
551
+ console.error(`⚠️ Model ${modelId} not found in OpenRouter API (including with limited metadata)`);
552
+ recommendations.push({
553
+ id: modelId,
554
+ name: modelId.split("/")[1].replace(/-/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()),
555
+ description: `${modelId} (metadata pending - not yet available in API)`,
556
+ provider: provider.charAt(0).toUpperCase() + provider.slice(1),
557
+ category: "programming",
558
+ priority: recommendations.length + 1,
559
+ pricing: {
560
+ input: "N/A",
561
+ output: "N/A",
562
+ average: "N/A"
563
+ },
564
+ context: "N/A",
565
+ maxOutputTokens: null,
566
+ modality: "text->text",
567
+ supportsTools: false,
568
+ supportsReasoning: false,
569
+ supportsVision: false,
570
+ isModerated: false,
571
+ recommended: true
572
+ });
573
+ providers.add(provider);
574
+ continue;
575
+ }
576
+ const name = model.name || modelId;
577
+ const description = model.description || `${name} model`;
578
+ const architecture = model.architecture || {};
579
+ const topProvider = model.top_provider || {};
580
+ const supportedParams = model.supported_parameters || [];
581
+ const promptPrice = parseFloat(model.pricing?.prompt || "0");
582
+ const completionPrice = parseFloat(model.pricing?.completion || "0");
583
+ const inputPrice = promptPrice > 0 ? `$${(promptPrice * 1e6).toFixed(2)}/1M` : "FREE";
584
+ const outputPrice = completionPrice > 0 ? `$${(completionPrice * 1e6).toFixed(2)}/1M` : "FREE";
585
+ const avgPrice = promptPrice > 0 || completionPrice > 0 ? `$${((promptPrice + completionPrice) / 2 * 1e6).toFixed(2)}/1M` : "FREE";
586
+ let category = "programming";
587
+ const lowerDesc = description.toLowerCase() + " " + name.toLowerCase();
588
+ if (lowerDesc.includes("vision") || lowerDesc.includes("vl-") || lowerDesc.includes("multimodal")) {
589
+ category = "vision";
590
+ } else if (lowerDesc.includes("reason")) {
591
+ category = "reasoning";
592
+ }
593
+ recommendations.push({
594
+ id: modelId,
595
+ name,
596
+ description,
597
+ provider: provider.charAt(0).toUpperCase() + provider.slice(1),
598
+ category,
599
+ priority: recommendations.length + 1,
600
+ pricing: {
601
+ input: inputPrice,
602
+ output: outputPrice,
603
+ average: avgPrice
604
+ },
605
+ context: topProvider.context_length ? `${Math.floor(topProvider.context_length / 1000)}K` : "N/A",
606
+ maxOutputTokens: topProvider.max_completion_tokens || null,
607
+ modality: architecture.modality || "text->text",
608
+ supportsTools: supportedParams.includes("tools") || supportedParams.includes("tool_choice"),
609
+ supportsReasoning: supportedParams.includes("reasoning") || supportedParams.includes("include_reasoning"),
610
+ supportsVision: (architecture.input_modalities || []).includes("image") || (architecture.input_modalities || []).includes("video"),
611
+ isModerated: topProvider.is_moderated || false,
612
+ recommended: true
613
+ });
614
+ providers.add(provider);
615
+ }
616
+ let version = "1.1.5";
617
+ if (existsSync2(MODELS_JSON_PATH)) {
618
+ try {
619
+ const existing = JSON.parse(readFileSync2(MODELS_JSON_PATH, "utf-8"));
620
+ version = existing.version || version;
621
+ } catch {}
622
+ }
623
+ const updatedData = {
624
+ version,
625
+ lastUpdated: new Date().toISOString().split("T")[0],
626
+ source: "https://openrouter.ai/models?categories=programming&fmt=cards&order=top-weekly",
627
+ models: recommendations
628
+ };
629
+ writeFileSync2(MODELS_JSON_PATH, JSON.stringify(updatedData, null, 2), "utf-8");
630
+ console.error(`✅ Updated ${recommendations.length} models (last updated: ${updatedData.lastUpdated})`);
631
+ } catch (error) {
632
+ console.error(`❌ Failed to update models: ${error instanceof Error ? error.message : String(error)}`);
633
+ console.error(" Using cached models (if available)");
634
+ }
635
+ }
636
+ async function checkAndUpdateModelsCache(forceUpdate = false) {
637
+ if (forceUpdate) {
638
+ console.error("\uD83D\uDD04 Force update requested...");
639
+ await updateModelsFromOpenRouter();
640
+ return;
641
+ }
642
+ if (isCacheStale()) {
643
+ console.error("⚠️ Model cache is stale (>2 days old), updating...");
644
+ await updateModelsFromOpenRouter();
645
+ } else {
646
+ try {
647
+ const data = JSON.parse(readFileSync2(MODELS_JSON_PATH, "utf-8"));
648
+ console.error(`✓ Using cached models (last updated: ${data.lastUpdated})`);
649
+ } catch {}
650
+ }
651
+ }
486
652
  function printVersion() {
487
653
  console.log(`claudish version ${VERSION}`);
488
654
  }
@@ -510,10 +676,13 @@ OPTIONS:
510
676
  --cost-tracker Enable cost tracking for API usage (NB!)
511
677
  --audit-costs Show cost analysis report
512
678
  --reset-costs Reset accumulated cost statistics
513
- --list-models List available OpenRouter models
679
+ --list-models List available OpenRouter models (auto-updates if stale >2 days)
514
680
  --list-models --json Output model list in JSON format
681
+ --force-update Force refresh model cache from OpenRouter API
515
682
  --version Show version information
516
683
  -h, --help Show this help message
684
+ --help-ai Show AI agent usage guide (file-based patterns, sub-agents)
685
+ --init Install Claudish skill in current project (.claude/skills/)
517
686
 
518
687
  MODES:
519
688
  • Interactive mode (default): Shows model selector, starts persistent session
@@ -574,29 +743,156 @@ EXAMPLES:
574
743
  claudish --verbose "analyze code structure"
575
744
 
576
745
  AVAILABLE MODELS:
577
- Run: claudish --list-models
746
+ List models: claudish --list-models
578
747
  JSON output: claudish --list-models --json
748
+ Force update: claudish --list-models --force-update
749
+ (Cache auto-updates every 2 days)
579
750
 
580
751
  MORE INFO:
581
752
  GitHub: https://github.com/MadAppGang/claude-code
582
753
  OpenRouter: https://openrouter.ai
583
754
  `);
584
755
  }
756
+ function printAIAgentGuide() {
757
+ try {
758
+ const guidePath = join3(__dirname3, "../AI_AGENT_GUIDE.md");
759
+ const guideContent = readFileSync2(guidePath, "utf-8");
760
+ console.log(guideContent);
761
+ } catch (error) {
762
+ console.error("Error reading AI Agent Guide:");
763
+ console.error(error instanceof Error ? error.message : String(error));
764
+ console.error(`
765
+ The guide should be located at: AI_AGENT_GUIDE.md`);
766
+ console.error("You can also view it online at:");
767
+ console.error("https://github.com/MadAppGang/claude-code/blob/main/mcp/claudish/AI_AGENT_GUIDE.md");
768
+ process.exit(1);
769
+ }
770
+ }
771
+ async function initializeClaudishSkill() {
772
+ console.log(`\uD83D\uDD27 Initializing Claudish skill in current project...
773
+ `);
774
+ const cwd = process.cwd();
775
+ const claudeDir = join3(cwd, ".claude");
776
+ const skillsDir = join3(claudeDir, "skills");
777
+ const claudishSkillDir = join3(skillsDir, "claudish-usage");
778
+ const skillFile = join3(claudishSkillDir, "SKILL.md");
779
+ if (existsSync2(skillFile)) {
780
+ console.log("✅ Claudish skill already installed at:");
781
+ console.log(` ${skillFile}
782
+ `);
783
+ console.log("\uD83D\uDCA1 To reinstall, delete the file and run 'claudish --init' again.");
784
+ return;
785
+ }
786
+ const sourceSkillPath = join3(__dirname3, "../skills/claudish-usage/SKILL.md");
787
+ if (!existsSync2(sourceSkillPath)) {
788
+ console.error("❌ Error: Claudish skill file not found in installation.");
789
+ console.error(` Expected at: ${sourceSkillPath}`);
790
+ console.error(`
791
+ \uD83D\uDCA1 Try reinstalling Claudish:`);
792
+ console.error(" npm install -g claudish@latest");
793
+ process.exit(1);
794
+ }
795
+ try {
796
+ if (!existsSync2(claudeDir)) {
797
+ mkdirSync(claudeDir, { recursive: true });
798
+ console.log("\uD83D\uDCC1 Created .claude/ directory");
799
+ }
800
+ if (!existsSync2(skillsDir)) {
801
+ mkdirSync(skillsDir, { recursive: true });
802
+ console.log("\uD83D\uDCC1 Created .claude/skills/ directory");
803
+ }
804
+ if (!existsSync2(claudishSkillDir)) {
805
+ mkdirSync(claudishSkillDir, { recursive: true });
806
+ console.log("\uD83D\uDCC1 Created .claude/skills/claudish-usage/ directory");
807
+ }
808
+ copyFileSync(sourceSkillPath, skillFile);
809
+ console.log("✅ Installed Claudish skill at:");
810
+ console.log(` ${skillFile}
811
+ `);
812
+ console.log("━".repeat(60));
813
+ console.log(`
814
+ \uD83C\uDF89 Claudish skill installed successfully!
815
+ `);
816
+ console.log(`\uD83D\uDCCB Next steps:
817
+ `);
818
+ console.log("1. Reload Claude Code to discover the skill");
819
+ console.log(" - Restart Claude Code, or");
820
+ console.log(` - Re-open your project
821
+ `);
822
+ console.log("2. Use Claudish with external models:");
823
+ console.log(' - User: "use Grok to implement feature X"');
824
+ console.log(` - Claude will automatically use the skill
825
+ `);
826
+ console.log("\uD83D\uDCA1 The skill enforces best practices:");
827
+ console.log(" ✅ Mandatory sub-agent delegation");
828
+ console.log(" ✅ File-based instruction patterns");
829
+ console.log(` ✅ Context window protection
830
+ `);
831
+ console.log(`\uD83D\uDCD6 For more info: claudish --help-ai
832
+ `);
833
+ console.log("━".repeat(60));
834
+ } catch (error) {
835
+ console.error(`
836
+ ❌ Error installing Claudish skill:`);
837
+ console.error(error instanceof Error ? error.message : String(error));
838
+ console.error(`
839
+ \uD83D\uDCA1 Make sure you have write permissions in the current directory.`);
840
+ process.exit(1);
841
+ }
842
+ }
585
843
  function printAvailableModels() {
844
+ let lastUpdated = "unknown";
845
+ let models = [];
846
+ try {
847
+ if (existsSync2(MODELS_JSON_PATH)) {
848
+ const data = JSON.parse(readFileSync2(MODELS_JSON_PATH, "utf-8"));
849
+ lastUpdated = data.lastUpdated || "unknown";
850
+ models = data.models || [];
851
+ }
852
+ } catch {
853
+ const basicModels = getAvailableModels();
854
+ const modelInfo = loadModelInfo();
855
+ for (const model of basicModels) {
856
+ const info = modelInfo[model];
857
+ console.log(` ${model}`);
858
+ console.log(` ${info.name} - ${info.description}`);
859
+ console.log("");
860
+ }
861
+ return;
862
+ }
586
863
  console.log(`
587
- Available OpenRouter Models (in priority order):
864
+ Available OpenRouter Models (last updated: ${lastUpdated}):
588
865
  `);
589
- const models = getAvailableModels();
590
- const modelInfo = loadModelInfo();
866
+ console.log(" Model Provider Pricing Context Capabilities");
867
+ console.log(" " + "─".repeat(86));
591
868
  for (const model of models) {
592
- const info = modelInfo[model];
593
- console.log(` ${model}`);
594
- console.log(` ${info.name} - ${info.description}`);
595
- console.log("");
596
- }
869
+ const modelId = model.id.length > 30 ? model.id.substring(0, 27) + "..." : model.id;
870
+ const modelIdPadded = modelId.padEnd(30);
871
+ const provider = model.provider.length > 10 ? model.provider.substring(0, 7) + "..." : model.provider;
872
+ const providerPadded = provider.padEnd(10);
873
+ let pricing = model.pricing?.average || "N/A";
874
+ if (pricing.includes("-1000000")) {
875
+ pricing = "varies";
876
+ } else if (pricing === "$0.00/1M" || pricing === "FREE") {
877
+ pricing = "FREE";
878
+ }
879
+ const pricingPadded = pricing.padEnd(10);
880
+ const context = model.context || "N/A";
881
+ const contextPadded = context.padEnd(7);
882
+ const tools = model.supportsTools ? "\uD83D\uDD27" : " ";
883
+ const reasoning = model.supportsReasoning ? "\uD83E\uDDE0" : " ";
884
+ const vision = model.supportsVision ? "\uD83D\uDC41️ " : " ";
885
+ const capabilities = `${tools} ${reasoning} ${vision}`;
886
+ console.log(` ${modelIdPadded} ${providerPadded} ${pricingPadded} ${contextPadded} ${capabilities}`);
887
+ }
888
+ console.log("");
889
+ console.log(" Capabilities: \uD83D\uDD27 Tools \uD83E\uDDE0 Reasoning \uD83D\uDC41️ Vision");
890
+ console.log("");
597
891
  console.log("Set default with: export CLAUDISH_MODEL=<model>");
598
892
  console.log(" or: export ANTHROPIC_MODEL=<model>");
599
- console.log(`Or use: claudish --model <model> ...
893
+ console.log("Or use: claudish --model <model> ...");
894
+ console.log(`
895
+ Force update: claudish --list-models --force-update
600
896
  `);
601
897
  }
602
898
  function printAvailableModelsJSON() {
@@ -776,7 +1072,7 @@ async function selectModelInteractively() {
776
1072
  }
777
1073
 
778
1074
  // src/logger.ts
779
- import { writeFileSync as writeFileSync2, appendFile, existsSync as existsSync2, mkdirSync } from "fs";
1075
+ import { writeFileSync as writeFileSync3, appendFile, existsSync as existsSync3, mkdirSync as mkdirSync2 } from "fs";
780
1076
  import { join as join4 } from "path";
781
1077
  var logFilePath = null;
782
1078
  var logLevel = "info";
@@ -807,7 +1103,7 @@ function scheduleFlush() {
807
1103
  flushTimer = null;
808
1104
  }
809
1105
  if (logFilePath && logBuffer.length > 0) {
810
- writeFileSync2(logFilePath, logBuffer.join(""), { flag: "a" });
1106
+ writeFileSync3(logFilePath, logBuffer.join(""), { flag: "a" });
811
1107
  logBuffer = [];
812
1108
  }
813
1109
  });
@@ -823,12 +1119,12 @@ function initLogger(debugMode, level = "info") {
823
1119
  }
824
1120
  logLevel = level;
825
1121
  const logsDir = join4(process.cwd(), "logs");
826
- if (!existsSync2(logsDir)) {
827
- mkdirSync(logsDir, { recursive: true });
1122
+ if (!existsSync3(logsDir)) {
1123
+ mkdirSync2(logsDir, { recursive: true });
828
1124
  }
829
1125
  const timestamp = new Date().toISOString().replace(/[:.]/g, "-").split("T").join("_").slice(0, -5);
830
1126
  logFilePath = join4(logsDir, `claudish_${timestamp}.log`);
831
- writeFileSync2(logFilePath, `Claudish Debug Log - ${new Date().toISOString()}
1127
+ writeFileSync3(logFilePath, `Claudish Debug Log - ${new Date().toISOString()}
832
1128
  Log Level: ${level}
833
1129
  ${"=".repeat(80)}
834
1130
 
@@ -3063,7 +3359,7 @@ var serve = (options, listeningListener) => {
3063
3359
  };
3064
3360
 
3065
3361
  // src/proxy-server.ts
3066
- import { writeFileSync as writeFileSync3 } from "node:fs";
3362
+ import { writeFileSync as writeFileSync4 } from "node:fs";
3067
3363
 
3068
3364
  // src/transform.ts
3069
3365
  function removeUriFormat(schema) {
@@ -3851,7 +4147,7 @@ data: ${JSON.stringify(data)}
3851
4147
  total_tokens: cumulativeInputTokens + cumulativeOutputTokens,
3852
4148
  updated_at: Date.now()
3853
4149
  };
3854
- writeFileSync3(tokenFilePath, JSON.stringify(tokenData), "utf-8");
4150
+ writeFileSync4(tokenFilePath, JSON.stringify(tokenData), "utf-8");
3855
4151
  } catch (error) {
3856
4152
  if (isLoggingEnabled()) {
3857
4153
  log(`[Proxy] Failed to write token file: ${error}`);
@@ -4330,7 +4626,7 @@ async function readStdin() {
4330
4626
  }
4331
4627
  async function main() {
4332
4628
  try {
4333
- const config = parseArgs(process.argv.slice(2));
4629
+ const config = await parseArgs(process.argv.slice(2));
4334
4630
  initLogger(config.debug, config.logLevel);
4335
4631
  if (config.debug && !config.quiet) {
4336
4632
  const logFile = getLogFilePath();
package/package.json CHANGED
@@ -1,29 +1,12 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "1.8.0",
3
+ "version": "2.0.0",
4
4
  "description": "CLI tool to run Claude Code with any OpenRouter model (Grok, GPT-5, MiniMax, etc.) via local Anthropic API-compatible proxy",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "bin": {
8
8
  "claudish": "dist/index.js"
9
9
  },
10
- "scripts": {
11
- "dev": "bun run src/index.ts",
12
- "dev:grok": "bun run src/index.ts --interactive --model x-ai/grok-code-fast-1",
13
- "dev:grok:debug": "bun run src/index.ts --interactive --debug --log-level info --model x-ai/grok-code-fast-1",
14
- "dev:info": "bun run src/index.ts --interactive --monitor",
15
- "extract-models": "bun run scripts/extract-models.ts",
16
- "build": "bun run extract-models && bun build src/index.ts --outdir dist --target node && chmod +x dist/index.js",
17
- "link": "npm link",
18
- "unlink": "npm unlink -g claudish",
19
- "install-global": "bun run build && npm link",
20
- "kill-all": "pkill -f 'bun.*claudish' || pkill -f 'claude.*claudish-settings' || echo 'No claudish processes found'",
21
- "test": "bun test ./tests/comprehensive-model-test.ts",
22
- "typecheck": "tsc --noEmit",
23
- "lint": "biome check .",
24
- "format": "biome format --write .",
25
- "postinstall": "node scripts/postinstall.cjs"
26
- },
27
10
  "dependencies": {
28
11
  "@hono/node-server": "^1.19.6",
29
12
  "hono": "^4.10.6"
@@ -35,7 +18,10 @@
35
18
  },
36
19
  "files": [
37
20
  "dist/",
38
- "scripts/"
21
+ "scripts/",
22
+ "skills/",
23
+ "AI_AGENT_GUIDE.md",
24
+ "recommended-models.json"
39
25
  ],
40
26
  "engines": {
41
27
  "node": ">=18.0.0",
@@ -51,5 +37,22 @@
51
37
  "ai"
52
38
  ],
53
39
  "author": "Jack Rudenko <i@madappgang.com>",
54
- "license": "MIT"
55
- }
40
+ "license": "MIT",
41
+ "scripts": {
42
+ "dev": "bun run src/index.ts",
43
+ "dev:grok": "bun run src/index.ts --interactive --model x-ai/grok-code-fast-1",
44
+ "dev:grok:debug": "bun run src/index.ts --interactive --debug --log-level info --model x-ai/grok-code-fast-1",
45
+ "dev:info": "bun run src/index.ts --interactive --monitor",
46
+ "extract-models": "bun run scripts/extract-models.ts",
47
+ "build": "bun run extract-models && bun build src/index.ts --outdir dist --target node && chmod +x dist/index.js",
48
+ "link": "npm link",
49
+ "unlink": "npm unlink -g claudish",
50
+ "install-global": "bun run build && npm link",
51
+ "kill-all": "pkill -f 'bun.*claudish' || pkill -f 'claude.*claudish-settings' || echo 'No claudish processes found'",
52
+ "test": "bun test ./tests/comprehensive-model-test.ts",
53
+ "typecheck": "tsc --noEmit",
54
+ "lint": "biome check .",
55
+ "format": "biome format --write .",
56
+ "postinstall": "node scripts/postinstall.cjs"
57
+ }
58
+ }
@@ -0,0 +1,154 @@
1
+ {
2
+ "version": "1.1.5",
3
+ "lastUpdated": "2025-11-19",
4
+ "source": "https://openrouter.ai/models?categories=programming&fmt=cards&order=top-weekly",
5
+ "models": [
6
+ {
7
+ "id": "x-ai/grok-code-fast-1",
8
+ "name": "xAI: Grok Code Fast 1",
9
+ "description": "Grok Code Fast 1 is a speedy and economical reasoning model that excels at agentic coding. With reasoning traces visible in the response, developers can steer Grok Code for high-quality work flows.",
10
+ "provider": "X-ai",
11
+ "category": "reasoning",
12
+ "priority": 1,
13
+ "pricing": {
14
+ "input": "$0.20/1M",
15
+ "output": "$1.50/1M",
16
+ "average": "$0.85/1M"
17
+ },
18
+ "context": "256K",
19
+ "maxOutputTokens": 10000,
20
+ "modality": "text->text",
21
+ "supportsTools": true,
22
+ "supportsReasoning": true,
23
+ "supportsVision": false,
24
+ "isModerated": false,
25
+ "recommended": true
26
+ },
27
+ {
28
+ "id": "google/gemini-2.5-flash",
29
+ "name": "Google: Gemini 2.5 Flash",
30
+ "description": "Gemini 2.5 Flash is Google's state-of-the-art workhorse model, specifically designed for advanced reasoning, coding, mathematics, and scientific tasks. It includes built-in \"thinking\" capabilities, enabling it to provide responses with greater accuracy and nuanced context handling. \n\nAdditionally, Gemini 2.5 Flash is configurable through the \"max tokens for reasoning\" parameter, as described in the documentation (https://openrouter.ai/docs/use-cases/reasoning-tokens#max-tokens-for-reasoning).",
31
+ "provider": "Google",
32
+ "category": "reasoning",
33
+ "priority": 2,
34
+ "pricing": {
35
+ "input": "$0.30/1M",
36
+ "output": "$2.50/1M",
37
+ "average": "$1.40/1M"
38
+ },
39
+ "context": "1048K",
40
+ "maxOutputTokens": 65535,
41
+ "modality": "text+image->text",
42
+ "supportsTools": true,
43
+ "supportsReasoning": true,
44
+ "supportsVision": true,
45
+ "isModerated": false,
46
+ "recommended": true
47
+ },
48
+ {
49
+ "id": "minimax/minimax-m2",
50
+ "name": "MiniMax: MiniMax M2",
51
+ "description": "MiniMax-M2 is a compact, high-efficiency large language model optimized for end-to-end coding and agentic workflows. With 10 billion activated parameters (230 billion total), it delivers near-frontier intelligence across general reasoning, tool use, and multi-step task execution while maintaining low latency and deployment efficiency.\n\nThe model excels in code generation, multi-file editing, compile-run-fix loops, and test-validated repair, showing strong results on SWE-Bench Verified, Multi-SWE-Bench, and Terminal-Bench. It also performs competitively in agentic evaluations such as BrowseComp and GAIA, effectively handling long-horizon planning, retrieval, and recovery from execution errors.\n\nBenchmarked by [Artificial Analysis](https://artificialanalysis.ai/models/minimax-m2), MiniMax-M2 ranks among the top open-source models for composite intelligence, spanning mathematics, science, and instruction-following. Its small activation footprint enables fast inference, high concurrency, and improved unit economics, making it well-suited for large-scale agents, developer assistants, and reasoning-driven applications that require responsiveness and cost efficiency.\n\nTo avoid degrading this model's performance, MiniMax highly recommends preserving reasoning between turns. Learn more about using reasoning_details to pass back reasoning in our [docs](https://openrouter.ai/docs/use-cases/reasoning-tokens#preserving-reasoning-blocks).",
52
+ "provider": "Minimax",
53
+ "category": "reasoning",
54
+ "priority": 3,
55
+ "pricing": {
56
+ "input": "$0.26/1M",
57
+ "output": "$1.02/1M",
58
+ "average": "$0.64/1M"
59
+ },
60
+ "context": "204K",
61
+ "maxOutputTokens": 131072,
62
+ "modality": "text->text",
63
+ "supportsTools": true,
64
+ "supportsReasoning": true,
65
+ "supportsVision": false,
66
+ "isModerated": false,
67
+ "recommended": true
68
+ },
69
+ {
70
+ "id": "z-ai/glm-4.6",
71
+ "name": "Z.AI: GLM 4.6",
72
+ "description": "Compared with GLM-4.5, this generation brings several key improvements:\n\nLonger context window: The context window has been expanded from 128K to 200K tokens, enabling the model to handle more complex agentic tasks.\nSuperior coding performance: The model achieves higher scores on code benchmarks and demonstrates better real-world performance in applications such as Claude Code、Cline、Roo Code and Kilo Code, including improvements in generating visually polished front-end pages.\nAdvanced reasoning: GLM-4.6 shows a clear improvement in reasoning performance and supports tool use during inference, leading to stronger overall capability.\nMore capable agents: GLM-4.6 exhibits stronger performance in tool using and search-based agents, and integrates more effectively within agent frameworks.\nRefined writing: Better aligns with human preferences in style and readability, and performs more naturally in role-playing scenarios.",
73
+ "provider": "Z-ai",
74
+ "category": "reasoning",
75
+ "priority": 4,
76
+ "pricing": {
77
+ "input": "$0.40/1M",
78
+ "output": "$1.75/1M",
79
+ "average": "$1.07/1M"
80
+ },
81
+ "context": "202K",
82
+ "maxOutputTokens": 202752,
83
+ "modality": "text->text",
84
+ "supportsTools": true,
85
+ "supportsReasoning": true,
86
+ "supportsVision": false,
87
+ "isModerated": false,
88
+ "recommended": true
89
+ },
90
+ {
91
+ "id": "openai/gpt-5",
92
+ "name": "OpenAI: GPT-5",
93
+ "description": "GPT-5 is OpenAI’s most advanced model, offering major improvements in reasoning, code quality, and user experience. It is optimized for complex tasks that require step-by-step reasoning, instruction following, and accuracy in high-stakes use cases. It supports test-time routing features and advanced prompt understanding, including user-specified intent like \"think hard about this.\" Improvements include reductions in hallucination, sycophancy, and better performance in coding, writing, and health-related tasks.",
94
+ "provider": "Openai",
95
+ "category": "reasoning",
96
+ "priority": 5,
97
+ "pricing": {
98
+ "input": "$1.25/1M",
99
+ "output": "$10.00/1M",
100
+ "average": "$5.63/1M"
101
+ },
102
+ "context": "400K",
103
+ "maxOutputTokens": 128000,
104
+ "modality": "text+image->text",
105
+ "supportsTools": true,
106
+ "supportsReasoning": true,
107
+ "supportsVision": true,
108
+ "isModerated": true,
109
+ "recommended": true
110
+ },
111
+ {
112
+ "id": "qwen/qwen3-vl-235b-a22b-instruct",
113
+ "name": "Qwen: Qwen3 VL 235B A22B Instruct",
114
+ "description": "Qwen3-VL-235B-A22B Instruct is an open-weight multimodal model that unifies strong text generation with visual understanding across images and video. The Instruct model targets general vision-language use (VQA, document parsing, chart/table extraction, multilingual OCR). The series emphasizes robust perception (recognition of diverse real-world and synthetic categories), spatial understanding (2D/3D grounding), and long-form visual comprehension, with competitive results on public multimodal benchmarks for both perception and reasoning.\n\nBeyond analysis, Qwen3-VL supports agentic interaction and tool use: it can follow complex instructions over multi-image, multi-turn dialogues; align text to video timelines for precise temporal queries; and operate GUI elements for automation tasks. The models also enable visual coding workflows—turning sketches or mockups into code and assisting with UI debugging—while maintaining strong text-only performance comparable to the flagship Qwen3 language models. This makes Qwen3-VL suitable for production scenarios spanning document AI, multilingual OCR, software/UI assistance, spatial/embodied tasks, and research on vision-language agents.",
115
+ "provider": "Qwen",
116
+ "category": "vision",
117
+ "priority": 6,
118
+ "pricing": {
119
+ "input": "$0.21/1M",
120
+ "output": "$1.90/1M",
121
+ "average": "$1.06/1M"
122
+ },
123
+ "context": "131K",
124
+ "maxOutputTokens": 32768,
125
+ "modality": "text+image->text",
126
+ "supportsTools": true,
127
+ "supportsReasoning": false,
128
+ "supportsVision": true,
129
+ "isModerated": false,
130
+ "recommended": true
131
+ },
132
+ {
133
+ "id": "openrouter/polaris-alpha",
134
+ "name": "Polaris Alpha",
135
+ "description": "openrouter/polaris-alpha (metadata pending - not yet available in API)",
136
+ "provider": "Openrouter",
137
+ "category": "programming",
138
+ "priority": 7,
139
+ "pricing": {
140
+ "input": "N/A",
141
+ "output": "N/A",
142
+ "average": "N/A"
143
+ },
144
+ "context": "N/A",
145
+ "maxOutputTokens": null,
146
+ "modality": "text->text",
147
+ "supportsTools": false,
148
+ "supportsReasoning": false,
149
+ "supportsVision": false,
150
+ "isModerated": false,
151
+ "recommended": true
152
+ }
153
+ ]
154
+ }
File without changes