The previous commit's messages were rejected by Codex. Checked against the
app-server documentation rather than guessing again:
- app-server omits the `"jsonrpc": "2.0"` header on the wire; we were sending
it on every message.
- `initialize` takes `params.capabilities.experimentalApi`, which part of the
server's surface is gated behind. We sent only `clientInfo`.
- The documented invocation is a bare `codex app-server`. The `-s read-only
-a never` prefix was defensive but undocumented, and nothing here starts a
thread or runs a turn for it to constrain.
Also fixed alongside:
- A PATH-only install was unreachable: `URL(fileURLWithPath: "codex")`
resolves against the working directory, so the fallback now goes through
`/usr/bin/env`.
- stdout and stderr are drained as they fill instead of after exit, which
removes both the pipe-buffer deadlock and the full timeout wait for a
server that outlives its stdin. The request returns as soon as its
response lands.
- Failures now carry the exit status and the stderr tail instead of a bare
"could not parse", so the next report says what actually happened.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The ChatGPT provider no longer touches credentials at all. Usage now comes
from `codex app-server`, the CLI's stdio JSON-RPC interface: handshake, then
`account/rateLimits/read`. Codex owns authentication end to end, so this works
wherever it keeps its credentials — file, keyring or ephemeral — and the app
never reads, stores or forwards a token.
Removed accordingly:
- Reading ~/.codex/auth.json and the CODEX_HOME environment variable.
- The manual-token and Admin API key modes for this provider, along with the
OpenAI organization usage/cost metrics. ChatGPT now offers Auto only, and
Settings no longer queries the Keychain for a provider that cannot use it.
- The shared JWT helper, which existed only to read claims out of Codex
tokens; CursorAuthService is back to its original form.
This also drops the HTTP path, whose endpoint was wrong: the earlier commit
used /backend-api/codex/usage, while Codex actually polls
/backend-api/wham/usage with a different response shape.
The app-server command is documented as experimental and
`account/rateLimits/read` is undocumented, so the decoder accepts the windows
wrapped in `rateLimits` or inlined at the root, and an absolute `resetsAt` or
a `resetsInSeconds` countdown.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Adds a ChatGPT provider alongside Cursor and Claude, following the same
provider/auth/metric structure:
- Auto mode reads the Codex CLI session from ~/.codex/auth.json (CODEX_HOME
aware) and queries the ChatGPT usage endpoint for the 5-hour and weekly
rate-limit windows.
- Manual mode accepts a pasted ChatGPT access token; the account id and plan
are recovered from the token's own claims.
- Admin mode reports 7-day input/output tokens and cost from the OpenAI
organization usage and costs APIs.
Supporting changes:
- Extract base64url JWT payload decoding into a shared JWT helper, reused by
CursorAuthService.
- Replace the duplicated provider lookup in UsageRefreshService and
SettingsView with ProviderID.provider.
- Build the Settings provider tabs from ProviderID.allCases.
- Providers missing from previously saved settings now start disabled, so the
upgrade does not add an unconfigured indicator to an existing menu bar.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>