Ask each agent whether it is logged in, without spending a request - #9
Merged
Merged
Conversation
A missing login was only discoverable by running a turn and catching Error::NotAuthenticated, which spends quota and is a poor way to populate a settings screen. AuthStatus::check(agent) asks the CLI directly. What each offers differs, and the interface reports that difference rather than hiding it: - Claude has `auth status`, which answers JSON, so login state, method, account and plan are all read directly. - Codex has `login status`, which answers prose. The negative is matched first, since "not logged in" contains "logged in". - Copilot has neither. That case is AuthState::Unknown, never LoggedOut: telling someone to re-authenticate a working setup is worse than admitting the question cannot be answered. `needs_login()` is true only for a confirmed logout, so gating on it never nags about an agent that cannot be asked. Also fixes a real gap found while reading Copilot's login help: COPILOT_GITHUB_TOKEN is the highest-precedence credential variable it accepts and it was missing from essential_env, so a host authenticating that way would have failed to authenticate at all once EnvPolicy::Minimal became the default. Parsing is split from spawning so each agent's real output is unit-tested without needing the CLI installed, and a live test checks the installed ones by default, since asking costs no quota. That test fails if a CLI changes its wording, rather than the crate quietly reporting a working login as unknown.
This was referenced Jul 28, 2026
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.
Answers "is each of the three agents logged in?", which previously had no clean answer: a missing login was only discoverable by running a turn and catching
Error::NotAuthenticated, which costs quota and is a poor way to populate a settings screen.Real output from the live test:
What each CLI actually offers
claude auth status --jsonloggedIn,authMethod,email,subscriptionTypecodex login statusTwo details worth flagging:
not logged incontainslogged in. Tested against all three phrasings.Unknown, neverLoggedOut. Telling someone to re-authenticate a working setup is worse than admitting the question cannot be answered, soneeds_login()is true only for a confirmed logout. A host gating on it never nags about an agent that simply cannot be asked. Where a credential env var is set, that is reported as context without claiming the token is valid, since we have not checked it.A real bug found on the way
Reading Copilot's
login --helpto write this turned up thatCOPILOT_GITHUB_TOKENis its highest-precedence credential variable and was missing fromessential_env. A host authenticating that way would have failed to authenticate at all onceEnvPolicy::Minimalbecame the default in this release. Fixed here, ahead of publishing.Testing
Parsing is split from spawning, so each agent's real output is unit-tested without needing its CLI installed. The live check runs by default alongside the version probe, since asking costs no quota, and fails loudly if a CLI changes its wording rather than letting the crate quietly report a working login as unknown.
107 unit tests, clippy clean,
cargo packageverifies.Worth noting for release sequencing: #8 was merged while this was in flight, so 0.2.0 is already on master. This adds to it, and
AuthStatusplus theCOPILOT_GITHUB_TOKENfix are both worth having in 0.2.0 rather than in a follow-up, since the token gap is a regression introduced by that release's own default change.