CodexSwitcher is a native macOS menu bar app for managing Codex CLI and ChatGPT Desktop accounts.
The app keeps saved profiles separate, switches the active Codex credentials atomically, and shows usage limits for every saved plan.
Status: beta candidate. An unsigned ZIP can be distributed for public preview testing. Trusted Gatekeeper distribution still requires an Apple Developer signing identity and notarization credentials.
Current profile list with grouped plans, quota windows, reset times, token totals, and update time.
Menu bar display and appearance settings.
Compact account and quota display. The account name is anonymised.
- Add accounts through an isolated Codex browser login.
- Dismiss login status notices manually or let them disappear automatically.
- Keep the current account active while a new login is in progress.
- Cancel or time out an incomplete browser login without leaving the app stuck.
- Save profile credentials in the macOS Keychain.
- Switch between saved profiles without running a logout flow.
- Replace
auth.jsonatomically to avoid partial credentials. - Group multiple plans under one email account.
- Rename the displayed email group without changing the email or credentials.
- Show usage limits and token activity for the active account and saved profiles.
- Show the account name, plan type, token total, and quota bars in the menu bar.
- Quit CodexSwitcher from the menu bar popover.
- Choose light, dark, or system appearance.
- Detect ChatGPT Desktop and offer a restart after an account switch.
- macOS 14 or newer
- Codex CLI or ChatGPT Desktop with Codex support
- Xcode 16 or newer
- XcodeGen
The app looks for Codex in these locations:
/opt/homebrew/bin/codex/usr/local/bin/codex/Applications/ChatGPT.app/Contents/Resources/codex
brew install xcodegen
xcodegen generate
xcodebuild \
-project CodexSwitcher.xcodeproj \
-scheme CodexSwitcher \
-configuration Debug \
-destination platform=macOS \
CODE_SIGNING_ALLOWED=NO \
SWIFT_ENABLE_EXPLICIT_MODULES=NO \
buildThe generated Xcode project is ignored. Run xcodegen generate after changing project.yml.
The beta script generates a Release archive, verifies the bundle version, creates a zip file, and writes a SHA-256 checksum.
For a local or unsigned public preview build without Apple credentials:
./scripts/build_beta.sh --unsigned --skip-notarizationThis creates dist/CodexSwitcher-0.1.0-unsigned.zip and matching metadata files. The -unsigned label must remain when the archive is shared publicly.
Users may need to choose Open Anyway in macOS Privacy & Security. Share the checksum with the archive and tell users to download it only from the official release page.
For a public beta, install a Developer ID Application certificate and configure a notarytool keychain profile first:
CODEXSWITCHER_DEVELOPMENT_TEAM=TEAMID \
CODEXSWITCHER_NOTARY_PROFILE=CodexSwitcher-notary \
CODEXSWITCHER_VERSION=0.1.0 \
CODEXSWITCHER_BUILD_NUMBER=1 \
./scripts/build_beta.shThe public beta tag should be v0.1.0-beta.1. The numeric bundle version remains 0.1.0 because macOS bundle metadata does not use the tag suffix.
See docs/RELEASING.md for the complete release checklist.
CodexSwitcher uses ~/.codex by default. Set CODEX_HOME to use another absolute directory:
CODEX_HOME=/path/to/codex-home open /path/to/CodexSwitcher.appThe app does not copy the current auth.json into the repository.
Add Account starts codex login with an isolated temporary CODEX_HOME. The browser login does not replace the current account. The new profile is saved only after the login succeeds.
Switch replaces the active Codex auth.json atomically. Saved credentials remain in the macOS Keychain. If ChatGPT Desktop is running, the app shows a restart action so the desktop app can load the new account.
The Rename action is on the parent email row. It changes only a local display label stored in UserDefaults. It does not change the email, plan type, auth.json, or Keychain credentials.
Usage is fetched when the app starts, when the user presses Refresh, after account changes, and automatically every 60 seconds while the app is running. The app queries the Codex app server for account details, rate limits, and token activity.
The status-bar timer only updates local display text and relative-time labels. It does not fetch quota data every few seconds.
Each usage request has a 20-second timeout. A failed request shows Quota unavailable and does not change the saved credentials.
| Data | Location | Purpose |
|---|---|---|
| Active Codex auth | $CODEX_HOME/auth.json or ~/.codex/auth.json |
Credentials used by Codex |
| Saved profile credentials | macOS Keychain service com.ahikmah.codexswitcher.profiles |
Credentials for account switching |
| Profile metadata | UserDefaults key codexswitcher.profiles.v1 |
Profile identity and timestamps |
| Email display labels | UserDefaults key codexswitcher.email-labels.v1 |
Local parent-account names |
| Login and usage temporary homes | Temporary directories | Isolated CLI operations; removed after use |
CodexSwitcher does not print credential values in logs. Do not share auth.json, Keychain exports, or screenshots that contain account information.
- The app requires a working Codex CLI or the Codex executable inside ChatGPT Desktop.
- Usage fields depend on the Codex app-server response. Some accounts may return no usage or token data.
- An unsigned public beta may trigger a Gatekeeper warning and requires a manual user override.
- Trusted public beta distribution requires an Apple Developer signing identity and a configured notarytool profile.
- The beta packaging path creates a zip archive. Sparkle updates and a DMG installer are not configured.
- The repository currently has build validation but no automated UI test suite.
- Change
project.ymlor files underCodexSwitcher/. - Run
xcodegen generate. - Run the Debug build command above.
- Launch the generated app from DerivedData.
- Test account actions with a non-critical Codex account.
For a beta archive, use scripts/build_beta.sh and follow docs/RELEASING.md.
Before submitting a change, check:
- Add Account success, cancel, timeout, and browser-abandon flows.
- Switch between two profiles and verify the active email.
- Usage display for the active and inactive profiles.
- Parent email rename without an auth-file change.
- Light, dark, and system appearance.
- Menu bar settings and quota display.
- ChatGPT Desktop restart behavior when the app is running.
See CONTRIBUTING.md for contribution rules and docs/ARCHITECTURE.md for the module boundaries.
The account-switching workflow and menu bar product direction were inspired by CCSwitcher by XueshiQiao.
CodexSwitcher is a separate Codex implementation for Codex CLI and ChatGPT Desktop. This repository contains only CodexSwitcher source files and assets. It does not include the original CCSwitcher source or assets.
This project is not affiliated with OpenAI, Anthropic, or XueshiQiao.
This project is licensed under the MIT License. See LICENSE.


