github Dicklesworthstone/coding_agent_account_manager v0.1.24

3 hours ago

Changed

  • Usage-aware selection only picks accounts with a measured quota. A Claude or Codex usage response whose percentages are missing, null or out of range, or that has no general usage window, is no longer read as unused capacity; plan, credit or model-only data cannot show an account is available. Such a read is now reported as unavailable or degraded instead of as spare capacity. Best-profile selection and threshold lists now leave out, for every provider, accounts whose quota read failed and accounts at a hard limit in any window, including model windows. When several model windows match, the most constrained one decides, so an idle family allowance can no longer hide an exhausted model cap or the reverse. Usage responses are read up to 1 MiB, and provider text is kept out of error messages.
  • Native Gemini CLI logins are treated as renewing themselves. Gemini CLI renews its own cache with its built-in OAuth client, which caam cannot use. Such a cache now reports no refresh_due, gets no caam refresh recommendation, and is not handed to the auth pool for a refresh that would only fail. A Gemini cache that carries its own client_id and client_secret keeps caam's refresh schedule.
  • Source builds need Go 1.26.10. The repository, CI and install.sh source fallback now pin Go 1.26.10, the current patched 1.26 release (#122). The new minimum matters only when the installer has to build from source; it will not build with an older Go.

Added

  • Isolated Claude logins can be saved to the vault without touching the live login (#125). caam backup claude <new-name> --from-profile <isolated>, or the equivalent caam profile backup claude <isolated> [--as <new-name>] [--json], saves a registered isolated OAuth login as a new vault entry. The active Claude login, the keychain and the isolated profile are left unchanged, and no tokens are refreshed, so agents on the live login keep running; activate the entry later with caam activate claude <new-name>. The backup reads the same config directory caam exec uses (the XDG layout, or a legacy-only home/.claude login when XDG holds no authentication) and never mixes files from both. It refuses a source whose two layouts hold different accounts, whose registered auth mode is not OAuth, or whose settings.json or .claude.json would make Claude use another credential or provider (API keys, helpers, cloud providers, endpoint or config-dir overrides), and it never replaces an existing vault entry. On Unix the snapshot is flushed to disk before success is reported; if only the final directory flush fails, the command exits with an error whose JSON says published: true and gives the snapshot's path, and the snapshot is kept rather than rolled back. Both commands share one locked capture and publication path. Details are in docs/isolated-claude-vault.md.
  • caam keepalive reports why a native CLI run failed (#129). On an unsuccessful run the JSON result now adds native_exit_code and, for Claude, native_api_error_status (the HTTP status of the rejected request, for example 401 or 429) and native_terminal_reason (Claude's own short reason, for example api_error). Keepalive runs Claude with --output-format json and reads back only those two fields, after checking their form; Claude's message text is never copied. The fields are omitted after a timeout or cancellation, and Grok's output stays discarded apart from its exit code.

Fixed

  • caam doctor checks Codex ChatGPT logins against an endpoint that accepts them (#127). It probed api.openai.com/v1/me, which answers 403 to every ChatGPT-login access token, working or not, so working logins failed with advice to log in again. Doctor now reads the ChatGPT backend usage endpoint that caam limits codex already uses, where 200 confirms the login and 401 rejects it. A 403 is reported as inconclusive instead of as a rejected login. A 401 for a vault snapshot whose access token has already expired by its own claim is a warning without login advice, because Codex rotates the active login in place and caam saves it back to the vault on the next switch.
  • caam cost tokens reads Claude Code and Codex session logs (#126). It looked for Claude usage in ~/.local/share/claude/logs and did not read Codex rollouts, so it returned nothing on hosts with fresh logs. It now reads Claude Code's per-session transcripts under <config>/projects/ ($CLAUDE_CONFIG_DIR, or both ~/.config/claude and ~/.claude), including subagent transcripts, and counts each message once. Codex usage comes from rollouts under $CODEX_HOME/sessions/ and archived_sessions/. A line longer than 1 MiB no longer ends the scan of its file.
  • Gemini CLI logins show their real expiry (#123). Health did not read expiry_date, the millisecond deadline Gemini CLI writes, so a native Gemini login always had an unknown expiry and a lapsed one stayed healthy. Health now reads it first, like the import validator. Gemini refresh updates expiry_date instead of writing a second, newer deadline next to the stale one.
  • Grok quota reads never start an interactive login (#124). The billing probe now starts Grok only with an access token whose absolute expiry is comfortably in the future, checks every entry of a multi-entry cache, and authenticates only when Grok advertises exactly one cached-token method, under its own 5-second deadline. It never falls back to an interactive method, and browser openers are stubbed out for the probe. A stale credential or an unexpected handshake used to leave Grok at a login prompt.
  • caam keepalive gives advice that works when two live homes hold one account (#128). The block told you to sign in to each home separately, which never clears it: keepalive cannot tell a home's own sign-in from a copy that rotated later. It now says to sign out of all but one of the listed homes. Homes for other accounts can still be selected while the conflict remains.
  • Quota for an isolated Claude profile comes from the login caam exec uses. caam limits tried legacy credentials before XDG. It now uses the same source selection as caam exec, keeps the token and its usage cache in one layout, and reports an invalid isolated account instead of reading another layout or a shallow profile.
  • Codex quota for an API-key profile no longer reads a leftover ChatGPT login. Quota readers check the profile's selected auth method before any stored OAuth tokens, so an unused subscription login cannot stand in for the account being measured, and such profiles stay out of the bulk quota pool.
  • The installer builds the version you asked for, or stops (#121). When --version fell back to a source build, it could build main and label the binary with the requested version. It now builds refs/tags/<version> and refuses to continue if that tag cannot be checked out. Unversioned source installs still build main.
  • caam login claude, caam auth import and caam rename say which store they use (#125). A rejected caam login claude now points to the isolated /login, /exit and caam backup claude <name> --from-profile <isolated> steps. caam auth import help says it creates an isolated profile for caam exec, not a vault entry, and caam rename says it copies vault profiles only. Renaming a profile that exists only as an isolated profile says so instead of reporting "not found", and for Claude it gives the exact backup command.
  • Switching honors the selected Codex or Gemini authentication method. Leftover OAuth tokens in an API-key profile no longer cause activation to keep the wrong live login, or allow outgoing OAuth preservation to overwrite the saved API key. Discovery and Codex restore use the same account boundary, while newer credentials for the same OAuth account remain protected.
  • Claude auth detection and import preserve native credentials. Detection reads the path-scoped native authority without creating or updating a keychain mirror. An explicit CLAUDE_CONFIG_DIR keeps its own account, and a denied or malformed keychain read cannot silently select a stale file. caam auth import claude and first-run caam init can import a keychain-only login directly into the new profile while leaving native files and the keychain unchanged.

Security

  • Token refreshes and token checks no longer follow HTTP redirects. The Codex and Gemini token exchanges, the Claude token helper and the Codex token check validated only the first URL and then followed redirects, so a 307 or 308 could replay a refresh request, refresh token included, to another URL, and a redirected 200 could pass a token check. They now use a client that never follows redirects: a 3xx is reported with its status, without a second request, a credential verdict or a retry, and the redirect target is not echoed in errors. Timeouts, TLS checks and the 429/5xx retries are unchanged.
  • Built with Go 1.26.10 and golang.org/x/net v0.60.0 (#122). Go 1.26.10 carries the October Go security fixes, including the October 19 crypto/x509 fix, and x/net v0.60.0 is the fixed line for the HTTP/2 advisories.

Don't miss a new coding_agent_account_manager release

NewReleases is sending notifications on new releases.