npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

claude-cli-switcher

v1.3.2

Published

Switch between multiple Claude Code (Anthropic Pro) accounts on one machine. Snapshot each native login as a profile, swap with one command, /status keeps showing the right Email/Organization. Interactive menu + CLI.

Readme

csw — Claude Account Switcher

npm version npm downloads License: MIT Platform: macOS · Linux · Windows

Switch between multiple Claude Code (Anthropic) accounts on the same machine in one command. Native Claude Pro logins (refresh token + access token + organization metadata) are snapshotted per profile, so /status keeps showing the right Email and Organization no matter which account you're using.

$ csw
╭───────────────────────────────────────────╮
│  csw — Claude Account Switcher
├───────────────────────────────────────────┤
│  ⚡ Active:   personal
│  👤 Profiles: 3
╰───────────────────────────────────────────╯

What do you want to do?

  ❯ Switch account
    Add account / save current login
    Remove a profile
    Run claude (with active account)
    Show /status
    Repair session index
    Quit

[↑↓ navigate · Enter select · Esc/q back]

Pure zsh with a small Python helper, zero npm runtime dependencies, works alongside the official Claude CLI without touching it.


Why

The official claude CLI stores one set of credentials at a time — in ~/.claude/.credentials.json and the macOS Keychain. Switching between, say, a personal Pro account and a work one means logging out and back in every single time. Tedious, and /status only shows the active login.

csw can either snapshot-and-swap a shared login (the original model, below) or — recommended — give each account its own isolated credential store.


Isolated accounts (recommended — v1.1+)

The snapshot-and-swap model has a fundamental limit: Claude Code's OAuth refresh token rotates — a new one is issued and the old one invalidated every time the (~8h) access token refreshes. A static snapshot therefore goes stale, and restoring it later fails with Please run /login · API Error: 401 Invalid authentication credentials. Swapping one shared credential store is also unsafe while a claude window is running (the running process rotates and writes that shared store).

Isolated mode fixes this for good. Each account gets its own CLAUDE_CONFIG_DIR — its own credentials + its own Keychain item — and Claude Code reads/writes/rotates that account's token in place, forever. csw never copies or snapshots credentials; "switching" only records which account is active and launches claude with that account's dir. Tokens never go stale, never get clobbered, and different accounts can even run in parallel windows.

Switching stays seamless. Only the credentials are per-account. Your plugins, MCP servers, sessions/transcripts, settings, and permissions are shared across all accounts (csw symlinks each account's CLAUDE_CONFIG_DIR to one shared store under ~/.claude-switcher/shared/, seeded once from your existing ~/.claude). So switching does not lose conversations or force you to re-install plugins or re-grant permissions.

What is per-account (isolated): the OAuth credentials, the account identity (oauthAccount), per-account usage stats, and command history. What is shared: plugins/, projects/ (sessions), settings.json/settings.local.json (incl. permissions), and related session state. Note: claude.ai-native MCP connectors (Canva, Google Drive, Linear, …) are tied to each claude.ai account by Anthropic, so those are inherently per-account — switching shows that account's connectors.

csw add personal                 # log in account "personal" (its own isolated store)
csw add work                     # log in account "work"
csw shell-init >> ~/.zshrc       # make plain `claude` follow `csw use` (then open a new shell)

csw use personal                 # make "personal" active — no credential copy
claude                           # ...runs as personal     (or: csw run)
csw use work && claude           # runs as work

| Command | What it does | |---|---| | csw add <name> | Create an isolated account and log into it. | | csw use <name> | Make <name> the active account. No credential copy. | | csw run [args…] | Run the real claude as the active account. | | csw list / csw current | List accounts / show the active one. | | csw remove <name> | Delete an account (its dir + Keychain item). | | csw config-dir | Print the active account's CLAUDE_CONFIG_DIR. | | csw shell-init | Shell snippet so plain claude follows csw use. | | csw migrate | Convert legacy snapshot profiles to isolated accounts. |

Routing plain claude: after csw use, open a new shell (with shell-init in your rc) or use csw run. A shell opened before the switch keeps its previous account — that is correct isolation, not a bug.

Migrating: run csw migrate once. A snapshot taken before a token rotation is already stale, so an account may 401 on first use — just run csw add <name> to re-login it in place; after that it never recurs.


Snapshot mode (legacy)

The commands below (save-native, use-native, the interactive menu) drive the original shared-store model. They still work, but prefer isolated mode above — it is the one that survives refresh-token rotation and concurrent claude windows.

Features

  • Interactive menu by default — csw with no args opens a polished arrow-key menu.
  • First-run account detection — if Claude Code is already logged in, csw shows that current login even before it has been saved as a profile.
  • One-command switching between any number of accounts.
  • Preserves native login state/status shows Email/Organization per profile, not just an opaque "Auth token".
  • Completes Claude Code onboarding state after restoring a valid profile, so first-run login-method prompts do not reappear on fresh machines.
  • Repairs Claude session visibility by rebuilding ~/.claude.json.projects from raw transcripts in ~/.claude/projects/, so old conversations remain resumable after account switches.
  • Secure by constructionumask 077 from line 3, credentials at 0600, dirs at 0700.
  • File-locking on mutating operations: atomic mkdir-based mutex, PID-based stale-lock recovery, configurable timeout.
  • Schema validation with CLAUDE_SKIP_VALIDATION=1 escape hatch if Anthropic ever changes the credential format.
  • Auto-cleanup of live credentials (file + Keychain + ~/.claude.json oauthAccount) when you remove the active profile.
  • Zero npm deps beyond zsh, python3, jq, and the real claude CLI.

Requirements

  • macOS, Linux, or Windows.
    • On Windows, WSL2 is recommended. Run csw inside WSL and install Claude Code inside the same distro, or let csw use the native Windows claude.exe when it is installed under your Windows profile.
    • Native Windows shells require a POSIX zsh runtime because csw is a zsh script.
  • zsh (default shell on modern macOS)
  • python3 for the session repair helper
  • The official Claude Code CLI installed somewhere reasonable — ~/.local/bin/claude, ~/.claude/local/claude, /opt/homebrew/bin/claude, /usr/local/bin/claude, on PATH, or pointed at via CLAUDE_REAL_BIN
  • jq (required for save-native, use, and remove-native) — used to validate credentials and patch ~/.claude.json oauthAccount so /status reports the right account. Install with brew install jq (macOS) or sudo apt-get install jq (Debian/Ubuntu). Read-only commands (list, current, status) still work without it.

Installation

Option 1 — npm (recommended)

npm install -g claude-cli-switcher

That puts csw on your PATH. Done.

Option 2 — git clone

git clone https://github.com/ntdung6868/claude-account-switcher.git
cd claude-account-switcher
chmod +x csw

# Put csw on your PATH (any one of these):
ln -s "$PWD/csw" ~/.local/bin/csw          # if ~/.local/bin is on PATH
sudo ln -s "$PWD/csw" /usr/local/bin/csw   # global
# …or add the repo dir to PATH in your shell rc.

Reload your shell, and you're done

csw          # opens the menu
csw help     # full CLI reference

Windows notes

Recommended WSL flow:

wsl

Then inside WSL:

curl -fsSL https://claude.ai/install.sh | bash
npm install -g claude-cli-switcher
csw

If you installed native Windows Claude Code instead, csw can be run from WSL and will look for %USERPROFILE%\.local\bin\claude.exe. In that mode, it uses the Windows-side Claude state by default:

  • %USERPROFILE%\.claude
  • %USERPROFILE%\.claude.json
  • %USERPROFILE%\.claude-switcher

You can still override everything explicitly:

CLAUDE_REAL_BIN=/mnt/c/Users/you/.local/bin/claude.exe \
CLAUDE_HOME_DIR=/mnt/c/Users/you/.claude \
CLAUDE_JSON_FILE=/mnt/c/Users/you/.claude.json \
csw

csw is completely independent of the official claude CLI. It doesn't wrap or shadow it — claude keeps doing exactly what it always did. All csw does is swap which credentials are sitting in ~/.claude/.credentials.json and the Keychain when you say "use this profile". The next claude call picks them up naturally.

The typical workflow is:

csw use work
claude          # now logged in as the "work" profile
# ... later ...
csw use personal
claude          # now logged in as "personal"

Profiles and state live in ~/.claude-switcher/ regardless of where the script is installed. Override with CLAUDE_ACCOUNT_DIR=/some/path.


Quick start

First run on a machine already logged into Claude Code

Just run csw. If Claude Code is already logged in, the header shows that current login as unsaved. Choose Add account / save current login to save it as your first profile.

Or do it from the CLI:

csw save-native personal             # snapshot under a name

Add a second account

From the menu, choose Add account / save current login. If the current Claude login has not been saved yet, csw asks for a profile name and saves it first. Then it opens the Claude OAuth login flow for the new account, asks for the new profile name, saves it, and switches to it.

CLI equivalent:

csw save-native personal             # only needed once if current login is not saved yet
csw use-native
csw run auth login --claudeai        # log in as the other account
csw save-native work

Switch between them

csw use personal
claude                                # the official Claude CLI now uses 'personal'
# ... do stuff as personal ...

csw use work
claude                                # ... and now 'work'
# ... do stuff as work ...

Check who's active

csw current   # → personal
csw list
# * personal
#   work

Commands

| Command | What it does | | --- | --- | | csw | Open the interactive menu. | | csw save-native <name> | Save the current Claude Code login into native-accounts/<name>/ and set it active. | | csw use <name> | Restore a saved profile to the live credential locations. Only valid saved profiles are shown in the switch menu. | | csw use-native | Switch to bare native mode without touching saved profiles. This is a utility mode for adding/logging in accounts; it is intentionally not shown as a selectable account in the switch menu. | | csw remove-native <name> | Delete a saved profile. If it was active, also clears the live credentials (file + Keychain + oauthAccount). | | csw list | List all profiles, marking the active one with *. | | csw current | Print the active profile name (or native-login). | | csw status | Run claude auth status against the active account. | | csw session-status | Show local Claude transcript/project-index counts. | | csw repair-sessions | Rebuild ~/.claude.json.projects from ~/.claude/projects/**/*.jsonl. | | csw repair-sessions --dry-run | Show what session metadata would be repaired without writing. | | csw run [args...] | Run the real claude CLI with the active account. Unsets any *_AUTH_TOKEN env vars first. | | csw init | Create the data directories. Idempotent. | | csw help | Print full help. |


Environment variables

| Variable | Default | Purpose | | --- | --- | --- | | CLAUDE_ACCOUNT_DIR | $HOME/.claude-switcher | Where profiles, lock, and state files live. | | CLAUDE_HOME_DIR | $HOME/.claude | Real Claude config dir, where .credentials.json lives. | | CLAUDE_JSON_FILE | $HOME/.claude.json | Real Claude top-level config (holds oauthAccount). | | CLAUDE_REAL_BIN | (auto-detected) | Absolute path to the real claude CLI. The script searches common install paths, PATH, and WSL-visible Windows claude.exe locations; set this if your install is elsewhere. | | CLAUDE_LOCK_TIMEOUT | 30 | Seconds to wait for the lock before failing. | | CLAUDE_SESSION_SYNC | 1 | Set to 0 to skip automatic session repair after save-native, use, or use-native. | | CLAUDE_SKIP_VALIDATION | (unset) | Set to 1 to bypass strict credential-schema validation. Use only if Anthropic changed the schema and the strict check is wrong. | | PYTHON_BIN | python3 | Python interpreter for helper scripts. |


How it works

Native Claude Pro credentials live in local Claude state:

  1. ~/.claude/.credentials.json — JSON with claudeAiOauth.{refreshToken, accessToken, …}.
  2. macOS Keychain — macOS only; entry with service Claude Code-credentials (suffixed with a hash of CLAUDE_CONFIG_DIR if set), account $USER.
  3. ~/.claude.json — top-level config; the oauthAccount field is what powers /status showing Email/Organization.

save-native <name> snapshots all three into native-accounts/<name>/.credentials.json and native-accounts/<name>/oauthAccount.json, then writes the saved credential back to the live file + Keychain so a browser login that only touched Keychain is immediately usable. use <name> writes them all back. After a valid OAuth profile is saved or restored, csw also marks Claude Code onboarding complete in ~/.claude.json, using the installed Claude Code version when available. The real claude CLI never knows it didn't log in normally.

When the active profile is removed, the script wipes the live credential locations so the next claude run isn't tied to a "deleted" account.

csw run [args...] execs the real CLI after unsetting any CLAUDE_CODE_OAUTH_TOKEN, CLAUDE_CODE_OAUTH_REFRESH_TOKEN, or ANTHROPIC_AUTH_TOKEN env vars that could shadow the native login.

Claude Code stores conversation transcripts under ~/.claude/projects/<project>/<session-id>.jsonl, but recent-session pointers live in ~/.claude.json.projects. csw repair-sessions scans the raw transcript files and merges missing or stale project pointers back into ~/.claude.json. It backs up ~/.claude.json under ~/.claude/backups/csw-sessions/ before writing and never modifies transcript contents.


Concurrency

Mutating commands (save-native, use, use-native, remove-native) take an exclusive lock at $BASE_DIR/.lock. Concurrent invocations wait up to CLAUDE_LOCK_TIMEOUT seconds (default 30) before failing. Read-only commands (list, current, status, run) are not locked. Stale locks from crashed processes are auto-detected via the recorded PID, so you never need to rm -rf .lock manually after a Ctrl-C.


Schema-change escape hatch

Credential validation checks for .claudeAiOauth.refreshToken and .claudeAiOauth.accessToken. If Anthropic changes the format, the strict check fails with a hint. Re-run with CLAUDE_SKIP_VALIDATION=1 to bypass — the script copies credentials raw and emits a warning rather than failing.


Security notes

  • Profile credentials are at 0600 under a 0700 parent. The script forces umask 077 from its third line, so even the brief window between file creation and an explicit chmod is safe.
  • The script never logs tokens.
  • csw run unsets known auth env vars (CLAUDE_CODE_OAUTH_TOKEN, CLAUDE_CODE_OAUTH_REFRESH_TOKEN, ANTHROPIC_AUTH_TOKEN) before exec'ing the real CLI, so a stray env var can't shadow your selected account.
  • Add the data directory to backups only if you understand that you're backing up active Claude Pro tokens.

Troubleshooting

Could not find the real Claude binary — your claude CLI is installed somewhere unusual. Set CLAUDE_REAL_BIN=/path/to/claude. On WSL, install Claude Code inside the distro or point to the Windows binary, for example CLAUDE_REAL_BIN=/mnt/c/Users/you/.local/bin/claude.exe.

saved credentials for 'X' are not a full Claude Pro login — the snapshot is missing claudeAiOauth.refreshToken / accessToken. Either re-save with csw save-native X after logging in again, or, if you suspect Anthropic changed the schema, retry with CLAUDE_SKIP_VALIDATION=1.

could not acquire lock after 30s — another csw process is still running or stuck. The script auto-detects stale PIDs; if it still complains, remove $BASE_DIR/.lock manually.

jq is required for this operationsave-native, use, and remove-native need jq to validate credentials and patch ~/.claude.json. Install it: brew install jq (macOS) or sudo apt-get install jq (Debian/Ubuntu).

/status still shows the old account after switching — switching restores the profile's saved oauthAccount into ~/.claude.json. If the profile was saved before its identity was recorded, csw clears the stale oauthAccount instead, and claude repopulates it on the next run. To capture the identity, re-save the profile (csw save-native <name>) while logged in as the desired account.

claude still asks you to select a login method after switching — run csw use <name> again with v1.0.2 or newer. This restores the profile and marks Claude Code onboarding complete.

Please run /login · API Error: 401 Invalid authentication credentials after resuming — the selected profile's OAuth token can no longer refresh. Log in again and re-save the same profile:

csw use-native
csw run auth login --claudeai
csw save-native <name>
csw use <name>

Old conversations disappear from /resume after switching accounts — run csw repair-sessions or switch again with CLAUDE_SESSION_SYNC=1. The repair step rebuilds ~/.claude.json.projects from the raw transcript files that Claude keeps under ~/.claude/projects/.

interactive menu requires a terminalcsw was invoked from a non-TTY context (a script, a pipe, CI). Use the CLI subcommands directly: csw use <name>, csw run, etc.


License

MIT — see LICENSE.