claudish 1.8.0 → 2.2.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 +130 -2
- package/dist/index.js +329 -22
- package/package.json +5 -2
- package/recommended-models.json +217 -0
- package/skills/claudish-usage/SKILL.md +1279 -0
package/dist/index.js
CHANGED
|
@@ -186,7 +186,14 @@ async function runClaudeWithProxy(config, proxyUrl) {
|
|
|
186
186
|
if (config.jsonOutput) {
|
|
187
187
|
claudeArgs.push("--output-format", "json");
|
|
188
188
|
}
|
|
189
|
-
|
|
189
|
+
if (config.agent && config.claudeArgs.length > 0) {
|
|
190
|
+
const modifiedArgs = [...config.claudeArgs];
|
|
191
|
+
const agentId = config.agent.startsWith("@agent-") ? config.agent : `@agent-${config.agent}`;
|
|
192
|
+
modifiedArgs[0] = `Use the ${agentId} agent to: ${modifiedArgs[0]}`;
|
|
193
|
+
claudeArgs.push(...modifiedArgs);
|
|
194
|
+
} else {
|
|
195
|
+
claudeArgs.push(...config.claudeArgs);
|
|
196
|
+
}
|
|
190
197
|
}
|
|
191
198
|
const env = {
|
|
192
199
|
...process.env,
|
|
@@ -331,14 +338,14 @@ function getAvailableModels() {
|
|
|
331
338
|
}
|
|
332
339
|
|
|
333
340
|
// src/cli.ts
|
|
334
|
-
import { readFileSync as readFileSync2 } from "node:fs";
|
|
341
|
+
import { readFileSync as readFileSync2, writeFileSync as writeFileSync3, existsSync as existsSync2, mkdirSync, copyFileSync } from "node:fs";
|
|
335
342
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
336
343
|
import { dirname as dirname2, join as join3 } from "node:path";
|
|
337
344
|
var __filename3 = fileURLToPath2(import.meta.url);
|
|
338
345
|
var __dirname3 = dirname2(__filename3);
|
|
339
346
|
var packageJson = JSON.parse(readFileSync2(join3(__dirname3, "../package.json"), "utf-8"));
|
|
340
347
|
var VERSION = packageJson.version;
|
|
341
|
-
function parseArgs(args) {
|
|
348
|
+
async function parseArgs(args) {
|
|
342
349
|
const config = {
|
|
343
350
|
model: undefined,
|
|
344
351
|
autoApprove: true,
|
|
@@ -429,8 +436,16 @@ function parseArgs(args) {
|
|
|
429
436
|
} else if (arg === "--help" || arg === "-h") {
|
|
430
437
|
printHelp();
|
|
431
438
|
process.exit(0);
|
|
439
|
+
} else if (arg === "--help-ai") {
|
|
440
|
+
printAIAgentGuide();
|
|
441
|
+
process.exit(0);
|
|
442
|
+
} else if (arg === "--init") {
|
|
443
|
+
await initializeClaudishSkill();
|
|
444
|
+
process.exit(0);
|
|
432
445
|
} else if (arg === "--list-models") {
|
|
433
446
|
const hasJsonFlag = args.includes("--json");
|
|
447
|
+
const forceUpdate = args.includes("--force-update");
|
|
448
|
+
await checkAndUpdateModelsCache(forceUpdate);
|
|
434
449
|
if (hasJsonFlag) {
|
|
435
450
|
printAvailableModelsJSON();
|
|
436
451
|
} else {
|
|
@@ -483,6 +498,164 @@ function parseArgs(args) {
|
|
|
483
498
|
}
|
|
484
499
|
return config;
|
|
485
500
|
}
|
|
501
|
+
var CACHE_MAX_AGE_DAYS = 2;
|
|
502
|
+
var MODELS_JSON_PATH = join3(__dirname3, "../recommended-models.json");
|
|
503
|
+
function isCacheStale() {
|
|
504
|
+
if (!existsSync2(MODELS_JSON_PATH)) {
|
|
505
|
+
return true;
|
|
506
|
+
}
|
|
507
|
+
try {
|
|
508
|
+
const jsonContent = readFileSync2(MODELS_JSON_PATH, "utf-8");
|
|
509
|
+
const data = JSON.parse(jsonContent);
|
|
510
|
+
if (!data.lastUpdated) {
|
|
511
|
+
return true;
|
|
512
|
+
}
|
|
513
|
+
const lastUpdated = new Date(data.lastUpdated);
|
|
514
|
+
const now = new Date;
|
|
515
|
+
const ageInDays = (now.getTime() - lastUpdated.getTime()) / (1000 * 60 * 60 * 24);
|
|
516
|
+
return ageInDays > CACHE_MAX_AGE_DAYS;
|
|
517
|
+
} catch (error) {
|
|
518
|
+
return true;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
async function updateModelsFromOpenRouter() {
|
|
522
|
+
console.error("\uD83D\uDD04 Updating model recommendations from OpenRouter...");
|
|
523
|
+
try {
|
|
524
|
+
const topWeeklyProgrammingModels = [
|
|
525
|
+
"x-ai/grok-code-fast-1",
|
|
526
|
+
"anthropic/claude-sonnet-4.5",
|
|
527
|
+
"google/gemini-2.5-flash",
|
|
528
|
+
"minimax/minimax-m2",
|
|
529
|
+
"anthropic/claude-sonnet-4",
|
|
530
|
+
"z-ai/glm-4.6",
|
|
531
|
+
"anthropic/claude-haiku-4.5",
|
|
532
|
+
"openai/gpt-5",
|
|
533
|
+
"qwen/qwen3-vl-235b-a22b-instruct",
|
|
534
|
+
"openrouter/polaris-alpha"
|
|
535
|
+
];
|
|
536
|
+
const apiResponse = await fetch("https://openrouter.ai/api/v1/models");
|
|
537
|
+
if (!apiResponse.ok) {
|
|
538
|
+
throw new Error(`OpenRouter API returned ${apiResponse.status}`);
|
|
539
|
+
}
|
|
540
|
+
const openrouterData = await apiResponse.json();
|
|
541
|
+
const allModels = openrouterData.data;
|
|
542
|
+
const modelMap = new Map;
|
|
543
|
+
for (const model of allModels) {
|
|
544
|
+
modelMap.set(model.id, model);
|
|
545
|
+
}
|
|
546
|
+
const recommendations = [];
|
|
547
|
+
const providers = new Set;
|
|
548
|
+
for (const modelId of topWeeklyProgrammingModels) {
|
|
549
|
+
const provider = modelId.split("/")[0];
|
|
550
|
+
if (provider === "anthropic") {
|
|
551
|
+
continue;
|
|
552
|
+
}
|
|
553
|
+
if (providers.has(provider)) {
|
|
554
|
+
continue;
|
|
555
|
+
}
|
|
556
|
+
const model = modelMap.get(modelId);
|
|
557
|
+
if (!model) {
|
|
558
|
+
console.error(`⚠️ Model ${modelId} not found in OpenRouter API (including with limited metadata)`);
|
|
559
|
+
recommendations.push({
|
|
560
|
+
id: modelId,
|
|
561
|
+
name: modelId.split("/")[1].replace(/-/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()),
|
|
562
|
+
description: `${modelId} (metadata pending - not yet available in API)`,
|
|
563
|
+
provider: provider.charAt(0).toUpperCase() + provider.slice(1),
|
|
564
|
+
category: "programming",
|
|
565
|
+
priority: recommendations.length + 1,
|
|
566
|
+
pricing: {
|
|
567
|
+
input: "N/A",
|
|
568
|
+
output: "N/A",
|
|
569
|
+
average: "N/A"
|
|
570
|
+
},
|
|
571
|
+
context: "N/A",
|
|
572
|
+
maxOutputTokens: null,
|
|
573
|
+
modality: "text->text",
|
|
574
|
+
supportsTools: false,
|
|
575
|
+
supportsReasoning: false,
|
|
576
|
+
supportsVision: false,
|
|
577
|
+
isModerated: false,
|
|
578
|
+
recommended: true
|
|
579
|
+
});
|
|
580
|
+
providers.add(provider);
|
|
581
|
+
continue;
|
|
582
|
+
}
|
|
583
|
+
const name = model.name || modelId;
|
|
584
|
+
const description = model.description || `${name} model`;
|
|
585
|
+
const architecture = model.architecture || {};
|
|
586
|
+
const topProvider = model.top_provider || {};
|
|
587
|
+
const supportedParams = model.supported_parameters || [];
|
|
588
|
+
const promptPrice = parseFloat(model.pricing?.prompt || "0");
|
|
589
|
+
const completionPrice = parseFloat(model.pricing?.completion || "0");
|
|
590
|
+
const inputPrice = promptPrice > 0 ? `$${(promptPrice * 1e6).toFixed(2)}/1M` : "FREE";
|
|
591
|
+
const outputPrice = completionPrice > 0 ? `$${(completionPrice * 1e6).toFixed(2)}/1M` : "FREE";
|
|
592
|
+
const avgPrice = promptPrice > 0 || completionPrice > 0 ? `$${((promptPrice + completionPrice) / 2 * 1e6).toFixed(2)}/1M` : "FREE";
|
|
593
|
+
let category = "programming";
|
|
594
|
+
const lowerDesc = description.toLowerCase() + " " + name.toLowerCase();
|
|
595
|
+
if (lowerDesc.includes("vision") || lowerDesc.includes("vl-") || lowerDesc.includes("multimodal")) {
|
|
596
|
+
category = "vision";
|
|
597
|
+
} else if (lowerDesc.includes("reason")) {
|
|
598
|
+
category = "reasoning";
|
|
599
|
+
}
|
|
600
|
+
recommendations.push({
|
|
601
|
+
id: modelId,
|
|
602
|
+
name,
|
|
603
|
+
description,
|
|
604
|
+
provider: provider.charAt(0).toUpperCase() + provider.slice(1),
|
|
605
|
+
category,
|
|
606
|
+
priority: recommendations.length + 1,
|
|
607
|
+
pricing: {
|
|
608
|
+
input: inputPrice,
|
|
609
|
+
output: outputPrice,
|
|
610
|
+
average: avgPrice
|
|
611
|
+
},
|
|
612
|
+
context: topProvider.context_length ? `${Math.floor(topProvider.context_length / 1000)}K` : "N/A",
|
|
613
|
+
maxOutputTokens: topProvider.max_completion_tokens || null,
|
|
614
|
+
modality: architecture.modality || "text->text",
|
|
615
|
+
supportsTools: supportedParams.includes("tools") || supportedParams.includes("tool_choice"),
|
|
616
|
+
supportsReasoning: supportedParams.includes("reasoning") || supportedParams.includes("include_reasoning"),
|
|
617
|
+
supportsVision: (architecture.input_modalities || []).includes("image") || (architecture.input_modalities || []).includes("video"),
|
|
618
|
+
isModerated: topProvider.is_moderated || false,
|
|
619
|
+
recommended: true
|
|
620
|
+
});
|
|
621
|
+
providers.add(provider);
|
|
622
|
+
}
|
|
623
|
+
let version = "1.1.5";
|
|
624
|
+
if (existsSync2(MODELS_JSON_PATH)) {
|
|
625
|
+
try {
|
|
626
|
+
const existing = JSON.parse(readFileSync2(MODELS_JSON_PATH, "utf-8"));
|
|
627
|
+
version = existing.version || version;
|
|
628
|
+
} catch {}
|
|
629
|
+
}
|
|
630
|
+
const updatedData = {
|
|
631
|
+
version,
|
|
632
|
+
lastUpdated: new Date().toISOString().split("T")[0],
|
|
633
|
+
source: "https://openrouter.ai/models?categories=programming&fmt=cards&order=top-weekly",
|
|
634
|
+
models: recommendations
|
|
635
|
+
};
|
|
636
|
+
writeFileSync3(MODELS_JSON_PATH, JSON.stringify(updatedData, null, 2), "utf-8");
|
|
637
|
+
console.error(`✅ Updated ${recommendations.length} models (last updated: ${updatedData.lastUpdated})`);
|
|
638
|
+
} catch (error) {
|
|
639
|
+
console.error(`❌ Failed to update models: ${error instanceof Error ? error.message : String(error)}`);
|
|
640
|
+
console.error(" Using cached models (if available)");
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
async function checkAndUpdateModelsCache(forceUpdate = false) {
|
|
644
|
+
if (forceUpdate) {
|
|
645
|
+
console.error("\uD83D\uDD04 Force update requested...");
|
|
646
|
+
await updateModelsFromOpenRouter();
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
if (isCacheStale()) {
|
|
650
|
+
console.error("⚠️ Model cache is stale (>2 days old), updating...");
|
|
651
|
+
await updateModelsFromOpenRouter();
|
|
652
|
+
} else {
|
|
653
|
+
try {
|
|
654
|
+
const data = JSON.parse(readFileSync2(MODELS_JSON_PATH, "utf-8"));
|
|
655
|
+
console.error(`✓ Using cached models (last updated: ${data.lastUpdated})`);
|
|
656
|
+
} catch {}
|
|
657
|
+
}
|
|
658
|
+
}
|
|
486
659
|
function printVersion() {
|
|
487
660
|
console.log(`claudish version ${VERSION}`);
|
|
488
661
|
}
|
|
@@ -510,10 +683,17 @@ OPTIONS:
|
|
|
510
683
|
--cost-tracker Enable cost tracking for API usage (NB!)
|
|
511
684
|
--audit-costs Show cost analysis report
|
|
512
685
|
--reset-costs Reset accumulated cost statistics
|
|
513
|
-
--list-models List available OpenRouter models
|
|
686
|
+
--list-models List available OpenRouter models (auto-updates if stale >2 days)
|
|
514
687
|
--list-models --json Output model list in JSON format
|
|
688
|
+
--force-update Force refresh model cache from OpenRouter API
|
|
515
689
|
--version Show version information
|
|
516
690
|
-h, --help Show this help message
|
|
691
|
+
--help-ai Show AI agent usage guide (file-based patterns, sub-agents)
|
|
692
|
+
--init Install Claudish skill in current project (.claude/skills/)
|
|
693
|
+
|
|
694
|
+
CUSTOM MODELS:
|
|
695
|
+
Claudish accepts ANY valid OpenRouter model ID, even if not in --list-models
|
|
696
|
+
Example: claudish --model your_provider/custom-model-123 "task"
|
|
517
697
|
|
|
518
698
|
MODES:
|
|
519
699
|
• Interactive mode (default): Shows model selector, starts persistent session
|
|
@@ -574,29 +754,156 @@ EXAMPLES:
|
|
|
574
754
|
claudish --verbose "analyze code structure"
|
|
575
755
|
|
|
576
756
|
AVAILABLE MODELS:
|
|
577
|
-
|
|
757
|
+
List models: claudish --list-models
|
|
578
758
|
JSON output: claudish --list-models --json
|
|
759
|
+
Force update: claudish --list-models --force-update
|
|
760
|
+
(Cache auto-updates every 2 days)
|
|
579
761
|
|
|
580
762
|
MORE INFO:
|
|
581
763
|
GitHub: https://github.com/MadAppGang/claude-code
|
|
582
764
|
OpenRouter: https://openrouter.ai
|
|
583
765
|
`);
|
|
584
766
|
}
|
|
767
|
+
function printAIAgentGuide() {
|
|
768
|
+
try {
|
|
769
|
+
const guidePath = join3(__dirname3, "../AI_AGENT_GUIDE.md");
|
|
770
|
+
const guideContent = readFileSync2(guidePath, "utf-8");
|
|
771
|
+
console.log(guideContent);
|
|
772
|
+
} catch (error) {
|
|
773
|
+
console.error("Error reading AI Agent Guide:");
|
|
774
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
775
|
+
console.error(`
|
|
776
|
+
The guide should be located at: AI_AGENT_GUIDE.md`);
|
|
777
|
+
console.error("You can also view it online at:");
|
|
778
|
+
console.error("https://github.com/MadAppGang/claude-code/blob/main/mcp/claudish/AI_AGENT_GUIDE.md");
|
|
779
|
+
process.exit(1);
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
async function initializeClaudishSkill() {
|
|
783
|
+
console.log(`\uD83D\uDD27 Initializing Claudish skill in current project...
|
|
784
|
+
`);
|
|
785
|
+
const cwd = process.cwd();
|
|
786
|
+
const claudeDir = join3(cwd, ".claude");
|
|
787
|
+
const skillsDir = join3(claudeDir, "skills");
|
|
788
|
+
const claudishSkillDir = join3(skillsDir, "claudish-usage");
|
|
789
|
+
const skillFile = join3(claudishSkillDir, "SKILL.md");
|
|
790
|
+
if (existsSync2(skillFile)) {
|
|
791
|
+
console.log("✅ Claudish skill already installed at:");
|
|
792
|
+
console.log(` ${skillFile}
|
|
793
|
+
`);
|
|
794
|
+
console.log("\uD83D\uDCA1 To reinstall, delete the file and run 'claudish --init' again.");
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
const sourceSkillPath = join3(__dirname3, "../skills/claudish-usage/SKILL.md");
|
|
798
|
+
if (!existsSync2(sourceSkillPath)) {
|
|
799
|
+
console.error("❌ Error: Claudish skill file not found in installation.");
|
|
800
|
+
console.error(` Expected at: ${sourceSkillPath}`);
|
|
801
|
+
console.error(`
|
|
802
|
+
\uD83D\uDCA1 Try reinstalling Claudish:`);
|
|
803
|
+
console.error(" npm install -g claudish@latest");
|
|
804
|
+
process.exit(1);
|
|
805
|
+
}
|
|
806
|
+
try {
|
|
807
|
+
if (!existsSync2(claudeDir)) {
|
|
808
|
+
mkdirSync(claudeDir, { recursive: true });
|
|
809
|
+
console.log("\uD83D\uDCC1 Created .claude/ directory");
|
|
810
|
+
}
|
|
811
|
+
if (!existsSync2(skillsDir)) {
|
|
812
|
+
mkdirSync(skillsDir, { recursive: true });
|
|
813
|
+
console.log("\uD83D\uDCC1 Created .claude/skills/ directory");
|
|
814
|
+
}
|
|
815
|
+
if (!existsSync2(claudishSkillDir)) {
|
|
816
|
+
mkdirSync(claudishSkillDir, { recursive: true });
|
|
817
|
+
console.log("\uD83D\uDCC1 Created .claude/skills/claudish-usage/ directory");
|
|
818
|
+
}
|
|
819
|
+
copyFileSync(sourceSkillPath, skillFile);
|
|
820
|
+
console.log("✅ Installed Claudish skill at:");
|
|
821
|
+
console.log(` ${skillFile}
|
|
822
|
+
`);
|
|
823
|
+
console.log("━".repeat(60));
|
|
824
|
+
console.log(`
|
|
825
|
+
\uD83C\uDF89 Claudish skill installed successfully!
|
|
826
|
+
`);
|
|
827
|
+
console.log(`\uD83D\uDCCB Next steps:
|
|
828
|
+
`);
|
|
829
|
+
console.log("1. Reload Claude Code to discover the skill");
|
|
830
|
+
console.log(" - Restart Claude Code, or");
|
|
831
|
+
console.log(` - Re-open your project
|
|
832
|
+
`);
|
|
833
|
+
console.log("2. Use Claudish with external models:");
|
|
834
|
+
console.log(' - User: "use Grok to implement feature X"');
|
|
835
|
+
console.log(` - Claude will automatically use the skill
|
|
836
|
+
`);
|
|
837
|
+
console.log("\uD83D\uDCA1 The skill enforces best practices:");
|
|
838
|
+
console.log(" ✅ Mandatory sub-agent delegation");
|
|
839
|
+
console.log(" ✅ File-based instruction patterns");
|
|
840
|
+
console.log(` ✅ Context window protection
|
|
841
|
+
`);
|
|
842
|
+
console.log(`\uD83D\uDCD6 For more info: claudish --help-ai
|
|
843
|
+
`);
|
|
844
|
+
console.log("━".repeat(60));
|
|
845
|
+
} catch (error) {
|
|
846
|
+
console.error(`
|
|
847
|
+
❌ Error installing Claudish skill:`);
|
|
848
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
849
|
+
console.error(`
|
|
850
|
+
\uD83D\uDCA1 Make sure you have write permissions in the current directory.`);
|
|
851
|
+
process.exit(1);
|
|
852
|
+
}
|
|
853
|
+
}
|
|
585
854
|
function printAvailableModels() {
|
|
855
|
+
let lastUpdated = "unknown";
|
|
856
|
+
let models = [];
|
|
857
|
+
try {
|
|
858
|
+
if (existsSync2(MODELS_JSON_PATH)) {
|
|
859
|
+
const data = JSON.parse(readFileSync2(MODELS_JSON_PATH, "utf-8"));
|
|
860
|
+
lastUpdated = data.lastUpdated || "unknown";
|
|
861
|
+
models = data.models || [];
|
|
862
|
+
}
|
|
863
|
+
} catch {
|
|
864
|
+
const basicModels = getAvailableModels();
|
|
865
|
+
const modelInfo = loadModelInfo();
|
|
866
|
+
for (const model of basicModels) {
|
|
867
|
+
const info = modelInfo[model];
|
|
868
|
+
console.log(` ${model}`);
|
|
869
|
+
console.log(` ${info.name} - ${info.description}`);
|
|
870
|
+
console.log("");
|
|
871
|
+
}
|
|
872
|
+
return;
|
|
873
|
+
}
|
|
586
874
|
console.log(`
|
|
587
|
-
Available OpenRouter Models (
|
|
875
|
+
Available OpenRouter Models (last updated: ${lastUpdated}):
|
|
588
876
|
`);
|
|
589
|
-
|
|
590
|
-
|
|
877
|
+
console.log(" Model Provider Pricing Context Capabilities");
|
|
878
|
+
console.log(" " + "─".repeat(86));
|
|
591
879
|
for (const model of models) {
|
|
592
|
-
const
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
880
|
+
const modelId = model.id.length > 30 ? model.id.substring(0, 27) + "..." : model.id;
|
|
881
|
+
const modelIdPadded = modelId.padEnd(30);
|
|
882
|
+
const provider = model.provider.length > 10 ? model.provider.substring(0, 7) + "..." : model.provider;
|
|
883
|
+
const providerPadded = provider.padEnd(10);
|
|
884
|
+
let pricing = model.pricing?.average || "N/A";
|
|
885
|
+
if (pricing.includes("-1000000")) {
|
|
886
|
+
pricing = "varies";
|
|
887
|
+
} else if (pricing === "$0.00/1M" || pricing === "FREE") {
|
|
888
|
+
pricing = "FREE";
|
|
889
|
+
}
|
|
890
|
+
const pricingPadded = pricing.padEnd(10);
|
|
891
|
+
const context = model.context || "N/A";
|
|
892
|
+
const contextPadded = context.padEnd(7);
|
|
893
|
+
const tools = model.supportsTools ? "\uD83D\uDD27" : " ";
|
|
894
|
+
const reasoning = model.supportsReasoning ? "\uD83E\uDDE0" : " ";
|
|
895
|
+
const vision = model.supportsVision ? "\uD83D\uDC41️ " : " ";
|
|
896
|
+
const capabilities = `${tools} ${reasoning} ${vision}`;
|
|
897
|
+
console.log(` ${modelIdPadded} ${providerPadded} ${pricingPadded} ${contextPadded} ${capabilities}`);
|
|
898
|
+
}
|
|
899
|
+
console.log("");
|
|
900
|
+
console.log(" Capabilities: \uD83D\uDD27 Tools \uD83E\uDDE0 Reasoning \uD83D\uDC41️ Vision");
|
|
901
|
+
console.log("");
|
|
597
902
|
console.log("Set default with: export CLAUDISH_MODEL=<model>");
|
|
598
903
|
console.log(" or: export ANTHROPIC_MODEL=<model>");
|
|
599
|
-
console.log(
|
|
904
|
+
console.log("Or use: claudish --model <model> ...");
|
|
905
|
+
console.log(`
|
|
906
|
+
Force update: claudish --list-models --force-update
|
|
600
907
|
`);
|
|
601
908
|
}
|
|
602
909
|
function printAvailableModelsJSON() {
|
|
@@ -776,7 +1083,7 @@ async function selectModelInteractively() {
|
|
|
776
1083
|
}
|
|
777
1084
|
|
|
778
1085
|
// src/logger.ts
|
|
779
|
-
import { writeFileSync as
|
|
1086
|
+
import { writeFileSync as writeFileSync4, appendFile, existsSync as existsSync3, mkdirSync as mkdirSync2 } from "fs";
|
|
780
1087
|
import { join as join4 } from "path";
|
|
781
1088
|
var logFilePath = null;
|
|
782
1089
|
var logLevel = "info";
|
|
@@ -807,7 +1114,7 @@ function scheduleFlush() {
|
|
|
807
1114
|
flushTimer = null;
|
|
808
1115
|
}
|
|
809
1116
|
if (logFilePath && logBuffer.length > 0) {
|
|
810
|
-
|
|
1117
|
+
writeFileSync4(logFilePath, logBuffer.join(""), { flag: "a" });
|
|
811
1118
|
logBuffer = [];
|
|
812
1119
|
}
|
|
813
1120
|
});
|
|
@@ -823,12 +1130,12 @@ function initLogger(debugMode, level = "info") {
|
|
|
823
1130
|
}
|
|
824
1131
|
logLevel = level;
|
|
825
1132
|
const logsDir = join4(process.cwd(), "logs");
|
|
826
|
-
if (!
|
|
827
|
-
|
|
1133
|
+
if (!existsSync3(logsDir)) {
|
|
1134
|
+
mkdirSync2(logsDir, { recursive: true });
|
|
828
1135
|
}
|
|
829
1136
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-").split("T").join("_").slice(0, -5);
|
|
830
1137
|
logFilePath = join4(logsDir, `claudish_${timestamp}.log`);
|
|
831
|
-
|
|
1138
|
+
writeFileSync4(logFilePath, `Claudish Debug Log - ${new Date().toISOString()}
|
|
832
1139
|
Log Level: ${level}
|
|
833
1140
|
${"=".repeat(80)}
|
|
834
1141
|
|
|
@@ -3063,7 +3370,7 @@ var serve = (options, listeningListener) => {
|
|
|
3063
3370
|
};
|
|
3064
3371
|
|
|
3065
3372
|
// src/proxy-server.ts
|
|
3066
|
-
import { writeFileSync as
|
|
3373
|
+
import { writeFileSync as writeFileSync5 } from "node:fs";
|
|
3067
3374
|
|
|
3068
3375
|
// src/transform.ts
|
|
3069
3376
|
function removeUriFormat(schema) {
|
|
@@ -3851,7 +4158,7 @@ data: ${JSON.stringify(data)}
|
|
|
3851
4158
|
total_tokens: cumulativeInputTokens + cumulativeOutputTokens,
|
|
3852
4159
|
updated_at: Date.now()
|
|
3853
4160
|
};
|
|
3854
|
-
|
|
4161
|
+
writeFileSync5(tokenFilePath, JSON.stringify(tokenData), "utf-8");
|
|
3855
4162
|
} catch (error) {
|
|
3856
4163
|
if (isLoggingEnabled()) {
|
|
3857
4164
|
log(`[Proxy] Failed to write token file: ${error}`);
|
|
@@ -4330,7 +4637,7 @@ async function readStdin() {
|
|
|
4330
4637
|
}
|
|
4331
4638
|
async function main() {
|
|
4332
4639
|
try {
|
|
4333
|
-
const config = parseArgs(process.argv.slice(2));
|
|
4640
|
+
const config = await parseArgs(process.argv.slice(2));
|
|
4334
4641
|
initLogger(config.debug, config.logLevel);
|
|
4335
4642
|
if (config.debug && !config.quiet) {
|
|
4336
4643
|
const logFile = getLogFilePath();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claudish",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.2.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",
|
|
@@ -35,7 +35,10 @@
|
|
|
35
35
|
},
|
|
36
36
|
"files": [
|
|
37
37
|
"dist/",
|
|
38
|
-
"scripts/"
|
|
38
|
+
"scripts/",
|
|
39
|
+
"skills/",
|
|
40
|
+
"AI_AGENT_GUIDE.md",
|
|
41
|
+
"recommended-models.json"
|
|
39
42
|
],
|
|
40
43
|
"engines": {
|
|
41
44
|
"node": ">=18.0.0",
|