Skip to content

feat: interactive picker when cloak switch is run with no name#11

Open
thekvn wants to merge 1 commit into
synth1s:masterfrom
thekvn:feat/interactive-switch-picker
Open

feat: interactive picker when cloak switch is run with no name#11
thekvn wants to merge 1 commit into
synth1s:masterfrom
thekvn:feat/interactive-switch-picker

Conversation

@thekvn
Copy link
Copy Markdown

@thekvn thekvn commented May 31, 2026

What

cloak switch (and its use alias) used to error when called without an argument. Now it shows an interactive list of your cloaks and lets you pick one — the current cloak is marked (current).

$ cloak switch
? Which cloak do you want to wear? (Use arrow keys)
❯ home
  work (current)

Why it's safe under shell integration

The shell wrapper runs command cloak switch --print-env, capturing stdout for eval. So the picker UI is rendered to stderr (via inquirer's output option); stdout still receives only the export CLAUDE_CONFIG_DIR=... line. Verified manually that stdout stays clean while the menu shows on the terminal.

Edge cases handled:

  • Abort (Ctrl-C / EOF): exits cleanly with empty stdout and no stack trace, so the shell eval "" is a harmless no-op.
  • No cloaks saved: exits 1 with a friendly "create one" hint.
  • Picking the cloak you're already wearing: same as before — message to stderr, nothing to eval.

Changes

  • src/commands/switch.js — picker path (injectable via options.pickChoice, matching the existing setupChoice test seam)
  • src/cli.jsswitch <name>switch [name]
  • src/lib/messages.jsswitchPick prompt
  • Docs: README.md, CLAUDE.md

Tests

Added to tests/switch.test.js (all existing cases still pass):

  • S-11 — no name + selection switches to the chosen cloak (emits its export)
  • S-12 — no name with no cloaks exits 1 and writes nothing to stdout
  • S-13 — picking the active cloak produces no stdout

Full suite green.

🤖 Generated with Claude Code

`cloak switch` (and `use`) previously errored without an argument. Now it
lists available cloaks and lets you pick one, marking the current one.

The picker renders to stderr (via inquirer's `output` option) so stdout stays
clean for the `--print-env` eval used by the shell integration — selecting a
cloak still produces only the `export CLAUDE_CONFIG_DIR=...` line on stdout.
Aborting the picker (Ctrl-C / EOF) exits cleanly with empty stdout and no
stack trace, so the shell `eval` is a harmless no-op. With no cloaks saved it
exits 1 with a friendly hint.

- src/commands/switch.js: picker path (injectable via options.pickChoice for tests)
- src/cli.js: `switch <name>` -> `switch [name]`
- src/lib/messages.js: switchPick prompt
- tests: S-11 (pick switches), S-12 (no cloaks exits 1, empty stdout), S-13 (picking active = no stdout)
- docs: README + CLAUDE.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant