# cc-switch Switch between multiple Claude Code coding-plan subscriptions with one command. If you've signed up for a few different Anthropic-compatible providers (official Anthropic, OpenRouter, DeepSeek, Moonshot/Kimi, Zhipu GLM, or your own proxy), each uses a slightly different set of environment variables. Swapping them by hand is fiddly and easy to get wrong. `cc-switch` stores them once, then: 1. Cleans your subprocess env of every variable any provider uses. 2. Injects the selected provider's env. 3. Launches `claude` with that environment. 4. On exit, your parent shell is untouched — nothing leaked. ## Install ``` go install github.com/kotoyuuko/cc-switch-cli/cmd/cc-switch@latest ``` Or clone and build: ``` git clone https://github.com/kotoyuuko/cc-switch-cli cd cc-switch-cli make build # binary at ./dist/cc-switch ``` Supported platforms: macOS, Linux. Windows users should use WSL. ## Quick start ```sh # 1. Add one or more providers. cc-switch add official \ --from-template anthropic-official \ --env ANTHROPIC_API_KEY=sk-ant-xxxxxxxxx cc-switch add or \ --from-template openrouter \ --env ANTHROPIC_AUTH_TOKEN=sk-or-xxxxxxxxx \ --env ANTHROPIC_MODEL=anthropic/claude-opus-4 # 2. (Optional) set a default so bare `cc-switch` picks it. cc-switch config set default official # 3. Run claude with a chosen provider. cc-switch use or # or just `cc-switch` — opens an interactive picker in a tty. ``` `cc-switch` passes its exit code through from `claude`, forwards SIGINT / SIGTERM / SIGHUP, and inherits stdio verbatim — it behaves like a thin wrapper. ## Commands | Command | What it does | | --- | --- | | `cc-switch add [--env K=V ...] [--from-template T] [--non-interactive]` | Register a provider. | | `cc-switch list [-V]` | Show providers; `-V` includes masked env keys. | | `cc-switch edit [--env K=V] [--remove-env K] [--description ...]` | Modify a provider. | | `cc-switch remove ` | Delete a provider (clears `default_provider` if applicable). | | `cc-switch use []` | Clean → inject → launch claude. Interactive picker when tty + no name. | | `cc-switch config show / set / get` | Inspect or change `claude_path` / `default_provider`. | | `cc-switch templates list / show ` | Explore built-in env-key skeletons. | | `cc-switch version` | Print build info. | Flags that work everywhere: - `-v / --verbose`: trace config path, resolved claude path, union keys, injected keys (never values) to stderr. - `--config `: override config file location (beats `$CC_SWITCH_CONFIG`). ## Using references to keep secrets out of the config file Instead of pasting your API key into `config.yaml`, you can reference any env variable present in your shell when `cc-switch use` runs: ```yaml providers: official: env: ANTHROPIC_API_KEY: env:MY_ANTHROPIC_KEY # resolved at launch ANTHROPIC_BASE_URL: https://api.anthropic.com ``` Pair it with [1Password CLI](https://developer.1password.com/docs/cli/), [direnv](https://direnv.net/), or any other secret-exposing tool: ```sh # ~/.zshrc export MY_ANTHROPIC_KEY="$(op item get 'Anthropic API' --field credential)" cc-switch use official ``` If the referenced variable is missing at launch, `cc-switch` refuses to start claude and tells you which key referenced which missing variable — no silent fallbacks. ## Why "union" cleanup? When `cc-switch use foo` runs, the cleanup step removes **every** env key that appears in **any** configured provider, not just the currently selected one. That way, if you used `openrouter` last time and it set `ANTHROPIC_AUTH_TOKEN`, switching to `official` (which only sets `ANTHROPIC_API_KEY`) doesn't leave the stale auth token around to confuse claude. Consequence: if a provider uses a key you haven't registered anywhere, that key won't be cleaned. So register every key you might use in at least one provider. ## Config file Located via `$CC_SWITCH_CONFIG` → `$XDG_CONFIG_HOME/cc-switch/config.yaml` → `~/.config/cc-switch/config.yaml`. Permissions are `0600` on create; if yours become more permissive, `cc-switch` prints a warning on every invocation. Example config (`examples/config.example.yaml`): ```yaml claude_path: ~/.claude/local/claude default_provider: official providers: official: description: "Anthropic official" env: ANTHROPIC_API_KEY: env:MY_ANTHROPIC_KEY ANTHROPIC_BASE_URL: https://api.anthropic.com openrouter: env: ANTHROPIC_BASE_URL: https://openrouter.ai/api/v1 ANTHROPIC_AUTH_TOKEN: sk-or-example ANTHROPIC_MODEL: anthropic/claude-opus-4 ``` ## Non-goals (v1) - Not a secret vault — values are stored in plain YAML (mitigations: `0600` permissions and `env:VAR` indirection). - Doesn't modify your shell profile, doesn't export anything into your parent shell — env changes live only in the claude subprocess. - No Windows support (macOS / Linux only; WSL works). - No user-supplied template directory (built-ins only; PRs welcome). - No chained `env:VAR` resolution (one hop only). - No escape for a literal `env:` prefix at value start (rare; file an issue if you hit it).