Authentication
PLCodex authenticates with either a ChatGPT sign-in, which draws on a ChatGPT plan’s Codex allowance and is required for Codex cloud, or an OpenAI API key, which bills per token and suits local and CI work. The Codex CLI stores the credential in ~/.codex/auth.json by default, and codex login status and codex doctor confirm which method is active.
You installed Codex, ran codex, and the sign-in screen offers ChatGPT, a device code, and an API key. On your laptop the choice takes a second. On a build server with no browser, in a Docker container, or in a GitHub Actions job, the wrong choice shows up later as a CI step that says “Not logged in” while the agent runs fine, or as codex cloud refusing to start.
This page is for the developer setting up Codex on a laptop, a remote box, or a CI runner, and for the tech lead who wants every machine on the team signed in the same, checkable way. Every command and message below was checked against Codex CLI 0.157.1 on 2026-09-26. Install Codex first with the installation guide.
What you get from a checked Codex sign-in
Section titled “What you get from a checked Codex sign-in”- A decision on ChatGPT sign-in versus API key, made on billing and on the features each one unlocks.
- Credentials stored where your security policy wants them: a file, the OS keyring, or memory only.
- A working sign-in on machines without a browser: SSH sessions, containers, and CI runners.
- A two-command check that proves which method is active, so nobody has to guess.
- A team-wide rule that pins the login method and the ChatGPT workspace.
Which Codex sign-in method should you choose?
Section titled “Which Codex sign-in method should you choose?”Pick by who pays and which features you need. The sign-in screen in 0.157.1 offers Sign in with ChatGPT, Sign in with Device Code, Provide your own API key, and Amazon Bedrock for organizations that route Codex through AWS.
| Situation | Use | Why |
|---|---|---|
| You have a ChatGPT Plus, Pro, Business, Edu, or Enterprise plan | ChatGPT sign-in | Codex usage comes out of the plan’s allowance, and cloud tasks, /usage, and remote control work |
| A machine with no browser, and you want your ChatGPT plan | Device code | Same account as ChatGPT sign-in; you finish the sign-in on any other device |
A CI job or script calling codex exec | API key in CODEX_API_KEY | Usage-based billing on your OpenAI Platform account, no personal session on a shared runner |
| You want Codex costs separate from any ChatGPT plan | API key | One bill per API organization and its policies |
| Your company runs models through AWS | Amazon Bedrock | See the enterprise governance guide |
OpenAI’s pricing page (read 2026-10-12) also lists Free and Go plans, for which it names only “GPT-6 Luna at Standard speed in the desktop app, subject to rollout”; the plan table on Codex credits, usage limits and cost optimization lists every plan and what it includes. For an API key, the page says “No cloud-based features”. Since 0.161.0 (2026-10-07), API-key model discovery is on by default (api_key_model_discovery is stable and on in 0.162.1), so a pipeline that logs in with an API key can behave differently from an older pin; re-run its smoke test after you upgrade.
An API key does not unlock everything. In Codex CLI 0.157.1, these features refuse API-key auth and ask for a ChatGPT sign-in:
codex cloud(“Not signed in. Please run ‘codex login’ to sign in with ChatGPT”).- Remote control (“remote control requires ChatGPT authentication; API key auth is not supported”).
- The remote plugin catalog and shared plugins.
/usageand rate-limit readouts in the terminal UI.
The model you get depends on the plan or API organization, not on the sign-in screen. The models hub lists what Codex runs by default and what each model costs.
Sign in to Codex and prove it worked
Section titled “Sign in to Codex and prove it worked”Run this in a terminal on a machine with a browser:
codex loginCodex starts a local callback server on 127.0.0.1:1455, opens the browser, and stores the returned tokens when you finish signing in. Running codex with no credentials shows the same choice in the terminal UI.
Pipe the key from an environment variable so it never appears in your shell history or on the command line:
printenv OPENAI_API_KEY | codex login --with-api-keyCreate the key in your OpenAI Platform account and keep it in a password manager or secret store. Codex stores the key in its credential store, so the environment variable is only needed once.
The desktop app and the IDE extension offer sign-in on their own screens. The CLI and the IDE extension read credentials from the same CODEX_HOME directory (default ~/.codex), so one sign-in serves both as long as CODEX_HOME matches.
Now check the result instead of assuming it:
-
Ask Codex which method it holds. The exit code is
0when signed in and1when not, so scripts can branch on it:Terminal window codex login statusExpect
Logged in using ChatGPT, orLogged in using an API key -followed by the key with its middle masked. The message goes to stderr, so redirect with2>&1when you capture it. -
Run the diagnosis. The
authrow names the source of the credentials, including keys that come from the environment, whichcodex login statusdoes not see:Terminal window codex doctor --summary -
For an onboarding ticket or a support case, save the redacted report and attach it:
Terminal window codex doctor --json > codex-doctor.json -
If you chose ChatGPT sign-in and need cloud tasks, confirm them from the terminal.
codex cloud listprints your cloud tasks without opening the TUI, and a task list, even an empty one, proves the cloud side accepts your account:Terminal window codex cloud list
The tech lead signs off on the codex doctor --json file, not on a screenshot of a sign-in page: the auth row and the version are in it, and the report redacts secrets.
Where does Codex store credentials?
Section titled “Where does Codex store credentials?”The cli_auth_credentials_store key in ~/.codex/config.toml decides. The default is file.
cli_auth_credentials_store = "auto"| Value | Where credentials live | Use it when |
|---|---|---|
file (default) | $CODEX_HOME/auth.json | You need the credential to survive reboots on a machine without a keyring |
keyring | macOS Keychain, Windows Credential Manager, or Linux Secret Service | Your laptop has an unlocked keyring and you want no token file on disk. Codex fails if the keyring is unavailable |
auto | Keyring when available, otherwise auth.json | Most laptops: the keyring where it works, a file where it does not |
ephemeral | Memory, for the current process only | Shared or short-lived machines where nothing may be written to disk |
Sign in to Codex over SSH, in a container, or on a headless server
Section titled “Sign in to Codex over SSH, in a container, or on a headless server”The browser sign-in needs the browser to reach Codex’s callback server on localhost:1455. On a remote machine it cannot, so use one of these.
Run this on the remote machine:
codex login --device-authCodex prints a URL and a one-time code. Open the URL on any device, sign in, and enter the code. The device code expires after 15 minutes. If Codex reports that device code login is not enabled, use SSH port forwarding instead.
Forward the callback port, then sign in from the forwarded session:
# On your laptopssh -L 1455:localhost:1455 -L 1457:localhost:1457 user@remote
# In that SSH session, on the remote machinecodex loginOpen the printed URL in your laptop’s browser. Port 1457 is the fallback Codex uses when 1455 is already taken, so forwarding both covers that case.
Sign in on your laptop, then copy the file over an encrypted channel:
ssh user@remote 'mkdir -p ~/.codex && chmod 700 ~/.codex'scp ~/.codex/auth.json user@remote:~/.codex/auth.jsonssh user@remote 'chmod 600 ~/.codex/auth.json && codex login status'This works only with file storage, and the remote machine now holds your personal session. Use it on machines only you can access, and run codex logout there when you finish.
Authenticate Codex in CI without a personal session
Section titled “Authenticate Codex in CI without a personal session”A CI runner must never hold a developer’s ChatGPT session. Give codex exec an API key through the CODEX_API_KEY environment variable, read from the CI platform’s secret store, and keep nothing on disk. The Codex CI/CD guide covers the openai/codex-action GitHub Action; this is the shell-level pattern it builds on.
name: codex-checkon: pull_requestpermissions: contents: readjobs: codex: # Skip pull requests from forks: they get no secrets if: github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 with: fetch-depth: 0 persist-credentials: false - run: npm install -g @openai/codex@0.157.1 - name: Check Codex sees a credential env: CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} run: | codex doctor --summary --no-color > doctor.txt || true grep -E '✓ auth' doctor.txt - name: Read-only review env: CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} run: | codex -c cli_auth_credentials_store=ephemeral \ -c default_permissions=":read-only" \ exec --ephemeral \ "Summarize the risk in this pull request's diff against origin/main. Do not modify files."on: pull_request does not pass repository secrets to pull requests from forks, which is what you want: a fork’s code never runs next to your key. The if: line skips fork pull requests outright, so the job runs only for branches pushed by people who already have write access. Do not switch it to pull_request_target to get secrets for forks. The job trusts branches from people with write access; a branch can still change project .codex/ config and AGENTS.md, so keep the agent step read-only and require review before merging workflow or .codex/ changes. --ephemeral keeps the session off the runner’s disk, and cli_auth_credentials_store=ephemeral keeps any credential in memory. The doctor step ignores the command’s exit code because other rows, such as network reachability, can fail on a runner while auth is fine. Use codex doctor, not codex login status, to check a key supplied this way: codex login status reports Not logged in for keys that come from the environment, while the doctor auth row reports auth is provided by environment. The auth row confirms a key is present, not that OpenAI accepts it; the exec step is what fails on a revoked or mistyped key. The agent step selects the built-in :read-only permission profile (beta), which OpenAI prefers over the legacy --sandbox flag; do not add --sandbox next to it, because the two systems do not compose. See Codex configuration.
The requirement list at the end is your acceptance check: each requirement maps to a line, so you check seven lines, not the whole file.
Enforce one login method across a team
Section titled “Enforce one login method across a team”For a single machine or a shared base config, pin the method and the workspace in config.toml:
# ~/.codex/config.toml, or a config your team distributesforced_login_method = "chatgpt" # or "api"forced_chatgpt_workspace_id = "00000000-0000-0000-0000-000000000000"If the stored credential does not match, Codex logs the user out and says why, for example “ChatGPT login is required, but an API key is currently being used. Logging out.” A user can edit their own config.toml, so for organization-wide rules, administrators set allowed_login_methods and allowed_chatgpt_workspaces in the managed requirements.toml. The enterprise governance guide covers managed configuration.
When Codex sign-in breaks
Section titled “When Codex sign-in breaks”The browser never returns to the terminal (WSL, SSH, containers). The browser cannot reach localhost:1455 on the machine running Codex. Cancel, then use codex login --device-auth or the SSH forwarding above.
“Port … is already in use”. Both callback ports, 1455 and the fallback 1457, are taken, usually by stale codex login processes. Codex has already tried to cancel the previous sign-in. Close terminals still running a sign-in (or kill the process holding the port) and run codex login again.
“device code login is not enabled for this Codex server”. Device-code sign-in is off for this account or server. Use SSH port forwarding, or ask your workspace admin whether the setting is available to you.
“device auth timed out after 15 minutes”. Run codex login --device-auth again and enter the new code promptly.
“Your access token could not be refreshed”. The session expired, or you signed in to another account elsewhere. Run codex logout, then codex login.
Codex logs you out on start with “ChatGPT login is required, but an API key is currently being used”. A forced_login_method rule does not match your credential. Sign in with the method the rule asks for. Change the rule only if you own it.
“API key login is disabled by this workspace”. Your admin allows only ChatGPT sign-in. Run codex login and choose ChatGPT.
keyring storage fails on a headless Linux box. No Secret Service is running, and keyring fails rather than falling back. Set cli_auth_credentials_store = "auto", or "ephemeral" on shared machines.
Signed in in one terminal, “Not logged in” in another. The two shells use different CODEX_HOME values. Run echo "$CODEX_HOME" in both and make them match, or unset it to use ~/.codex.
codex login status fails in CI although the job works. The key comes from CODEX_API_KEY, which login status does not report. Check with codex doctor --summary as in the CI example.
codex cloud says “Not signed in” while local work runs. You are on an API key. Cloud tasks need ChatGPT sign-in: run codex login and choose ChatGPT.
For errors after sign-in, such as rate limits or sandbox denials, see Codex error recovery.
Where to go next after Codex sign-in
Section titled “Where to go next after Codex sign-in”Did this guide help you?
One tap, no sign-in.
What will you do with it?
How did it read?
What got in the way? Pick any that apply
Your role?
Thanks. I read every answer. Michał Jaskólski
Did this guide help?
One tap each. Close whenever you like.
no sign-in