Skip to content

euforicio/Codexer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Codexer

Codexer is a native macOS profile manager for running multiple isolated instances of the OpenAI Codex desktop app at the same time. It is built for the common personal/work-account case: create a profile for each account, launch Codex from that profile, and optionally install a Dock-pinnable shortcut for quick access.

Codexer does not modify /Applications/Codex.app, ~/.codex, or existing Codex authentication files. Each profile gets its own local state directory.

Features

  • Add and remove Codex profiles from a SwiftUI macOS app.
  • Launch multiple Codex instances side by side with separate state.
  • See whether each profile is running, focus its existing instance, and close only that profile without quitting the stock app or another profile.
  • View per-profile session totals, weekly activity, Codex usage-limit windows, job status, log warnings/errors, last activity, and local storage use.
  • Install profile-specific .app shortcuts in ~/Applications/Codexer/.
  • Use native arm64 shortcut launchers, avoiding Rosetta prompts.
  • Remove shortcuts without deleting profile data.
  • Remove a profile from Codexer while preserving its data.
  • Delete profile data only through a separate destructive confirmation.
  • Restore a previously removed profile from Codexer's managed Profiles folder.
  • Reject unsigned, modified, or incorrectly signed Codex app bundles.

How It Works

Codexer asks macOS to create a new instance of the official signed Codex app with profile-specific environment and arguments equivalent to:

CODEX_HOME=<profile>/CODEX_HOME \
  open -n /Applications/Codex.app \
  --args --user-data-dir=<profile>/ElectronUserData

This isolates:

  • Codex CLI/app-server config and auth state through CODEX_HOME.
  • Electron/browser state through --user-data-dir.
  • Local profile data under Codexer-owned folders.

Codexer intentionally does not override HOME, so Codex agents can still use your normal shell, git config, SSH keys, project files, and developer tools.

Codexer maps each managed ElectronUserData path to the exact main-app PID. Opening a running profile focuses that PID instead of creating a duplicate. Closing a profile sends a graceful termination request only to the PID or PIDs whose command line contains that exact profile path. The stock app, other profiles, and Electron helper processes do not match. Immediately before focus or termination, Codexer re-verifies the official bundle, executable, PID, and profile argument.

Open, Close, shortcut changes, and destructive deletion share a per-profile cross-process lock. This prevents two launchers from opening the same Electron directory at once and prevents launch or shortcut operations from racing deletion. Shortcut configurations are also bound to the profile's ownership marker.

Storage Layout

Codexer stores profile metadata here:

~/Library/Application Support/Codexer/profiles.json

Each profile stores isolated state here:

~/Library/Application Support/Codexer/Profiles/<profile-slug>/
  CODEX_HOME/
  ElectronUserData/

New profile shortcuts use a stable, path-safe profile slug and are installed here:

~/Applications/Codexer/<profile-slug>.app

Duplicate names receive numbered slugs, such as personal.app and personal-2.app. Renaming a profile does not move its state or shortcut.

Shortcut Behavior

Installed shortcuts are real macOS .app bundles. Each shortcut contains:

  • Contents/MacOS/CodexerShortcutLauncher: a native Swift launcher executable.
  • Contents/Resources/ShortcutConfig.plist: the profile-specific launch paths.
  • Contents/Info.plist: profile-specific bundle name and display name.
  • Contents/Resources/ProfileIcon.icns: a generated profile-color icon.

The shortcut's displayed name uses the profile name. Its stable filename uses the profile slug. For example, a profile named Work Account installs as:

~/Applications/Codexer/work-account.app

The running OpenAI Codex window and Dock icon still identify themselves as the official app. A shortcut can have a profile-specific Finder, Spotlight, and Launchpad name, but once it launches the official signed app, macOS uses the official app's runtime identity. Giving the running instance a different name would require copying and modifying the official bundle, invalidating its signature and complicating updates. Codexer therefore uses named profiles and PID-scoped Open/Focus/Close controls instead.

Both direct launches and generated shortcuts verify the app's bundle identity and OpenAI signing team before launch.

Requirements

  • macOS 13 or newer.
  • Swift 5.9 or newer.
  • The official Codex desktop app installed at /Applications/Codex.app.

If Codex is installed elsewhere, use the app's Select Codex.app action to point Codexer at the correct bundle.

Build And Run

Build and launch the app bundle:

./script/build_and_run.sh

Build, launch, and verify the process exists:

./script/build_and_run.sh --verify

The generated app bundle is written to:

dist/Codexer.app

The Codex desktop Run action is configured in:

.codex/environments/environment.toml

Tests

Run the test suite:

swift test

Run the installed-app lifecycle test, which opens and closes a temporary isolated profile:

CODEXER_LIVE_LIFECYCLE=1 swift test \
  --filter CodexLauncherTests/testLiveProfileCanOpenAndCloseWithoutTouchingStockInstance

Run a normal SwiftPM build:

swift build

Current test coverage includes:

  • Profile creation and duplicate slug handling.
  • Persisted-path, ownership-marker, and directory-containment validation.
  • Rename behavior that keeps profile paths stable.
  • Safe profile removal that preserves data by default.
  • Transactional destructive deletion and refusal while a profile is in use.
  • Read-only profile status scanning from Codex state/log databases.
  • Bounded output and timeout handling for external status processes.
  • Codex usage-limit parsing for 5-hour and weekly windows from the profile's authenticated Codex app-server.
  • Isolated launch generation across 100 simultaneous profile configurations.
  • Exact PID discovery, focus-without-duplicate, and profile-scoped close.
  • Opt-in live Open/Close verification against the installed official app.
  • Validation of the installed official Codex app's code signature.
  • Native, atomically replaced shortcut bundle generation.
  • Shortcut removal without deleting profile data.

Project Structure

Package.swift
Assets/
  AppIcon.png               Generated Codexer app icon source
  AppIcon.icns              macOS app icon used by the app bundle
Sources/
  Codexer/                  SwiftUI macOS app
  CodexerCore/              Profile, launcher, and shortcut logic
  CodexerShortcutLauncher/  Native helper copied into generated shortcuts
Tests/
  CodexerCoreTests/         Unit tests for core behavior
script/
  build_app.sh              Build dist/Codexer.app without launching it
  build_and_run.sh          Build, bundle, launch, and verify helper
  package_app.sh            Create shareable ZIP and DMG packages
.github/workflows/
  release.yml               Build/test/package workflow and tagged releases

Packaging And Releases

Create local shareable packages from an existing app bundle:

./script/build_app.sh
./script/package_app.sh

The package script writes:

dist/Codexer-<version>.zip
dist/Codexer-<version>.dmg

GitHub Actions builds and tests the app on pushes and pull requests. Pushing a tag that starts with v creates a GitHub Release and uploads the generated ZIP and DMG:

git tag v1.0.0
git push origin v1.0.0

Typical Workflow

  1. Launch Codexer.
  2. Click Add Profile.
  3. Enter a profile name such as Personal or Work.
  4. Select the profile and click Open. The action becomes Focus while that profile is running.
  5. Sign into the desired Codex account inside that launched instance.
  6. Click Install Shortcut to create a Dock-pinnable launcher.
  7. Repeat for additional accounts.

Use Close to quit only the selected profile. Closing a profile quits all Codex windows belonging to that profile so its Electron state can shut down cleanly.

To remove a profile safely, use Remove From List. This removes the profile from Codexer but leaves its data on disk. Use Delete Data only when you want to remove the profile's login state, Codex state, Electron data, and shortcut. Quit that profile's Codex instance first; deletion fails closed if any process is still using its directory.

Restore accepts only an unlisted direct child of Codexer's managed Profiles folder. It does not import arbitrary folders or accept paths that overlap an active profile.

Notes And Limitations

  • Codexer relies on Codex continuing to honor CODEX_HOME and --user-data-dir.
  • Isolation covers Codex configuration/authentication state and Electron user data. It is not an operating-system sandbox: instances retain access to the user's files, shell environment, network, keychain, git, and SSH credentials.
  • Existing generated shortcuts should be reinstalled after changes to shortcut naming or launcher behavior. Shortcuts created before profile identity was added to their configuration must be reinstalled before they can launch.
  • Codexer does not copy OAuth tokens between profiles. Each profile signs in independently.
  • Codexer is not an OpenAI product and does not redistribute the Codex app.

Related Open-Source Work

Codexer's lifecycle design was checked against several open-source profile and process managers:

Codexer combines those patterns with official-bundle signature validation and exact profile-path-to-PID matching.

About

A macOS launcher for isolated multi-account Codex profiles

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages