Skip to content

fix(e13-s7): --auto is nameless multi-profile discovery with lenient reads + interactive naming - #65

Merged
imneov merged 3 commits into
mainfrom
feat/e13-s7-auto-multi
Jul 8, 2026
Merged

fix(e13-s7): --auto is nameless multi-profile discovery with lenient reads + interactive naming#65
imneov merged 3 commits into
mainfrom
feat/e13-s7-auto-multi

Conversation

@imneov

@imneov imneov commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Why

E13-S6 shipped --auto in 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: --auto reused the strict write-path Import, which treats a config.toml with [projects."…"] sections as a hard parse failure and never reads auth.json's OPENAI_API_KEY.

What

claudecm add --auto / -a is now a nameless, multi-profile discovery:

  • Sweeps clipboard / env / ~/.claude / ~/.codex with lenient read-only discovery (not strict Import). A malformed/unknown-section config.toml no longer suppresses the auth.json credential; config.toml's provider base_url is line-scanned best-effort.
  • Collapses candidates sharing (base_url, api_key) across sources (env + ~/.claude sharing 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.
  • Interactive naming: in a TTY, prompts 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.
  • Registers one profile per new credential; reports created / already-recorded / source-skip reasons (text and structured --output json).
  • No positional name allowed with --auto; refuses when nothing is found; exit 0 + informational when everything is already recorded.

Security / correctness (from adversarial review, all fixed in 6f610f6)

  • High — lenient readers now enforce the same read-containment as the adapters: an auth.json/settings.json symlinked outside $HOME is refused (NFR-S2 regression closed).
  • High — partial batch-save failure now reports which profiles were created before the failure.
  • High — empty-base_url codex credential dedups by api_key; never writes a keyless profile.
  • Medium/Low--output json now includes discovery/created/skipped; the two-profile test asserts the created profiles: section itself.

Live evidence (real ~/.claude + ~/.codex, config.toml with 14 [projects] sections)

  • -a --dry-run → discovers env(anthropic) + codex OPENAI_API_KEY (found despite projects sections); env and ~/.claude collapse to one; proposes bray-neov-im + codex.
  • Interactive: Enter accepts bray-neov-im; typed my-codex → both written (bray-neov-im.yaml, my-codex.yaml).
  • -a --yes then re-run → all "already recorded", exit 0, nothing written (idempotent).
  • Symlinked-outside-HOME auth.jsonread target refused: path resolves outside HOME; outside secret not discovered.
  • go test ./... + go vet ./... clean.

Supersedes E13-S6's --auto single-name/refuse behavior.

🤖 Generated with Claude Code

imneov and others added 3 commits July 8, 2026 07:13
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>
@imneov
imneov merged commit 5cc4260 into main Jul 8, 2026
8 of 9 checks passed
@imneov
imneov deleted the feat/e13-s7-auto-multi branch July 8, 2026 08:12
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