Star 历史趋势
数据来源: GitHub API · 生成自 Stargazers.cn
README.md

codex-swap (xswap)

A CLI for running Codex under different ChatGPT accounts, with usage reporting, directory mappings, portable account backups and optional shared conversation history. Inspired by the cswap run workflow from claude-swap, using the permanent account-directory approach from swapdex.

Save your current Codex login with xswap add, then use xswap switch to change the login used by a plain codex command. Saved accounts have private credential snapshots. The globally active account uses the main Codex home; explicit launches of other accounts use their separate homes. Codex owns token refresh.

Install

Supports macOS 11 or newer, Linux, WSL and native Windows on ARM64 and x86-64. Install the official Codex CLI separately and make sure codex is on PATH.

macOS and Linux (install script)

Install or upgrade the native executable with one command, without Homebrew, Rust or administrator access:

curl -fsSL https://github.com/maddada/codex-swap/releases/latest/download/install.sh | sh

The script selects the build for your computer (native Apple Silicon even from a Rosetta shell; static musl on Linux), verifies the archive against the release’s SHA-256 checksums and checks xswap --version before installing xswap to ~/.local/bin. LICENSE and THIRD_PARTY_NOTICES.md go to ~/.local/share/doc/codex-swap (or $XDG_DATA_HOME/doc/codex-swap). It uses curl or wget, needs no terminal input and never edits shell profiles; it prints a note when the directory is not on PATH. Set XSWAP_VERSION=0.3.4 for a specific release or XSWAP_INSTALL_DIR=/path/to/bin for another directory.

The script writes .xswap-install-receipt.json beside the executable, recording the method, directory, version and the executable’s SHA-256. xswap upgrade reruns the same installer for that directory when the receipt matches the running executable.

Homebrew (recommended)

Run this command to install on macOS and linux (requires homebrew to be installed)

brew tap maddada/tap && brew trust --formula maddada/tap/codex-swap && brew install maddada/tap/codex-swap

This command adds the tap, marks it as trusted, then installs codex-swap.

Homebrew installs a prebuilt xswap executable, with LICENSE and THIRD_PARTY_NOTICES.md in its documentation directory. Rust and Cargo are not required. Linux releases are statically linked with musl, so they do not depend on a particular glibc version.

To update:

xswap upgrade

For Homebrew installations on macOS and Linux this runs brew upgrade maddada/tap/codex-swap; install-script installations rerun the install script for the same directory. xswap update and xswap --upgrade are also accepted, matching cswap.

Windows (PowerShell)

Install or upgrade the native executable with one command:

irm https://github.com/maddada/codex-swap/releases/latest/download/install.ps1 | iex

The installer selects x64 or ARM64, verifies the archive against the release’s SHA-256 checksums and installs the executable, LICENSE and THIRD_PARTY_NOTICES.md to %LOCALAPPDATA%\Programs\codex-swap, adding it to your user PATH. Upgrades replace the executable and notices together, restoring the previous files if replacement fails. No Cargo or administrator access is needed for installation. Open a new terminal afterward. xswap upgrade runs the same installer for the directory containing your current executable.

Managed accounts share configuration through symbolic links. Enable Windows Developer Mode (or grant your account the Create symbolic links privilege) before creating or importing managed accounts or enabling shared history. Existing adopted homes can run without shared links. npm’s codex.cmd launcher is supported. Windows batch launchers use Rust’s batch-file handling through cmd.exe, which can reject special-character or multiline arguments. Use a native codex.exe via --codex-bin for those prompts.

For an explicit version or installation directory, download the script and run it locally:

Invoke-WebRequest https://github.com/maddada/codex-swap/releases/latest/download/install.ps1 -OutFile install.ps1
.\install.ps1 -Version v0.3.1 -InstallDir "$env:LOCALAPPDATA\Programs\codex-swap"

Use -NoPathUpdate to manage PATH yourself. The installer also upgrades existing installations; a running old executable is retired and cleaned up by a later installer run after it exits.

Download a binary

Download the archive for your computer and SHA256SUMS from GitHub Releases:

ComputerArchive target
macOS Apple Siliconaarch64-apple-darwin
macOS Intelx86_64-apple-darwin
Linux / WSL ARM64aarch64-unknown-linux-musl
Linux / WSL x86-64x86_64-unknown-linux-musl
Windows ARM64aarch64-pc-windows-msvc
Windows x64x86_64-pc-windows-msvc

Verify the downloaded archive against its entry in SHA256SUMS using shasum -a 256 on macOS, sha256sum on Linux or Get-FileHash -Algorithm SHA256 in PowerShell. Unix archives contain xswap; Windows ZIP archives contain xswap.exe. Extract the executable into a directory on PATH and retain the accompanying LICENSE and THIRD_PARTY_NOTICES.md. Any product embedding or redistributing the executable must include these documents. No compiler is needed.

Build from source

Developers building from source need Rust 1.85 or newer:

cargo install --git https://github.com/maddada/codex-swap --locked
xswap --version

From a checkout:

cargo install --path . --locked

Cargo installs the xswap executable into ~/.cargo/bin. To use ~/.local/bin instead, add --root ~/.local to the install command.

On macOS and Linux, xswap upgrade first recognises install-script installations by their receipt, then detects Cargo installations and runs cargo install --git https://github.com/maddada/codex-swap --locked --force --root <original-root>, including for installations originally built with --path. Detection follows executable symlinks and preserves custom install roots. Homebrew installations use Homebrew without requiring Cargo. An unrecognized Unix installation prints manual upgrade instructions and exits with status 1; a missing package manager also exits with status 1. Package-manager output and exit status are preserved, and upgrading does not initialize accounts or launch Codex.

Set up accounts

Close existing Codex sessions. Sign into the first account using Codex, then save it after the login command exits:

codex login
xswap add --alias personal

Before signing into another account, save the current account again to capture any credentials Codex refreshed. Then register the new login:

xswap add
codex login
xswap add --alias work
xswap list

add snapshots the current file-based ChatGPT credentials into a private managed account home. Changing the normal Codex login afterward does not overwrite the saved account. Saving an already registered identity refreshes that account’s saved credentials rather than creating a duplicate slot. Existing aliases and directory mappings stay attached to the account. After reauthentication, run xswap add again to save the replacement credentials. A direct codex login replaces the previous main-home login; xswap cannot recover refreshed credentials that were overwritten before they were saved.

The original account means the first saved account from the main Codex home. xswap switch default restores it. Existing 0.2 registries preserve their original account’s slot and alias when moving its credentials from an adopted main home into a managed snapshot.

As a convenience, xswap can also open Codex’s sign-in flow directly in a new account home:

xswap add --login --alias secondary --share-history
# On a headless computer:
xswap add --login --alias another --share-history --device-auth

Enter the new account’s email when prompted, or pass --email user@example.com, then choose that account in the browser. xswap verifies the returned email and rejects accounts already registered. The slot is saved only after login succeeds; cancellation or a mismatched email leaves saved accounts unchanged.

To reconnect an existing account:

xswap login 2

You can choose an explicit slot or register a login from another Codex home:

xswap add --slot 5 --alias another
xswap add --home ~/.codex-profiles/work --alias work

Email selection is case-insensitive. If the same email belongs to multiple workspaces, select a slot number or unique alias.

Aliases are 1-64 ASCII letters, digits, dots, hyphens or underscores. They cannot start with a hyphen, be a number or be default; aliases are unique regardless of case. To repair an older alias beginning with a hyphen, use its slot number: xswap rename 2 work-team.

Run, resume and fork

xswap run personal --share-history
xswap run work --share-history
xswap run 2 --share-history -- resume SESSION_ID
xswap run work --share-history -- fork SESSION_ID
xswap run user@example.com --share-history -- --model MODEL "Your prompt"

Everything after -- is passed as individual arguments to Codex. Unix and native Windows .exe launches do not use a shell; Windows .cmd/.bat launchers have the batch-file limitations described above. xswap preserves the working directory, terminal and Codex exit status. On Windows, Codex and its descendants are tied to the launcher’s lifetime: closing or killing xswap ends that spawned process tree. It does not add permission-bypass flags. If you want those, put them in your own wrappers:

x1() { xswap run personal --share-history -- --yolo "$@"; }
xw() { xswap run work --share-history -- --yolo "$@"; }
xr() { x1 resume "$@"; }
xf() { x1 fork "$@"; }

Account selection removes inherited OPENAI_API_KEY, CODEX_API_KEY, CODEX_ACCESS_TOKEN and OPENAI_ACCESS_TOKEN from the child environment. Registered accounts use Codex's file credential backend. Overrides of that backend, or of sqlite_home while sharing history, are rejected rather than silently changing the selected account or conversation store. Other Codex arguments are forwarded unchanged.

Switch the global Codex login

Exit existing Codex sessions, then switch:

xswap switch work
codex                         # now uses work
xswap switch personal
xswap switch                  # next complete, enabled account
xswap switch default           # restore the original saved account
xswap --status --json          # cswap-compatible spelling
xswap --switch-to 1            # cswap-compatible spelling

switch saves the latest outgoing main-home credentials before restoring the selected account into the main home’s regular auth.json. It also sets the saved default for future xswap run launches. Self-switching keeps the live credentials, including refreshes Codex has already performed. The command does not create an auth symlink or refresh tokens itself.

Existing Codex processes cache authentication. Before replacing the global login, xswap conservatively refuses while it detects a running Codex process for your user, including independently launched Codex sessions and sessions using another account home. In a terminal xswap lists those processes and offers to end them; --stop-codex ends them without asking, and XSWAP_STOP_CODEX=never always refuses instead. Restart Codex after switching. The check detects existing processes, but a new external launch does not share xswap’s lock. Keep Codex closed until add or switch finishes so it cannot write cached credentials during the operation.

On Windows, the Codex desktop app must also exit completely before a global switch. Recent Microsoft Store builds run as ChatGPT.exe inside the OpenAI.Codex package; xswap checks that package path to distinguish Codex from the separate ChatGPT app. Run the switch from an external PowerShell window, then reopen Codex desktop and start new CLI sessions:

xswap switch 2
codex login status

xswap run 2 selects account 2 only for that CLI launch; it does not change the desktop account. list showing present means that local credentials exist, not that the server accepts them. Check a saved account with xswap usage 2. If its credentials are rejected, reconnect that account with xswap login 2, complete the browser sign-in for the matching email, and retry. Avoid codex logout when switching: use the saved accounts instead.

If Windows denies process inspection, xswap reports the blocking PID and leaves the global login unchanged. Close that process, or run the external PowerShell window with the same privileges as that process. This can happen when an elevated terminal is open alongside a normal terminal.

status reports the identity currently installed in the main Codex home; launchDefault separately reports the saved choice for xswap run. Signing into another account directly with codex login can change the global login without changing that saved choice. Run xswap add to save the new login, or xswap switch ACCOUNT to restore a saved account.

Explicit xswap run work and directory mappings select an account for that launch without switching the global login. An explicit xswap run default selects the saved original account, even when a different account is globally active.

An invalid, incomplete or unsupported login in the main Codex home does not block listing, launching, reconnecting or exporting an account with a separate saved home. xswap reports a main-login diagnostic on stderr and uses the selected account's own credentials unless a valid main identity positively matches it. status still reports main-home errors, and global switching refuses to replace an unrecognized main login. Entries whose saved home is the main home still report errors from that source. Home aliases resolve to their physical destinations so leases and main-home replacement checks apply to the same directory.

Directory mappings

xswap map work ~/projects/company
xswap map personal ~/projects/company/personal-tool
xswap map                          # list mappings
xswap run                          # choose the mapping for this directory
xswap unmap ~/projects/company/personal-tool

A mapping applies to its directory and all subfolders. The nearest mapped ancestor wins. Paths are canonicalized, so a symlink to the same project uses the same mapping. Omit the directory in map ACCOUNT or unmap to use the current directory. unmap removes only the exact directory’s mapping; removing a nested mapping reveals its parent’s mapping again.

Selection order is an explicit xswap run ACCOUNT, then the nearest directory mapping, then the saved global default. xswap run default explicitly chooses the saved original account. status reports the installed main-home login; switch updates it and the saved launch default. Mapping default requires the original account to be saved first with xswap add.

Mappings stay attached to their account when you rename aliases or move/swap slots. Removing an account clears its mappings. If a mapped account is disabled, a bare launch fails with a clear message instead of choosing another account.

Usage and pacing

xswap usage                        # saved global default
xswap usage work
xswap usage --all
xswap usage --all --json

Usage reports each available Codex quota window’s percentage used and remaining, duration, reset timestamp and time until reset. It also includes additional model-specific or code-review windows and extra-use credits when the service reports them. A weekly window is identified by its reported duration even when Codex sends it in the primary slot.

Malformed optional model limits are skipped while healthy core and supplementary windows remain available. Console output shows a warning, and JSON includes usage.warnings when supplementary data was skipped. Warnings identify the field or entry number and validation failure without including response contents. A missing or null additional_rate_limits field produces no warning; malformed core quotas still fail the account report.

Pacing estimates end-of-window usage from the amount used and time elapsed. ahead means at least 10% projected quota remains; on_track means less than 10% remains; behind means the quota is projected to run out before reset. An exhaustion estimate appears only when it precedes reset. Pacing is unavailable for zero usage, a missing/expired reset window, or until at least 60 seconds and 1% of the window have elapsed. It is an estimate of a changing usage rate.

The API request and pacing follow OpenUsage. xswap reads the account’s current Codex access token and account ID to request https://chatgpt.com/backend-api/wham/usage. Codex still owns token refresh. If a token is expired, run Codex for that account to refresh it or use xswap login ACCOUNT. list and status remain local and make no usage requests. --all includes disabled accounts and reports account failures individually; it exits unsuccessfully if any report fails while preserving successful reports in the output.

Manage accounts

xswap rename work company
xswap rename company --clear
xswap move 2 5                     # swaps if slot 5 is occupied
xswap swap 1 5
xswap disable 5
xswap enable 5

Renaming, enabling, disabling, moving and swapping work while that account's Codex sessions run. Aliases must be unique, ignoring case. Moving or swapping changes only slot numbers, preserving account homes, credentials, directory mappings and the account selected as global default. disable prevents implicit selection, rotation and choosing that account as a new mapping. An explicit switch or run can still select a disabled account. It does not erase credentials, stop running sessions or remove a saved default/mapping. Explicit commands such as xswap run 5 still work; a disabled implicit choice produces an error until you enable it or explicitly select another account.

Back up and migrate accounts

xswap export accounts-backup.json
xswap export work-backup.json --account work
xswap import accounts-backup.json
xswap import accounts-backup.json --remap-slots

Backups contain plaintext login credentials. xswap creates a new private JSON file and refuses to overwrite an existing file. Keep backups private and transfer them securely. The backup includes account credentials, aliases, slot numbers, enabled state, history-sharing preferences and the selected default. It excludes conversation history, configuration files, directory mappings and machine-local paths.

Import creates fresh managed account homes and validates all accounts before saving the registry. Imported shared settings/history use the destination computer’s main Codex home. Duplicate identities or aliases are refused. Occupied slots are refused unless --remap-slots is provided; remapping allocates free slots and prints the assignments. Failed validation leaves the saved registry unchanged and removes staged credentials. An import restores its backed-up launch default into an empty registry; an established registry keeps its existing launch default. Import does not change the installed global Codex login or redefine the destination’s original account. Use xswap switch ACCOUNT when you want to activate an imported account globally.

If saving the registry fails during import or add --login, xswap restores the previous registry before removing the new account homes. If that restoration also fails, xswap retains the new homes and reports their paths for recovery.

Export reads the latest main-home credentials for the globally active account and the saved home for inactive accounts. It works while that account's Codex sessions run. Imported credentials do not invalidate the original copy, but Codex’s refresh-token behavior still applies when using copies on multiple machines.

What is shared

New managed homes share existing main-home settings and customizations: config.toml, named *.config.toml profiles, AGENTS.md, AGENTS.override.md, skills, hooks, hooks.json, rules and agents. These are symlinks, so edits are shared. Adopted homes keep their own configuration.

Managed launches also preserve relative model_instructions_file, model_catalog_json, experimental_compact_prompt_file and agent role config_file references from the main config and selected profile. Referenced files are linked within the account home; agent role directories are linked so nested references retain the role file's base. Put relative role files in a subdirectory such as agents/, or use an absolute path. Active references that require writing outside the managed home, root-level relative role files, account runtime paths and conflicting destination files are refused with guidance. Home references overridden by enabled project config or CLI settings are left to Codex's higher layer. Runtime aliases are checked against the account filesystem, including Codex's default log directory. Missing assets keep a link to their source; Codex decides whether the effective settings require them. Source settings remain editable through the existing shared config links.

Asset linking inspects user, selected-profile, project and CLI settings. If a system config, legacy managed config or macOS managed preference contains file paths, runtime locations, project-root markers or trust entries, relative user assets are conservatively refused because those controlled layers can change the projection. Use absolute file references in the shared config or launch Codex directly. xswap does not reproduce Codex's full managed-policy loader.

Help/version requests and exec --ignore-user-config skip user-asset inspection, as Codex does; arguments after the forwarded -- remain literal. On case-insensitive filesystems, new links with non-ASCII relative path components, or non-ASCII runtime locations, are conservatively refused because native Unicode aliases can overlap private account state. Use absolute asset references for those paths. Safe Unicode asset paths remain supported on case-sensitive filesystems.

New login and reauthentication copy configs independently and resolve these file references against their original home. Native login can write its staging config without changing source settings, credentials or conversations. Adopted homes retain their own configuration base.

--share-history enables sharing with the main Codex home for:

ItemPurpose
sessions/Conversation transcripts and resume/fork
archived_sessions/Archived transcripts
session_index.jsonlSession names and lookup
history.jsonlPrompt history
thread-writer-locks/One active writer per conversation across accounts
SQLite state directoryThread discovery and related persistent state

The SQLite directory is selected through Codex's sqlite_home configuration, keeping databases and their WAL/SHM files together. If the main config.toml specifies sqlite_home, xswap uses it; otherwise it uses the main Codex home. Paths expand bare ~ and ~/... against the user home (~\... is also supported on Windows, using its native profile directory); other relative paths resolve against the main Codex home. . and .. are normalized without creating the destination. An inherited CODEX_SQLITE_HOME is not used as the sharing anchor. Account credentials, logs and account-local runtime state remain in their account home. History sharing is remembered once enabled.

Enable sharing when adding an account, before it creates private history. If an adopted or previously private home already contains history at these paths, xswap refuses to overwrite it. Preserve and merge that history explicitly before linking it, or keep that home private. Existing links must point to the chosen main home. xswap also refuses divergent config files or links rather than erasing them. If a Codex operation replaces a shared symlink with a real file, preserve/merge that file before the next shared launch; xswap detects the divergence.

Sharing means conversations are available to all the accounts you opt in. Resuming a conversation sends its context using the newly selected account. Sharing across Claude and Codex is not supported; this tool manages Codex only.

Reauthenticate and remove

xswap login work
xswap login work --device-auth
xswap remove work

Reauthentication shows the expected saved account and opens a fresh Codex sign-in. Choosing the wrong browser account or cancelling leaves existing credentials unchanged. Retry the same xswap login ACCOUNT command and select the intended account; this also repairs a saved home left with another account’s credentials by an older version. A successful sign-in preserves the slot, alias and mappings.

Reauthentication works while Codex sessions on that account keep running: the new login replaces the same account's credentials, and running sessions pick it up the next time they refresh their token. Replacing a main-home login that belongs to a different account still requires existing Codex processes to be closed first. Removal also works while that account's sessions run, since it keeps the account's files. Other accounts remain available during login.

remove unregisters the account and prints its retained directory. It does not delete credentials or history, and does not log out Codex. Removing the selected launch default returns future launches to the saved original account when available. Removal does not rewrite the installed global login. Slot numbers are not automatically reused.

Configuration and cleanup

xswap config
xswap config path
xswap config get codex-bin
xswap config set codex-bin /path/to/codex
xswap config set default-account work
xswap config unset codex-bin
xswap config unset default-account

The supported preferences are codex-bin (default codex) and default-account (default default, the saved original account). Preferences live in the registry shown by config path. config set default-account ACCOUNT performs the same global switch as xswap switch ACCOUNT, including its running-Codex guard. config unset default-account switches back to the saved original account. The preference stores a slot so renames and moves keep selecting the same account. config get and config list show the saved preference or its default. For launches/login, executable selection is --codex-bin, then XSWAP_CODEX_BIN, then the saved preference, then codex on PATH. A relative executable path saved by config set is resolved when you set it.

To erase xswap’s registry, preferences, mappings and managed account credentials/history:

xswap purge
# Noninteractive, explicitly confirm the deletion:
xswap purge --yes

purge requires typing purge at its interactive prompt or passing --yes. While Codex sessions or sign-ins still use an xswap account, purge names those processes and, in a terminal, offers to end them (--stop-codex ends them without asking). It deletes the managed accounts/ tree, including homes retained by earlier remove commands, and abandoned sign-in staging created with the current xswap provenance marker. The marker binds staging to its filesystem directory identity; login-*/new-login-* names alone never authorize deletion. Unmarked legacy staging or unrelated folders with those prefixes stop purge before confirmation: inspect the reported directory and move it outside the data directory before retrying, or remove it manually only after confirming it is abandoned sign-in data.

Original and adopted Codex homes, and the targets of shared settings/history links, remain intact. Purge refuses if a cleanup directory overlaps an original/adopted home, or an account/sign-in has a live xswap lease. Staging must be owned real directories inside the private data root; links and invalid candidates cause an error. Sign-in staging stays leased through credential saving; interrupted launchers retain that lease in their Unix child, and Windows terminates the child with the launcher.

Before deletion, staging is moved into a fresh private quarantine and its captured filesystem identity is verified there. A changed object or cleanup failure is retained at the reported quarantine path for manual recovery, and a remaining quarantine stops subsequent purge attempts. This narrows replacement races at the original staging path; advisory leases and private quarantine do not defend against hostile code running as the same OS user and mutating the quarantine itself.

JSON preserves managedHomesRemoved and reports staging separately as loginStagingHomesRemoved. Advisory lock files remain so concurrent processes keep using the same locks. The installed executable is retained; use Homebrew or your installer directory to uninstall it separately.

JSON interface for integrations

xswap list --json
xswap status --json
xswap switch work --json
xswap add --alias personal --json
xswap remove work --json
xswap map --json
xswap usage --all --json
xswap config get codex-bin --json

Successful JSON operations emit one object to stdout; login messages and diagnostics go to stderr. Account objects contain:

{
  "number": 2,
  "alias": "work",
  "email": "user@example.com",
  "accountId": "account-id",
  "userId": "chatgpt-user-id",
  "plan": "pro",
  "home": "/path/to/effective/codex/home",
  "savedHome": "/path/to/saved/account/home",
  "managed": true,
  "enabled": true,
  "shareHistory": true,
  "isDefault": false,
  "loginStatus": "present"
}

Every response has schemaVersion: 1. list contains accounts; add contains account; status and switch contain active, defaultHome and usesOriginalDefault; remove contains removed and retainedHome. active describes a saved account matching the actual main-home login, or is null when that login does not match a registered account. launchDefault reports the separately saved launch choice. Each account’s home is its effective credential/launch home (the main home when globally active); savedHome is its stored snapshot directory. Use home when reading current authentication or usage.

loginStatus is present, login_required, invalid_credentials, or identity_changed. present means structurally valid credentials exist locally; it does not promise that the server will accept the token or that quota remains. Identity fields can be null before login completes. Console and JSON status output omit tokens; export writes credentials only to the requested backup file. No command rotates tokens itself. Integrations must tolerate additional fields in future versions.

xswap follows Codex's authentication-mode precedence: explicit chatgpt permits stored credentials for other modes, but a missing/null mode with a non-null API key, personal access token, or Bedrock credential is rejected. Legacy ChatGPT files with missing/null mode and missing/null material for those other modes remain supported. list marks incompatible saved snapshots invalid_credentials. Incompatible main-home authentication makes status and switch return an authentication error. Use xswap login <slot-or-alias> to sign in with the registered ChatGPT identity. Credentials and account metadata stay in place until a verified login succeeds.

usage performs an on-demand request. xswap runs no daemon or proxy and does not automatically switch accounts near quota limits. Continuous polling and automatic switching policy can remain in a consuming application such as gxserver. A consumer switches a session by stopping that session at an appropriate point, then launching the chosen account with resume and the same session ID.

Storage and authentication scope

On macOS/Linux, the registry defaults to $XDG_DATA_HOME/codex-swap when XDG_DATA_HOME is absolute, otherwise ~/.local/share/codex-swap. On native Windows it defaults to %LOCALAPPDATA%\codex-swap. It contains accounts.json, permanent account directories, and advisory lock files. Registry writes are atomic. On Unix, registry/account directories use mode 0700 and registry/lock files use mode 0600; Windows uses owner-only ACLs. Codex writes its own auth.json credentials. Protect this runtime directory like your normal Codex home.

Option / environmentMeaning
--data-dir / XSWAP_HOMESeparate xswap registry and managed homes
--codex-home / XSWAP_CODEX_HOMEMain Codex login, configuration and history home
--codex-bin / XSWAP_CODEX_BINCodex executable, default codex on PATH

On first use, the main home defaults to CODEX_HOME, then ~/.codex (%USERPROFILE%\.codex on Windows). It is persisted on the first registry mutation, so an inherited account-specific CODEX_HOME does not subsequently move the sharing anchor. A different explicit main home requires a different registry.

xswap manages file-based ChatGPT logins. New managed accounts select that backend explicitly through the official login command. It does not import OS-keyring/auto credentials, API-key logins or externally managed tokens. For a keyring-based existing setup, use xswap add --login to create an independent login instead of copying a potentially stale auth.json. Managed enterprise requirements still apply through Codex itself.

Saved logins match by workspace (accountId) and stable ChatGPT member (userId); email and plan changes do not create a new account when both user IDs are known. Older logins or registries without a user ID require a shared nonempty email. Registry metadata stays in place, and a safely matched save, login or switch fills in the user ID. Missing owner evidence or multiple legacy matches require repairing the registration; xswap never assigns the current main-home login to an unknown saved owner.

Older registered homes physically separate from the main home resolve their user ID in memory from their saved identity token only when its workspace and known nonempty email match the registry. This includes adopted homes outside the store. Read-only commands leave the registry and credentials unchanged. Missing, unreadable or mismatched hints cannot match an installed main login; matching email-only legacy tokens retain their fallback. Owner labels may survive an unusable authentication mode, but using credentials still requires a complete ChatGPT login.

For an unresolved legacy slot, including one without a matching saved snapshot hint, keep the old slot and register the intended owner with xswap add --login --email owner@example.com --slot UNUSED_SLOT. Set its alias and directory mappings explicitly with rename, map and unmap; moving or swapping slots keeps mappings attached to their existing accounts. The old credentials and metadata remain until you explicitly use remove. Resolve multiple matching legacy registrations explicitly before retrying; remove retains credential homes.

Development

cargo fmt --check
cargo test --locked
cargo clippy --all-targets -- -D warnings
cargo build --release --locked

See THIRD_PARTY_NOTICES.md for reference-code attribution. The project is MIT licensed.

关于 About

Rust CLI for account-specific Codex launches with shared conversation history

语言 Languages

Rust89.3%
PowerShell6.2%
Python3.1%
Shell1.5%

提交活跃度 Commit Activity

代码提交热力图
过去 52 周的开发活跃度
69
Total Commits
峰值: 53次/周
Less
More

核心贡献者 Contributors