I use Claude Code with two accounts on one laptop: one from my office and a personal one. I do not want personal projects on the office account, or the other way round, and I do not want to log out and back in every time I switch.
This is the first in a series of short Claude Code tips. It covers how I keep the two accounts apart and how I always know which one I am in.
One alias, two profiles
Claude Code keeps its login, settings, history and memory in a config folder, ~/.claude by default. The CLAUDE_CONFIG_DIR environment variable points it at a different folder. That is all a second profile is.
I added one line to ~/.zshrc:
# Claude Code: personal account profile (office = plain `claude`)
alias claude-personal='CLAUDE_CONFIG_DIR="$HOME/.claude-personal" claude'
Now there are two commands:
clauderuns with the office account.claude-personalruns with the personal account.
The first time I ran claude-personal it asked me to log in, because the new folder was empty. I logged in with the personal account once, and both logins have stayed in place since. I can have both open in two terminal tabs at the same time.
Showing the active account
Two profiles that look identical are an accident waiting to happen. So the status line at the bottom of Claude Code tells me where I am:
🏠 Personal · me@example.com
and in the other profile:
🏢 Office · me@company.com
Claude Code can run a command to produce its status line. The setting goes in settings.json, in each profile’s folder:
{
"statusLine": {
"type": "command",
"command": "/Users/me/.claude/statusline-account.sh"
}
}
Both profiles point at the same script. The script works out which profile it is running in from CLAUDE_CONFIG_DIR, and reads the logged-in email from that profile’s .claude.json:
#!/bin/bash
# Shows which Claude account profile is active.
cat >/dev/null
dir="${CLAUDE_CONFIG_DIR:-$HOME/.claude}"
if [ "$dir" = "$HOME/.claude-personal" ]; then
label="🏠 Personal"
else
label="🏢 Office"
fi
read_email='import json,sys; print(json.load(open(sys.argv[1])).get("oauthAccount",{}).get("emailAddress",""))'
email=$(/usr/bin/python3 -c "$read_email" "$dir/.claude.json" 2>/dev/null)
[ -z "$email" ] && [ "$dir" = "$HOME/.claude" ] && email=$(/usr/bin/python3 -c "$read_email" "$HOME/.claude.json" 2>/dev/null)
echo "$label${email:+ · $email}"
A few notes on it:
cat >/dev/nullis there because Claude Code sends session details to the script as JSON on standard input. This script does not need them, so it reads and discards them.- The second lookup covers the default profile, which keeps its
.claude.jsonin the home folder and not inside~/.claude. - The email comes from an internal file. The
oauthAccountfield is not a documented setting, so it may change in a future version. If it does, the script still prints the label and leaves the email out.
Remember to make the script executable with chmod +x.
Sharing instructions between the two
Each profile has its own global CLAUDE.md, the file with instructions that apply to every project. I want the same working rules in both accounts, so the personal one is a symlink to the office one:
ln -s ~/.claude/CLAUDE.md ~/.claude-personal/CLAUDE.md
I edit one file and both profiles follow it.
What stays separate
Everything else lives in the profile’s folder, so it is separate by default:
- Login and usage. Each profile uses its own account and its own plan limits.
- Settings and permissions. A permission I allow in one profile is not allowed in the other.
- Skills and plugins. Office skills stay in the office profile. I copy over only the ones I want in both.
- History and memory. Conversations and saved memory for a project are per profile, even for the same folder on disk.
That separation is the point. Office work stays on the office account, and my own projects stay on mine. The status line makes sure I notice before I start typing in the wrong one.
Leave a Reply