Authorization in Codex is not only the question of "how to sign in" but also of whose billing it is, what the policy is and what is available at all. For OpenAI models the local clients support two main paths: signing in through ChatGPT and an API key. Codex cloud requires exactly ChatGPT sign-in. The login method determines not only payment but also workspace policy, retention and the availability of cloud and connector features - so it is chosen consciously, not by the first prompt that comes up.
The difference between signing in through ChatGPT and an API key is fundamental. ChatGPT sign-in ties the work to your plan and workspace controls, enables cloud capabilities and obeys the account's policy. An API key is usage-based billing, convenient for local clients, CI and programmatic integration, but it does not give the cloud part. Mixing them in one environment is easy, and the consequences are not obvious: a request may go the wrong route and to the wrong bill, so the real source is always checked.
You check the sign-in with a command, not from memory. codex login status shows the current authorization state, codex logout resets it. An important detail: the CLI and the IDE extension use a shared cached login, so a sign-in in one place is visible in the other. This is convenient but also demands attention: signing out in one client affects both, and an unexpected change of the login source is a frequent cause of "it worked yesterday and not today".
Where the credentials live is a matter of both convenience and security. They may be stored in the $CODEX_HOME/auth.json file or in the system credential store. The cli_auth_credentials_store setting forces the behavior: the value keyring chooses the system store, while auto uses it when available and otherwise falls back to the file. On shared or CI machines the system store is preferable to a file that is easier to read by accident or carry off together with the home directory.
It helps to gather the sign-in methods into a table once, to choose by the task. Below is the map: ChatGPT sign-in for interactive local work and the cloud, device code for headless and remote hosts, an API key for local clients, CI and usage-based billing. You return to this map when changing the environment: each method has its own area of use, its own billing and its own limits, and mixing them means one day being surprised by a bill or an unavailable feature.
Device code is a separate path for machines without a convenient browser. It lets you sign in on a headless or remote host through a confirmation code, while staying under the same ChatGPT controls. But it is a feature that must be allowed, not a given: the availability of device-auth depends on the settings, so its presence is checked in advance rather than relied on in a critical pipeline without a check. For steady automation it is more of a convenience than a guarantee.
| Method | Suitable for | Billing and policy | Command |
|---|---|---|---|
| ChatGPT sign-in | Interactive local work and cloud | ChatGPT plan and workspace controls | codex login |
| Device code (beta) | Headless and remote host | Same ChatGPT controls; must be allowed | codex login --device-auth |
| API key | Local clients and CI | Usage-based billing | environment variable / config |
For CI the default choice is an API key passed only to the Codex process, not to the whole job environment. This is not a formality but a security boundary. If the job runs scripts controlled by the repository - dependency hooks, build steps - then a secret set at the whole-job level can be read by compromised or untrusted code. The key is given narrowly: only to the command that actually needs it, and no wider.
The typical authorization failures are predictable and costly. Mixing a ChatGPT sign-in and an API key in one environment and sending a request to the wrong billing. Keeping credentials in a file on a shared machine instead of the system keyring. Setting a secret at the whole CI-job level and exposing it to repository-controlled scripts. And relying on device-auth without checking that it is allowed. Check the sign-in with a command, keep credentials in a secure store and give a secret only to the process that needs it.
codex login status # current sign-in state
codex logout # reset the sign-in
codex login --device-auth # device code (if the feature is allowed)
# CLI and IDE share a cached login; credentials - in $CODEX_HOME/auth.json or keyring
# cli_auth_credentials_store = "keyring" | "auto" | "file"