claudish 1.7.1 → 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,21 @@ 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
- printAvailableModels();
439
+ const hasJsonFlag = args.includes("--json");
440
+ const forceUpdate = args.includes("--force-update");
441
+ await checkAndUpdateModelsCache(forceUpdate);
442
+ if (hasJsonFlag) {
443
+ printAvailableModelsJSON();
444
+ } else {
445
+ printAvailableModels();
446
+ }
434
447
  process.exit(0);
435
448
  } else {
436
449
  config.claudeArgs = args.slice(i);
@@ -478,6 +491,164 @@ function parseArgs(args) {
478
491
  }
479
492
  return config;
480
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
+ }
481
652
  function printVersion() {
482
653
  console.log(`claudish version ${VERSION}`);
483
654
  }
@@ -505,9 +676,13 @@ OPTIONS:
505
676
  --cost-tracker Enable cost tracking for API usage (NB!)
506
677
  --audit-costs Show cost analysis report
507
678
  --reset-costs Reset accumulated cost statistics
508
- --list-models List available OpenRouter models
679
+ --list-models List available OpenRouter models (auto-updates if stale >2 days)
680
+ --list-models --json Output model list in JSON format
681
+ --force-update Force refresh model cache from OpenRouter API
509
682
  --version Show version information
510
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/)
511
686
 
512
687
  MODES:
513
688
  • Interactive mode (default): Shows model selector, starts persistent session
@@ -568,30 +743,185 @@ EXAMPLES:
568
743
  claudish --verbose "analyze code structure"
569
744
 
570
745
  AVAILABLE MODELS:
571
- Run: claudish --list-models
746
+ List models: claudish --list-models
747
+ JSON output: claudish --list-models --json
748
+ Force update: claudish --list-models --force-update
749
+ (Cache auto-updates every 2 days)
572
750
 
573
751
  MORE INFO:
574
752
  GitHub: https://github.com/MadAppGang/claude-code
575
753
  OpenRouter: https://openrouter.ai
576
754
  `);
577
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
+ }
578
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
+ }
579
863
  console.log(`
580
- Available OpenRouter Models (in priority order):
864
+ Available OpenRouter Models (last updated: ${lastUpdated}):
581
865
  `);
582
- const models = getAvailableModels();
583
- const modelInfo = loadModelInfo();
866
+ console.log(" Model Provider Pricing Context Capabilities");
867
+ console.log(" " + "─".repeat(86));
584
868
  for (const model of models) {
585
- const info = modelInfo[model];
586
- console.log(` ${model}`);
587
- console.log(` ${info.name} - ${info.description}`);
588
- console.log("");
589
- }
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("");
590
891
  console.log("Set default with: export CLAUDISH_MODEL=<model>");
591
892
  console.log(" or: export ANTHROPIC_MODEL=<model>");
592
- 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
593
896
  `);
594
897
  }
898
+ function printAvailableModelsJSON() {
899
+ const jsonPath = join3(__dirname3, "../recommended-models.json");
900
+ try {
901
+ const jsonContent = readFileSync2(jsonPath, "utf-8");
902
+ const data = JSON.parse(jsonContent);
903
+ console.log(JSON.stringify(data, null, 2));
904
+ } catch (error) {
905
+ const models = getAvailableModels();
906
+ const modelInfo = loadModelInfo();
907
+ const output = {
908
+ version: VERSION,
909
+ lastUpdated: new Date().toISOString().split("T")[0],
910
+ source: "runtime",
911
+ models: models.filter((m) => m !== "custom").map((modelId) => {
912
+ const info = modelInfo[modelId];
913
+ return {
914
+ id: modelId,
915
+ name: info.name,
916
+ description: info.description,
917
+ provider: info.provider,
918
+ priority: info.priority
919
+ };
920
+ })
921
+ };
922
+ console.log(JSON.stringify(output, null, 2));
923
+ }
924
+ }
595
925
 
596
926
  // src/index.ts
597
927
  init_config();
@@ -742,7 +1072,7 @@ async function selectModelInteractively() {
742
1072
  }
743
1073
 
744
1074
  // src/logger.ts
745
- 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";
746
1076
  import { join as join4 } from "path";
747
1077
  var logFilePath = null;
748
1078
  var logLevel = "info";
@@ -773,7 +1103,7 @@ function scheduleFlush() {
773
1103
  flushTimer = null;
774
1104
  }
775
1105
  if (logFilePath && logBuffer.length > 0) {
776
- writeFileSync2(logFilePath, logBuffer.join(""), { flag: "a" });
1106
+ writeFileSync3(logFilePath, logBuffer.join(""), { flag: "a" });
777
1107
  logBuffer = [];
778
1108
  }
779
1109
  });
@@ -789,12 +1119,12 @@ function initLogger(debugMode, level = "info") {
789
1119
  }
790
1120
  logLevel = level;
791
1121
  const logsDir = join4(process.cwd(), "logs");
792
- if (!existsSync2(logsDir)) {
793
- mkdirSync(logsDir, { recursive: true });
1122
+ if (!existsSync3(logsDir)) {
1123
+ mkdirSync2(logsDir, { recursive: true });
794
1124
  }
795
1125
  const timestamp = new Date().toISOString().replace(/[:.]/g, "-").split("T").join("_").slice(0, -5);
796
1126
  logFilePath = join4(logsDir, `claudish_${timestamp}.log`);
797
- writeFileSync2(logFilePath, `Claudish Debug Log - ${new Date().toISOString()}
1127
+ writeFileSync3(logFilePath, `Claudish Debug Log - ${new Date().toISOString()}
798
1128
  Log Level: ${level}
799
1129
  ${"=".repeat(80)}
800
1130
 
@@ -3029,7 +3359,7 @@ var serve = (options, listeningListener) => {
3029
3359
  };
3030
3360
 
3031
3361
  // src/proxy-server.ts
3032
- import { writeFileSync as writeFileSync3 } from "node:fs";
3362
+ import { writeFileSync as writeFileSync4 } from "node:fs";
3033
3363
 
3034
3364
  // src/transform.ts
3035
3365
  function removeUriFormat(schema) {
@@ -3817,7 +4147,7 @@ data: ${JSON.stringify(data)}
3817
4147
  total_tokens: cumulativeInputTokens + cumulativeOutputTokens,
3818
4148
  updated_at: Date.now()
3819
4149
  };
3820
- writeFileSync3(tokenFilePath, JSON.stringify(tokenData), "utf-8");
4150
+ writeFileSync4(tokenFilePath, JSON.stringify(tokenData), "utf-8");
3821
4151
  } catch (error) {
3822
4152
  if (isLoggingEnabled()) {
3823
4153
  log(`[Proxy] Failed to write token file: ${error}`);
@@ -4296,7 +4626,7 @@ async function readStdin() {
4296
4626
  }
4297
4627
  async function main() {
4298
4628
  try {
4299
- const config = parseArgs(process.argv.slice(2));
4629
+ const config = await parseArgs(process.argv.slice(2));
4300
4630
  initLogger(config.debug, config.logLevel);
4301
4631
  if (config.debug && !config.quiet) {
4302
4632
  const logFile = getLogFilePath();
package/package.json CHANGED
@@ -1,29 +1,12 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "1.7.1",
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
+ }