paperctl start codex configures Codex for one terminal launch. The ChatGPT desktop app doesn’t launch from your terminal, so it needs a persistent setup instead: one command that points Codex’s shared config at paperd and delivers the plugin the app loads, covering the desktop app, the IDE extension, and ordinary codex launches alike. The default setup keeps Codex’s ChatGPT subscription sign-in. If you use an OpenAI API key, follow API-key mode instead. Codex supplies the provider credential; paperd forwards it without managing Codex’s credential store.
Prerequisites: paperctl installed and authenticated, with the daemon running.
Point the app at paperd
Preview what would change, then apply it:
paperctl plugin install codex-app --dry-run
paperctl plugin install codex-app
The command reconciles Codex’s shared config file — $CODEX_HOME/config.toml, or ~/.codex/config.toml when CODEX_HOME is unset — and extracts the Paper plugin the app loads. It sets a Paper-owned provider that routes Codex’s traffic through the local paperd proxy while reusing Codex’s ChatGPT subscription sign-in. It’s safe to run repeatedly: Paper updates only the values it owns, preserves everything else in the file, and writes only when something actually changed.
codex-desktop is accepted as an alias for codex-app. The terminal Codex CLI needs no plugin — it’s captured by redirection, which is what paperctl start codex does, and asking to install a plugin for it says so.
Finish the two steps in Codex
Codex deliberately gates two steps on you, and the install summary lists them. Until both are done the app is configured but its hooks are inert, so sessions arrive without attribution:
- Enable the plugin. In the ChatGPT app’s plugin directory, enable Paper in the Installed row. The app runs the installed cached copy, not the extracted source directory.
- Trust its hooks. Enabling a plugin does not trust its hooks. Run
/hooksand trust theSessionStart,UserPromptSubmit,Stop,SubagentStart, andSubagentStopentries whose source ispaper-codex. If the app’s/hooksselector doesn’t list them, run/hooksin the codex CLI with the sameCODEX_HOME— trust is shared state recorded inconfig.toml, so doing it once in the CLI covers the app.
Then fully quit and restart the app. Codex reads its config at startup, so sessions started before the restart are not captured.
Trust binds to the exact hook-definition hash, which means every plugin upgrade re-requires it. After a paperctl upgrade that ships new hooks, expect to run /hooks again.
Verify the capture
Start a conversation in the ChatGPT app, then:
paperctl sessions list
The session appears at the top with its turn count, cost, and status, and shows up in paper console moments later. Codex subagents — spawn_agent threads, however deeply nested — appear inside that one session, each under the tool call that spawned it, and the session’s usage and cost totals include them. See How capture works for the full picture.
API-key mode
Choose the setup that matches where Codex gets your API key. A saved
OPENAI_API_KEY field in auth.json is a JSON credential, not a shell environment
variable. Exporting a variable in your terminal also does not make it available
to a ChatGPT app launched from the Dock or Finder.
Paper’s default chatgpt mode uses the ChatGPT subscription backend. API keys
need the OpenAI API backend, so switching to the default mode does not fix a
missing API-key environment variable.
Key saved by Codex
Unreleased: --auth api-key-login is implemented for the next release; it is
not available in paperctl 0.33.0. Check paperctl version and
paperctl plugin install --help before using it. In releases through 0.33.0,
--auth api-key supports only the process environment.
If you are already signed in to Codex with an API key, keep that login. With
file-based credential storage, Codex reads OPENAI_API_KEY from
$CODEX_HOME/auth.json, defaulting to ~/.codex/auth.json. The directory is
.codex. Codex can also use its OS credential store; Paper delegates credential
loading to Codex. See OpenAI’s authentication documentation.
On a version with saved-key support, preview and apply the local setup:
paperctl plugin install codex-app --auth api-key-login --dry-run
paperctl plugin install codex-app --auth api-key-login
The preview shows requires_openai_auth = true, no env_key, and a base URL
ending in /v1/openai-responses/openai-transparent/v1. The install reports
API key saved by Codex. These commands update local integration files; they
neither read nor rewrite auth.json nor copy the key into Paper configuration.
There is no API key to set in paperd or its service environment.
Run setup with the same CODEX_HOME the app uses. Fully quit and restart the app,
then complete the plugin enablement and hook trust steps above and
verify the capture.
If you have not saved an API-key login yet, use Sign in another way in the ChatGPT app and enter your API key. Alternatively, if the key is already in your terminal environment, save it with the Codex CLI:
printenv OPENAI_API_KEY | codex login --with-api-key
This changes Codex’s saved login. Existing API-key users do not need to sign in
again, export their saved key, or show an agent the contents of auth.json.
A saved ChatGPT subscription login cannot authenticate to the OpenAI API route.
Key in the process environment
For a key supplied to the Codex process through its environment, use:
paperctl plugin install codex-app --auth api-key
This writes env_key = "OPENAI_API_KEY" and uses the OpenAI API backend. Codex
requires the environment variable even if auth.json already contains a key.
The variable must reach the app process, not just your shell or paperd.
A normal macOS app launch does not inherit shell variables; use saved-key
support above when available unless you already manage app environment variables.
Remove it
paperctl plugin uninstall codex-app --dry-run
paperctl plugin uninstall codex-app
This reverses the install in the order that keeps the app working at every step: the Paper provider declaration first, then the Paper-owned handoff files, then the extracted marketplace. Codex’s own cached copy of the plugin is left registered — removing it by spec would also remove a copy you installed by hand — so the command prints how to remove that yourself. It runs even when daemon.toml is unparseable, which is exactly when you tend to want it.
If something’s off
- Sessions from the app aren’t captured: rerun the install command for your chosen auth mode and restart the app. (If it reports drift — a Codex update can rewrite the config — it will repair it.)
- Sessions arrive but aren’t attributed to you: the hooks are installed but untrusted. Run
/hooksas above; a plugin upgrade silently un-trusts them. - The command reports it repaired settings: restart the app before continuing; the running session keeps its old config and isn’t sent to paper.
- Missing
OPENAI_API_KEYdespite a saved key: the provider is using environment auth. Follow Key saved by Codex, including its version requirement. Do not pasteauth.jsonor put the key inconfig.toml. - Authentication fails after setup: confirm that your Codex login matches the selected route (ChatGPT subscription or OpenAI API key) and that setup and the app use the same
CODEX_HOME. - Daemon not running:
paperctl status, then CLI troubleshooting.