@cbuk100011/claude-mode 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +13 -10
  2. package/dist/index.js +681 -65
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Claude Mode
2
2
 
3
+ ![npm version](https://img.shields.io/npm/v/%40cbuk100011%2Fclaude-mode)
4
+
3
5
  A Node.js CLI launcher for Claude Code that supports multiple AI providers and models.
4
6
 
5
7
  ## Features
@@ -17,12 +19,19 @@ A Node.js CLI launcher for Claude Code that supports multiple AI providers and m
17
19
 
18
20
  ## Installation
19
21
 
22
+ ### npm Package (Recommended)
23
+
24
+ ```bash
25
+ # Install globally
26
+ npm install -g @cbuk100011/claude-mode
27
+ ```
28
+
20
29
  ### From Source
21
30
 
22
31
  ```bash
23
32
  # Clone the repository
24
- git clone <repo-url>
25
- cd claude-mode
33
+ git clone https://github.com/Cam10001110101/claude-mode-cli.git
34
+ cd claude-mode-cli
26
35
 
27
36
  # Install dependencies
28
37
  npm install
@@ -30,16 +39,10 @@ npm install
30
39
  # Build
31
40
  npm run build
32
41
 
33
- # Link globally (optional)
42
+ # Link globally
34
43
  npm link
35
44
  ```
36
45
 
37
- ### Global Installation (after npm publish)
38
-
39
- ```bash
40
- npm install -g claude-mode
41
- ```
42
-
43
46
  ## Usage
44
47
 
45
48
  ### Interactive Menu
@@ -293,7 +296,7 @@ npm run typecheck
293
296
  ## Project Structure
294
297
 
295
298
  ```
296
- claude-mode/
299
+ claude-mode-cli/
297
300
  ├── src/
298
301
  │ ├── index.ts # Main CLI entry point
299
302
  │ ├── providers.ts # Provider and model configurations
package/dist/index.js CHANGED
@@ -2,12 +2,12 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { Command } from "commander";
5
- import chalk2 from "chalk";
6
- import { select, input } from "@inquirer/prompts";
5
+ import chalk3 from "chalk";
6
+ import { select as select2, input as input2, confirm as confirm2 } from "@inquirer/prompts";
7
7
  import { spawn, execSync } from "child_process";
8
8
  import { config } from "dotenv";
9
9
  import { fileURLToPath } from "url";
10
- import path2 from "path";
10
+ import path3 from "path";
11
11
 
12
12
  // src/config.ts
13
13
  import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
@@ -37,6 +37,7 @@ var DEFAULT_CONFIG = {
37
37
  healthCheckTimeout: 2e3,
38
38
  cacheTTL: 3e4,
39
39
  customProviders: [],
40
+ configuredProviders: [],
40
41
  skipHealthCheck: false,
41
42
  offlineMode: false,
42
43
  headlessAllowedTools: "Read,Edit,Write,Bash,Glob,Grep"
@@ -210,6 +211,33 @@ function claudeNotFoundError() {
210
211
  hint: "Install Claude Code CLI: npm install -g @anthropic-ai/claude-code\nOr check that it is in your PATH."
211
212
  };
212
213
  }
214
+ function setupConfigWriteError(message, hint) {
215
+ return {
216
+ code: "SETUP_CONFIG_WRITE_FAILED" /* SETUP_CONFIG_WRITE_FAILED */,
217
+ message: `Failed to write config: ${message}`,
218
+ hint: hint || "Check file permissions and try again, or use a different config location."
219
+ };
220
+ }
221
+ function setupEnvWriteError(message, hint) {
222
+ return {
223
+ code: "SETUP_ENV_WRITE_FAILED" /* SETUP_ENV_WRITE_FAILED */,
224
+ message: `Failed to write .env file: ${message}`,
225
+ hint: hint || "Check file permissions or specify a different location."
226
+ };
227
+ }
228
+ function setupCancelledError() {
229
+ return {
230
+ code: "SETUP_CANCELLED" /* SETUP_CANCELLED */,
231
+ message: "Setup cancelled"
232
+ };
233
+ }
234
+ function setupIncompleteError(message) {
235
+ return {
236
+ code: "SETUP_INCOMPLETE" /* SETUP_INCOMPLETE */,
237
+ message,
238
+ hint: "Run claude-mode setup to complete configuration."
239
+ };
240
+ }
213
241
 
214
242
  // src/providers.ts
215
243
  var builtInProviders = {
@@ -508,12 +536,57 @@ async function checkAllProvidersHealth() {
508
536
  return results;
509
537
  }
510
538
 
511
- // src/index.ts
512
- config();
513
- var __filename = fileURLToPath(import.meta.url);
514
- var __dirname = path2.dirname(__filename);
515
- config({ path: path2.join(__dirname, "..", ".env") });
516
- var program = new Command();
539
+ // src/setup.ts
540
+ import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync as existsSync2, mkdirSync as mkdirSync2 } from "fs";
541
+ import { homedir as homedir2 } from "os";
542
+ import path2 from "path";
543
+ import chalk2 from "chalk";
544
+ import {
545
+ confirm,
546
+ select,
547
+ checkbox,
548
+ input,
549
+ password
550
+ } from "@inquirer/prompts";
551
+ function getConfigDir2() {
552
+ return path2.join(homedir2(), ".claude-mode");
553
+ }
554
+ function getConfigPath() {
555
+ return path2.join(getConfigDir2(), "claude-mode.json");
556
+ }
557
+ function getEnvPath(envPath) {
558
+ return envPath || path2.join(process.cwd(), ".env");
559
+ }
560
+ function detectSetupStatus() {
561
+ const configPath = getConfigPath();
562
+ const envPath = getEnvPath();
563
+ if (!existsSync2(configPath)) {
564
+ return "first-time";
565
+ }
566
+ try {
567
+ const config2 = loadConfig();
568
+ const hasDefaults = !!(config2.defaultProvider && config2.defaultModel);
569
+ const hasProviders = !!config2.configuredProviders && config2.configuredProviders.length > 0;
570
+ if (!hasDefaults || !hasProviders) {
571
+ return "incomplete";
572
+ }
573
+ if (config2.configuredProviders) {
574
+ for (const providerKey of config2.configuredProviders) {
575
+ const provider = getProvider(providerKey);
576
+ if (provider) {
577
+ const hasKey = !!provider.getAuthToken();
578
+ const needsKey = providerKey === "openrouter" || providerKey === "ollama-cloud";
579
+ if (needsKey && !hasKey) {
580
+ return "incomplete";
581
+ }
582
+ }
583
+ }
584
+ }
585
+ return "complete";
586
+ } catch {
587
+ return "first-time";
588
+ }
589
+ }
517
590
  function printHeader(text) {
518
591
  console.log("");
519
592
  console.log(chalk2.bold.blue("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
@@ -521,13 +594,539 @@ function printHeader(text) {
521
594
  console.log(chalk2.bold.blue("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
522
595
  console.log("");
523
596
  }
597
+ function printSection(title) {
598
+ console.log("");
599
+ console.log(chalk2.bold.cyan("\u2501\u2501\u2501 " + title + " \u2501\u2501\u2501"));
600
+ console.log("");
601
+ }
602
+ function printProviderInfo() {
603
+ console.log(chalk2.bold("Available Providers:"));
604
+ console.log("");
605
+ console.log(" " + chalk2.green("OpenRouter") + " - Access to Claude, GPT-5, DeepSeek, and more");
606
+ console.log(" " + chalk2.gray("Requires: API key"));
607
+ console.log("");
608
+ console.log(" " + chalk2.green("Ollama Local") + " - Run models locally on your machine");
609
+ console.log(" " + chalk2.gray("Requires: Local Ollama instance"));
610
+ console.log("");
611
+ console.log(" " + chalk2.green("Ollama Cloud") + " - Managed Ollama service");
612
+ console.log(" " + chalk2.gray("Requires: API key"));
613
+ console.log("");
614
+ console.log(" " + chalk2.green("Ollama Custom") + " - Connect to remote Ollama instance");
615
+ console.log(" " + chalk2.gray("Requires: Custom URL"));
616
+ console.log("");
617
+ }
618
+ async function displayWelcome(isFirstTime) {
619
+ console.clear();
620
+ if (isFirstTime) {
621
+ printHeader("Welcome to Claude Mode Setup");
622
+ console.log(chalk2.bold.cyan("Claude Mode") + " is a CLI launcher for Claude Code");
623
+ console.log("that supports multiple AI providers.");
624
+ console.log("");
625
+ console.log("This wizard will help you configure your providers");
626
+ console.log("and set up your default settings.");
627
+ console.log("");
628
+ } else {
629
+ printHeader("Claude Mode Configuration");
630
+ console.log("Update your configuration or add new providers.");
631
+ console.log("");
632
+ }
633
+ printProviderInfo();
634
+ const ready = await confirm({
635
+ message: "Ready to configure?",
636
+ default: true
637
+ });
638
+ if (!ready) {
639
+ throw setupCancelledError();
640
+ }
641
+ }
642
+ async function displayUpdatePrompt() {
643
+ console.clear();
644
+ printHeader("Configuration Found");
645
+ console.log("A configuration file already exists.");
646
+ console.log("");
647
+ console.log("You can:");
648
+ console.log(" " + chalk2.cyan("\u2022") + " Re-run full setup to reconfigure all providers");
649
+ console.log(" " + chalk2.cyan("\u2022") + " Configure a single provider");
650
+ console.log(" " + chalk2.cyan("\u2022") + " Skip and use existing configuration");
651
+ console.log("");
652
+ const action = await select({
653
+ message: "What would you like to do?",
654
+ choices: [
655
+ { name: "Re-run full setup", value: "full" },
656
+ { name: "Configure specific provider", value: "single" },
657
+ { name: "Skip (use existing config)", value: "skip" }
658
+ ]
659
+ });
660
+ return action !== "skip";
661
+ }
662
+ async function selectProviders(forceProvider) {
663
+ if (forceProvider) {
664
+ const provider = getProvider(forceProvider);
665
+ if (!provider) {
666
+ console.error(chalk2.red(`Unknown provider: ${forceProvider}`));
667
+ throw setupIncompleteError(`Provider "${forceProvider}" not found`);
668
+ }
669
+ return [forceProvider];
670
+ }
671
+ const allProviders = getProviders();
672
+ const choices = Object.entries(allProviders).map(([key, provider]) => ({
673
+ name: provider.name,
674
+ value: key,
675
+ description: provider.getDescription()
676
+ }));
677
+ const selected = await checkbox({
678
+ message: "Select providers to configure:",
679
+ choices,
680
+ validate: (value) => value.length > 0 ? true : "Select at least one provider"
681
+ });
682
+ return selected;
683
+ }
684
+ async function configureProvider(providerKey, skipValidation) {
685
+ const provider = getProvider(providerKey);
686
+ if (!provider) {
687
+ throw setupIncompleteError(`Provider "${providerKey}" not found`);
688
+ }
689
+ printSection(`Configuring ${provider.name}`);
690
+ const config2 = {
691
+ key: providerKey,
692
+ name: provider.name,
693
+ validated: false
694
+ };
695
+ if (providerKey === "openrouter" || providerKey === "ollama-cloud") {
696
+ const existingKey = provider.getAuthToken();
697
+ const keyMsg = existingKey ? `Enter API key (current: ${existingKey.substring(0, 8)}...)` : "Enter API key:";
698
+ config2.apiKey = await password({
699
+ message: keyMsg,
700
+ validate: (value) => {
701
+ if (existingKey && !value) return true;
702
+ return value.length > 0 ? true : "API key is required";
703
+ }
704
+ });
705
+ if (config2.apiKey) {
706
+ if (providerKey === "openrouter") {
707
+ process.env.ANTHROPIC_AUTH_TOKEN = config2.apiKey;
708
+ } else if (providerKey === "ollama-cloud") {
709
+ process.env.OLLAMA_API_KEY = config2.apiKey;
710
+ }
711
+ }
712
+ }
713
+ if (providerKey === "ollama-custom") {
714
+ const existingUrl = provider.getBaseUrl();
715
+ const defaultUrl = existingUrl || "http://192.168.86.101:11434";
716
+ config2.customUrl = await input({
717
+ message: "Enter Ollama URL:",
718
+ default: defaultUrl,
719
+ validate: (value) => {
720
+ try {
721
+ new URL(value);
722
+ return true;
723
+ } catch {
724
+ return "Please enter a valid URL";
725
+ }
726
+ }
727
+ });
728
+ if (config2.customUrl) {
729
+ process.env.OLLAMA_BASE_URL_CUSTOM = config2.customUrl;
730
+ }
731
+ }
732
+ if (!skipValidation) {
733
+ config2.validated = await validateProvider(providerKey);
734
+ } else {
735
+ config2.validated = true;
736
+ }
737
+ return config2;
738
+ }
739
+ async function validateProvider(providerKey) {
740
+ console.log(chalk2.gray("Validating provider connection..."));
741
+ const result = await checkProviderHealth(providerKey);
742
+ if (result.healthy) {
743
+ const latency = result.latencyMs ? ` (${result.latencyMs}ms)` : "";
744
+ console.log(chalk2.green(`\u2713 ${providerKey} is reachable${latency}`));
745
+ return true;
746
+ } else {
747
+ console.log(chalk2.yellow(`\u26A0 ${providerKey} validation failed`));
748
+ if (result.error) {
749
+ console.log(chalk2.gray(` ${result.error.message}`));
750
+ }
751
+ const retry = await confirm({
752
+ message: "Continue anyway?",
753
+ default: false
754
+ });
755
+ return retry;
756
+ }
757
+ }
758
+ async function selectDefaults(configuredProviders, currentDefaults) {
759
+ printSection("Set Defaults");
760
+ let defaultProvider;
761
+ let defaultModel;
762
+ if (currentDefaults && configuredProviders.includes(currentDefaults.provider)) {
763
+ const useCurrent = await confirm({
764
+ message: `Keep default provider as ${currentDefaults.provider}?`,
765
+ default: true
766
+ });
767
+ if (useCurrent) {
768
+ defaultProvider = currentDefaults.provider;
769
+ } else {
770
+ defaultProvider = await select({
771
+ message: "Select default provider:",
772
+ choices: configuredProviders.map((key) => ({
773
+ name: getProvider(key)?.name || key,
774
+ value: key
775
+ }))
776
+ });
777
+ }
778
+ } else {
779
+ defaultProvider = await select({
780
+ message: "Select default provider:",
781
+ choices: configuredProviders.map((key) => ({
782
+ name: getProvider(key)?.name || key,
783
+ value: key
784
+ }))
785
+ });
786
+ }
787
+ const models3 = await getModels(defaultProvider);
788
+ console.log("");
789
+ console.log(chalk2.gray("Available models for " + getProvider(defaultProvider)?.name + ":"));
790
+ if (models3.length === 0) {
791
+ console.log(" " + chalk2.gray("(no models found - will use manual input)"));
792
+ console.log("");
793
+ const modelInput = await input({
794
+ message: "Enter default model ID:",
795
+ validate: (value) => value.length > 0 ? true : "Model ID cannot be empty"
796
+ });
797
+ defaultModel = modelInput;
798
+ } else {
799
+ for (const model of models3) {
800
+ console.log(` ${chalk2.green(model.shortcut.padEnd(20))} ${chalk2.gray(model.id)}`);
801
+ }
802
+ console.log("");
803
+ defaultModel = await select({
804
+ message: "Select default model:",
805
+ choices: models3.map((model) => ({
806
+ name: `${model.name} (${model.shortcut})`,
807
+ value: model.id
808
+ }))
809
+ });
810
+ }
811
+ return { provider: defaultProvider, model: defaultModel };
812
+ }
813
+ function formatProviderConfig(config2) {
814
+ const lines = [];
815
+ lines.push(chalk2.cyan(` ${config2.name} (${config2.key})`));
816
+ if (config2.apiKey) {
817
+ const masked = config2.apiKey.substring(0, 8) + "..." + config2.apiKey.slice(-4);
818
+ lines.push(` API Key: ${chalk2.gray(masked)}`);
819
+ }
820
+ if (config2.customUrl) {
821
+ lines.push(` URL: ${chalk2.gray(config2.customUrl)}`);
822
+ }
823
+ if (config2.validated) {
824
+ lines.push(` Status: ${chalk2.green("\u2713 Validated")}`);
825
+ } else {
826
+ lines.push(` Status: ${chalk2.yellow("\u26A0 Not validated")}`);
827
+ }
828
+ return lines.join("\n");
829
+ }
830
+ async function reviewAndConfirm(providerConfigs, defaults, currentConfig) {
831
+ printSection("Review Configuration");
832
+ console.log(chalk2.bold("Configured Providers:"));
833
+ console.log("");
834
+ for (const config2 of providerConfigs) {
835
+ console.log(formatProviderConfig(config2));
836
+ }
837
+ console.log("");
838
+ console.log(chalk2.bold("Defaults:"));
839
+ console.log(` ${chalk2.cyan("Provider:")} ${defaults.provider}`);
840
+ console.log(` ${chalk2.cyan("Model:")} ${defaults.model}`);
841
+ console.log("");
842
+ console.log(chalk2.bold("Files to be created/updated:"));
843
+ console.log(` ${chalk2.cyan("Config:")} ${getConfigPath()}`);
844
+ console.log(` ${chalk2.cyan("Env:")} ${getEnvPath()}`);
845
+ console.log("");
846
+ const confirmed = await confirm({
847
+ message: "Save this configuration?",
848
+ default: true
849
+ });
850
+ return confirmed;
851
+ }
852
+ function buildEnvVars(providerConfigs) {
853
+ const envVars = {};
854
+ for (const config2 of providerConfigs) {
855
+ switch (config2.key) {
856
+ case "openrouter":
857
+ if (config2.apiKey) {
858
+ envVars.ANTHROPIC_BASE_URL = "https://openrouter.ai/api";
859
+ envVars.ANTHROPIC_AUTH_TOKEN = config2.apiKey;
860
+ envVars.OPEN_ROUTER_API_KEY = config2.apiKey;
861
+ }
862
+ break;
863
+ case "ollama-cloud":
864
+ if (config2.apiKey) {
865
+ envVars.OLLAMA_HOST = "https://ollama.com";
866
+ envVars.OLLAMA_API_KEY = config2.apiKey;
867
+ }
868
+ break;
869
+ case "ollama-local":
870
+ envVars.OLLAMA_BASE_URL_LOCAL = "http://localhost:11434";
871
+ break;
872
+ case "ollama-custom":
873
+ if (config2.customUrl) {
874
+ envVars.OLLAMA_BASE_URL_CUSTOM = config2.customUrl;
875
+ }
876
+ break;
877
+ }
878
+ }
879
+ return envVars;
880
+ }
881
+ function formatEnvFile(envVars) {
882
+ const lines = [];
883
+ lines.push("# claude-mode configuration");
884
+ lines.push("# Generated by: claude-mode setup");
885
+ lines.push(`# Date: ${(/* @__PURE__ */ new Date()).toISOString()}`);
886
+ lines.push("");
887
+ if (envVars.ANTHROPIC_BASE_URL || envVars.ANTHROPIC_AUTH_TOKEN) {
888
+ lines.push("# OpenRouter");
889
+ if (envVars.ANTHROPIC_BASE_URL) {
890
+ lines.push(`ANTHROPIC_BASE_URL=${envVars.ANTHROPIC_BASE_URL}`);
891
+ }
892
+ if (envVars.ANTHROPIC_AUTH_TOKEN) {
893
+ lines.push(`ANTHROPIC_AUTH_TOKEN=${envVars.ANTHROPIC_AUTH_TOKEN}`);
894
+ }
895
+ if (envVars.OPEN_ROUTER_API_KEY) {
896
+ lines.push(`OPEN_ROUTER_API_KEY=${envVars.OPEN_ROUTER_API_KEY}`);
897
+ }
898
+ lines.push("");
899
+ }
900
+ if (envVars.OLLAMA_HOST || envVars.OLLAMA_API_KEY) {
901
+ lines.push("# Ollama Cloud");
902
+ if (envVars.OLLAMA_HOST) {
903
+ lines.push(`OLLAMA_HOST=${envVars.OLLAMA_HOST}`);
904
+ }
905
+ if (envVars.OLLAMA_API_KEY) {
906
+ lines.push(`OLLAMA_API_KEY=${envVars.OLLAMA_API_KEY}`);
907
+ }
908
+ lines.push("");
909
+ }
910
+ if (envVars.OLLAMA_BASE_URL_LOCAL) {
911
+ lines.push("# Ollama Local");
912
+ lines.push(`OLLAMA_BASE_URL_LOCAL=${envVars.OLLAMA_BASE_URL_LOCAL}`);
913
+ lines.push("");
914
+ }
915
+ if (envVars.OLLAMA_BASE_URL_CUSTOM) {
916
+ lines.push("# Ollama Custom");
917
+ lines.push(`OLLAMA_BASE_URL_CUSTOM=${envVars.OLLAMA_BASE_URL_CUSTOM}`);
918
+ lines.push("");
919
+ }
920
+ return lines.join("\n");
921
+ }
922
+ function mergeEnvFile(envVars, envPath) {
923
+ const targetPath = getEnvPath(envPath);
924
+ const existingVars = loadEnvFile(targetPath);
925
+ const merged = { ...existingVars, ...envVars };
926
+ const lines = [];
927
+ lines.push("# claude-mode configuration");
928
+ lines.push("# Generated by: claude-mode setup");
929
+ lines.push(`# Date: ${(/* @__PURE__ */ new Date()).toISOString()}`);
930
+ lines.push("");
931
+ for (const [key, value] of Object.entries(merged)) {
932
+ if (!key.startsWith("_claude_mode_")) {
933
+ lines.push(`${key}=${value}`);
934
+ }
935
+ }
936
+ try {
937
+ writeFileSync2(targetPath, lines.join("\n") + "\n", "utf-8");
938
+ } catch (error) {
939
+ const classified = classifyError(error);
940
+ throw setupEnvWriteError(classified.message, classified.hint);
941
+ }
942
+ }
943
+ function saveEnvFile(envVars, envPath) {
944
+ const targetPath = getEnvPath(envPath);
945
+ try {
946
+ const content = formatEnvFile(envVars);
947
+ writeFileSync2(targetPath, content + "\n", "utf-8");
948
+ } catch (error) {
949
+ const classified = classifyError(error);
950
+ throw setupEnvWriteError(classified.message, classified.hint);
951
+ }
952
+ }
953
+ function loadEnvFile(envPath) {
954
+ const targetPath = getEnvPath(envPath);
955
+ if (!existsSync2(targetPath)) {
956
+ return {};
957
+ }
958
+ try {
959
+ const content = readFileSync2(targetPath, "utf-8");
960
+ const vars = {};
961
+ for (const line of content.split("\n")) {
962
+ const trimmed = line.trim();
963
+ if (trimmed === "" || trimmed.startsWith("#")) {
964
+ continue;
965
+ }
966
+ const eqIndex = trimmed.indexOf("=");
967
+ if (eqIndex > 0) {
968
+ const key = trimmed.substring(0, eqIndex).trim();
969
+ let value = trimmed.substring(eqIndex + 1).trim();
970
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
971
+ value = value.slice(1, -1);
972
+ }
973
+ vars[key] = value;
974
+ }
975
+ }
976
+ return vars;
977
+ } catch {
978
+ return {};
979
+ }
980
+ }
981
+ function saveConfiguration(providerConfigs, defaults, currentConfig) {
982
+ const envVars = buildEnvVars(providerConfigs);
983
+ let config2 = currentConfig || loadConfig();
984
+ config2.defaultProvider = defaults.provider;
985
+ config2.defaultModel = defaults.model;
986
+ config2.configuredProviders = providerConfigs.map((c) => c.key);
987
+ try {
988
+ const configDir = getConfigDir2();
989
+ if (!existsSync2(configDir)) {
990
+ mkdirSync2(configDir, { recursive: true });
991
+ }
992
+ const configPath = getConfigPath();
993
+ writeFileSync2(configPath, JSON.stringify(config2, null, 2), "utf-8");
994
+ } catch (error) {
995
+ const classified = classifyError(error);
996
+ throw setupConfigWriteError(classified.message, classified.hint);
997
+ }
998
+ if (existsSync2(getEnvPath())) {
999
+ mergeEnvFile(envVars);
1000
+ } else {
1001
+ saveEnvFile(envVars);
1002
+ }
1003
+ }
1004
+ function displaySuccess(providerConfigs, defaults) {
1005
+ console.clear();
1006
+ printHeader("Setup Complete!");
1007
+ console.log(chalk2.green("\u2713") + " Configuration saved successfully!");
1008
+ console.log("");
1009
+ console.log(chalk2.bold("Configured Providers:"));
1010
+ for (const config2 of providerConfigs) {
1011
+ const status = config2.validated ? chalk2.green("\u2713") : chalk2.yellow("\u26A0");
1012
+ console.log(` ${status} ${config2.name}`);
1013
+ }
1014
+ console.log("");
1015
+ console.log(chalk2.bold("Default Configuration:"));
1016
+ console.log(` Provider: ${chalk2.cyan(defaults.provider)}`);
1017
+ console.log(` Model: ${chalk2.cyan(defaults.model)}`);
1018
+ console.log("");
1019
+ console.log(chalk2.bold("Next Steps:"));
1020
+ console.log(" Run " + chalk2.cyan("claude-mode") + " to start using Claude Code");
1021
+ console.log(" Run " + chalk2.cyan("claude-mode --list") + " to see all available models");
1022
+ console.log(" Run " + chalk2.cyan('claude-mode -p "your prompt"') + " for headless mode");
1023
+ console.log("");
1024
+ console.log(chalk2.gray("Configuration files:"));
1025
+ console.log(chalk2.gray(` Config: ${getConfigPath()}`));
1026
+ console.log(chalk2.gray(` Env: ${getEnvPath()}`));
1027
+ console.log("");
1028
+ }
1029
+ async function runSetup(options = {}) {
1030
+ try {
1031
+ const { force = false, provider: forceProvider, skipValidation = false } = options;
1032
+ const status = detectSetupStatus();
1033
+ const isFirstTime = status === "first-time";
1034
+ if (!force && !isFirstTime) {
1035
+ const shouldContinue = await displayUpdatePrompt();
1036
+ if (!shouldContinue) {
1037
+ return;
1038
+ }
1039
+ }
1040
+ await displayWelcome(isFirstTime);
1041
+ const providerKeys = await selectProviders(forceProvider);
1042
+ const providerConfigs = [];
1043
+ const currentConfig = loadConfig();
1044
+ for (const providerKey of providerKeys) {
1045
+ try {
1046
+ const config2 = await configureProvider(providerKey, skipValidation);
1047
+ providerConfigs.push(config2);
1048
+ } catch (error) {
1049
+ console.log("");
1050
+ const errorMessage = error instanceof Error ? error.message : String(error);
1051
+ console.log(chalk2.yellow(`Failed to configure ${providerKey}: ${errorMessage}`));
1052
+ const shouldContinue = await confirm({
1053
+ message: "Continue with remaining providers?",
1054
+ default: true
1055
+ });
1056
+ if (!shouldContinue) {
1057
+ throw setupCancelledError();
1058
+ }
1059
+ }
1060
+ }
1061
+ if (providerConfigs.length === 0) {
1062
+ throw setupIncompleteError("No providers were configured");
1063
+ }
1064
+ let currentDefaults;
1065
+ if (currentConfig.defaultProvider && currentConfig.defaultModel) {
1066
+ currentDefaults = {
1067
+ provider: currentConfig.defaultProvider,
1068
+ model: currentConfig.defaultModel
1069
+ };
1070
+ }
1071
+ const configuredProviderKeys = providerConfigs.map((c) => c.key);
1072
+ const defaults = await selectDefaults(configuredProviderKeys, currentDefaults);
1073
+ const confirmed = await reviewAndConfirm(providerConfigs, defaults, currentConfig);
1074
+ if (!confirmed) {
1075
+ throw setupCancelledError();
1076
+ }
1077
+ console.log("");
1078
+ console.log(chalk2.gray("Saving configuration..."));
1079
+ saveConfiguration(providerConfigs, defaults, currentConfig);
1080
+ displaySuccess(providerConfigs, defaults);
1081
+ } catch (error) {
1082
+ const classified = classifyError(error);
1083
+ if (classified.message === "Setup cancelled") {
1084
+ console.log("");
1085
+ console.log(chalk2.yellow("Setup cancelled."));
1086
+ console.log("Run " + chalk2.cyan("claude-mode setup") + " to try again.");
1087
+ console.log("");
1088
+ return;
1089
+ }
1090
+ console.log("");
1091
+ console.log(chalk2.red("Setup failed:"));
1092
+ printError(classified);
1093
+ console.log("");
1094
+ console.log(chalk2.gray("You can run " + chalk2.cyan("claude-mode setup") + " to try again."));
1095
+ console.log("");
1096
+ process.exit(1);
1097
+ }
1098
+ }
1099
+
1100
+ // src/index.ts
1101
+ config();
1102
+ var __filename = fileURLToPath(import.meta.url);
1103
+ var __dirname = path3.dirname(__filename);
1104
+ config({ path: path3.join(__dirname, "..", ".env") });
1105
+ var program = new Command();
1106
+ function printHeader2(text) {
1107
+ console.log("");
1108
+ console.log(chalk3.bold.blue("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
1109
+ console.log(chalk3.bold.blue("\u2551") + " " + chalk3.cyan(text));
1110
+ console.log(chalk3.bold.blue("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
1111
+ console.log("");
1112
+ }
524
1113
  function printConfig(provider, modelId, mode) {
525
- console.log(chalk2.cyan("Provider:") + " " + provider.name);
526
- console.log(chalk2.cyan("Model:") + " " + modelId);
527
- console.log(chalk2.cyan("Base URL:") + " " + provider.getBaseUrl());
528
- console.log(chalk2.cyan("Mode:") + " " + mode);
1114
+ console.log(chalk3.cyan("Provider:") + " " + provider.name);
1115
+ console.log(chalk3.cyan("Model:") + " " + modelId);
1116
+ console.log(chalk3.cyan("Base URL:") + " " + provider.getBaseUrl());
1117
+ console.log(chalk3.cyan("Mode:") + " " + mode);
529
1118
  console.log("");
530
1119
  }
1120
+ function shouldTriggerSetup() {
1121
+ const status = detectSetupStatus();
1122
+ if (status === "first-time") {
1123
+ return true;
1124
+ }
1125
+ if (status === "incomplete") {
1126
+ return true;
1127
+ }
1128
+ return false;
1129
+ }
531
1130
  function isClaudeInstalled() {
532
1131
  try {
533
1132
  execSync("which claude", { stdio: "ignore" });
@@ -602,16 +1201,16 @@ function formatHealthStatus(result) {
602
1201
  const name = provider?.name || result.provider;
603
1202
  if (result.healthy) {
604
1203
  const latency = result.latencyMs ? ` (${result.latencyMs}ms)` : "";
605
- return `${chalk2.green("\u2713")} ${name}${chalk2.gray(latency)}`;
1204
+ return `${chalk3.green("\u2713")} ${name}${chalk3.gray(latency)}`;
606
1205
  } else {
607
1206
  const error = result.error?.message || "unavailable";
608
- return `${chalk2.red("\u2717")} ${name} ${chalk2.gray(`- ${error}`)}`;
1207
+ return `${chalk3.red("\u2717")} ${name} ${chalk3.gray(`- ${error}`)}`;
609
1208
  }
610
1209
  }
611
1210
  async function displayHealthCheck() {
612
1211
  const skipHealthCheck = getConfig("skipHealthCheck");
613
1212
  if (skipHealthCheck) return;
614
- console.log(chalk2.gray("Checking provider availability..."));
1213
+ console.log(chalk3.gray("Checking provider availability..."));
615
1214
  const results = await checkAllProvidersHealth();
616
1215
  console.log("");
617
1216
  for (const result of results) {
@@ -621,10 +1220,10 @@ async function displayHealthCheck() {
621
1220
  }
622
1221
  async function interactiveMode(skipPermissions) {
623
1222
  console.clear();
624
- printHeader("Claude Mode");
1223
+ printHeader2("Claude Mode");
625
1224
  await displayHealthCheck();
626
1225
  const allProviders = getProviders();
627
- const providerKey = await select({
1226
+ const providerKey = await select2({
628
1227
  message: "Select Provider:",
629
1228
  choices: getProviderKeys().map((key) => ({
630
1229
  name: allProviders[key].name,
@@ -633,20 +1232,20 @@ async function interactiveMode(skipPermissions) {
633
1232
  }))
634
1233
  });
635
1234
  const provider = getProvider(providerKey);
636
- console.log(chalk2.yellow("\u2192 Selected:") + " " + provider.name);
1235
+ console.log(chalk3.yellow("\u2192 Selected:") + " " + provider.name);
637
1236
  const providerModels = await getModels(providerKey);
638
1237
  if (providerModels.length === 0) {
639
- console.log(chalk2.yellow("No models available for this provider."));
640
- console.log(chalk2.gray("You can enter a model ID manually."));
641
- const modelId2 = await input({
1238
+ console.log(chalk3.yellow("No models available for this provider."));
1239
+ console.log(chalk3.gray("You can enter a model ID manually."));
1240
+ const modelId2 = await input2({
642
1241
  message: "Enter model ID:",
643
1242
  validate: (value) => value.length > 0 ? true : "Model ID cannot be empty"
644
1243
  });
645
- console.log(chalk2.yellow("\u2192 Model:") + " " + modelId2);
1244
+ console.log(chalk3.yellow("\u2192 Model:") + " " + modelId2);
646
1245
  await continueInteractiveMode(provider, modelId2, skipPermissions);
647
1246
  return;
648
1247
  }
649
- const modelId = await select({
1248
+ const modelId = await select2({
650
1249
  message: "Select Model:",
651
1250
  choices: providerModels.map((model) => ({
652
1251
  name: model.name,
@@ -655,11 +1254,11 @@ async function interactiveMode(skipPermissions) {
655
1254
  }))
656
1255
  });
657
1256
  const selectedModel = providerModels.find((m) => m.id === modelId);
658
- console.log(chalk2.yellow("\u2192 Selected:") + " " + selectedModel?.name + ` (${modelId})`);
1257
+ console.log(chalk3.yellow("\u2192 Selected:") + " " + selectedModel?.name + ` (${modelId})`);
659
1258
  await continueInteractiveMode(provider, modelId, skipPermissions);
660
1259
  }
661
1260
  async function continueInteractiveMode(provider, modelId, skipPermissions) {
662
- const mode = await select({
1261
+ const mode = await select2({
663
1262
  message: "Select Mode:",
664
1263
  choices: [
665
1264
  { name: "Terminal (interactive)", value: "terminal" },
@@ -668,13 +1267,13 @@ async function continueInteractiveMode(provider, modelId, skipPermissions) {
668
1267
  });
669
1268
  let prompt;
670
1269
  if (mode === "headless") {
671
- prompt = await input({
1270
+ prompt = await input2({
672
1271
  message: "Enter your prompt:",
673
1272
  validate: (value) => value.length > 0 ? true : "Prompt cannot be empty"
674
1273
  });
675
1274
  }
676
1275
  if (!skipPermissions) {
677
- skipPermissions = await select({
1276
+ skipPermissions = await select2({
678
1277
  message: "Skip permission prompts when executing commands?",
679
1278
  choices: [
680
1279
  { name: "No (ask for permission)", value: false },
@@ -683,19 +1282,19 @@ async function continueInteractiveMode(provider, modelId, skipPermissions) {
683
1282
  });
684
1283
  }
685
1284
  console.log(
686
- chalk2.yellow("\u2192 Skip permissions:") + " " + (skipPermissions ? chalk2.red("Yes (\u26A0\uFE0F auto-approve)") : chalk2.green("No (ask)"))
1285
+ chalk3.yellow("\u2192 Skip permissions:") + " " + (skipPermissions ? chalk3.red("Yes (\u26A0\uFE0F auto-approve)") : chalk3.green("No (ask)"))
687
1286
  );
688
1287
  const isHeadless = mode === "headless";
689
1288
  if (isHeadless) {
690
- printHeader("Executing Claude Code (Headless)");
1289
+ printHeader2("Executing Claude Code (Headless)");
691
1290
  } else {
692
- printHeader("Launching Claude Code (Interactive)");
1291
+ printHeader2("Launching Claude Code (Interactive)");
693
1292
  }
694
1293
  printConfig(provider, modelId, isHeadless ? "Headless" : "Interactive");
695
1294
  try {
696
1295
  await runClaude(provider, modelId, isHeadless, skipPermissions, prompt);
697
1296
  } catch (error) {
698
- console.error(chalk2.red("Error:"), error);
1297
+ console.error(chalk3.red("Error:"), error);
699
1298
  process.exit(1);
700
1299
  }
701
1300
  }
@@ -703,8 +1302,8 @@ async function quickMode(providerArg, modelArg, skipPermissions, modeArg, prompt
703
1302
  const providerKey = resolveProvider(providerArg);
704
1303
  const provider = getProvider(providerKey);
705
1304
  if (!provider) {
706
- console.error(chalk2.red(`Unknown provider: ${providerArg}`));
707
- console.log(chalk2.gray("Available providers: " + getProviderKeys().join(", ")));
1305
+ console.error(chalk3.red(`Unknown provider: ${providerArg}`));
1306
+ console.log(chalk3.gray("Available providers: " + getProviderKeys().join(", ")));
708
1307
  process.exit(1);
709
1308
  }
710
1309
  const modelId = await resolveModel(providerKey, modelArg);
@@ -729,7 +1328,7 @@ async function quickMode(providerArg, modelArg, skipPermissions, modeArg, prompt
729
1328
  }
730
1329
  }
731
1330
  if (isHeadless && !prompt) {
732
- prompt = await input({
1331
+ prompt = await input2({
733
1332
  message: "Enter your prompt:",
734
1333
  validate: (value) => value.length > 0 ? true : "Prompt cannot be empty"
735
1334
  });
@@ -738,23 +1337,23 @@ async function quickMode(providerArg, modelArg, skipPermissions, modeArg, prompt
738
1337
  try {
739
1338
  await runClaude(provider, modelId, isHeadless, skipPermissions, prompt);
740
1339
  } catch (error) {
741
- console.error(chalk2.red("Error:"), error);
1340
+ console.error(chalk3.red("Error:"), error);
742
1341
  process.exit(1);
743
1342
  }
744
1343
  }
745
1344
  async function listModels() {
746
- console.log(chalk2.bold("\nAvailable Models by Provider:\n"));
1345
+ console.log(chalk3.bold("\nAvailable Models by Provider:\n"));
747
1346
  const allProviders = getProviders();
748
1347
  for (const providerKey of getProviderKeys()) {
749
1348
  const provider = allProviders[providerKey];
750
1349
  const providerModels = await getModels(providerKey);
751
- console.log(chalk2.cyan(`${provider.name}:`));
752
- console.log(chalk2.gray(` ${provider.getDescription()}`));
1350
+ console.log(chalk3.cyan(`${provider.name}:`));
1351
+ console.log(chalk3.gray(` ${provider.getDescription()}`));
753
1352
  if (providerModels.length === 0) {
754
- console.log(` ${chalk2.gray("(no models found)")}`);
1353
+ console.log(` ${chalk3.gray("(no models found)")}`);
755
1354
  } else {
756
1355
  for (const model of providerModels) {
757
- console.log(` ${chalk2.green(model.shortcut.padEnd(14))} \u2192 ${model.id}`);
1356
+ console.log(` ${chalk3.green(model.shortcut.padEnd(14))} \u2192 ${model.id}`);
758
1357
  }
759
1358
  }
760
1359
  console.log("");
@@ -762,14 +1361,14 @@ async function listModels() {
762
1361
  }
763
1362
  function showConfig() {
764
1363
  const config2 = loadConfig();
765
- console.log(chalk2.bold("\nCurrent Configuration:\n"));
1364
+ console.log(chalk3.bold("\nCurrent Configuration:\n"));
766
1365
  console.log(JSON.stringify(config2, null, 2));
767
1366
  console.log("");
768
1367
  }
769
1368
  function initConfigCommand() {
770
1369
  const configPath = initConfig();
771
- console.log(chalk2.green(`Config file created at: ${configPath}`));
772
- console.log(chalk2.gray("Edit this file to customize your settings."));
1370
+ console.log(chalk3.green(`Config file created at: ${configPath}`));
1371
+ console.log(chalk3.gray("Edit this file to customize your settings."));
773
1372
  }
774
1373
  function generateBashCompletion() {
775
1374
  const providerKeys = getProviderKeys();
@@ -897,13 +1496,13 @@ function printCompletion(shell) {
897
1496
  console.log(generateFishCompletion());
898
1497
  break;
899
1498
  default:
900
- console.error(chalk2.red(`Unknown shell: ${shell}`));
901
- console.log(chalk2.gray("Supported shells: bash, zsh, fish"));
1499
+ console.error(chalk3.red(`Unknown shell: ${shell}`));
1500
+ console.log(chalk3.gray("Supported shells: bash, zsh, fish"));
902
1501
  process.exit(1);
903
1502
  }
904
1503
  }
905
1504
  async function healthCommand() {
906
- console.log(chalk2.bold("\nProvider Health Check:\n"));
1505
+ console.log(chalk3.bold("\nProvider Health Check:\n"));
907
1506
  const results = await checkAllProvidersHealth();
908
1507
  for (const result of results) {
909
1508
  console.log(" " + formatHealthStatus(result));
@@ -912,40 +1511,40 @@ async function healthCommand() {
912
1511
  const healthy = results.filter((r) => r.healthy).length;
913
1512
  const total = results.length;
914
1513
  if (healthy === total) {
915
- console.log(chalk2.green(`All ${total} providers are healthy.`));
1514
+ console.log(chalk3.green(`All ${total} providers are healthy.`));
916
1515
  } else {
917
- console.log(chalk2.yellow(`${healthy}/${total} providers are healthy.`));
1516
+ console.log(chalk3.yellow(`${healthy}/${total} providers are healthy.`));
918
1517
  }
919
1518
  }
920
1519
  program.name("claude-mode").description(
921
1520
  `
922
- ${chalk2.bold("Claude Mode")} - Launch Claude Code with different providers
1521
+ ${chalk3.bold("Claude Mode")} - Launch Claude Code with different providers
923
1522
 
924
- ${chalk2.bold("Providers:")}
1523
+ ${chalk3.bold("Providers:")}
925
1524
  openrouter OpenRouter API
926
1525
  ollama-cloud Ollama Cloud (OLLAMA_HOST)
927
1526
  ollama-local Ollama Local (OLLAMA_BASE_URL_LOCAL)
928
1527
  ollama-custom Ollama Custom (OLLAMA_BASE_URL_CUSTOM)
929
1528
 
930
- ${chalk2.bold("Model shortcuts:")}
1529
+ ${chalk3.bold("Model shortcuts:")}
931
1530
  OpenRouter (Premium): gpt52, gpt52-pro, gpt52-codex, opus, grok
932
1531
  OpenRouter (Value): deepseek, zai-glm47-flash, seed16, sonnet, haiku
933
1532
  OpenRouter (Existing): gpt120, glm47, gemini-pro, gemini-flash
934
1533
  Ollama: Models discovered dynamically via API
935
1534
 
936
- ${chalk2.bold("Mode shortcuts:")}
1535
+ ${chalk3.bold("Mode shortcuts:")}
937
1536
  terminal, t, interactive, i - Interactive terminal mode
938
1537
  headless, h, prompt, p - Headless mode with prompt
939
1538
 
940
- ${chalk2.bold("Options:")}
1539
+ ${chalk3.bold("Options:")}
941
1540
  -p, --prompt <prompt> Headless mode (uses defaults if provider/model not set)
942
1541
  -d, --dangerously-skip-permissions Skip permission prompts (\u26A0\uFE0F use with caution)
943
1542
 
944
- ${chalk2.bold("Default Provider/Model:")}
1543
+ ${chalk3.bold("Default Provider/Model:")}
945
1544
  Set in ~/.claude-mode/claude-mode.json:
946
1545
  { "defaultProvider": "openrouter", "defaultModel": "sonnet" }
947
1546
 
948
- ${chalk2.bold("Examples:")}
1547
+ ${chalk3.bold("Examples:")}
949
1548
  claude-mode Interactive menu
950
1549
  claude-mode -p "perform a code review" Headless with default provider/model
951
1550
  claude-mode openrouter sonnet Interactive with Claude Sonnet
@@ -978,7 +1577,24 @@ program.command("config").description("Manage configuration").argument("[action]
978
1577
  program.command("completion").description("Generate shell completion scripts").argument("<shell>", "Shell type: bash, zsh, fish").action((shell) => {
979
1578
  printCompletion(shell);
980
1579
  });
1580
+ program.command("setup").description("Interactive setup wizard for first-time configuration").option("-f, --force", "Re-run setup even if config exists").option("-p, --provider <provider>", "Configure only this provider").option("--skip-validation", "Skip API key validation").action(async (options) => {
1581
+ await runSetup({
1582
+ force: options.force,
1583
+ provider: options.provider,
1584
+ skipValidation: options.skipValidation
1585
+ });
1586
+ });
981
1587
  program.option("-d, --dangerously-skip-permissions", "Skip permission prompts when executing commands").option("-l, --list", "List all available providers and models").option("-p, --prompt <prompt>", "Run in headless mode with the given prompt (uses defaults if provider/model not specified)").argument("[provider]", "Provider (openrouter, ollama-cloud, ollama-local, ollama-custom)").argument("[model]", "Model ID or shortcut").argument("[mode]", "Mode (terminal/t, headless/h) or prompt for headless").argument("[promptArg]", "Prompt for headless mode").action(async (provider, model, mode, promptArg, options) => {
1588
+ if (shouldTriggerSetup()) {
1589
+ const shouldSetup = await confirm2({
1590
+ message: "No configuration found. Would you like to run setup?",
1591
+ default: true
1592
+ });
1593
+ if (shouldSetup) {
1594
+ await runSetup({ force: false });
1595
+ return;
1596
+ }
1597
+ }
982
1598
  if (options.list) {
983
1599
  await listModels();
984
1600
  return;
@@ -990,14 +1606,14 @@ program.option("-d, --dangerously-skip-permissions", "Skip permission prompts wh
990
1606
  const effectiveProvider = provider || defaultProvider;
991
1607
  const effectiveModel = model || defaultModel;
992
1608
  if (!effectiveProvider || !effectiveModel) {
993
- console.error(chalk2.red("Error: Provider and model are required"));
1609
+ console.error(chalk3.red("Error: Provider and model are required"));
994
1610
  if (!effectiveProvider && !effectiveModel) {
995
- console.log(chalk2.gray("Set defaults in config: claude-mode config init"));
996
- console.log(chalk2.gray("Then edit ~/.claude-mode/claude-mode.json to set defaultProvider and defaultModel"));
1611
+ console.log(chalk3.gray("Set defaults in config: claude-mode config init"));
1612
+ console.log(chalk3.gray("Then edit ~/.claude-mode/claude-mode.json to set defaultProvider and defaultModel"));
997
1613
  } else if (!effectiveProvider) {
998
- console.log(chalk2.gray("Missing: provider (set defaultProvider in config or pass as argument)"));
1614
+ console.log(chalk3.gray("Missing: provider (set defaultProvider in config or pass as argument)"));
999
1615
  } else {
1000
- console.log(chalk2.gray("Missing: model (set defaultModel in config or pass as argument)"));
1616
+ console.log(chalk3.gray("Missing: model (set defaultModel in config or pass as argument)"));
1001
1617
  }
1002
1618
  process.exit(1);
1003
1619
  }
@@ -1011,10 +1627,10 @@ program.option("-d, --dangerously-skip-permissions", "Skip permission prompts wh
1011
1627
  if (defaultModel) {
1012
1628
  await quickMode(provider, defaultModel, skipPermissions, mode, promptArg);
1013
1629
  } else {
1014
- console.error(chalk2.red("Error: Model is required when provider is specified"));
1015
- console.log(chalk2.gray("Usage: claude-mode <provider> <model> [mode] [prompt]"));
1016
- console.log(chalk2.gray("Or set defaultModel in ~/.claude-mode/claude-mode.json"));
1017
- console.log(chalk2.gray("Run claude-mode --list to see available models"));
1630
+ console.error(chalk3.red("Error: Model is required when provider is specified"));
1631
+ console.log(chalk3.gray("Usage: claude-mode <provider> <model> [mode] [prompt]"));
1632
+ console.log(chalk3.gray("Or set defaultModel in ~/.claude-mode/claude-mode.json"));
1633
+ console.log(chalk3.gray("Run claude-mode --list to see available models"));
1018
1634
  process.exit(1);
1019
1635
  }
1020
1636
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cbuk100011/claude-mode",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "CLI launcher for Claude Code with multiple AI providers",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",