# agentkeyswitch

`agentkeyswitch` is a Linux-first CLI for switching API profiles used by local AI agents such as Claude Code and Codex.

It keeps your reusable profiles in one local store and applies them to the real config files only when you run a switch command.

## Current scope

- Linux only
- Supported agents:
  - `claude`
  - `codex`
- Supported commands:
  - `agswitch list`
  - `agswitch status`
  - `agswitch add <profile>`
  - `agswitch import <profile>`
  - `agswitch import-existing`
  - `agswitch use <agent> <profile>`
  - `agswitch remove <profile>`
  - `agswitch help [command]`

## Install

```bash
pip install agentkeyswitch
```

For local development:

```bash
pip install -e .
```

## Profile store

Profiles are stored at:

```text
~/.config/agentkeyswitch/profiles.json
```

You can override the runtime locations with environment variables:

- `AGSWITCH_HOME`
- `AGSWITCH_STORE`
- `XDG_CONFIG_HOME`

This is mainly useful for testing or migration.

## Examples

Add a profile interactively:

```bash
agswitch add max
```

Add a profile non-interactively:

```bash
agswitch add CCC \
  --agent all \
  --claude-token 'xxx' \
  --claude-base-url 'https://CCCai.online/v1' \
  --claude-model 'opus' \
  --codex-key 'xxx' \
  --codex-base-url 'https://CCCai.online/v1' \
  --codex-provider 'CCC'
```

Import the current live configs into a reusable profile:

```bash
agswitch import max --agent all
```

Batch import your existing named files:

```bash
agswitch import-existing
```

Batch import when your filenames use another separator:

```bash
agswitch import-existing --separator "_"
```

Also include the current live config as `current`:

```bash
agswitch import-existing --include-current
```

Switch Claude only:

```bash
agswitch use claude max
```

Switch both Claude and Codex:

```bash
agswitch use all CCC
```

Check current live status:

```bash
agswitch status
```

Show detailed help:

```bash
agswitch help
agswitch help use
```

## Output style

`agswitch list` now prints profiles as readable blocks instead of one compressed line:

```text
Stored Profiles (3)
-------------------
- AAA
  claude       yes (token: AAA-...oken)
  codex        no
- BBB
  claude       no
  codex        yes (key: BBB...-key)
- CCC
  claude       yes (token: CCC...oken)
  codex        yes (key: CCC...-key)
```

`agswitch status` uses the same block style:

```text
Live Status
-----------
- claude
  profile      CCC
  base_url     https://CCCai.online/v1
  token        CCC...oken
  model        opus
  paths        1
               /home/you/.claude/settings.json
- codex
  profile      CCC
  base_url     https://CCCai.online/v1
  api_key      CCC...-key
  provider     CCC
  wire_api     responses
  paths        2
               /home/you/.codex/auth.json
               /home/you/.codex/config.toml
```

`agswitch import-existing` also shows imported items in the same format:

```text
Imported Profiles (2)
---------------------
- max
  agents       claude
- CCC
  agents       claude, codex
```

`agswitch use all CCC` will print the applied profile and backup files:

```text
Applied Profile
---------------
  profile      CCC
  agent        all
- claude
  backups      1
               /home/you/.config/agentkeyswitch/backups/.../settings.json
- codex
  backups      2
               /home/you/.config/agentkeyswitch/backups/.../auth.json
               /home/you/.config/agentkeyswitch/backups/.../config.toml
```

## What gets changed

`claude`

- `~/.claude/settings.json`

`codex`

- `~/.codex/auth.json`
- `~/.codex/config.toml`

Named files discovered by `import-existing`

Default naming rule:

- Claude: `~/.claude/settings - <profile>.json`
- Codex: `~/.codex/auth - <profile>.json`

That means these files:

- `~/.claude/settings - max.json`
- `~/.codex/auth - max.json`

will be imported as the same profile: `max`

If you use a different separator, pass it explicitly:

- `agswitch import-existing --separator "_"`:
  - Claude: `~/.claude/settings_<profile>.json`
  - Codex: `~/.codex/auth_<profile>.json`
- `agswitch import-existing --separator "-"`:
  - Claude: `~/.claude/settings-<profile>.json`
  - Codex: `~/.codex/auth-<profile>.json`

Import behavior:

- If only Claude exists for a profile name, the stored profile gets only a `claude` section.
- If only Codex exists for a profile name, the stored profile gets only a `codex` section.
- If both exist with the same profile name, they are merged into one stored profile.
- `--include-current` will additionally import the currently active live config as profile `current`.
- `--overwrite` allows replacing already stored sections with newly imported ones.

The tool updates only the necessary fields and keeps unrelated settings intact. Before writing, it creates timestamped backups under:

```text
~/.config/agentkeyswitch/backups/
```

## Notes

- Secrets are not bundled with the package.
- The package is designed so you can publish the code without publishing your tokens.
- For Codex, the tool updates both `auth.json` and `config.toml` so provider selection remains consistent.
