feat(multi-account): account picker, claude tab completion, naming & rename (Batch 2c-lite)

Merged
GR
4mo ago
+642-63

Summary

Batch 2c-lite (follows #125): pick the account when launching a new Claude session — ⌥⌘+Enter on a project opens a small account picker; plain ⌘+Enter stays exactly as before.

Design decision (per discussion): the picker is behind a modifier, never forced — quick-launch speed is preserved, and "which account does bare ⌘+Enter use" remains the global default (codev account default / Settings → Accounts), which shipped with 2e. Cross-account resume is deliberately NOT here — a session's transcript lives in its own account's projects/ dir, so "resume under another account" must be an explicit copy-fork (Batch 3), never a link.

Behavior

GestureResult
⌘+Enterunchanged — instant launch under the global default (bare claude → dispatcher)
⇧+Enterunchanged — launch in the CodeV embedded terminal
⌥⌘+Enteraccount picker (↑↓ / Enter / Esc, click and hover work; default marker + email shown) → launches with explicit CLAUDE_CONFIG_DIR='…' command claude (dispatcher bypassed, mirroring resume)
⌥⌘+Enter, single account / no registryno picker — falls through to a normal launch

Implementation

  • launchNewClaudeSession(projectPath, terminalApp, terminalMode, accountLabel?) — with a label, builds the env-prefixed command claude (single-quote-escaped); without, bare claude as before. VS Code (#121) and the embedded codev terminal ignore the label (logged).
  • IPC launch-new-claude-session + preload + types gain the optional label.
  • Renderer: launchClaudeRef gains 'external-pick'; the picker overlay reuses the data-settings-panel escape hatch so the global focus-stealing click handler leaves it alone; Esc closes only the picker (stopPropagation).
  • Hover tooltip on the "⌘+Enter: New Claude" hint advertises ⌥⌘+Enter.

Also in this PR (grew during review/testing)

  • Fix (critical, review-caught): runCommandInTerminal now receives claudeCmd as its 2nd arg — Ghostty/cmux build their launch scripts from it, so the picked account's env prefix reaches those terminals too (iTerm2/Terminal.app were unaffected; resume already did this).
  • Live hint: the search-bar hint shows · ⌥⌘+Enter: pick account only for multi-account setups, and refreshes after account add/remove (same-window codev-accounts-changed event + window-focus re-check) — no app restart (user-reported).
  • Picker error handling: if getAccounts() fails, the picker logs and aborts instead of silently launching the global default.
  • Tab completion for claude <name>: claude <TAB> completes account labels; registered only when nothing else completes claude (_comps guard — a future official completion wins automatically); other argument positions keep zsh's default file completion (_files fallback).
  • UI polish: removed react-select's default IndicatorSeparator (the stray | before the hint; user-reported).
  • Docs: README gains a full Multi-Account section (setup, shell-command table, codev account CLI table, UI map, common-scenarios table, session-probe gotcha); design doc marks 2e as shipped and drops 2d (folder→account auto-switch) — one folder legitimately hosts sessions from multiple accounts, so a folder default would guess wrong exactly where it matters; 2e global default + this picker cover the need.

Account naming & rename (second wave, from a design session on the name/folder model)

The model: an account is a name → config-folder mapping. The name is a mutable label; the folder is fixed at creation and never moves (credentials are keyed by the folder path). The UI now states this and shows · folder: … on a row whenever they diverge.

  • codev account rename <old> <new> (CLI) + a per-row Rename button (UI, inline input with Enter/Esc). This is also the only way to rename the anchor (~/.claude) account, which can't be removed.
  • First-ever add asks what to name your existing ~/.claude login — a prefilled field (main) in the UI, --anchor-name in the CLI — replacing the old auto-assumed personal (the machine's first login may well be a company account).
  • default is a reserved name (add/rename/anchor-name all reject it): it already denotes the dispatcher's global-default concept (the default badge, codev account default), so an account named default would permanently collide.
  • One folder = one account: registering an already-registered folder under a second name is rejected (a duplicate mapping would double-scan sessions and blur attribution).
  • Remove notice now shows the kept folder and folder-suffix reattach guidance (after a rename, "add the old label back" would have targeted a wrong, empty folder).
  • Follow-ups filed: onboarding niceties (detect existing config dirs & one-click register, wrapper-collision warning) in #127; cross-account copy-fork resume in #128. Internal isDefault→isAnchor schema rename agreed as a separate small PR.

How to test (needs yarn make)

  1. Projects tab → select a project → ⌥⌘+Enter → picker shows personal/work (+default marker, emails).
  2. Pick work → terminal opens a new claude in that project → !command claude auth status shows the work identity (!claude auth status would show the global default — see #123's gotcha).
  3. Pick personal → same check, personal identity.
  4. Esc closes the picker; clicking the dimmed backdrop closes it; ⌘+Enter still launches instantly.
  5. Settings → Accounts: add/remove an account → the search-bar hint switches between the short/long form without restarting the app; the stray | before the hint is gone.
  6. Shell: after codev account regenerate + a new shell, claude w<TAB> completes work; claude -p ./<TAB> still completes files.
  7. If you use Ghostty or cmux as the session terminal: pick an account via ⌥⌘+Enter and verify with !command claude auth status (this path carried the critical fix).
  8. Rename: per-row Rename → change a name and back (folder shown unchanged via · folder: … while diverged); renaming anything to default is rejected (reserved).
  9. First-add flow (fresh-registry simulation): cp ~/.config/codev/accounts.json /tmp/bak && rm ~/.config/codev/accounts.json → Accounts tab shows the anchor-naming field (prefilled main) → add a test account → both rows appear (anchor named as chosen). Restore: cp /tmp/bak ~/.config/codev/accounts.json && codev account regenerate.

tsc --noEmit 0 errors; yarn test 18/18.

🤖 Generated with Claude Code


Summary by cubic

Adds an account picker for new Claude sessions, zsh completion for claude <TAB>, and account naming/rename. Improves multi-account safety, external-terminal launches, and docs.

  • New Features

    • ⌥⌘+Enter opens an account picker for new sessions; single-account skips. External terminals launch via explicit CLAUDE_CONFIG_DIR + command claude; a default pick uses env -u CLAUDE_CONFIG_DIR claude. The search-bar hint shows the picker shortcut only when multiple accounts exist and updates live.
    • zsh: claude <TAB> completes account labels; registers only if no existing claude completion; other positions fall back to _files.
    • Naming & rename: codev account rename <old> <new> and a per-row Rename in the UI. On first add, you choose a name for the existing ~/.claude account (empty uses a safe default: main, or primary when the new account is named main); default is reserved. The UI shows the config folder when name ≠ folder suffix; add explains create‑or‑attach (~/.claude-<name>) and rejects duplicate folder mappings.
  • Bug Fixes

    • External terminals (Ghostty/cmux): pass the computed claudeCmd so the picked account’s env is preserved; explicit default picks clear CLAUDE_CONFIG_DIR; the picker aborts on account‑load failure or a stale/removed label.
    • UI/Docs: hide the stray IndicatorSeparator; remove is non‑destructive and now shows the kept folder with re‑attach guidance; README and design docs updated (2d dropped; 2c‑lite clarifies the main→primary fallback).

Summary by CodeRabbit

  • New Features

    • Added multi-account “account-first” session picker for ⌥⌘+Enter (keyboard/mouse) with session launch using the selected account; ⌘+Enter keeps default behavior.
    • Added codev account rename <old> <new> plus improved account management (anchor options, richer account hints, per-row rename).
    • Added claude <TAB> label completion and updated shell completion behavior.
  • Bug Fixes

    • Improved live hint/account updates without restart and refined picker hint text.
  • Documentation

    • Updated README with Multi-Account Support details and revised Batch 2 phasing guidance.