codexctl

command module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 24, 2026 License: MIT Imports: 3 Imported by: 0

README

codexctl

codexctl is a small, local-only profile switcher for Codex accounts.

codexctl login personal
codexctl login work --device-auth
codexctl import existing        # save the login Codex already has
codexctl use personal
codexctl list -v
codexctl current
codexctl show work
codexctl sync
codexctl rename personal home
codexctl remove work
codexctl logout existing

list, current, show, and doctor accept --json for scripting.

It keeps Codex's normal configuration, history, sessions, skills, and plugins in the same CODEX_HOME. Only the file-backed login cache is switched. This makes the selected account visible to the Codex CLI and other Codex clients that use the same CODEX_HOME.

Install

With Go
go install github.com/AbdelrhmanSaid/codexctl@latest

This requires Go 1.24 or newer. Make sure Go's binary directory (usually $HOME/go/bin) is on PATH.

Prebuilt binaries

Download the archive for your operating system and CPU from the latest GitHub release, extract it, and move codexctl (or codexctl.exe on Windows) to a directory on PATH. Releases are provided for macOS, Linux, Windows, and FreeBSD on x86-64 and ARM64. SHA-256 hashes are published in checksums.txt with every release.

Linux releases also include native packages:

  • Debian and Ubuntu: download the matching .deb, then run sudo apt install ./codexctl_*.deb.
  • Fedora, RHEL, and related distributions: download the matching .rpm, then run sudo rpm -i codexctl_*.rpm.
  • Alpine Linux: download the matching .apk, then run sudo apk add --allow-untrusted ./codexctl_*.apk.
  • Arch Linux: download the matching .pkg.tar.zst, then run sudo pacman -U ./codexctl_*.pkg.tar.zst.
Build locally
go build -o codexctl .

Shell completion is available through codexctl completion bash, zsh, fish, or powershell.

Updating
codexctl update --check   # report whether a newer release exists
codexctl update           # download, verify, and replace this executable
codexctl update --to 0.2.0

update downloads the release archive for the current platform from GitHub, checks its SHA-256 against the release's checksums.txt, and verifies the Ed25519 signature on that file with a public key built into the binary. A release that fails either check is never installed. The new executable is written next to the old one and renamed over it; on Windows the old file is moved aside as codexctl.exe.old and cleaned up by the next update.

Binaries installed with a Linux package or go install are told to update the same way they were installed. --force overrides that, and is also required to downgrade with --to. update never contacts the network unless you run it.

Releasing

Pushing a semantic-version tag creates a GitHub release with native archives, Linux packages, and checksums:

git tag -a v0.1.0 -m "codexctl v0.1.0"
git push origin v0.1.0

Releases are signed so that codexctl update can verify them. The Ed25519 private key lives in the CODEXCTL_SIGNING_KEY repository secret and the matching public key is embedded in internal/update/sign.go. To create a key:

go run ./tools/sign keygen -out signing.key
gh secret set CODEXCTL_SIGNING_KEY < signing.key

Then paste the printed public key into internal/update/sign.go. Binaries only trust the key they were built with, so rotate a key by publishing one release, signed with the old key, that embeds the new one.

To validate the release locally without publishing it, install GoReleaser and run:

goreleaser check
CODEXCTL_SIGNING_KEY=$(cat signing.key) goreleaser release --snapshot --clean
go run ./tools/sign verify dist/checksums.txt

Snapshot builds in CI skip signing.

How it works

Profiles are stored as private files:

~/.codexctl/
├── current
├── lock
└── profiles/
    ├── personal.json
    └── work.json

lock serializes codexctl operations. It is an OS-level file lock, so it is released automatically if codexctl crashes or is interrupted; the file itself stays in place and never needs to be removed.

codexctl login NAME runs the official codex login command with an isolated temporary CODEX_HOME. A successful login is validated, saved, and activated. A cancelled or failed login leaves the active account untouched.

codexctl use NAME atomically copies that profile to $CODEX_HOME/auth.json (normally ~/.codex/auth.json). Before switching away, it saves any token refreshes Codex wrote for the current profile. If the account ID unexpectedly changed, it refuses to overwrite the saved profile.

A switch also records a short-lived recovery marker before updating auth.json and current. If the process is interrupted between those writes, the next successful login or use completes the interrupted switch before continuing.

codexctl import NAME saves the auth.json Codex is already using as a profile and selects it, for accounts that were logged in with plain codex login. It refuses an account that is already saved under another name.

codexctl sync saves token refreshes from the active auth.json into the selected profile on demand. login and use do this automatically before switching away.

codexctl show NAME and codexctl list -v print the account ID, email, plan, and last refresh time read from the saved snapshot. Tokens and API keys are never printed.

codexctl rename OLD NEW renames a saved profile. If it is the selected profile, any token refreshes are saved first and the selection follows the new name. codexctl remove NAME deletes a saved profile. Removing the selected profile clears the selection but leaves auth.json in place, so Codex stays logged in until you use another profile.

codexctl logout NAME ends the account's session: it runs the official codex logout in an isolated temporary CODEX_HOME that holds only that profile's credentials, then deletes the profile. If the profile was selected and the active auth.json holds the same account, that file is removed too, since its tokens are no longer usable.

Because swapping auth.json only works with file-backed credentials, login and use ensure this root setting exists in $CODEX_HOME/config.toml:

cli_auth_credentials_store = "file"

Profile directories use mode 0700 and credential/state files use 0600 on POSIX systems. Credential contents are never printed. Symlinked credential and state paths are refused.

Important behavior

  • Restart already-running Codex CLI, IDE, or app processes after switching; they may retain credentials in memory.
  • Do not use codex logout to switch profiles. Logout is broader than a local file swap and can invalidate a session you intended to keep. Use codexctl logout NAME when you do want to end a specific account's session.
  • Two simultaneously running clients that use the same CODEX_HOME still share one active account. Separate CODEX_HOME directories are required for truly parallel accounts.
  • An administrator-enforced keyring credential policy can override user config; codexctl doctor catches the common local configuration problems, but cannot override managed policy.
  • auth.json contains live credentials. Do not commit, sync, or share ~/.codexctl.

License

MIT

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
internal
cli
codex
Package codex runs the official Codex CLI as a child process.
Package codex runs the official Codex CLI as a child process.
update
Package update fetches signed codexctl releases from GitHub and replaces the running executable.
Package update fetches signed codexctl releases from GitHub and replaces the running executable.
tools
sign command
Command sign manages the Ed25519 key that signs codexctl releases.
Command sign manages the Ed25519 key that signs codexctl releases.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL