{"id":50077457,"url":"https://github.com/Ducksss/codex-profiles","last_synced_at":"2026-05-24T00:01:00.550Z","repository":{"id":353724650,"uuid":"1220652910","full_name":"Ducksss/codex-profiles","owner":"Ducksss","description":"Isolated CODEX_HOME profiles for Codex CLI/Desktop: switch accounts without copying auth.json","archived":false,"fork":false,"pushed_at":"2026-05-21T17:57:57.000Z","size":778,"stargazers_count":7,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-21T23:37:59.439Z","etag":null,"topics":["account-switcher","ai-tools","automation","bash","chatgpt","cli","codex","codex-cli","codex-desktop","codex-home","codex-profiles","developer-tools","linux","macos","openai","openai-codex","productivity","shell-script","vibe-coding"],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Ducksss.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-25T06:39:30.000Z","updated_at":"2026-05-21T17:57:09.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/Ducksss/codex-profiles","commit_stats":null,"previous_names":["ducksss/codex-profiles"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/Ducksss/codex-profiles","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ducksss%2Fcodex-profiles","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ducksss%2Fcodex-profiles/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ducksss%2Fcodex-profiles/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ducksss%2Fcodex-profiles/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Ducksss","download_url":"https://codeload.github.com/Ducksss/codex-profiles/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ducksss%2Fcodex-profiles/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33416315,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-23T22:14:44.296Z","status":"ssl_error","status_checked_at":"2026-05-23T22:14:43.778Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["account-switcher","ai-tools","automation","bash","chatgpt","cli","codex","codex-cli","codex-desktop","codex-home","codex-profiles","developer-tools","linux","macos","openai","openai-codex","productivity","shell-script","vibe-coding"],"created_at":"2026-05-22T09:00:35.929Z","updated_at":"2026-05-24T00:01:00.526Z","avatar_url":"https://github.com/Ducksss.png","language":"Shell","funding_links":[],"categories":["🖥️ AI-Native IDEs \u0026 Editors","Command Line Tools","Applications","Tools"],"sub_categories":["Tools","Development Tools"],"readme":"# codex-profiles\n\n[![CI](https://github.com/Ducksss/codex-profiles/actions/workflows/ci.yml/badge.svg)](https://github.com/Ducksss/codex-profiles/actions/workflows/ci.yml)\n[![Latest release](https://img.shields.io/github/v/release/Ducksss/codex-profiles?sort=semver)](https://github.com/Ducksss/codex-profiles/releases)\n[![npm](https://img.shields.io/npm/v/codex-profile.svg)](https://www.npmjs.com/package/codex-profile)\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n[![Shell: Bash](https://img.shields.io/badge/shell-bash-4EAA25.svg)](bin/codex-profile)\n[![Platform: macOS + Linux](https://img.shields.io/badge/platform-macOS%20%2B%20Linux-lightgrey.svg)](#platform-support)\n\nSwitch Codex CLI and Desktop accounts with isolated `CODEX_HOME` profiles\ninstead of copying `auth.json` token files around.\n\n`codex-profiles` is a small Bash wrapper around Codex's `CODEX_HOME` support.\nEach profile gets its own Codex home directory, so auth, settings, sessions,\nconnectors, plugins, caches, logs, and local state stay separated while the\nwrapper launches Codex CLI or Codex Desktop with the selected profile.\n\n```sh\ncodex-profile cli personal\ncodex-profile cli work exec \"review this repo\"\ncodex-profile app edu\n```\n\n## Why It Exists\n\nCodex already supports custom state directories through `CODEX_HOME`:\n\n```sh\nCODEX_HOME=\"$HOME/.codex-personal\" codex\nCODEX_HOME=\"$HOME/.codex-work\" codex exec \"review this repo\"\nCODEX_HOME=\"$HOME/.codex-edu\" /Applications/Codex.app/Contents/MacOS/Codex\n```\n\nThat is the right boundary, but it is awkward to type and easy to forget.\nCopying `auth.json` is worse: it moves tokens while leaving sessions, config,\nconnector state, plugins, caches, and logs shared.\n\n`codex-profile` gives the clean boundary a short command.\n\n## Why Not Swap Auth Files?\n\nAuth-file switchers only move `auth.json`. That can change who Codex logs in as,\nbut it still leaves unrelated account state in the same `CODEX_HOME`: sessions,\nconfig, plugins, connector and app caches, logs, and other local files.\n\n`codex-profile` switches the whole Codex home instead. The boundary is the same\none Codex already supports, just named and wrapped in a CLI:\n\n```text\nauth.json switcher      -\u003e one shared CODEX_HOME with swapped tokens\ncodex-profile \u003cprofile\u003e -\u003e one CODEX_HOME per profile\n```\n\nThat makes it a better fit for work, personal, education, and client accounts\nwhere local Codex state should not bleed between contexts.\n\n## Demo\n\n![codex-profiles promo frame](media/codex-profiles-saas-promo-frame.png)\n\n[Watch the short reveal video](media/codex-profiles-apple-reveal.mp4)\n\n## Highlights\n\n- Isolated Codex homes per profile.\n- CLI and Codex Desktop launch support.\n- No token copying, parsing, printing, or migration.\n- Read-only `list`, `status`, and `doctor` commands for diagnostics.\n- JSON output for automation.\n- Profile lifecycle commands: `init` and confirmed `remove`.\n- Profile-local desktop logs with private permissions.\n- Safe config cloning for known non-secret config files.\n- Bash, Zsh, and Fish completion generators.\n- Source-style self-upgrade with dry-run preview.\n- No third-party runtime dependencies.\n- Tested on macOS and Ubuntu.\n\n## Install\n\nWith npm:\n\n```sh\nnpm install -g codex-profile\n```\n\nThe npm package is `codex-profile` (singular). It installs both the\n`codex-profile` and `codex-profiles` commands. Use the singular package name;\nthe plural `codex-profiles` package on npm is a different project.\n\nWith Homebrew:\n\n```sh\nbrew install Ducksss/tap/codex-profile\n```\n\nWith npm directly from this GitHub repo:\n\n```sh\nnpm install -g github:Ducksss/codex-profiles\n```\n\nFrom source:\n\n```sh\ngit clone https://github.com/Ducksss/codex-profiles.git\ncd codex-profiles\nmake install\n```\n\nSource installs copy `bin/codex-profile` to\n`~/.local/bin/codex-profile`. Make sure `~/.local/bin` is on your `PATH`.\n\nVerify the install:\n\n```sh\ncodex-profile doctor\n```\n\n## Quick Start\n\nCreate and log in to each profile once:\n\n```sh\ncodex-profile init personal\ncodex-profile init work\ncodex-profile login personal\ncodex-profile login work\n```\n\nRun Codex CLI with a profile:\n\n```sh\ncodex-profile cli personal\ncodex-profile cli work exec \"run tests and summarize failures\"\n```\n\nRun Codex Desktop with a profile on macOS:\n\n```sh\ncodex-profile app personal ~/Dev/my-project\ncodex-profile app work\n```\n\nCheck what exists and what is logged in:\n\n```sh\ncodex-profile list\ncodex-profile status\ncodex-profile doctor\n```\n\n## How Profiles Map To Disk\n\nOnly `default` is special:\n\n```text\ndefault     -\u003e ~/.codex\n\u003cprofile\u003e   -\u003e ~/.codex-\u003cprofile\u003e\n```\n\nExamples:\n\n```text\npersonal -\u003e ~/.codex-personal\nwork     -\u003e ~/.codex-work\ndev      -\u003e ~/.codex-dev\nmain     -\u003e ~/.codex-main\nedu      -\u003e ~/.codex-edu\n```\n\nProfile names must start with a letter or number, then may contain letters,\nnumbers, dots, dashes, or underscores. You can inspect a path without launching\nCodex:\n\n```sh\ncodex-profile path personal\n```\n\n## Common Workflows\n\n### Manage Profiles\n\nCreate a profile home without launching Codex:\n\n```sh\ncodex-profile init client-a\n```\n\nRemove a profile home interactively:\n\n```sh\ncodex-profile remove client-a\n```\n\nUse `--yes` for scripts:\n\n```sh\ncodex-profile remove client-a --yes\n```\n\nUse `default` explicitly if you intend to remove `~/.codex`. Every other valid\nname removes only its own `.codex-\u003cprofile\u003e` directory.\n\n### Inspect Status\n\nHuman-readable output:\n\n```sh\ncodex-profile status\ncodex-profile status personal\ncodex-profile doctor\n```\n\nMachine-readable output:\n\n```sh\ncodex-profile status --json\ncodex-profile doctor --json\n```\n\n`status` and `list` are read-only. They report missing profiles instead of\ncreating directories for typos.\n\n### Read Desktop Logs\n\nDesktop logs live inside the selected profile home:\n\n```sh\ncodex-profile logs personal --path\ncodex-profile logs personal\ncodex-profile logs personal --tail 100\n```\n\n### Clone Safe Config\n\nCopy known non-secret config files from one profile to another:\n\n```sh\ncodex-profile clone-config personal work\ncodex-profile clone-config personal work --force\n```\n\nOnly these root-level files are considered:\n\n```text\nconfig.toml\nAGENTS.md\ninstructions.md\ncustom-instructions.md\n```\n\n`clone-config` never copies `auth.json`, sessions, plugins, logs, caches, or\ndirectories. It also refuses files with sensitive-looking key names such as\n`token`, `secret`, `password`, `credential`, or `api_key`.\n\n### Upgrade Source Installs\n\nPreview the upgrade:\n\n```sh\ncodex-profile upgrade --dry-run\n```\n\nInstall from the default project repo and branch:\n\n```sh\ncodex-profile upgrade\n```\n\nBy default, `upgrade` fetches `main` from\n`https://github.com/Ducksss/codex-profiles.git` into\n`~/.cache/codex-profile/source`, then runs `make install` with\n`PREFIX=~/.local`.\n\nUse a different install prefix or source ref:\n\n```sh\ncodex-profile upgrade --prefix /usr/local\ncodex-profile upgrade --ref v0.2.0\ncodex-profile upgrade --ref \u003ccommit-sha\u003e\n```\n\nUpgrade refuses to install a candidate with no declared version, or a candidate\nwhose declared version is older than the running `codex-profile`.\n\nIf you installed with Homebrew and do not want a source-style\n`~/.local/bin/codex-profile`, use Homebrew instead:\n\n```sh\nbrew upgrade Ducksss/tap/codex-profile\n```\n\n## Shell Completions\n\nGenerate completions for Bash, Zsh, or Fish:\n\n```sh\ncodex-profile completions bash\ncodex-profile completions zsh\ncodex-profile completions fish\n```\n\nBash example:\n\n```sh\nmkdir -p ~/.local/share/bash-completion/completions\ncodex-profile completions bash \u003e ~/.local/share/bash-completion/completions/codex-profile\n```\n\nZsh example:\n\n```sh\nmkdir -p ~/.zfunc\ncodex-profile completions zsh \u003e ~/.zfunc/_codex-profile\n```\n\nAdd the directory to `fpath` in `~/.zshrc` before `compinit`:\n\n```sh\nfpath=(~/.zfunc $fpath)\nautoload -Uz compinit\ncompinit\n```\n\n## Aliases\n\nAliases are optional, but useful for accounts you use every day:\n\n```sh\nalias codex-personal='codex-profile cli personal'\nalias codex-work='codex-profile cli work'\nalias codex-app-work='codex-profile app work'\n```\n\n## Command Reference\n\n```text\ncodex-profile app \u003cprofile\u003e [workspace]\ncodex-profile cli \u003cprofile\u003e [codex-args...]\ncodex-profile login \u003cprofile\u003e [codex-login-args...]\ncodex-profile init \u003cprofile\u003e\ncodex-profile remove \u003cprofile\u003e [--yes]\ncodex-profile status [profile]\ncodex-profile status --json [profile]\ncodex-profile path \u003cprofile\u003e\ncodex-profile logs \u003cprofile\u003e [--path|--tail [lines]]\ncodex-profile clone-config \u003csource-profile\u003e \u003ctarget-profile\u003e [--force]\ncodex-profile list\ncodex-profile doctor [--json]\ncodex-profile completions \u003cbash|zsh|fish\u003e\ncodex-profile upgrade [--dry-run] [--prefix \u003cpath\u003e] [--ref \u003cgit-ref\u003e]\ncodex-profile version\ncodex-profile --version\n```\n\n## Environment Overrides\n\n```text\nCODEX_APP                      Override Codex.app path\nCODEX_APP_BIN                  Override Codex Desktop binary path\nCODEX_CLI                      Override Codex CLI binary path\nCODEX_PROFILE_UPGRADE_REPO     Override upgrade repository\nCODEX_PROFILE_UPGRADE_REF      Override upgrade git ref\nCODEX_PROFILE_UPGRADE_CACHE    Override upgrade cache checkout\nCODEX_PROFILE_UPGRADE_PREFIX   Override upgrade install prefix\n```\n\nExamples:\n\n```sh\nCODEX_CLI=/path/to/codex codex-profile cli personal\nCODEX_PROFILE_UPGRADE_REF=v0.2.0 codex-profile upgrade --dry-run\n```\n\n## Platform Support\n\nCLI-oriented commands are Bash-based and tested on macOS and Ubuntu/Linux:\n\n```text\ncli login init remove status path logs clone-config list doctor completions upgrade\n```\n\nThe `app` command is macOS-only because it launches `Codex.app` and uses macOS\napp-control tooling to quit the running desktop app before relaunching it with a\ndifferent `CODEX_HOME`.\n\n## Desktop App Notes\n\nCodex Desktop should run one profile at a time. `codex-profile app \u003cprofile\u003e`\nasks the running Codex app to quit, waits for it to close, then launches the app\nwith the selected `CODEX_HOME`.\n\nFor predictable account switching, launch Codex Desktop through `codex-profile`\ninstead of Dock or Spotlight.\n\n## Security Model\n\n`codex-profile` does one security-sensitive thing: it sets `CODEX_HOME` before\nrunning Codex. It does not read, copy, print, parse, or migrate auth tokens.\n\n`clone-config` uses a small allowlist and refuses sensitive-looking config\nfiles. It does not inspect or rewrite Codex auth files.\n\n`upgrade` fetches and installs code from the configured git repository. The\ndefault repository is this project. `--dry-run` prints the source ref, cache\npath, and install prefix before anything changes. Do not point upgrade at a\nrepository you do not trust.\n\nSeparate Codex homes are cleaner than swapping `auth.json`, but they are not\nfull OS-level isolation. Your operating system user still shares SSH keys,\nGitHub CLI auth, browser cookies, cloud CLI credentials, npm state, and other\nexternal credentials.\n\nFor strict work/personal separation, use separate OS users.\n\n## FAQ\n\n### Is this an official OpenAI project?\n\nNo. This project is community-maintained and is not affiliated with OpenAI.\n\n### Is this the same as Codex's built-in config profiles?\n\nNo. Codex config profiles switch settings inside one `CODEX_HOME`, such as\nmodel, approval policy, sandboxing, and hooks.\n\n`codex-profiles` switches `CODEX_HOME` itself, so each account can have separate\nauth, config, sessions, plugins, logs, caches, and local Codex state.\n\n### Does it copy my tokens?\n\nNo. It does not read or copy `auth.json`. Codex itself creates and uses auth\ninside the selected `CODEX_HOME`.\n\n### Why not just swap `auth.json`?\n\nSwapping only `auth.json` leaves other Codex state shared: sessions, config,\nplugins, logs, connector/app caches, and more. Separate `CODEX_HOME` directories\nare a cleaner boundary.\n\n### Can I run two desktop profiles at once?\n\nNot safely. Codex Desktop is treated as one active profile at a time. The `app`\ncommand quits the current Codex app before launching the selected profile.\n\n### Does this isolate external tools too?\n\nNo. Your OS user still shares SSH keys, GitHub CLI auth, cloud CLIs, browser\nstate, and other non-Codex credentials.\n\n## Development\n\nRun the test suite:\n\n```sh\nmake test\n```\n\nRun ShellCheck:\n\n```sh\nmake lint\n```\n\nThe test suite covers Bash syntax, profile path mapping, install smoke tests,\nCLI/login pass-through, list/version output, npm package installation, source\nupgrades, fresh-profile status checks, hardened status discovery, private\ndesktop log placement, and missing-CLI doctor output.\n\n## Contributing\n\nIssues and pull requests are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for\nlocal setup, testing, and contribution guidelines.\n\nQuestions, workflow ideas, and launch feedback are welcome in the\n[Codex profile workflows discussion](https://github.com/Ducksss/codex-profiles/discussions/1).\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDucksss%2Fcodex-profiles","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FDucksss%2Fcodex-profiles","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDucksss%2Fcodex-profiles/lists"}