ccsw 0.1.0

Claude Code account switcher — run multiple Claude Code accounts concurrently with shared plugins and settings
Documentation

ccsw — Claude Code Switcher

Run multiple Claude Code accounts concurrently from different terminals, with plugins, settings, hooks, skills, and CLAUDE.md shared across accounts. No CLAUDE_CONFIG_DIR juggling, no ~/.claude/ copies.

Terminal A                 Terminal B
┌─────────────┐            ┌─────────────┐
│ $ claude    │            │ $ ccsw work │
│ (personal)  │            │ (team seat) │
└─────────────┘            └─────────────┘
       │                          │
       ▼                          ▼
~/.claude (base)          ~/.claude-profiles/work
  real creds                 real creds
  + real .claude.json        + real .claude.json
  plugins/ ◄────symlink────  plugins/
  settings.json ◄──symlink── settings.json
  CLAUDE.md ◄─────symlink──  CLAUDE.md
  hooks/   ◄──────symlink──  hooks/
  ... (allowlist)

Each terminal launches claude pinned to one account via CLAUDE_CONFIG_DIR. Because Claude Code derives every path — credentials, lockfiles, and (on macOS) even the Keychain service name — from that one env var, pinning it at launch gives full, concurrent isolation without touching Claude Code internals.

Install

cargo install ccsw

Or build from source:

git clone https://github.com/jv-vogler/claude-acc-switcher
cd claude-acc-switcher
cargo install --path .

Requires Rust 1.80+.

Quickstart

# You're already logged in as your personal account in ~/.claude.
# Create a second profile for a team seat:
ccsw add work

# Launch claude with the work profile:
ccsw work
# → inside claude: /login and authenticate the work account

# Meanwhile, another terminal stays on your personal account:
claude

That's the whole loop. You can open as many terminals as you like — each one runs the profile it was launched with, for its whole lifetime.

Commands

Command What it does
ccsw Open the TUI picker, then launch claude.
ccsw <name> Shortcut: launch claude pinned to that profile.
ccsw run <name> -- <cmd> Run any command with CLAUDE_CONFIG_DIR set.
ccsw shell <name> Spawn your $SHELL with the env exported.
ccsw ls List profiles with email + last-used.
ccsw add <name> Create a profile. Copies .claude.json forward, builds symlinks.
ccsw rm <name> Delete a profile. Snapshots first.
ccsw rename <old> <new> Rename a profile. Snapshots first.
ccsw sync Re-evaluate symlinks for every profile against the current allowlist.
ccsw doctor Read-only health check: symlinks, credentials, orphans.
ccsw restore <ts> Restore a profile from a snapshot (unique prefix accepted).
ccsw backups List snapshots.
ccsw current Print the profile name of the current shell.
ccsw completions <shell> Emit shell completions (bash/zsh/fish/powershell/elvish).

Shell completions

# bash
ccsw completions bash > /etc/bash_completion.d/ccsw

# zsh
ccsw completions zsh > "${fpath[1]}/_ccsw"

# fish
ccsw completions fish > ~/.config/fish/completions/ccsw.fish

Layout

~/.claude/                      ← base profile (personal / default)
  .credentials.json
  .claude.json
  settings.json
  CLAUDE.md
  plugins/  agents/  hooks/ ... (shared sources)

~/.claude-profiles/
  .ccsw.json                    ← profile registry
  .backups/                     ← timestamped snapshots
  work/
    .credentials.json           ← real file, per-profile
    .claude.json                ← real file, per-profile
    settings.json  → symlink → ~/.claude/settings.json
    CLAUDE.md      → symlink → ~/.claude/CLAUDE.md
    plugins/       → symlink → ~/.claude/plugins/
    ...

Shared (symlinks into ~/.claude)

settings.json, CLAUDE.md, RTK.md, keybindings.json, hooks/, plugins/, agents/, skills/, rules/, ide/, history.jsonl, shell-snapshots/, paste-cache/, cache/, downloads/, file-history/, plans/, tasks/, session-env/, projects/.

Sharing projects/ means conversation transcripts are visible across every profile, so /resume works after switching accounts — useful when one account hits a rate limit mid-task.

Per-profile (never symlinked)

.credentials.json, .claude.json, sessions/, backups/, debug/, telemetry/, usage-data/, mcp-needs-auth-cache.json.

Override an entry per-profile

If you want a profile to have its own settings.json (breaking the share), just drop a real file into ~/.claude-profiles/<name>/settings.json. Heal-on-launch detects the real file and never clobbers it — it logs a skip and moves on. Remove the real file to rejoin the shared copy on next launch.

Design notes

  • Heal-on-launch (~1ms): every ccsw <name> walks the allowlist and repairs broken/missing symlinks before exec. New entries added to the base (e.g. installing a new plugin) appear across every profile on the next launch.
  • Directories are linked as directories, not their contents recursively. Siblings added later to plugins/ just work across profiles.
  • Absolute paths in symlink targets, so profiles can be moved without breaking shares.
  • Backups before every destructive op (add, rm, rename, restore). restore is itself reversible — it snapshots current state first.
  • ccsw does not stay resident: on Unix it execvps into claude. No parent process overhead.

Windows caveat

Windows symlinks require Developer Mode or an elevated (admin) shell. Everything still works once symlinks are permitted; the symlink creation will otherwise fail with a clear error message on the first ccsw add.

macOS and Linux don't need anything special.

Verification

# Create a second profile.
ccsw add work
ccsw ls

# Concurrent use:
# Terminal A
claude
# Terminal B
ccsw work        # launches claude with CLAUDE_CONFIG_DIR=~/.claude-profiles/work
# inside claude: /login → authenticate the other account
# confirm `/status` shows the right account in each terminal

# Share confirmation
ls -l ~/.claude-profiles/work/plugins
ls -l ~/.claude-profiles/work/CLAUDE.md

# Heal-on-launch
rm ~/.claude-profiles/work/CLAUDE.md
ccsw work                                    # re-heals then launches
ls -l ~/.claude-profiles/work/CLAUDE.md      # symlink restored

# Backup + restore
ccsw rm work
ccsw backups                                 # shows <ts>-rm-work
ccsw restore <ts>                            # profile returns

License

MIT OR Apache-2.0.