feat(multi-account): codev command via bundled CLI (Batch 2b part 2)
Summary
Batch 2b part 2 (follows #124): the codev command — run codev account <cmd> from any zsh shell, no repo checkout / no system Node / no sudo required.
Also carries the §6.C supported-shells docs note (written during #124, moved here per review-batching).
How it works
-
Bundled CLI: forge's
generateAssetshook tsc-compilessrc/cli/*.ts(plain fs/os/path — no bundling needed) intoresources/cli/, shipped inside the app viaextraResource→CodeV.app/Contents/Resources/cli/. -
codev()launcher in accounts.sh: the generator emitscodev() { ELECTRON_RUN_AS_NODE=1 "<app>/Contents/MacOS/CodeV" "<app>/Contents/Resources/cli/codev-account.js" "$@" }ELECTRON_RUN_AS_NODEmakes the app binary act as plain Node (the VS Codecodetrick) — so the CLI runs on the app's own runtime. It rides the existing shell-integration install: zero sudo, zero PATH edits. -
No hardcoded
/Applications(review point from planning): the app records its real.appbundle root in the registry (appPath) on every launch and regeneratesaccounts.sh. Moving the app self-heals on next CodeV launch; generator-template updates (like the earlierclaude-whoamifix) now propagate automatically too. No-op for single-account users (no registry → no writes). -
The CLI accepts the
accountprefix, socodev account list(installed form) andyarn account list(dev form) both work.
Verification
- Simulated the exact packaged invocation locally:
ELECTRON_RUN_AS_NODE=1 node_modules/electron/dist/.../Electron resources/cli/codev-account.js account listagainst the real registry → correct output. tsc --noEmit0 errors;yarn test15/15 (+2:codev()emitted whenappPathrecorded, omitted otherwise).
How to test (needs yarn make)
yarn make→ launch the built app once (it recordsappPathinto~/.config/codev/accounts.jsonand refreshesaccounts.sh— check the file gains thecodev()function).- Open a new shell (or
source ~/.zshrc) → runcodev account list→ same output asyarn account list. codev account show,codev account helpetc. all work anywhere (no repo cwd needed).- Optional: move CodeV.app somewhere else → relaunch it → new shell →
codev account liststill works (self-heal).
Tab completion
accounts.sh also ships zsh completion for codev: codev <TAB> → account, codev account <TAB> → subcommands, codev account default|remove <TAB> → account labels (baked in, refreshed on regenerate; remove offers only non-anchor labels). Registration is guarded (zsh + loaded compinit) so the file stays bash-sourceable — verified with both zsh -n and bash -n.
MAS builds (why the launcher is skipped there)
- Mac App Store builds are sandboxed and
ELECTRON_RUN_AS_NODEis unsupported in MAS Electron — the bundled CLI could never run from a MAS install (exec'ing the app binary from a terminal still enforces its embedded sandbox). - CodeV therefore skips recording
appPathon MAS (!isMAS()gate), so accounts.sh never advertises a brokencodev(). - Context: the wider
~/.claude-reading feature set (Sessions tab etc.) has the same sandbox constraint — pre-existing, not introduced here; and no MAS build with the Claude-sessions feature set has shipped. Build-wise,yarn makeandyarn make_masboth compile/bundle the CLI fine — the gate is runtime-only.
Notes
- The
codevfunction only exists in shells that sourceaccounts.sh(consistent with the zsh-only support documented in this PR); a "real file on PATH" shim (/usr/local/bin, admin prompt) can be a later upgrade if scripts need it. resources/cliis a build artifact (gitignored).
🤖 Generated with Claude Code
Summary by cubic
Adds a bundled codev command so you can run codev account <cmd> from any zsh shell without Node, sudo, or PATH edits. The app records its real install path, regenerates accounts.sh on launch and account changes, adds zsh tab completion, survives .app renames via appExec, and fully suppresses the launcher on MAS builds.
- Bug Fixes
- MAS: clear stale
appPath/appExecand regenerateaccounts.shunconditionally socodev()is never advertised on MAS. - Accounts tab: show the empty-state only after a successful load; no flashing or mixed error states.
- Completion: add the
rmalias to subcommand suggestions.
- MAS: clear stale
Summary by CodeRabbit
-
New Features
- Added support for launching the app’s account CLI directly from the app without requiring a separate Node installation.
- Improved the Accounts view with clearer guidance, a new header explaining per-account config storage, and a message when no accounts are set up.
-
Bug Fixes
- Account setup and management now keep shell integration in sync after adding, removing, or changing the default account.
- Launcher paths now stay accurate even if the app is moved or renamed.