Switch between multiple Claude Code subscription logins on a single host. Each profile runs with its own isolated login (CLAUDE_CONFIG_DIR), stored in ~/.claude-sessions/profiles by default.
You have multiple Claude Code subscriptions (work, personal, partner accounts). Without csm, switching between them means manually logging out and in, clearing credentials, or maintaining separate machines. csm isolates each login to a named profile so plain claude runs against your current account — switching is instant and safe.
Requires Node.js >= 20.
curl -fsSL https://raw.githubusercontent.com/ilomon10/csm/main/scripts/install.sh | shirm https://raw.githubusercontent.com/ilomon10/csm/main/scripts/install.ps1 | iexAdd flags to the one-liner:
# sh: version pinning
curl -fsSL https://raw.githubusercontent.com/ilomon10/csm/main/scripts/install.sh | sh -s -- --version 0.1.0-beta.1
# sh: skip shell setup
curl -fsSL https://raw.githubusercontent.com/ilomon10/csm/main/scripts/install.sh | sh -s -- --no-setup
# PowerShell: version pinning
& ([scriptblock]::Create((irm https://raw.githubusercontent.com/ilomon10/csm/main/scripts/install.ps1))) -Version 0.1.0-beta.1
# PowerShell: skip shell setup
& ([scriptblock]::Create((irm https://raw.githubusercontent.com/ilomon10/csm/main/scripts/install.ps1))) -NoSetupThe installers are also attached to every release, so you can pin the exact script that runs:
curl -fsSL https://github.com/ilomon10/csm/releases/download/v0.1.0-beta.1/install.sh | sh -s -- --version 0.1.0-beta.1& ([scriptblock]::Create((irm https://github.com/ilomon10/csm/releases/download/v0.1.0-beta.1/install.ps1))) -Version 0.1.0-beta.1The installer only downloads over HTTPS, verifies every binary against the release's SHA256SUMS, and refuses to run as root (override with --allow-root).
VER=v0.1.0-beta.1
ASSET=csm-linux-x64 # or csm-linux-arm64, csm-darwin-x64, csm-darwin-arm64
curl -fsSLO "https://github.com/ilomon10/csm/releases/download/$VER/$ASSET"
curl -fsSLO "https://github.com/ilomon10/csm/releases/download/$VER/SHA256SUMS"
grep " $ASSET\$" SHA256SUMS | sha256sum -c - # macOS: shasum -a 256 -c -
chmod +x "$ASSET" && mv "$ASSET" ~/.local/bin/csm$Ver = 'v0.1.0-beta.1'; $Asset = 'csm-windows-x64.exe'
irm "https://github.com/ilomon10/csm/releases/download/$Ver/$Asset" -OutFile $Asset
$sums = irm "https://github.com/ilomon10/csm/releases/download/$Ver/SHA256SUMS"
$want = (($sums -split "`n") | Where-Object { $_ -match " \*?$([regex]::Escape($Asset))$" }).Split(' ')[0]
(Get-FileHash $Asset -Algorithm SHA256).Hash -eq $want.ToUpper()Release binaries also carry build provenance: verify with gh attestation verify <file> --repo ilomon10/csm.
npm install -g https://github.com/ilomon10/csm/releases/download/v0.1.0-beta.1/claude-session-manager-0.1.0-beta.1.tgzgit clone https://github.com/ilomon10/csm.git
cd csm
corepack enable # or install pnpm 9
pnpm install
pnpm build
pnpm add -g "$PWD"Create two profiles and switch between them:
csm add work # Creates profile, launches claude to log in
csm add personal # Create another profile with a different account
csm use work # Switch to work account
claude # Runs Claude Code with the work profile
csm use personal
claude # Runs Claude Code with the personal profileBefore plain claude will use your selected profile, add a shell initialization snippet to your shell's rc file and restart your shell.
Run this once to auto-detect your shell and add the block:
csm setupOr add manually:
Add to ~/.bashrc (and ~/.bash_profile on macOS/Windows):
if command -v csm >/dev/null 2>&1; then eval "$(csm shell-init bash)"; fiAdd to ~/.zshrc:
if command -v csm >/dev/null 2>&1; then eval "$(csm shell-init zsh)"; fiAdd to ~/.config/fish/conf.d/csm.fish (create the file):
if command -q csm; csm shell-init fish | source; endAdd to your PowerShell profile ($PROFILE):
if (Get-Command csm -CommandType Application -ErrorAction SilentlyContinue) { csm shell-init pwsh | Out-String | Invoke-Expression }Then restart your shell:
exec $SHELLTo confirm shell integration is active:
type claude # Should show a function (bash/zsh) or definition (fish/pwsh), not a commandcsm add <name> [--no-login]
Create a profile and launch Claude Code to log in.
csm add work # Creates profile and opens login
csm add test --no-login # Creates profile without logging in yetcsm use <name>
Set the current profile. Plain claude will use this after shell init.
csm use workcsm list or csm ls
List all profiles. The * marks the current profile.
$ csm list
* work user@work.com
personal user@personal.com
testing (not logged in)csm current
Print the name of the current profile.
$ csm current
workcsm run [name] [-- args...]
Run Claude Code with a specific profile (default: current profile).
csm run work # Uses work profile
csm run work -- -p # Pass arguments to claude
csm run -- -p # Uses current profilecsm env [name]
Print a shell export statement to temporarily set CLAUDE_CONFIG_DIR for a profile. Use with eval.
eval "$(csm env work)"
claude -pcsm rm <name> [--yes|-y]
Delete a profile and its login.
csm rm work # Prompts for confirmation
csm rm work --yes # Deletes without promptingcsm import <name> [--move] [--force]
Import an existing file-based login (e.g., from ~/.claude) into a new profile.
csm import work # Copies login from ~/.claude to profile "work"
csm import work --move # Also removes the source, so login exists only in the profile
csm import work --force # Force import even if source is another csm profileNote: On macOS, logins stored in the Keychain cannot be imported — use csm add instead.
csm sync [name] [--repair=adopt|discard]
Detect and repair shared config drift (see Shared Config).
csm sync work # Report any drift in the work profile
csm sync --repair=discard # Fix all profiles by discarding their drifted copies
csm sync work --repair=adopt # Fix work profile by adopting its drifted copy as sharedcsm share-history <from-profile>
Enable cross-profile session history sharing. All profiles will share transcripts, allowing --resume to access prior sessions from any account.
csm share-history workcsm adopt-config [--from <dir>] [--history] [--dry-run]
Share an existing config dir (default ~/.claude) with every profile. Settings, commands, agents, and skills are linked into shared/; profiles' own copies are backed up.
csm adopt-config --dry-run # Show what would change
csm adopt-config # Share settings, skills, agents, commands, CLAUDE.md
csm adopt-config --history # Also pool transcripts and history.jsonlcsm shell-init [shell]
Print a shell snippet for rc files. Detects your shell automatically.
csm shell-init # Auto-detect bash/zsh/fish/pwsh
csm shell-init bash # Explicitly output bash snippetcsm setup [bash|zsh|fish|pwsh] [--yes|-y]
Add the csm block to your shell rc (default: detected shell).
csm setup # Auto-detect and setup
csm setup zsh --yes # Setup zsh without promptingcsm doctor [--json]
Diagnose install, shell wrapper, links and profiles.
csm doctor # Human-readable output
csm doctor --json # Machine-readable JSONcsm uninstall [--purge] [--yes|-y]
Remove every csm rc block; --purge also deletes CSM_HOME (all logins).
csm uninstall # Remove rc blocks only
csm uninstall --purge # Also delete all profiles and logins
csm uninstall --yes # Don't prompt for confirmationcsm --version or csm -v
Print the installed version.
$ csm --version
0.1.0-beta.1Several settings are shared across all profiles via links from ~/.claude-sessions/shared:
settings.json— General preferencesCLAUDE.md— Custom instructionscommands/— Custom commandsagents/— Custom agentsskills/— Custom skills
Per-profile items (not shared):
.credentials.json— Login credentials.claude.json— Account info and per-profile MCP serversprojects/— Session transcripts (unless history sharing is enabled)history.jsonl— Prompt history (unless shared withadopt-config --history)policy-limits.json— Account usage limits
Claude Code can replace symlinks with regular files (e.g., when saving settings after permission approvals). This causes profiles to have different copies, losing the intent of sharing.
When drift is detected, csm sync reports it:
$ csm sync
work: settings.json drifted, agents drifted
personal: settings.json drifted — run "csm sync personal --repair=adopt|discard" to fix.Fix drift with --repair:
# Discard work's copy (backed up) and relink to shared
csm sync work --repair=discard
# Adopt work's copy as the new shared version for all profiles
csm sync work --repair=adoptOn Windows, csm uses junctions instead of symlinks (no admin required). Junction behavior:
- Symlink shorthand: junctions point to directories; they act like symlinks but don't require Developer Mode.
- Developer Mode: With Developer Mode enabled (Settings > System > For developers), csm prefers true symlinks.
- Hardlink fallback: For files, when symlinks fail, csm falls back to hardlinks. If those fail too, an error is reported.
- Stale detection: If a hardlinked file is edited by Claude Code (which breaks the inode),
csm syncdetects it as "stale" and can refresh it.
See csm doctor to check link support on your system.
- Run
type claude— it must report a shell function, not a command path. If it shows a path, the rc line is missing or your shell wasn't restarted: add it and runexec $SHELL. - Verify
csm shell-initworks:csm shell-initshould output shell code, not "Unknown command". - Check that your profile is logged in:
csm listshows the email for each profile. A profile showing(not logged in)never finished login — runcsm run <name>and log in.
Profiles only see what is in ~/.claude-sessions/shared/. By default, csm import copies only the login. Run csm adopt-config to link your original ~/.claude config into every profile. Add --history to also pool transcripts and memory.
If Out-String | Invoke-Expression fails (error about piping), try piping differently:
csm shell-init pwsh | Out-String | Invoke-ExpressionThis converts the multi-line script to a single string before invoking it. The installers do this automatically; if you're running manually, use this form.
For any other issue, run csm doctor. It checks:
- Runtime version (Node 20+)
- Claude Code installation
- Shell wrapper integration
- Shell rc file blocks
- Profile directory permissions
- Linked shared config
- Profile login status
csm doctor # Human-readable
csm doctor --json # JSON for scriptingcurl -fsSL https://raw.githubusercontent.com/ilomon10/csm/main/scripts/install.sh | sh -s -- --uninstall [--purge]Add --purge to also delete all profiles and logins.
& ([scriptblock]::Create((irm https://raw.githubusercontent.com/ilomon10/csm/main/scripts/install.ps1))) -Uninstall [-Purge]csm uninstall [--purge] [--yes]On macOS, Claude Code stores logins in the system Keychain by default. csm import only works with file-based logins (the fallback when Keychain write fails). To import a Keychain login:
- Use
csm add <name>to log in fresh - Or run
csm importafter manually creating a file-based fallback (unsetCLAUDE_CONFIG_DIR, log in once to create a.credentials.jsonfile, then import)
csm import copies a refresh token. If the source login (e.g., ~/.claude) is later refreshed, the profile's copy becomes invalid. Solutions:
- Use
csm import --moveto remove the source after copying - Log out from the source (
~/.claude) - Or accept that only one copy can stay logged in at a time
csm share-history moves a profile's projects/ to shared/, visible to all profiles. If you later log out of one account, its transcripts remain accessible from another account. This is intentional but worth knowing.
csm shell-init pwshgenerates PowerShell script; cmd.exe is not supported (install PowerShell 7 or runcsm rundirectly)- On Windows, csm uses junctions and hardlinks instead of symlinks (no admin required)
- If csm was installed with npm (a
csm.cmdshim), PowerShell drops empty-string arguments such asclaude ""before they reach csm. This is PowerShell's legacy handling of batch files; the standalonecsm.exefrom the installer is not affected.
CSM_HOME— Override the data directory (default:~/.claude-sessions)CSM_CLAUDE_BIN— Override the claude binary path (default:claudeon PATH)CSM_DEBUG=1— Print stack traces on errorsNO_COLOR— Disable colored output incsm doctor
Contributions are welcome. See CONTRIBUTING.md for dev setup, testing, and coding style.
For security issues, see SECURITY.md.
MIT. See LICENSE.
This is a beta release (v0.1.0-beta.1). The CLI and shell integration are stable, but the feature set may evolve. Please report bugs at github.com/ilomon10/csm/issues.