ccs — Claude Code Switcher
A fast, single-binary CLI launcher for Claude Code and Codex that lets you interactively select a launch profile before each session — no more juggling shell aliases.
Select profile
[Recent] All ←/→ switch list, ↑/↓ move, Enter select, Esc cancel
TOOL PROVIDER MODEL
> claude DeepSeek deepseek-v4-pro
claude DeepSeek deepseek-v4-flash
claude Mimo mimo-v2.5-pro
Features
- Interactive three-column menu — tool / provider / model, with Recent / All lists switched by left and right arrows
- Direct selection via
-p <id>to skip the menu - Resume support —
-rmaps toclaude -rorcodex resumeautomatically - Dry-run mode —
-nprints the exact command and env vars without launching - Config-driven — add or remove profiles by editing
~/.config/ccs/config.toml; no recompile needed - Remembers last choice — the previous selection is highlighted by default
- Zero runtime deps — single static binary, ~1 MB
Requirements
- macOS or Linux (uses
exec(2)— Unix only) claudeand/orcodexinPATH- Rust 1.95+ (for building from source)
Installation
From crates.io (recommended)
From source
⚠️ Do not install as
cc— that name is reserved for the system C compiler and will break your Rust/C toolchain.
Verify
Updating
With cargo-update (recommended):
# cargo install-update -a # or update all installed crates
Without extra tools:
Configuration
On first run, ccs generates a template config at ~/.config/ccs/config.toml.
Edit it to add your API keys and desired profiles.
# ~/.config/ccs/config.toml
[[]]
= "deepseek-pro"
= "DeepSeek"
= "deepseek-v4-pro"
= "claude"
= true
= ["--dangerously-skip-permissions"]
[]
= "https://api.deepseek.com/anthropic"
= "YOUR_DEEPSEEK_API_KEY"
= "deepseek-v4-pro"
= "deepseek-v4-pro"
= "deepseek-v4-pro"
= "deepseek-v4-flash"
= "deepseek-v4-pro"
= "max"
Each [[providers]] block defines one profile: a provider, model, agent CLI, and launch settings. The existing TOML keys are retained. Profile IDs must be unique; id, provider, and model must not be blank.
Config fields
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | ✅ | Unique identifier, used with -p |
provider |
string | ✅ | Service name shown in column 2 |
model |
string | ✅ | Model name shown in column 3 |
executable |
"claude" | "codex" |
✅ | Binary to launch |
supports_resume |
bool | — | Enable -r / resume (default: false) |
resume_as_subcommand |
bool | — | Use codex resume style instead of -r flag (default: false) |
base_args |
string[] | — | Args always prepended to the command |
[providers.env] |
table | — | Environment variables injected into the subprocess |
Resume behaviour
| Agent | Config | Resulting command |
|---|---|---|
| claude | supports_resume = true |
claude … -r |
| codex | supports_resume = trueresume_as_subcommand = true |
codex resume … |
Usage
Claude Code / Codex launcher 🚀
Config: ~/.config/ccs/config.toml
Usage: ccs [OPTIONS] [PASSTHROUGH]... [COMMAND]
Commands:
list List configured profiles
edit Open the config file in $EDITOR (falls back to vi)
help Print this message or the help of the given subcommand(s)
Arguments:
[PASSTHROUGH]... Arguments passed through to claude/codex
Options:
-r, --resume Resume the last session (passes -r to claude)
-p, --profile <PROFILE_ID> Skip the menu and use a specific profile ID
-n, --dry-run Print the command that would run, without executing
--show-secrets Show full secret values in dry-run / list output (default: masked)
-h, --help Print help
-V, --version Print version
Examples
# Interactive profile selection
# Resume last session with the same interactive selection
# Jump straight to a specific profile
# Resume with a specific profile
# Debug: see exactly what command would be executed
# Reveal the real API key in dry-run output (default is masked)
# Pass extra arguments to the underlying tool
# Inspect all configured profiles
# Show environment configuration and local checks
# Show original environment values
# Edit your config in $EDITOR (falls back to vi)
Recent selections
ccs remembers the last 3 profile IDs you used and shows them in a
dedicated Recent list. The menu defaults to the most recent profile, and left
and right arrows switch between Recent and All profiles. The list is stored as
plain lines (newest first) in ~/.config/ccs/recent.
List profiles
ccs list shows only the profile ID, provider, model, and agent:
ID PROVIDER MODEL AGENT
────────────────────────────────────────────────────────
deepseek DeepSeek deepseek-v4-pro Claude Code
codex OpenAI gpt-4o Codex
The list preserves configuration order, aligns Unicode text, and uses a stacked layout in narrow terminals. Color is disabled when output is redirected or NO_COLOR is set.
ccs list --verbose adds each profile's agent path, environment configuration, and local check results. It checks unknown configuration fields and executable permissions using the profile's effective PATH, including a configured environment override. It does not execute the agent or check credentials and service connectivity. All local checks passing returns exit code 0; any failed check returns 1. Default ccs list only requires a structurally valid configuration and does not check agent availability.
Environment values
ccs list does not display environment variables. ccs list --verbose and --dry-run mask every environment value as ***masked***. Add --show-secrets to display original values. Other profile fields and command arguments are displayed as configured.
Upgrading from 0.2.x
- Replace
ccs validatewithccs list --verbose. - Replace
--provider <ID>with--profile <PROFILE_ID>. The short option-pis unchanged. - Existing
[[providers]]configuration and recent profile IDs are retained. Correct duplicate IDs or blankid,provider, andmodelfields before use. - Unknown top-level or profile fields fail verbose checks. Custom keys inside
[providers.env]remain supported.
Dry-run output example
[dry-run] env:
ANTHROPIC_AUTH_TOKEN=***masked***
ANTHROPIC_BASE_URL=***masked***
...
[dry-run] cmd:
claude --dangerously-skip-permissions --print 'explain this code'
Adding a custom profile
Add a new [[providers]] block to ~/.config/ccs/config.toml:
[[]]
= "my-profile"
= "MyService"
= "my-model-v1"
= "claude"
= true
= ["--dangerously-skip-permissions"]
[]
= "https://api.myservice.com/v1"
= "sk-..."
No recompile needed — changes take effect immediately on the next run.
Project structure
ccs/
├── src/
│ ├── main.rs # CLI, configuration, menu, and launching
│ ├── listing.rs # List rendering and local checks
│ └── default_profiles.toml # Template config embedded in the binary
├── tests/cli.rs # CLI integration tests
├── Cargo.toml
├── Cargo.lock
├── LICENSE
├── README.md
└── CONTRIBUTING.md
Contributing
See CONTRIBUTING.md.