Imported from Hung2124/codex-multi-profile (
SKILL.md). Install upstream withnpx skills add Hung2124/codex-multi-profile. Copyright stays with the author.
Codex Multi-Profile (Windows)
Unofficial helper for Codex Desktop on Windows when you need more than one authorized ChatGPT login and still want one shared workspace. Not for account sharing, quota bypass, or Terms-of-Use violations.
Pick an account (humans)
The product is Codex Accounts (Show-CodexAccountApp.ps1): a dark WPF window that lists profiles (masked email, last-used, depleted, sticky paths). Click a row launches Launch-CodexProfile.ps1 -FastSwitch (closes any open clone, uses saved auth.json, no password). This app does not implement chatgpt.com / device-code login; first-run still uses AuthSwap bootstrap inside Codex.
$root = "$env:LOCALAPPDATA\CodexParallelDesktop"
powershell -NoProfile -STA -ExecutionPolicy Bypass -File "$root\Show-CodexAccountApp.ps1"
# or
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action accounts
CLI route / pool / stick / depleted stay for agents.
Default: ShareLive + AuthSwap
| Piece | Where it lives |
|---|---|
| Sessions, skills, MCP, memories, projects | Always %USERPROFILE%\.codex |
| Account | profiles\<name>\auth.json, swapped into ~\.codex\auth.json at launch |
| On close | Watcher saves secondary auth back, then restores main auth.json |
| Electron UI | --user-data-dir=profiles\<name> (profile root, not a nested electron\ folder) |
Do not open the main Store Codex and a profile at the same time.
Why AuthSwap (not a second CODEX_HOME)
The Desktop app-server sometimes ignores CODEX_HOME and reads ~\.codex\auth.json anyway. A second home then shows the main account. AuthSwap puts the secondary token in the path the app actually reads.
Launch rules (verified)
- Do not run executables from
WindowsApps(Access Denied). CloneChatGPT.exefirst. - Entry point is
ChatGPT.exe.Codex.exeexits 1. Get-AppxPackage.InstallLocationcan be empty — prefer an existing local clone.- Set both
CODEX_ELECTRON_USER_DATA_PATHand--user-data-dirto the profile root. - Do not rely on
Start-Processinheriting$env:CODEX_HOME. Write a.cmdwithsetandstart. - PowerShell 5.1
Set-Content -Encoding UTF8writes a BOM. That can invalidateconfig.toml. Use[IO.File]::WriteAllText(..., UTF8Encoding $false). - Never set a persistent user-level
CODEX_HOME. - Never copy
auth.jsonbetween machines or into git.
Paths
| Item | Path |
|---|---|
| Install root | %LOCALAPPDATA%\CodexParallelDesktop |
| Shared module | CodexMultiProfile.psm1 |
| Account picker | Show-CodexAccountApp.ps1 (Desktop: Codex Accounts) |
| Profile launcher | Launch-CodexProfile.ps1 |
| Restore main | Launch-CodexMain.ps1 |
| Manager | CodexProfile.ps1 (accounts, new, list, status, doctor, pool, stick, route, depleted, layer, models, …) |
| Profiles | ...\profiles\<name>\ |
| Clone | ...\versions\<ver>\app\ChatGPT.exe |
| Shared home | %USERPROFILE%\.codex |
Commands
$root = "$env:LOCALAPPDATA\CodexParallelDesktop"
# Recommended: account picker
powershell -NoProfile -STA -ExecutionPolicy Bypass -File "$root\Show-CodexAccountApp.ps1"
# Recommended launch (AuthSwap, one named profile)
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\Launch-CodexProfile.ps1" -Name codex1
# Restore main Store Codex
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\Launch-CodexMain.ps1"
# Manager
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action new -Name codex2
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action list
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action status
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action status -AsJson
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action doctor
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action processes
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action repair
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action sync-check
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action diagnostics
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action verify
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action stop -Name codex1
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action remove -Name codex2 -Force
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action pool
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action stick -Name codex1
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action route
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action depleted -Name codex1
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action layer
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action models
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action accounts
Agent workflow
- Human wants to pick an account →
Show-CodexAccountApp.ps1(or-Action accounts). Do not treat PowerShellrouteas the product UI. - "Switch account / keep my data" → AuthSwap via
Launch-CodexProfile.ps1. - "Create another profile" →
-Action new, then launch withLaunch-CodexProfile.ps1. - Wrong account in the UI → compare emails in the two
auth.jsonfiles; fix launch (cmd wrapper); do not tell the user to log in again if profile auth is still valid. - Access Denied / empty path / exit 1 → clone
ChatGPT.exe, neverWindowsApps, never emptyInstallLocation. - After editing scripts, copy
CodexMultiProfile.psm1and the launchers into%LOCALAPPDATA%\CodexParallelDesktopand intoscripts\in this skill. Launchers import the module from$PSScriptRoot. - "Is it installed / which account is active?" →
-Action status(emails are masked) then-Action doctor/-Action verify. - "Stuck on secondary account / stale lock" →
-Action repair(close clones first). - "Bug report" / safe GitHub log →
-Action diagnosticsorRedact-LaunchTrace.ps1.
Router (opt-in, one window)
Humans pick in Codex Accounts. Agents use the actions below. Windows counterpart of b-nnett/codex-subscription-router routing, still AuthSwap (one auth.json).
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action pool
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action stick -Name codex1
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action route
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action depleted -Name codex1
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action depleted -Name codex1 -Disable
New work -> least-recently-used non-depleted profile. Same git repo -> sticky. Depleted owner -> failover. All depleted -> one message. If a Codex window is open, print the choice (do not launch a second window).
Layer and ChatGPT Web models are off by default:
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action layer
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action layer -Disable
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action models
powershell -NoProfile -ExecutionPolicy Bypass -File "$root\CodexProfile.ps1" -Action models -Disable
Layer targets the cloned ChatGPT.exe only. Models only write config.toml (no BOM) for a local Responses bridge on 127.0.0.1. This repo does not log into chatgpt.com and does not name a companion app.
Poisoned profile auth
If the user opens Codex Main while a profile is still running, restore can write the main token into profiles\<name>\auth.json.
Guards already in the scripts:
- Watcher /
Launch-CodexMainonly save profile auth when the active email differs fromauth.json.__main__ - Keep
auth.json.secondary.bak - If profile auth is missing or equals main → bootstrap login (clear active auth, force secondary sign-in)
Do not
- Copy or commit
auth.json - Open main + profile ShareLive together
- Launch
Codex.exeor aWindowsAppspath Start-Processwithout an explicit cmd/CODEX_HOME- Write
config.tomlwithSet-Content -Encoding UTF8on Windows PowerShell 5.1
Details: docs/architecture.md, docs/troubleshooting.md.