GitHub CLI Expiring Tokens: What Happens to Scripts That Copy Them?

GitHub CLI 2.103.0 now refreshes its own OAuth sign-in. What about the token your deploy script copied into an environment variable last month?

GitHub CLI Expiring Tokens: What Happens to Scripts That Copy Them?
TLDR
  • GitHub CLI 2.103.0 introduces optional, refreshable OAuth credentials in public preview.
  • For HTTPS Git, configure gh as the credential helper; Git 2.46 or later is recommended.
  • A script that saves a token once can eventually be left using an expired value.

A token can expire without ending your CLI session. GitHub's October 21 release lets gh exchange a refresh token for a fresh access token when needed. The gap appears when another program keeps a copy: that saved string does not change when the CLI renews its credentials.

Upgrading does not migrate existing sign-ins

The feature is optional. Existing authentication continues to work unless you choose the new flow. GitHub plans to make refreshable credentials the default for new sign-ins later; as of October 25, the feature remains an opt-in preview. See the release announcement.

A shorter access-token lifetime limits how long a leaked access token remains usable. A rotating refresh token keeps the legitimate CLI authenticated. Whether another tool benefits depends on how it obtains credentials.

A cached token cannot refresh itself

The 2.103.0 release notes distinguish credentials managed by gh from values handed to another process. When a script needs the active token, obtaining it again through gh auth token allows gh to refresh it first if necessary.

Credential consumerRefresh behavior
gh using its stored credentialRefreshes when needed.
HTTPS Git using the gh helperThe helper supplies a valid credential.
A tool retaining a copied tokenIts copy eventually expires; it must obtain a current value.
GH_TOKEN or GITHUB_TOKENSupplied values are not automatically refreshed by gh.

This means a workstation login change does not add refresh support to a CI job using an environment variable. Review where each consumer reads its token and how long it retains it.

Also distinguish automatic renewal from gh auth refresh. The latter adjusts stored authentication scopes; it is not a command to schedule for routine access-token renewal. Its --expiring option explicitly requests refreshable credentials when changing authentication. The command reference describes the supported options.

Enable it for gh and HTTPS Git

With GitHub CLI 2.103.0 or newer, request the new credentials and inspect what the host issued:

gh auth login --expiring
gh auth status

To prefer this flow for future sign-ins, use gh config set expiring_credentials enabled. Check the active credential separately; a preference for future logins is not evidence that every stored account has migrated.

For HTTPS Git, run gh auth setup-git. This makes gh the helper that supplies and refreshes Git's credentials. Git 2.46 or newer supports the expiration handling that prevents cached credentials from outliving their validity. Older Git versions still work, with an upgrade recommendation. These requirements are documented in the authentication guide.

The host must support the requested credentials

GitHub.com and ghe.com support the preview. GitHub Enterprise Server supports it starting with 3.23. Older servers fall back to a nonexpiring token, so the login flag alone does not establish that the credential has an expiry.

For an interactive workstation, start with the login and HTTPS helper. For long-running automation, first review copied-token consumers. The practical dividing line is whether the consumer can obtain the replacement credential.

Frequently asked questions

Will I have to sign in whenever the token expires?

No. For supported refreshable credentials, gh renews the access token using its refresh token.

Is Git 2.46 a hard minimum?

No. GitHub recommends it for correct expiration-aware caching; older versions still work.

Does gh refresh a token supplied in an environment variable?

No. GH_TOKEN and GITHUB_TOKEN values do not receive automatic refresh.