1use clap::{Parser, Subcommand};
2
3#[derive(Parser)]
5#[command(name = "cc-switch")]
6#[command(about = "A CLI tool for managing Claude API configurations")]
7#[command(version)]
8#[command(disable_help_subcommand = true)]
9#[command(
10 long_about = "cc-switch helps you manage multiple Claude API configurations and switch between them easily.
11
12EXAMPLES:
13 cc-switch add my-config sk-ant-xxx https://api.anthropic.com
14 cc-switch add my-config -t sk-ant-xxx -u https://api.anthropic.com
15 cc-switch add my-config -t sk-ant-xxx -u https://api.anthropic.com -m claude-3-5-sonnet-20241022
16 cc-switch add my-config -t sk-ant-xxx -u https://api.anthropic.com --small-fast-model claude-3-haiku-20240307
17 cc-switch add my-config -t sk-ant-xxx -u https://api.anthropic.com --max-thinking-tokens 8192
18 cc-switch add my-config -i # Interactive mode
19 cc-switch add my-config --from-file # Import from ~/.claude/settings.json
20 cc-switch add my-config --from-file ./other.json # Import from an explicit JSON file
21 cc-switch add my-config --force # Overwrite existing config
22 cc-switch list
23 cc-switch remove config1 config2 config3
24 cc-switch current # Interactive mode to view and switch configurations
25 cc-switch # Enter interactive mode (same as 'current' without arguments)
26
27CODEX CONFIGURATIONS:
28 cc-switch codex add work --from-file # Import from ~/.codex/auth.json
29 cc-switch codex add work --from-file ~/other/auth.json # Import from an explicit path
30 cc-switch codex add personal -i # Interactive mode
31 cc-switch codex list
32 cc-switch codex use work # Switch and launch Codex
33 cc-switch codex remove work
34
35SHELL COMPLETION AND ALIASES:
36 cc-switch completion fish # Generates shell completions
37 cc-switch alias fish # Generates aliases for eval
38
39 These aliases are available:
40 - cs='cc-switch' # Quick access to cc-switch
41 - ccd='claude --dangerously-skip-permissions' # Quick Claude launch
42
43 To use aliases immediately:
44 eval \"$(cc-switch alias fish)\" # Add aliases to current session
45
46 Or add them permanently:
47 cc-switch completion fish > ~/.config/fish/completions/cc-switch.fish
48 echo \"alias cs='cc-switch'\" >> ~/.config/fish/config.fish
49 echo \"alias ccd='claude --dangerously-skip-permissions'\" >> ~/.config/fish/config.fish
50
51 Then use:
52 cs current # Instead of cc-switch current
53 ccd # Quick Claude launch"
54)]
55pub struct Cli {
56 #[command(subcommand)]
57 pub command: Option<Commands>,
58
59 #[arg(long = "list-aliases", hide = true)]
61 pub list_aliases: bool,
62
63 #[arg(long = "list-codex-aliases", hide = true)]
65 pub list_codex_aliases: bool,
66
67 #[arg(
69 long = "migrate",
70 help = "Migrate old config path to new path and exit"
71 )]
72 pub migrate: bool,
73
74 #[arg(
76 long = "store",
77 help = "Storage mode for writing configuration (env: write to env field, config: write to root with camelCase)",
78 global = true
79 )]
80 pub store: Option<String>,
81}
82
83#[derive(Subcommand)]
85#[allow(clippy::large_enum_variant)]
86pub enum Commands {
87 Add {
91 #[arg(help = "Configuration alias name (cannot be 'cc')")]
93 alias_name: String,
94
95 #[arg(
97 long = "token",
98 short = 't',
99 help = "API token (optional if not using interactive mode)"
100 )]
101 token: Option<String>,
102
103 #[arg(
105 long = "url",
106 short = 'u',
107 help = "API endpoint URL (optional if not using interactive mode)"
108 )]
109 url: Option<String>,
110
111 #[arg(long = "model", short = 'm', help = "Custom model name (optional)")]
113 model: Option<String>,
114
115 #[arg(
117 long = "small-fast-model",
118 help = "Haiku-class model for background tasks (optional)"
119 )]
120 small_fast_model: Option<String>,
121
122 #[arg(
124 long = "max-thinking-tokens",
125 help = "Maximum thinking tokens limit (optional)"
126 )]
127 max_thinking_tokens: Option<u32>,
128
129 #[arg(
131 long = "api-timeout-ms",
132 help = "API timeout in milliseconds (optional)"
133 )]
134 api_timeout_ms: Option<u32>,
135
136 #[arg(
138 long = "disable-nonessential-traffic",
139 help = "Disable non-essential traffic flag (optional)"
140 )]
141 claude_code_disable_nonessential_traffic: Option<u32>,
142
143 #[arg(
145 long = "default-sonnet-model",
146 help = "Default Sonnet model name (optional)"
147 )]
148 anthropic_default_sonnet_model: Option<String>,
149
150 #[arg(
152 long = "default-opus-model",
153 help = "Default Opus model name (optional)"
154 )]
155 anthropic_default_opus_model: Option<String>,
156
157 #[arg(
159 long = "default-haiku-model",
160 help = "Default Haiku model name (optional)"
161 )]
162 anthropic_default_haiku_model: Option<String>,
163
164 #[arg(long = "subagent-model", help = "Subagent model name (optional)")]
166 claude_code_subagent_model: Option<String>,
167
168 #[arg(
170 long = "disable-nonstreaming-fallback",
171 help = "Disable non-streaming fallback flag (optional)"
172 )]
173 claude_code_disable_nonstreaming_fallback: Option<u32>,
174
175 #[arg(
177 long = "effort-level",
178 help = "Effort level for Claude Code (optional, e.g., 'max')"
179 )]
180 claude_code_effort_level: Option<String>,
181
182 #[arg(
184 long = "force",
185 short = 'f',
186 help = "Overwrite existing configuration with same alias"
187 )]
188 force: bool,
189
190 #[arg(
192 long = "interactive",
193 short = 'i',
194 help = "Enter configuration values interactively"
195 )]
196 interactive: bool,
197
198 #[arg(help = "API token (if not using -t flag)")]
200 token_arg: Option<String>,
201
202 #[arg(help = "API endpoint URL (if not using -u flag)")]
204 url_arg: Option<String>,
205
206 #[arg(
211 long = "from-file",
212 num_args = 0..=1,
213 value_name = "PATH",
214 help = "Import configuration from JSON file (defaults to ~/.claude/settings.json if no path)"
215 )]
216 from_file: Option<Option<String>>,
217 },
218 Remove {
222 #[arg(required = true)]
224 alias_names: Vec<String>,
225 },
226 List {
230 #[arg(long = "plain", short = 'p')]
232 plain: bool,
233 #[arg(long = "name", short = 'n')]
235 name: bool,
236 },
237 #[command(alias = "C")]
241 Completion {
242 #[arg(default_value = "fish")]
244 shell: String,
245 },
246 #[command(trailing_var_arg = true)]
253 Use {
254 alias_name: String,
256
257 #[arg(long, short = 'r')]
259 resume: Option<String>,
260
261 #[arg(long, short = 'c')]
263 r#continue: bool,
264
265 #[arg(trailing_var_arg = true, allow_hyphen_values = true)]
267 prompt: Vec<String>,
268 },
269 Codex {
271 #[command(subcommand)]
272 command: Option<CodexCommands>,
273 },
274 #[command(name = "statusline")]
283 Statusline {
284 #[arg(value_enum, default_value = "install")]
286 action: StatuslineAction,
287 },
288}
289
290#[derive(Clone, Copy, clap::ValueEnum)]
292pub enum StatuslineAction {
293 Install,
295 Uninstall,
297}
298
299#[derive(Subcommand)]
301pub enum CodexCommands {
302 Add {
304 #[arg(help = "Configuration alias name")]
305 alias_name: String,
306 #[arg(long = "api-key", help = "OpenAI API key (optional)")]
307 api_key: Option<String>,
308 #[arg(long = "force", short = 'f', help = "Overwrite existing configuration")]
309 force: bool,
310 #[arg(
311 long = "interactive",
312 short = 'i',
313 help = "Enter configuration values interactively"
314 )]
315 interactive: bool,
316 #[arg(
321 long = "from-file",
322 num_args = 0..=1,
323 value_name = "PATH",
324 help = "Import from auth.json (defaults to ~/.codex/auth.json if no path)"
325 )]
326 from_file: Option<Option<String>>,
327 },
328 List {
329 #[arg(long = "plain", short = 'p')]
330 plain: bool,
331 #[arg(long = "name", short = 'n', help = "Show only name and auth mode")]
332 name: bool,
333 },
334 #[command(trailing_var_arg = true)]
335 Use {
336 alias_name: String,
337 #[arg(long = "continue", short = 'c')]
338 r#continue: bool,
339 #[arg(long = "resume", short = 'r')]
340 resume: Option<String>,
341 #[arg(trailing_var_arg = true, allow_hyphen_values = true)]
342 prompt: Vec<String>,
343 },
344 Remove {
345 #[arg(required = true)]
346 alias_names: Vec<String>,
347 },
348}