feat(e11): interactive fuzzy switch (TTY selector, preview, script-stable fallback) - #58
Merged
Conversation
added 5 commits
July 7, 2026 17:55
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Story map
28f183f feat(e11-s1): gate bare switch on interactive TTYclaudecm switchonly when stdin and stdout are TTYs.a0b44e2 feat(e11-s2): add fuzzy profile selector coreinternal/tuiselector core, strict profile loading, active marker, fuzzy filtering over name/notes/provider/base URL/model, and already-active no-op handling.4e6d0d0 feat(e11-s3): show redacted selector preview--revealis the only reveal path.9588f08 feat(e11-s4): document selector handoff boundaryinternal/tuidoes not importinternal/writepathorinternal/commit.Dependency decision
No new dependency was added. The selector uses the existing
golang.org/x/termdependency for TTY detection, terminal size, and raw mode, plus a small local fuzzy matcher/render loop ininternal/tui. This keeps the dependency surface smaller than bringing in Bubble Tea while still satisfying the story requirements: type-to-filter, arrow navigation, active marker, preview, clean terminal capability fallback, and testable filtering/detection logic.Hard requirement compliance
claudecm switchopens the selector only in an interactive TTY where both stdin and stdout are TTYs. The selector supports type-to-filter, Up/Down navigation, active-profile marker, and redacted preview.runSwitch, so the existing named switch pipeline performs diff, confirmation, dry-run, commit, state update, backup reporting, and error handling.claudecm switch <name>,--yes,--dry-run, and existing flags keep the named path. Bare switch in non-TTY keeps the existing usage error and exit code; sanity run:echo | ./claudecm switchexits 1 withaccepts 1 arg(s), received 0.TERM=dumband terminal size before raw mode. On failure it prints a clear selector-unavailable message and falls back to command usage instead of corrupting the terminal.golang.org/x/termonly, with local selector code.internal/tui. Fuzzy matching, active-marker item building, preview rendering, terminal capability detection, key parsing, and writepath/commit boundary are unit-tested. The raw terminal loop itself remains thin and is not fully unit-tested.docs/quickstart.mdmention interactive switch with the boundary wording: terminal-only optional UX; scripts/non-TTY/named--yesbehavior unaffected.Verification
go build ./...go vet ./...go test -race ./internal/tui -count=1 -timeout=120sgo test -race ./cmd -run 'TestSwitch(ArgsBareNonTTY|BareTTY|NamedBypasses)' -count=1 -timeout=300sgo test ./... -p 1 -timeout=900sgo build -o ./claudecm . && echo | ./claudecm switchconfirmed non-TTY fallback: exit 1, usage error, no selector.