I have a Claude Code account from work and a personal one, and both live on the same MacBook. Claude Code keeps one login per config folder, so the fix is to give each account its own folder with the CLAUDE_CONFIG_DIR environment variable. Then I go one step further and block the plain claude command, so I can never start a session without saying which account it runs on.
The short version: two config folders plus two shell functions, and bare
clauderefuses to run.
- Separate folders: each one keeps its own login, settings and history, and both accounts stay logged in at the same time.
- Named commands:
claude-workandclaude-personalset the folder and start the real program.- No default: typing
claudeprints an error instead of quietly picking an account for you.
Why one login isn’t enough
Logging out and back in works, but it’s slow and easy to forget. The worse problem is the silent one: you open a terminal, type claude, and spend an hour on a personal project using your work quota, with that history saved next to your work sessions.
I wanted the account choice to be part of the command I type, every time.
Give each account its own config folder
Claude Code reads its config from ~/.claude by default. Point CLAUDE_CONFIG_DIR somewhere else and it treats that folder as a completely separate install: separate login, separate settings.json, separate session history.
Keep the work account on the default folder so nothing already set up there moves, and give the personal one a new folder:
CLAUDE_CONFIG_DIR="$HOME/.claude-personal" claude
The first run starts logged out. Run /login, sign in with the second account, and from then on that folder remembers it. Use /status inside a session to confirm which account you’re on.
How do you stop bare claude from running?
Typing that environment variable every time gets old fast, so I wrapped it in shell functions. The trick is to also define a function called claude that does nothing except complain. This goes in ~/.zshrc:
# Block bare `claude`, force an explicit account
claude() {
echo "Use claude-work or claude-personal" >&2
return 1
}
claude-work() { CLAUDE_CONFIG_DIR="$HOME/.claude" command claude "$@"; }
claude-personal() { CLAUDE_CONFIG_DIR="$HOME/.claude-personal" command claude "$@"; }
Reload with source ~/.zshrc and try it:
$ claude
Use claude-work or claude-personal
command claude is what makes this work. It skips shell functions and aliases and runs the real binary from your PATH, so the two wrappers reach the actual program while the blocker catches everything else. "$@" passes your flags through, so claude-personal --resume behaves the way you’d expect.
A few things this does not cover:
- Only your interactive shell sees it. Scripts, cron jobs and IDE extensions call the binary directly and don’t read
~/.zshrc, so they still use the default folder (the work account here). For me that’s the right behavior, since nothing automated breaks. - One-off escape hatch:
command claudein the terminal runs the default account without going through the blocker. - Bash users: the same functions work in
~/.bashrcunchanged.
What do you share between accounts?
The new folder starts empty. Your global CLAUDE.md, custom skills, plugins and settings all stay behind in ~/.claude.
I symlink the parts that describe how I work, because those are the same no matter who pays for the tokens:
ln -s ~/.claude/CLAUDE.md ~/.claude-personal/CLAUDE.md
ln -s ~/.claude/skills ~/.claude-personal/skills
I keep settings.json and plugins separate. A work account usually carries org-specific setup like MCP servers, connectors and permission rules, and none of that belongs in personal sessions.
Note: a skill shared through a symlink can’t count on other skills being installed in both folders. If one skill reads another, point it at the file path directly.
What about the desktop app and the web?
The environment variable only helps in the terminal. The desktop app signs in to one account at a time. On the web, I use one Chrome profile per account, which keeps the cookies apart and lets both stay open in separate windows.
My split ends up as: work in the desktop app and claude-work, personal in its own Chrome profile and claude-personal. The same pattern works for any CLI that reads its config path from an environment variable, which is worth checking the next time you hit this with another tool.