feat: multi-account support (Batch 1) — CLI + CodeV sessions
Run multiple Claude Code accounts (e.g. personal + work) from one machine. Built on the verified fact that CLAUDE_CONFIG_DIR fully isolates a Claude Code account on macOS (docs/multi-account-support-design.md §3).
What it does
- CLI (via
~/.config/codev/accounts.sh, sourced from your shell rc):claude <account>/claude-<account>launch the officialclaudeunder that account'sCLAUDE_CONFIG_DIR; bareclaudestays the default account;claude-whoami/claude-accountsinspect. All native flags pass through. - CodeV Sessions tab: reads every configured account's config dir (not just
~/.claude) and merges into one recency-sorted list; badges non-default accounts (WORK); resumes each session under its own account; per-account active dots, custom titles/branches, and previews; registers status hooks in each account'ssettings.json.
Is it fully functional?
- Multi-account: yes — once the registry (
~/.config/codev/accounts.json) +accounts.share set up and the extra account is logged in. Validated end-to-end (list,WORKbadge, account-aware resume, active dots, titles) viayarn make. - If you do nothing / single account: CodeV behaves exactly as before.
getAccounts()falls back to a single default account when there's no registry, so the feature is entirely opt-in and invisible to single-account users — all pre-PR functionality is preserved.
⚠️ Setup is manual for now (Batch 1)
Account setup (the ~/.config/codev/accounts.json registry + ~/.config/codev/accounts.sh) is hand-created in this batch — CodeV reads the registry but doesn't yet generate it. A point-and-click management UI + codev account CLI is planned (Batch 2). See design doc §11 "How to use it now".
CodeV never touches tokens
CodeV only ever sets CLAUDE_CONFIG_DIR and launches the official claude binary — it never reads OAuth tokens, calls the model, or embeds an agent. This keeps it inside Anthropic's "use the official product" terms (design doc §2).
Commits
ee4a546design doc + registry reader (src/accounts.ts)57f609bsession aggregation + badge + account-aware resume5f05d9aactive dots + enrichment per account46c49d1status hooks per account5cb3c1asame-cwd cross-ref per account9b45dc7docs + changelog + version bump (1.0.76)
Caller audit (per shared-change guidance)
src/accounts.ts is a new util (no existing callers). The session-reading changes tag each session with its account; the enrichment/preview/hook callers (main.ts IPC handlers, switcher-ui.tsx) pass full session objects, so accountDir flows through (verified). Graceful fallback to ~/.claude when a session has no account tag (e.g. VS Code).
Deferred
- VS Code (
claude-vscode) sessions can't be account-switched (URI-handler launch) — #121 - Batch 2: management UI +
codev accountCLI, per-launch account picker, configurable global-default (nvm alias default-style), pyenv-style folder auto-switch - Batch 3: cross-account symlink reuse of global
CLAUDE.md/ skills
Testing
tsc --noEmitclean throughout; each commit is a minimal, focused diff.- User-validated (personal + work): session list,
WORKbadge, account-aware resume, active dots, titles — all correct afteryarn make.
🤖 On behalf of @grimmerk — generated with Claude Code
Summary by cubic
Add multi-account support so you can run multiple Claude Code accounts on one machine. CodeV now merges sessions across accounts and resumes each under the correct account using the registry’s configDirEnv; setup is manual (accounts.json + accounts.sh), and single-account users see no change.
-
New Features
- Sessions tab reads all configured account dirs and shows one recency-sorted list with a badge for non-default accounts; resume/new launches inject
CLAUDE_CONFIG_DIRfor the right account (VS Code unchanged). - Per-account active dots, custom titles/branches, and previews; status hooks are installed in each account’s
settings.jsonand write to a shared status dir. - Registry reader for
~/.config/codev/accounts.jsonwith default fallback; optional CLI helpers via a sourced~/.config/codev/accounts.sh(claude <account>,claude-<account>,claude-whoami,claude-accounts). Docs include a copy-paste example.
- Sessions tab reads all configured account dirs and shows one recency-sorted list with a badge for non-default accounts; resume/new launches inject
-
Bug Fixes
- Ghostty resume: single-quoted
CLAUDE_CONFIG_DIRprefix to avoid breaking its AppleScript string. - Initial status: reads each session’s own account dir, fixing stuck purple dots for non-default accounts.
- Robustness/correctness: resume uses the registry’s
configDirEnv(not the scan dir); per-account history reads are isolated; hook install detection checks all accounts; clipboard copy usespbcopyviaexecFileSync; accounts inferisDefaultfromdefaultAccount. - Formatting: wrapped long lines flagged in review (no behavior changes).
- Ghostty resume: single-quoted
Summary by CodeRabbit
- New Features
- Added multi-account support with unified session discovery across accounts and account-specific badges in the Sessions list.
- Updated resume commands to reopen sessions in the correct account context (non-default accounts only); note: VS Code sessions can’t switch accounts.
- Extended status hook installation so it’s managed per configured account.
- Documentation
- Added multi-account support design documentation and updated the changelog for version 1.0.76.
- Chores
- Bumped the application version to 1.0.76.
Follow-up (post-open fixes)
Found while testing non-default (work) account sessions:
- Ghostty resume fix (
7b9705e): the injectedCLAUDE_CONFIG_DIRprefix was double-quoted, which broke Ghostty's unescapedinitial input:"..."AppleScript string — non-default accounts couldn't resume in Ghostty (iTerm2/Terminal/cmux were fine). Now single-quoted (safe across all terminals). - Purple-dot fix (
7b9705e): work sessions stayed on the "active-unknown" purple dot after resume becausescanInitialStatusesread~/.claude/projectsfor every session, so a work session's JSONL wasn't found. Now reads each session's own account dir (getProjectsDirmoved toaccounts.ts;accountDirthreaded throughget-session-statuses). - Docs (
ca8f0be): §11 "How to use it now" now has a copy-paste-readyaccounts.json+accounts.shexample.
Minor perf note (non-blocking): getResumeConfigDirEnv calls readClaudeSessions(Number.MAX_SAFE_INTEGER), which copies the full session array before .find() — O(n) per resume click, n≈hundreds, negligible; can later be changed to query the cache directly.