You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Support GitHub CLI as a GitHub Authentication Mode #4953
As a developer who authenticates with the GitHub CLI, I want Specify to obtain its GitHub credential from gh automatically so that I do not have to store a token at rest, either in auth.json or in an environment variable.
Background
Specify reads authentication configuration from the user-level ~/.specify/auth.json. It does not read a project-local .specify/auth.json. A provider entry can supply a credential in two ways today:
token: a static value stored in the file.
token_env: the name of an environment variable, resolved from the process environment at request time.
token_env avoids a token in the file. For example, GH_TOKEN="$(gh auth token)" specify <command> works today. It still requires the user to export a token into the process environment on every invocation, and users who want no token at rest, including in a shell profile or environment variable, have no automatic option.
Developers who use the GitHub CLI already have a credential managed by gh (OS keychain or gh auth login session). Specify has an azure-cli auth mode that resolves credentials from the Azure CLI on demand. A matching github-cli mode would give GitHub the same behavior and align with the GitHub affinity described in the authentication reference.
This replaces the original proposal of general $(command) substitution in token. A dedicated mode runs a fixed command, so configuration cannot cause arbitrary command execution.
Acceptance Criteria
A provider entry with "auth": "github-cli" is accepted by the auth.json schema and loaded from the user-level ~/.specify/auth.json
When a credential is needed, Specify runs gh auth token and sends the trimmed stdout as the bearer token
The command is not run through a shell and is not configurable from auth.json
The resolved token is cached in memory for the current run, so gh runs at most once per host per run
The resolved token is not written to disk, logged, or included in error messages
If gh is not installed, the request fails with a clear error that names the provider and states that the GitHub CLI was not found
If gh is installed but not authenticated, the request fails with a clear error that suggests gh auth login
If gh exits non-zero, returns empty output, or exceeds a timeout, the request fails with a clear error that does not include command output
For GitHub Enterprise hosts, Specify requests the token for the matching host (for example gh auth token --hostname <host>) and has documented behavior when a host is not configured in gh
Existing auth modes (bearer, azure-cli, token, token_env) behave unchanged, and existing tests pass without modification
The authentication documentation includes github-cli with the full auth.json example above and the gh auth login prerequisite
New tests cover: token resolved from gh, per-run caching, gh missing, gh unauthenticated, non-zero exit, empty output, timeout, and token absent from logs and errors
Technical Notes
Follow the existing azure-cli implementation for mode registration, schema validation, and error handling
Spawn gh with an argv list and no shell, with a timeout (for example, 10 seconds) and the inherited environment
Memoize per host per run. This keeps the cost at O(h) subprocess spawns for h distinct hosts, not O(r) for r requests
Redact the token in all log output and exceptions
Specify reads only the user-level ~/.specify/auth.json, so no project-level trust handling is needed for this mode
Out of Scope
General-purpose $(command) substitution in token or any other field
Reading authentication configuration from a project-local .specify/auth.json
Credential helpers for tools other than the GitHub CLI
Persisting the resolved token across runs
Drafted with Claude Code using Claude Sonnet 5.5 in human-supervised interactive mode; issue drafting and revision based on contributor feedback. The author reviewed the content before publishing.
Thanks for raising this. We agree with the goal of using credentials managed by GitHub CLI without storing another copy of the token, but a couple of assertions about the current behavior need clarification.
Specify does not read authentication configuration from a project-local .specify/auth.json. It reads only the user-level ~/.specify/auth.json. The file also does not need to contain a token: the existing token_env field resolves it from the process environment at request time.
We verified this end to end: Specify loaded the user-level configuration, resolved the token from GH_TOKEN, and sent the expected bearer header. We also verified that placing the same configuration in a project-local .specify/auth.json has no effect.
We suspect the intended request is therefore not general command substitution, but making GitHub CLI credential resolution automatic on every Specify invocation. That is a reasonable convenience feature, but we would prefer a dedicated authentication mode over allowing arbitrary $(command) execution from configuration.
This follows the existing azure-cli convention. Specify would invoke gh auth token when the credential is needed, cache the result for the current run, and avoid writing it to disk or including it in logs and errors. The implementation would also need clear handling for a missing or unauthenticated gh, command failures and timeouts, and GitHub Enterprise host selection.
Would you be open to reframing this issue as “Support GitHub CLI as a GitHub authentication mode”, using auth: \"github-cli\" rather than general-purpose command substitution?
Posted on behalf of @mnriem. Drafted with GitHub Copilot using GPT-5.6 Sol in human-supervised interactive mode; code tracing, end-to-end validation, and issue-response drafting.
We suspect the intended request is therefore not general command substitution, but making GitHub CLI credential resolution automatic on every Specify invocation. That is a reasonable convenience feature, but we would prefer a dedicated authentication mode over allowing arbitrary `$(command)` execution from configuration.
Ultimately, yes, this is the intended effect. The goal would be not relying on storing a token at rest, including in an environment variable.
Thank you for your guidance - i will revise this issue based on it.
changed the title [-]Support Dynamic Command Substitution for Tokens in .specify/auth.json[/-][+]Support GitHub CLI as a GitHub Authentication Mode[/+]on Oct 14, 2026
Activity
mnriem commentedon Oct 13, 2026
Thanks for raising this. We agree with the goal of using credentials managed by GitHub CLI without storing another copy of the token, but a couple of assertions about the current behavior need clarification.
Specify does not read authentication configuration from a project-local
.specify/auth.json. It reads only the user-level~/.specify/auth.json. The file also does not need to contain a token: the existingtoken_envfield resolves it from the process environment at request time.For example:
{ \"providers\": [ { \"hosts\": [ \"github.com\", \"api.github.com\", \"raw.githubusercontent.com\", \"codeload.github.com\" ], \"provider\": \"github\", \"auth\": \"bearer\", \"token_env\": \"GH_TOKEN\" } ] }This works today:
We verified this end to end: Specify loaded the user-level configuration, resolved the token from
GH_TOKEN, and sent the expected bearer header. We also verified that placing the same configuration in a project-local.specify/auth.jsonhas no effect.We suspect the intended request is therefore not general command substitution, but making GitHub CLI credential resolution automatic on every Specify invocation. That is a reasonable convenience feature, but we would prefer a dedicated authentication mode over allowing arbitrary
$(command)execution from configuration.A possible configuration would be:
{ \"providers\": [ { \"hosts\": [ \"github.com\", \"api.github.com\", \"raw.githubusercontent.com\", \"codeload.github.com\" ], \"provider\": \"github\", \"auth\": \"github-cli\" } ] }This follows the existing
azure-cliconvention. Specify would invokegh auth tokenwhen the credential is needed, cache the result for the current run, and avoid writing it to disk or including it in logs and errors. The implementation would also need clear handling for a missing or unauthenticatedgh, command failures and timeouts, and GitHub Enterprise host selection.Would you be open to reframing this issue as “Support GitHub CLI as a GitHub authentication mode”, using
auth: \"github-cli\"rather than general-purpose command substitution?karldreher commentedon Oct 14, 2026
Ultimately, yes, this is the intended effect. The goal would be not relying on storing a token at rest, including in an environment variable.
Thank you for your guidance - i will revise this issue based on it.
[-]Support Dynamic Command Substitution for Tokens in .specify/auth.json[/-][+]Support GitHub CLI as a GitHub Authentication Mode[/+]