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/AI_AGENT_GUIDE.md +534 -0
- package/README.md +102 -0
- package/dist/index.js +352 -22
- package/package.json +24 -21
- package/recommended-models.json +154 -0
- package/scripts/postinstall.cjs +0 -0
- package/skills/claudish-usage/SKILL.md +1127 -0
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
|
-
|
|
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
|
-
|
|
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 (
|
|
864
|
+
Available OpenRouter Models (last updated: ${lastUpdated}):
|
|
581
865
|
`);
|
|
582
|
-
|
|
583
|
-
|
|
866
|
+
console.log(" Model Provider Pricing Context Capabilities");
|
|
867
|
+
console.log(" " + "─".repeat(86));
|
|
584
868
|
for (const model of models) {
|
|
585
|
-
const
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
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(
|
|
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
|
|
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
|
-
|
|
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 (!
|
|
793
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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": "
|
|
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
|
+
}
|