5.1 KiB
5.1 KiB
Gas Town Account Management Design
Problem Statement
Claude Code users with multiple accounts (e.g., personal, work, team) need to:
- Switch between accounts easily when quotas are exhausted
- Set a global default account for all agents
- Override per-spawn or per-role as needed
Current State
- Claude Code stores config in
~/.claude/and~/.claude.json - Auth tokens stored in system keychain
CLAUDE_CONFIG_DIRenv var controls config location/logincommand switches accounts but overwrites in-place- No built-in profile/multi-account support
Proposed Solution
Core Mechanism
Each registered account gets its own config directory:
~/.claude-accounts/
├── yegge/ # steve.yegge@gmail.com
│ ├── .claude/ # Full Claude Code config
│ └── .claude.json # Root config file
├── ghosttrack/ # steve@ghosttrack.com
│ ├── .claude/
│ └── .claude.json
└── default -> ghosttrack/ # Symlink to current default
Town Configuration
File: ~/gt/mayor/accounts.json
This follows the existing pattern where town-level config lives in mayor/.
{
"version": 1,
"accounts": {
"yegge": {
"email": "steve.yegge@gmail.com",
"description": "Personal/Gmail account",
"config_dir": "~/.claude-accounts/yegge"
},
"ghosttrack": {
"email": "steve@ghosttrack.com",
"description": "Ghost Track business account",
"config_dir": "~/.claude-accounts/ghosttrack"
}
},
"default": "ghosttrack"
}
Environment Variable: GT_ACCOUNT
Highest priority override. Set this to use a specific account:
export GT_ACCOUNT=yegge
gt spawn gastown # Uses yegge account
Command Interface
Account Management
# List registered accounts
gt account list
# Output:
# yegge steve.yegge@gmail.com (personal)
# * ghosttrack steve@ghosttrack.com (default)
# Add new account (creates config dir, prompts login)
gt account add <handle> [email]
gt account add work steve@company.com
# Set default
gt account default <handle>
gt account default ghosttrack
# Remove account (keeps config dir by default)
gt account remove <handle>
gt account remove yegge --delete-config
# Check current/status
gt account status
# Output:
# Current: ghosttrack (steve@ghosttrack.com)
# GT_ACCOUNT env: not set
Spawn/Attach with Account Override
# Override for a specific spawn
gt spawn --account=yegge gastown
# Override for crew attach
gt crew at --account=ghosttrack max
# With env var (highest precedence)
GT_ACCOUNT=yegge gt spawn gastown
Implementation Details
Account Resolution Order
GT_ACCOUNTenvironment variable (highest)--accountflag on commanddefaultin accounts.yaml (lowest)
How Spawning Works
When gt spawn or gt crew at runs Claude Code:
func resolveAccountConfigDir() string {
// Check env var first
if handle := os.Getenv("GT_ACCOUNT"); handle != "" {
return getAccountConfigDir(handle)
}
// Check flag
if handle := flags.Account; handle != "" {
return getAccountConfigDir(handle)
}
// Use default from config
return getAccountConfigDir(config.Default)
}
func spawnClaudeCode(workdir string, account string) {
configDir := resolveAccountConfigDir()
cmd := exec.Command("claude", args...)
cmd.Env = append(os.Environ(),
fmt.Sprintf("CLAUDE_CONFIG_DIR=%s", configDir),
)
// ...
}
Account Login Flow
gt account add ghosttrack steve@ghosttrack.com
- Creates
~/.claude-accounts/ghosttrack/ - Sets
CLAUDE_CONFIG_DIRand runsclaude - User completes
/loginwith their account - Adds entry to
accounts.yaml
Security Considerations
- No secrets in accounts.yaml - Only handles and email addresses
- Auth tokens in keychain - Claude Code handles this per-config-dir
- Config dir permissions - Should be user-readable only
Future Extensions
-
Usage tracking -
gt account status --usageto show quota info -
Auto-switching - When one account hits limits, prompt to switch
-
Per-role defaults - Different accounts for different roles:
role_defaults: witness: yegge # Long-running patrol uses less quota refinery: ghosttrack -
API key accounts - For when we support direct API access:
accounts: api-team: type: api_key key_ref: GT_API_KEY # Env var containing key
Migration Path
Immediate (Manual)
Users can start using separate config dirs today:
# Set up account directories
mkdir -p ~/.claude-accounts/ghosttrack
export CLAUDE_CONFIG_DIR=~/.claude-accounts/ghosttrack
claude # Login as ghosttrack
Phase 1: Basic Support
- Add
accounts.jsonparsing - Add
gt accountsubcommands - Wire up
GT_ACCOUNTenv var in spawn
Phase 2: Full Integration
- Add
--accountflags to all relevant commands - Add status/usage tracking
- Add per-role defaults
Testing Plan
- Create test accounts config
- Verify spawn uses correct config dir
- Test override precedence
- Test
gt account addlogin flow