fix(e13-s7): --auto is nameless multi-profile discovery with lenient reads + interactive naming - #65
Merged
Merged
Conversation
S6 wrongly forced --auto into add <name> (one profile, refuse on multiple credentials). A sweep finds several distinct credentials; each is a distinct profile. S7: --auto takes no name, registers one auto-named profile per new credential, and reads sources leniently so a config.toml with [projects] sections no longer suppresses the codex auth.json key. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Why
E13-S6 shipped
--autoin the wrong shape: it required a positional name and refused when it found more than one credential. But a sweep finds several distinct credentials — Claude Code's, Codex's, an env key — and each is a distinct profile. Worse, the Codex key was never found:--autoreused the strict write-pathImport, which treats aconfig.tomlwith[projects."…"]sections as a hard parse failure and never readsauth.json'sOPENAI_API_KEY.What
claudecm add --auto/-ais now a nameless, multi-profile discovery:~/.claude/~/.codexwith lenient read-only discovery (not strictImport). A malformed/unknown-sectionconfig.tomlno longer suppresses theauth.jsoncredential;config.toml's providerbase_urlis line-scanned best-effort.(base_url, api_key)across sources (env +~/.claudesharing a key → one profile); dedups against existing profiles, with an api_key fallback when a base_url is empty so a keyed-but-URL-less codex credential still matches an existing profile.Save profile for <source, redacted key> as [<derived>]:per credential — Enter accepts the rule-derived default (claude-code/codex/host-slug), or type a custom name (validated).--yes/non-interactive uses the derived names. Then one final confirm.--output json).--auto; refuses when nothing is found; exit 0 + informational when everything is already recorded.Security / correctness (from adversarial review, all fixed in 6f610f6)
auth.json/settings.jsonsymlinked outside$HOMEis refused (NFR-S2 regression closed).--output jsonnow includes discovery/created/skipped; the two-profile test asserts thecreated profiles:section itself.Live evidence (real
~/.claude+~/.codex, config.toml with 14[projects]sections)-a --dry-run→ discovers env(anthropic) + codexOPENAI_API_KEY(found despite projects sections); env and~/.claudecollapse to one; proposesbray-neov-im+codex.bray-neov-im; typedmy-codex→ both written (bray-neov-im.yaml,my-codex.yaml).-a --yesthen re-run → all "already recorded", exit 0, nothing written (idempotent).auth.json→read target refused: path resolves outside HOME; outside secret not discovered.go test ./...+go vet ./...clean.Supersedes E13-S6's
--autosingle-name/refuse behavior.🤖 Generated with Claude Code