Managing Multiple Claude Code Profiles
When working with multiple Claude accounts (work, personal, client projects), you need an easy way to switch between profiles without manually changing configuration files or OAuth tokens every time.
This tutorial shows how to set up a profile switcher that handles both configuration directories and authentication tokens seamlessly.
Why Multiple Profiles?
Common use cases:
- Work vs Personal: Separate API usage and conversation history
- Client Projects: Different billing accounts per client
- Team Accounts: Switch between team and personal accounts
- Testing: Sandbox environment for experimenting
Architecture Overview
The setup consists of three components:
- Profile directories - Store settings, history, and tokens separately
- Symlink switcher - Point to the active profile
- Shell function - Update current session immediately
~/.claude/
├── current -> profiles/work # Symlink to active profile
└── profiles/
├── work/
│ ├── settings.json
│ ├── history.jsonl
│ └── token # OAuth token
├── personal/
│ ├── settings.json
│ ├── history.jsonl
│ └── token
└── project-a/
├── settings.json
├── history.jsonl
└── token
Setup Instructions
Step 1: Create Profile Structure
First, create the directory structure:
# Create profiles directory
mkdir -p ~/.claude/profiles
# Move existing config to a profile (if you have one)
if [ -d ~/.claude ] && [ ! -L ~/.claude/current ]; then
mkdir -p ~/.claude/profiles/work
mv ~/.claude/settings.json ~/.claude/profiles/work/ 2>/dev/null || true
mv ~/.claude/history.jsonl ~/.claude/profiles/work/ 2>/dev/null || true
fi
# Create additional profiles
mkdir -p ~/.claude/profiles/personal
mkdir -p ~/.claude/profiles/project-a
# Create initial symlink to work profile
ln -sfn ~/.claude/profiles/work ~/.claude/current
Step 2: Store Authentication Tokens
Store your authentication tokens securely in each profile. Claude Code supports two types of tokens:
OAuth tokens (recommended for standard Claude.ai accounts):
# Work profile OAuth token
echo "sk-ant-oat01-YOUR_WORK_TOKEN_HERE" > ~/.claude/profiles/work/.oauth-token
chmod 600 ~/.claude/profiles/work/.oauth-token
# Personal profile OAuth token
echo "sk-ant-oat01-YOUR_PERSONAL_TOKEN_HERE" > ~/.claude/profiles/personal/.oauth-token
chmod 600 ~/.claude/profiles/personal/.oauth-token
API tokens (for custom endpoints or API-based authentication):
# Project A profile with API token (takes precedence over OAuth)
echo "sk-ant-api03-YOUR_API_TOKEN_HERE" > ~/.claude/profiles/project-a/.auth-token
chmod 600 ~/.claude/profiles/project-a/.auth-token
Getting OAuth tokens: Run claude setup-token
for each account you want to configure.
Step 2b (Optional): Configure Custom Base URLs
If you’re using a custom Claude endpoint (e.g., enterprise deployment, proxy, or alternative API), you can configure the base URL per profile:
# Configure custom endpoint for project-a profile
echo "https://api.custom-claude.company.com" > ~/.claude/profiles/project-a/.base-url
chmod 600 ~/.claude/profiles/project-a/.base-url
This sets the ANTHROPIC_BASE_URL
environment variable for that profile.
Step 3: Update Shell Configuration
Add these exports to your shell profile (~/.bashrc
or ~/.zshrc
):
# Claude Code configuration
export CLAUDE_CONFIG_DIR="$HOME/.claude/current"
# Load base URL if configured
if [[ -f "$HOME/.claude/current/.base-url" ]]; then
export ANTHROPIC_BASE_URL=$(cat "$HOME/.claude/current/.base-url")
fi
# Load authentication token from current profile
# Auth token takes precedence over OAuth token
if [[ -f "$HOME/.claude/current/.auth-token" ]]; then
export ANTHROPIC_AUTH_TOKEN=$(cat "$HOME/.claude/current/.auth-token")
elif [[ -f "$HOME/.claude/current/.oauth-token" ]]; then
export CLAUDE_CODE_OAUTH_TOKEN=$(cat "$HOME/.claude/current/.oauth-token")
fi
This ensures:
CLAUDE_CONFIG_DIR
points to the active profileANTHROPIC_BASE_URL
is set if you’re using a custom endpoint- Authentication tokens are loaded automatically (API token takes precedence over OAuth)
Step 4: Create Profile Switcher Function
Add this function to your shell profile (after the exports above):
# Claude profile switcher
# Usage: switch-claude <profile-name>
switch-claude() {
local profile="$1"
if [[ -z "$profile" ]]; then
echo "Usage: switch-claude <profile-name>"
echo ""
echo "Available profiles:"
ls -1 "$HOME/.claude/profiles/" 2>/dev/null || echo " (none found)"
return 1
fi
# Validate profile exists
if [[ ! -d "$HOME/.claude/profiles/$profile" ]]; then
echo "Error: Profile '$profile' not found"
echo ""
echo "Available profiles:"
ls -1 "$HOME/.claude/profiles/"
return 1
fi
# Switch the symlink
ln -sfn "$HOME/.claude/profiles/$profile" "$HOME/.claude/current"
# Update current session
export CLAUDE_CONFIG_DIR="$HOME/.claude/current"
# Load base URL if configured
if [[ -f "$HOME/.claude/current/.base-url" ]]; then
export ANTHROPIC_BASE_URL=$(cat "$HOME/.claude/current/.base-url")
else
unset ANTHROPIC_BASE_URL
fi
# Load authentication token (auth token takes precedence)
local token_loaded=false
if [[ -f "$HOME/.claude/current/.auth-token" ]]; then
export ANTHROPIC_AUTH_TOKEN=$(cat "$HOME/.claude/current/.auth-token")
unset CLAUDE_CODE_OAUTH_TOKEN
token_loaded=true
elif [[ -f "$HOME/.claude/current/.oauth-token" ]]; then
export CLAUDE_CODE_OAUTH_TOKEN=$(cat "$HOME/.claude/current/.oauth-token")
unset ANTHROPIC_AUTH_TOKEN
token_loaded=true
else
unset CLAUDE_CODE_OAUTH_TOKEN
unset ANTHROPIC_AUTH_TOKEN
fi
# Display status
echo "✓ Switched to Claude profile: $profile"
echo " CLAUDE_CONFIG_DIR: $CLAUDE_CONFIG_DIR"
if [[ -n "$ANTHROPIC_BASE_URL" ]]; then
echo " Base URL: $ANTHROPIC_BASE_URL"
fi
if [[ "$token_loaded" == true ]]; then
echo " Token: loaded"
else
echo " Warning: No token file found"
fi
}
Step 5: Apply Changes
Reload your shell configuration:
# Reload shell config
source ~/.zshrc # or source ~/.bashrc
Usage
Switch Profiles
# Switch to work profile
switch-claude work
# Switch to personal profile
switch-claude personal
# Switch to project-a profile
switch-claude project-a
Output example:
✓ Switched to Claude profile: work
CLAUDE_CONFIG_DIR: /Users/username/.claude/current
Token loaded from profile
List Available Profiles
# Show all profiles
switch-claude
Output:
Usage: switch-claude <profile-name>
Available profiles:
personal
project-a
work
Verify Current Profile
# Check which profile is active
readlink ~/.claude/current
# Check current token (first 20 chars)
echo ${CLAUDE_CODE_OAUTH_TOKEN:0:20}...
How It Works
Current Session (Immediate)
When you run switch-claude
:
- Symlink updated:
~/.claude/current
→~/.claude/profiles/<profile>
- Environment updated: Function exports
CLAUDE_CONFIG_DIR
andCLAUDE_CODE_OAUTH_TOKEN
- Ready to use: Next
claude
command uses the new profile immediately
Future Sessions (Persistent)
When you open a new terminal:
- Shell config loads: Sources
~/.bashrc
or~/.zshrc
- Exports run: Sets
CLAUDE_CONFIG_DIR
to~/.claude/current
- Token loaded: Reads token from current profile’s token file
- Active profile used: Symlink points to the profile you last switched to
Advanced: Per-Profile Settings
Each profile can have its own settings:
// ~/.claude/profiles/work/settings.json
{
"alwaysThinkingEnabled": true,
"model": "claude-sonnet-4-5-20250929",
"verbose": false
}
// ~/.claude/profiles/personal/settings.json
{
"alwaysThinkingEnabled": false,
"model": "claude-3-5-haiku-20250311",
"verbose": true
}
When you switch profiles, Claude Code automatically loads the corresponding settings.
Security Notes
Token File Permissions
Always set restrictive permissions on token and configuration files:
# Correct permissions (owner read/write only)
chmod 600 ~/.claude/profiles/*/.oauth-token 2>/dev/null || true
chmod 600 ~/.claude/profiles/*/.auth-token 2>/dev/null || true
chmod 600 ~/.claude/profiles/*/.base-url 2>/dev/null || true
# Verify permissions
ls -l ~/.claude/profiles/*/.oauth-token ~/.claude/profiles/*/.auth-token 2>/dev/null
Expected output:
-rw------- 1 username staff 109 Oct 11 12:56 .../.oauth-token
-rw------- 1 username staff 109 Oct 11 12:56 .../.auth-token
-rw------- 1 username staff 38 Oct 11 12:56 .../.base-url
Git Ignore
If you store your dotfiles in git, add sensitive files to .gitignore
:
# Add to ~/.gitignore or your dotfiles .gitignore
cat >> ~/.gitignore << 'EOF'
.claude/profiles/*/.oauth-token
.claude/profiles/*/.auth-token
.claude/profiles/*/.base-url
EOF
Troubleshooting
“Profile not found” Error
Issue: Profile directory doesn’t exist
Solution: Create the profile directory
mkdir -p ~/.claude/profiles/<profile-name>
Token Not Loading
Issue: Token file missing or wrong permissions
Solution: Check file exists and is readable
# Check token files exist
ls -l ~/.claude/current/.oauth-token ~/.claude/current/.auth-token 2>/dev/null
# Fix permissions if needed
chmod 600 ~/.claude/current/.oauth-token 2>/dev/null || true
chmod 600 ~/.claude/current/.auth-token 2>/dev/null || true
Wrong Profile After Restart
Issue: New terminal session uses old profile
Solution: Check symlink points to correct profile
# Verify current profile
readlink ~/.claude/current
# Re-run switch if needed
switch-claude work
Function Not Found
Issue: switch-claude: command not found
Solution: Function not loaded in shell
# Reload shell config
source ~/.zshrc # or source ~/.bashrc
# Or add function to correct file
# Make sure function is in ~/.zshrc (for zsh) or ~/.bashrc (for bash)
Comparison: Before and After
Before (Manual Switching)
# Change config directory
export CLAUDE_CONFIG_DIR=~/.claude-work
export CLAUDE_CODE_OAUTH_TOKEN="sk-ant-oat01-WORK_TOKEN..."
# Later, switch to personal
export CLAUDE_CONFIG_DIR=~/.claude-personal
export CLAUDE_CODE_OAUTH_TOKEN="sk-ant-oat01-PERSONAL_TOKEN..."
# Have to remember to do this in every terminal
# Have to copy-paste tokens from password manager
# Easy to use wrong token with wrong config
After (Profile Switcher)
# Switch to work
switch-claude work
# Switch to personal
switch-claude personal
# All new terminals automatically use the last selected profile
# No manual token management
# Profile and token always match
Advanced: Profile-Specific Accessor Functions
While switch-claude
is great for switching between profiles, you can take it further with profile-specific accessor functions that let you run commands directly with a specific profile without switching your default.
This approach is inspired by the Nix configuration pattern and is particularly useful when you need to:
- Quickly run a one-off command with a different profile
- Keep your current profile active while checking something in another
- Script automated tasks that use different profiles
The Concept
Instead of just switch-claude work
, you create functions like:
claude-work
- Run claude with the work profileclaude-personal
- Run claude with the personal profilehappy-work
- Run happy (if installed) with the work profile
Implementation
Add this to your shell configuration (~/.bashrc
or ~/.zshrc
):
# List of Claude profiles to create accessor functions for
CLAUDE_PROFILES=("work" "personal" "project-a")
# Generate profile-specific accessor function
# Usage: claude-work, claude-personal, etc.
_mk_claude_profile_function() {
local profile="$1"
local command="$2"
eval "${command}-${profile}() {
local profile_dir=\"\$HOME/.claude/profiles/${profile}\"
local oauth_token_file=\"\$profile_dir/.oauth-token\"
local auth_token_file=\"\$profile_dir/.auth-token\"
local base_url_file=\"\$profile_dir/.base-url\"
# Set up environment variables
local env_vars=(
\"CLAUDE_CONFIG_DIR=\$profile_dir\"
)
# Add base URL if available
if [[ -f \"\$base_url_file\" ]]; then
env_vars+=(\"ANTHROPIC_BASE_URL=\$(cat \"\$base_url_file\")\")
fi
# Add auth token if available (takes precedence over OAuth token)
if [[ -f \"\$auth_token_file\" ]]; then
env_vars+=(\"ANTHROPIC_AUTH_TOKEN=\$(cat \"\$auth_token_file\")\")
elif [[ -f \"\$oauth_token_file\" ]]; then
env_vars+=(\"CLAUDE_CODE_OAUTH_TOKEN=\$(cat \"\$oauth_token_file\")\")
fi
# Execute command with profile-specific environment
env \"\${env_vars[@]}\" ${command} \"\$@\"
}"
}
# Generate accessor functions for all profiles
for profile in "${CLAUDE_PROFILES[@]}"; do
_mk_claude_profile_function "$profile" "claude"
_mk_claude_profile_function "$profile" "happy"
done
Usage Examples
# Run claude with work profile (doesn't change your default)
claude-work
# Run claude with personal profile
claude-personal
# Run happy with work profile
happy-work
# Pass additional arguments
claude-work --help
claude-personal /chat "What's the weather like?"
# Meanwhile, your default profile stays unchanged
echo $CLAUDE_CONFIG_DIR
# Still points to: ~/.claude/current
Recommended Setup: Combine Both Approaches
The best setup uses both the switcher and the accessor functions:
- Switcher (
switch-claude
) - Set your default profile for the session - Accessors (
claude-work
, etc.) - Quick one-off commands with other profiles
# Complete shell configuration example
# Add this to ~/.zshrc or ~/.bashrc
# ====================================
# Claude Code Configuration
# ====================================
# Default profile location
export CLAUDE_CONFIG_DIR="$HOME/.claude/current"
# Load base URL if configured
if [[ -f "$HOME/.claude/current/.base-url" ]]; then
export ANTHROPIC_BASE_URL=$(cat "$HOME/.claude/current/.base-url")
fi
# Load authentication token from current profile
# Auth token takes precedence over OAuth token
if [[ -f "$HOME/.claude/current/.auth-token" ]]; then
export ANTHROPIC_AUTH_TOKEN=$(cat "$HOME/.claude/current/.auth-token")
elif [[ -f "$HOME/.claude/current/.oauth-token" ]]; then
export CLAUDE_CODE_OAUTH_TOKEN=$(cat "$HOME/.claude/current/.oauth-token")
fi
# Profile switcher function
switch-claude() {
local profile="$1"
if [[ -z "$profile" ]]; then
echo "Usage: switch-claude <profile-name>"
echo ""
echo "Available profiles:"
ls -1 "$HOME/.claude/profiles/" 2>/dev/null || echo " (none found)"
return 1
fi
if [[ ! -d "$HOME/.claude/profiles/$profile" ]]; then
echo "Error: Profile '$profile' not found"
echo ""
echo "Available profiles:"
ls -1 "$HOME/.claude/profiles/"
return 1
fi
ln -sfn "$HOME/.claude/profiles/$profile" "$HOME/.claude/current"
export CLAUDE_CONFIG_DIR="$HOME/.claude/current"
# Load base URL if configured
if [[ -f "$HOME/.claude/current/.base-url" ]]; then
export ANTHROPIC_BASE_URL=$(cat "$HOME/.claude/current/.base-url")
else
unset ANTHROPIC_BASE_URL
fi
# Load authentication token (auth token takes precedence)
local token_loaded=false
if [[ -f "$HOME/.claude/current/.auth-token" ]]; then
export ANTHROPIC_AUTH_TOKEN=$(cat "$HOME/.claude/current/.auth-token")
unset CLAUDE_CODE_OAUTH_TOKEN
token_loaded=true
elif [[ -f "$HOME/.claude/current/.oauth-token" ]]; then
export CLAUDE_CODE_OAUTH_TOKEN=$(cat "$HOME/.claude/current/.oauth-token")
unset ANTHROPIC_AUTH_TOKEN
token_loaded=true
else
unset CLAUDE_CODE_OAUTH_TOKEN
unset ANTHROPIC_AUTH_TOKEN
fi
echo "✓ Switched to Claude profile: $profile"
[[ -n "$ANTHROPIC_BASE_URL" ]] && echo " Base URL: $ANTHROPIC_BASE_URL"
[[ "$token_loaded" == true ]] && echo " Token: loaded" || echo " Warning: No token found"
}
# List of profiles for accessor functions
CLAUDE_PROFILES=("work" "personal" "project-a")
# Generate profile-specific accessor function
_mk_claude_profile_function() {
local profile="$1"
local command="$2"
eval "${command}-${profile}() {
local profile_dir=\"\$HOME/.claude/profiles/${profile}\"
local oauth_token_file=\"\$profile_dir/.oauth-token\"
local auth_token_file=\"\$profile_dir/.auth-token\"
local base_url_file=\"\$profile_dir/.base-url\"
local env_vars=(\"CLAUDE_CONFIG_DIR=\$profile_dir\")
# Add base URL if available
if [[ -f \"\$base_url_file\" ]]; then
env_vars+=(\"ANTHROPIC_BASE_URL=\$(cat \"\$base_url_file\")\")
fi
# Add auth token if available (takes precedence over OAuth token)
if [[ -f \"\$auth_token_file\" ]]; then
env_vars+=(\"ANTHROPIC_AUTH_TOKEN=\$(cat \"\$auth_token_file\")\")
elif [[ -f \"\$oauth_token_file\" ]]; then
env_vars+=(\"CLAUDE_CODE_OAUTH_TOKEN=\$(cat \"\$oauth_token_file\")\")
fi
env \"\${env_vars[@]}\" ${command} \"\$@\"
}"
}
# Generate accessor functions for all profiles
for profile in "${CLAUDE_PROFILES[@]}"; do
_mk_claude_profile_function "$profile" "claude"
_mk_claude_profile_function "$profile" "happy"
done
# Clean up helper function
unset -f _mk_claude_profile_function
Adding New Profiles
To add a new profile to the accessor functions:
-
Add the profile name to the
CLAUDE_PROFILES
array:CLAUDE_PROFILES=("work" "personal" "project-a" "new-client")
-
Create the profile directory:
mkdir -p ~/.claude/profiles/new-client
-
Add the token:
# For OAuth token (standard accounts) echo "sk-ant-oat01-YOUR_TOKEN" > ~/.claude/profiles/new-client/.oauth-token chmod 600 ~/.claude/profiles/new-client/.oauth-token # OR for API token (custom endpoints) echo "sk-ant-api03-YOUR_TOKEN" > ~/.claude/profiles/new-client/.auth-token chmod 600 ~/.claude/profiles/new-client/.auth-token # Optionally configure custom base URL echo "https://api.custom.com" > ~/.claude/profiles/new-client/.base-url chmod 600 ~/.claude/profiles/new-client/.base-url
-
Reload your shell:
source ~/.zshrc # or source ~/.bashrc
-
Use the new accessor:
claude-new-client
Benefits of Profile Accessors
✅ No context switching - Keep working in one profile while checking another
✅ Scripting friendly - Easy to automate tasks across multiple profiles
✅ Explicit profile selection - Clear which profile you’re using
✅ Parallel usage - Open multiple terminals with different profiles simultaneously
✅ No side effects - Doesn’t change your default CLAUDE_CONFIG_DIR
Real-World Workflow Example
# Morning: Switch to work profile for the day
switch-claude work
# Work on project all morning
claude
# (uses work profile)
# Lunch break: Quick check on personal project
# Don't want to switch default profile
claude-personal /chat "Show me the latest commit in my blog repo"
# Back to work (still on work profile)
claude
# (still uses work profile)
# Evening: Switch to personal for the rest of the day
switch-claude personal
# Meanwhile in scripts: Always use specific profiles
#!/bin/bash
# backup-all-conversations.sh
claude-work /history export work-history.json
claude-personal /history export personal-history.json
claude-project-a /history export project-a-history.json
Alternative: Custom Profile Location
If you prefer a different base directory (like /dt/claude/profiles/
), just update the paths:
# Use /dt/claude instead of ~/.claude
CLAUDE_BASE="/dt/claude"
export CLAUDE_CONFIG_DIR="$CLAUDE_BASE/current"
# Update profile accessor to use custom base
_mk_claude_profile_function() {
local profile="$1"
local command="$2"
eval "${command}-${profile}() {
local profile_dir=\"$CLAUDE_BASE/profiles/${profile}\"
local oauth_token_file=\"\$profile_dir/.oauth-token\"
local auth_token_file=\"\$profile_dir/.auth-token\"
local base_url_file=\"\$profile_dir/.base-url\"
local env_vars=(\"CLAUDE_CONFIG_DIR=\$profile_dir\")
# Add base URL if available
if [[ -f \"\$base_url_file\" ]]; then
env_vars+=(\"ANTHROPIC_BASE_URL=\$(cat \"\$base_url_file\")\")
fi
# Add auth token if available (takes precedence over OAuth token)
if [[ -f \"\$auth_token_file\" ]]; then
env_vars+=(\"ANTHROPIC_AUTH_TOKEN=\$(cat \"\$auth_token_file\")\")
elif [[ -f \"\$oauth_token_file\" ]]; then
env_vars+=(\"CLAUDE_CODE_OAUTH_TOKEN=\$(cat \"\$oauth_token_file\")\")
fi
env \"\${env_vars[@]}\" ${command} \"\$@\"
}"
}
Integration with Other Tools
Tmux Session Names
Automatically show current profile in tmux:
# Add to ~/.tmux.conf
set -g status-right "Claude: #(readlink ~/.claude/current | xargs basename)"
Shell Prompt
Show current profile in your prompt:
# Add to ~/.zshrc (for zsh with oh-my-zsh)
claude_profile() {
local profile=$(readlink ~/.claude/current 2>/dev/null | xargs basename)
if [[ -n "$profile" ]]; then
echo "claude:$profile"
fi
}
# Add $(claude_profile) to your PROMPT variable
Starship Prompt
Add to ~/.config/starship.toml
:
[custom.claude_profile]
command = "readlink ~/.claude/current 2>/dev/null | xargs basename"
when = "test -L ~/.claude/current"
format = "[$output]($style) "
style = "bold blue"
Summary
The profile switcher provides:
✅ Instant switching - No manual file editing ✅ Persistent profiles - Survives terminal restarts ✅ Secure tokens - Stored with proper permissions ✅ Isolated history - Separate conversation history per profile ✅ Per-profile settings - Different configurations per account ✅ Simple usage - One command to switch everything
Complete Setup Script
Copy-paste this entire script to set up everything:
#!/usr/bin/env bash
set -e
echo "Setting up Claude Code profile switcher..."
# Create profile structure
mkdir -p ~/.claude/profiles/{work,personal,project-a}
# Move existing config if present
if [ -f ~/.claude/settings.json ] && [ ! -d ~/.claude/profiles/work/settings.json ]; then
mv ~/.claude/settings.json ~/.claude/profiles/work/settings.json 2>/dev/null || true
fi
if [ -f ~/.claude/history.jsonl ]; then
mv ~/.claude/history.jsonl ~/.claude/profiles/work/history.jsonl 2>/dev/null || true
fi
# Create current symlink
ln -sfn ~/.claude/profiles/work ~/.claude/current
# Detect shell config file
SHELL_CONFIG="$HOME/.bashrc"
if [[ "$SHELL" == *"zsh"* ]]; then
SHELL_CONFIG="$HOME/.zshrc"
fi
# Add configuration if not already present
if ! grep -q "CLAUDE_CONFIG_DIR" "$SHELL_CONFIG"; then
cat >> "$SHELL_CONFIG" << 'EOF'
# Claude Code Profile Switcher
export CLAUDE_CONFIG_DIR="$HOME/.claude/current"
# Load base URL if configured
if [[ -f "$HOME/.claude/current/.base-url" ]]; then
export ANTHROPIC_BASE_URL=$(cat "$HOME/.claude/current/.base-url")
fi
# Load authentication token from current profile
# Auth token takes precedence over OAuth token
if [[ -f "$HOME/.claude/current/.auth-token" ]]; then
export ANTHROPIC_AUTH_TOKEN=$(cat "$HOME/.claude/current/.auth-token")
elif [[ -f "$HOME/.claude/current/.oauth-token" ]]; then
export CLAUDE_CODE_OAUTH_TOKEN=$(cat "$HOME/.claude/current/.oauth-token")
fi
# Profile switcher function
switch-claude() {
local profile="$1"
if [[ -z "$profile" ]]; then
echo "Usage: switch-claude <profile-name>"
echo ""
echo "Available profiles:"
ls -1 "$HOME/.claude/profiles/" 2>/dev/null || echo " (none found)"
return 1
fi
if [[ ! -d "$HOME/.claude/profiles/$profile" ]]; then
echo "Error: Profile '$profile' not found"
echo ""
echo "Available profiles:"
ls -1 "$HOME/.claude/profiles/"
return 1
fi
ln -sfn "$HOME/.claude/profiles/$profile" "$HOME/.claude/current"
export CLAUDE_CONFIG_DIR="$HOME/.claude/current"
# Load base URL if configured
if [[ -f "$HOME/.claude/current/.base-url" ]]; then
export ANTHROPIC_BASE_URL=$(cat "$HOME/.claude/current/.base-url")
else
unset ANTHROPIC_BASE_URL
fi
# Load authentication token (auth token takes precedence)
local token_loaded=false
if [[ -f "$HOME/.claude/current/.auth-token" ]]; then
export ANTHROPIC_AUTH_TOKEN=$(cat "$HOME/.claude/current/.auth-token")
unset CLAUDE_CODE_OAUTH_TOKEN
token_loaded=true
elif [[ -f "$HOME/.claude/current/.oauth-token" ]]; then
export CLAUDE_CODE_OAUTH_TOKEN=$(cat "$HOME/.claude/current/.oauth-token")
unset ANTHROPIC_AUTH_TOKEN
token_loaded=true
else
unset CLAUDE_CODE_OAUTH_TOKEN
unset ANTHROPIC_AUTH_TOKEN
fi
echo "✓ Switched to Claude profile: $profile"
[[ -n "$ANTHROPIC_BASE_URL" ]] && echo " Base URL: $ANTHROPIC_BASE_URL"
[[ "$token_loaded" == true ]] && echo " Token: loaded" || echo " Warning: No token found"
}
EOF
echo "✓ Added configuration to $SHELL_CONFIG"
else
echo "✓ Configuration already present in $SHELL_CONFIG"
fi
echo ""
echo "Setup complete!"
echo ""
echo "Next steps:"
echo "1. Run 'claude setup-token' for each account and save tokens:"
echo " # For OAuth tokens (standard accounts):"
echo " echo 'sk-ant-oat01-YOUR_TOKEN' > ~/.claude/profiles/work/.oauth-token"
echo " echo 'sk-ant-oat01-YOUR_TOKEN' > ~/.claude/profiles/personal/.oauth-token"
echo " # For API tokens (custom endpoints):"
echo " echo 'sk-ant-api03-YOUR_TOKEN' > ~/.claude/profiles/project-a/.auth-token"
echo ""
echo "2. (Optional) Configure custom base URLs:"
echo " echo 'https://api.custom.com' > ~/.claude/profiles/project-a/.base-url"
echo ""
echo "3. Secure token files:"
echo " chmod 600 ~/.claude/profiles/*/.oauth-token ~/.claude/profiles/*/.auth-token 2>/dev/null || true"
echo ""
echo "4. Reload your shell:"
echo " source $SHELL_CONFIG"
echo ""
echo "5. Switch profiles:"
echo " switch-claude work"
echo " switch-claude personal"
Save as setup-claude-profiles.sh
, make executable, and run:
chmod +x setup-claude-profiles.sh
./setup-claude-profiles.sh