CodeRelay is a macOS companion app for people who manage more than one Codex account. It keeps each account in its own isolated CODEX_HOME, lets you re-authenticate accounts without mixing credentials, shows which accounts look ready based on the latest usage snapshot, and warns when the active account is getting close to exhaustion.
The current codebase is usable for managed-account enrollment, usage visibility, and threshold warnings, but it is not a full account switcher yet.
Implemented now:
- add a managed account by running
codex logininside a CodeRelay-owned home directory - list, re-authenticate, and remove managed accounts
- mark one managed account as the locally selected active account
- read managed-account identity from
auth.json - detect whether the managed account is file-backed, keyring-backed, or unverified
- refresh usage snapshots for all managed accounts and surface readiness information in the app UI
- refresh the currently active managed account in the background on a configurable cadence
- configure one global warning threshold plus a notifications toggle
- warn once per depletion cycle when the active account falls below threshold in either tracked window
- surface stale, error, and unknown monitoring risk states in both the management window and menu bar
- use a menu bar icon as the primary post-setup entry point, while keeping first-run enrollment in a dedicated setup window
- localize the app shell in English and Simplified Chinese
- persist account metadata and usage snapshots under
~/Library/Application Support/CodeRelay
Not implemented yet:
- swapping the live
~/.codex/auth.jsonand~/.codex/config.toml - reopening Codex sessions or restoring CLI/App workflows after a switch
- macOS 15.0+
- Swift toolchain with SwiftPM support
codexavailable onPATH
Add Account shells out to:
codex -c 'cli_auth_credentials_store="file"' loginThat means CodeRelay currently works best with file-backed Codex credentials. Keyring-backed accounts are detected and shown as unsupported for safe file-based switching.
For local development:
swift build
swift test
swift run CodeRelayAppFor a local ad-hoc bundle plus archive formats:
zsh ./scripts/package_macos_release.shFor a production Developer ID signed + notarized release:
NOTARYTOOL_PROFILE=CodeRelayNotary \
zsh ./scripts/sign_and_notarize_macos_release.shThat release wrapper produces the GitHub-facing zip + dmg set by default. If you also need a signed installer package, override PACKAGE_FORMATS="zip pkg dmg" explicitly.
Artifacts are written to dist/:
CodeRelay.appCodeRelay-<VERSION>-macOS.zipCodeRelay-<VERSION>.pkgCodeRelay-<VERSION>.dmg
Production release prerequisites:
Developer ID Applicationcertificate in your login keychainDeveloper ID Installercertificate in your login keychainxcrun notarytoolkeychain profile, for exampleCodeRelayNotary
Security note:
- the release scripts read signing identities from your local keychain and read notarization credentials from an existing
notarytoolkeychain profile - no Apple private keys,
.p8files, exported certificates, or account secrets are stored in this repository or embedded into GitHub release metadata
The local packaging script stays ad-hoc by default. The notarized wrapper script switches signing to Developer ID, submits the app/pkg/dmg to Apple, staples the tickets, and validates the final app with codesign and spctl.
- Each managed account gets its own isolated home under
~/Library/Application Support/CodeRelay/managed-codex-homes/<uuid>/. - CodeRelay runs
codex loginwithCODEX_HOMEpointed at that managed home. - It reads identity details from the managed
auth.jsonand stores account metadata in a local JSON registry. - Usage refresh reads the managed account token and calls the Codex usage endpoint, then stores the latest snapshot locally.
- The UI uses those snapshots to show the selected active account's usage and other accounts' readiness.
- A runtime-owned scheduler can refresh the active managed account in the background and evaluate warning state after each refresh.
- Warning state is deduplicated per depletion cycle, so the app does not spam repeated notifications while the active account remains below threshold.
- After first setup, CodeRelay is primarily opened from the menu bar instead of living as a permanent main window.
The current Set Active action only changes CodeRelay's local selection. It does not mutate the live ~/.codex files yet.
CodeRelay currently stores data here:
~/Library/Application Support/CodeRelay/managed-codex-accounts.json~/Library/Application Support/CodeRelay/usage-snapshots.json~/Library/Application Support/CodeRelay/managed-codex-homes/<uuid>/
The JSON stores are written atomically and locked down to 0600 permissions on macOS.
Sources/CodeRelayApp: SwiftUI app shell and account-management UISources/CodeRelayCore: account models, projection logic, persistence, and filesystem safety checksSources/CodeRelayCodex: Codex-specific login, identity, credential-mode detection, and usage refresh logicTests/CodeRelayAppTests: UI-facing feature testsTests/CodeRelayCoreTests: core model and storage testsTests/CodeRelayCodexTests: Codex integration unit tests
- macOS only
- depends on the installed
codexCLI - no live account switch into
~/.codexyet - background refresh only covers the active managed account in this phase
- no automatic session resume yet