Back to Blog
CLAUDE CODE · WORKFLOWPublished Updated 6 min read

Run Multiple Claude Code Accounts Without Logging Out

Client-provided Claude Code subscriptions mean a /login every time you switch, a real risk of billing the wrong client, and no way to leave a long task running. One environment variable fixes all three.

Claude CodeAI Coding ToolsDeveloper WorkflowShell

Two clients, two Claude Code subscriptions, one laptop. You finish a morning on the client A repo, switch to client B after lunch, and the switch costs you a /login, a browser round trip, and a fresh authentication. Do that twice a day and you lose a few minutes each time.

The billing risk bothered me more than the lost minutes. Log in as client A, forget you did, then spend an afternoon on client B's codebase, and client A pays for that afternoon. Nothing in the terminal warns you. The prompt looks the same either way.

The morning that decided it for me, I had a long task running for client A with subagents still working through it. My hours for that client ran out before the task did. Client B was waiting, and the only way into their account was to end the session in front of me. Logging out threw away work that was still running, and none of it came back when I logged in again that evening.

One environment variable removes all three. CLAUDE_CONFIG_DIR tells Claude Code where to keep its state. Point it at two directories and each one carries its own account, its own history, and its own settings. I run my personal account as claude and my contract account as claude-work, side by side in two tabs.

Inside the config directory

Claude Code keeps its per-user state in ~/.claude by default. Set CLAUDE_CONFIG_DIR and it reads and writes somewhere else instead. That directory holds the pieces that make one account feel like one workspace:

  • Credentials. The login behind /login, along with the account record that /status reads, so each directory answers to a different account.
  • Conversation history. Sessions and transcripts under projects/, which keeps one client's transcripts out of the other's --resume list.
  • Settings and extensions. settings.json, plus installed plugins and skills.
  • Global memory. The user-level CLAUDE.md that applies across your projects.

Isolating all of that is the point. Two accounts stop sharing a login, and they also stop sharing usage limits, so a heavy morning on one contract leaves the other untouched.

Project-level files stay where they are. A repo's own CLAUDE.md and .claude/ directory live in the repo, so both profiles pick them up when you open that repo. You split the account, not the project.

Set up the second profile

Leave your existing account on the default ~/.claude and give the new one its own directory. Nothing you already have moves, and the claude command keeps working as before.

bash
mkdir -p ~/.claude-work

Add an alias that sets the variable for that one command. Put it in ~/.zshrc on macOS, or ~/.bashrc on most Linux setups.

~/.zshrcbash
# Double quotes would keep the ~ literal; $HOME survives either style.
alias claude-work="CLAUDE_CONFIG_DIR=$HOME/.claude-work claude"

Note

A bare ~ expands, and it survives single quotes too, so the tilde form of this alias works. Wrap it in double quotes and the tilde stays a literal character, at which point Claude Code creates a folder named ~ under the directory you launched from and your profile starts over from scratch. $HOME works under either style, which is why the alias above uses it.

Reload the shell so the alias exists.

bash
source ~/.zshrc

Run claude-work, then /login, and authenticate the second account in the browser. The new directory fills up on first run, and you go through onboarding again, which is the profile behaving as a clean install.

Then check that the profile landed where you meant it to. The -d flag prints the directory itself rather than listing what is inside it, which keeps the answer to one line.

bash
ls -d ~/.claude-work
# /Users/you/.claude-work

Getting the path back means the alias pointed at the directory you created. A No such file or directory means the two disagree, and the usual cause is the quoting above: Claude Code made a folder named ~ in whatever directory you launched it from. Run ls -d ./~ there to confirm before deleting it.

Confirm which account a session is using

Run /status inside a session. It prints the account and the config path it loaded, which settles the billing question on the spot.

Running both at once

Open a terminal tab, run claude in the personal repo. Open a second tab, run claude-work in the client repo. Both sessions run at the same time against separate accounts and separate quotas, and neither one logs the other out. A long task can keep running in the first tab while you start the day's second client in the other.

The alias covers interactive use. Scripts and CI need the variable on the command itself, because a non-interactive shell never reads your .zshrc, so the alias does not exist there.

bash
CLAUDE_CONFIG_DIR=$HOME/.claude-work claude -p "summarise the open PRs"

That line runs one prompt on the work profile and exits. The -p flag makes it non-interactive, so Claude Code answers on stdout and returns, which is what lets you pipe the reply somewhere or run it from a CI job. The assignment in front applies to that command alone.

One function instead of many aliases

One alias per account works until you hold four or five. At that point write a single function that takes the profile name as an argument and passes the rest through to Claude Code. It replaces the aliases rather than joining them.

~/.zshrcbash
# Usage: cc acme            -> interactive session on the acme profile
#        cc acme -p "..."    -> flags pass straight through
cc() {
  local profile=$1
  if [[ -z $profile ]]; then
    echo "usage: cc <profile> [claude args...]" >&2
    return 1
  fi
  shift
  CLAUDE_CONFIG_DIR="$HOME/.claude-$profile" claude "$@"
}

Try running cc work to start Claude Code using your work profile.

Adding a client becomes one mkdir and one /login, with no new alias to write. The assignment sits on the same line as the command here too, so cc leaves the shell exactly as it found it. Like the alias it lives in .zshrc, so scripts and CI still need the variable written out in full.

Worth knowing before you commit

A few things surprised me after I had been running this for a while.

Your setup does not follow you. Skills, plugins, MCP servers and your global CLAUDE.md belong to whichever directory you configured them in. Install a skill in the personal profile and the work profile has never heard of it. Copy the files across when you want both to have something, or symlink the ones you keep in sync.

Two accounts, not two seats on one. This splits logins you already hold. Check the terms before you point a second profile at a subscription somebody else pays for.

The directory holds a live session. Back it up like credentials rather than like dotfiles, and keep it out of any repo you push.

Credentials sit in different places per platform. On Linux and Windows, Claude Code writes a .credentials.json inside the config directory. On macOS it uses the system Keychain, which reads like a problem for this setup, since the Keychain belongs to your macOS user rather than to any one directory. In practice the profiles still resolve to separate accounts: each config directory carries its own account record, and /status in each tab reports its own login. I have had a personal and a contract account signed in together on macOS for months without either one displacing the other.

I have run two profiles this way for months. The part I value is not the saved minutes. Opening a client repo in a tab that can only bill that client removes a decision I used to make wrong.

Work With Me

Got a project that needs this kind of thinking?

I build web applications for teams who need them done right: architecture, AI integration, and the unglamorous parts that keep a product running. Tell me what you're working on.

Let's Work Together