codex-accounts 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. codex_accounts-0.1.0/.gitignore +66 -0
  2. codex_accounts-0.1.0/CHANGELOG.md +31 -0
  3. codex_accounts-0.1.0/CODE_OF_CONDUCT.md +29 -0
  4. codex_accounts-0.1.0/CONTRIBUTING.md +97 -0
  5. codex_accounts-0.1.0/LICENSE +21 -0
  6. codex_accounts-0.1.0/PKG-INFO +238 -0
  7. codex_accounts-0.1.0/README.md +185 -0
  8. codex_accounts-0.1.0/README.zh-CN.md +159 -0
  9. codex_accounts-0.1.0/SECURITY.md +54 -0
  10. codex_accounts-0.1.0/completions/_codex-accounts +84 -0
  11. codex_accounts-0.1.0/completions/codex-accounts.bash +57 -0
  12. codex_accounts-0.1.0/docs/add-account.md +156 -0
  13. codex_accounts-0.1.0/docs/auto-refresh.md +151 -0
  14. codex_accounts-0.1.0/docs/faq.md +121 -0
  15. codex_accounts-0.1.0/docs/installation.md +95 -0
  16. codex_accounts-0.1.0/docs/internals/codex-app-internals.md +244 -0
  17. codex_accounts-0.1.0/docs/internals/codex-rs-api-map.md +461 -0
  18. codex_accounts-0.1.0/install.sh +159 -0
  19. codex_accounts-0.1.0/packaging/com.codex-accounts.refresh.plist +51 -0
  20. codex_accounts-0.1.0/pyproject.toml +101 -0
  21. codex_accounts-0.1.0/scripts/install-launchagent.sh +46 -0
  22. codex_accounts-0.1.0/src/codex_switch/__init__.py +6 -0
  23. codex_accounts-0.1.0/src/codex_switch/__main__.py +8 -0
  24. codex_accounts-0.1.0/src/codex_switch/accounts.py +265 -0
  25. codex_accounts-0.1.0/src/codex_switch/api.py +144 -0
  26. codex_accounts-0.1.0/src/codex_switch/cli.py +532 -0
  27. codex_accounts-0.1.0/src/codex_switch/config.py +96 -0
  28. codex_accounts-0.1.0/src/codex_switch/stats.py +139 -0
  29. codex_accounts-0.1.0/src/codex_switch/utils.py +302 -0
  30. codex_accounts-0.1.0/tests/__init__.py +0 -0
  31. codex_accounts-0.1.0/tests/conftest.py +131 -0
  32. codex_accounts-0.1.0/tests/test_accounts.py +100 -0
  33. codex_accounts-0.1.0/tests/test_cli.py +68 -0
  34. codex_accounts-0.1.0/tests/test_utils.py +83 -0
@@ -0,0 +1,66 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ dist/
9
+ *.egg-info/
10
+ *.egg
11
+ .eggs/
12
+ .pytest_cache/
13
+ .mypy_cache/
14
+ .ruff_cache/
15
+ .coverage
16
+ .coverage.*
17
+ coverage.xml
18
+ htmlcov/
19
+ .tox/
20
+ .nox/
21
+
22
+ # Virtual environments
23
+ .venv/
24
+ venv/
25
+ env/
26
+ ENV/
27
+ .python-version
28
+ .envrc
29
+ .direnv/
30
+
31
+ # Editors / OS
32
+ .idea/
33
+ .vscode/
34
+ *.swp
35
+ *.swo
36
+ .DS_Store
37
+ Thumbs.db
38
+ *.orig
39
+
40
+ # Local artifacts
41
+ *.log
42
+ /tmp/
43
+ .scratch/
44
+ .cache/
45
+ .hypothesis/
46
+
47
+ # User-specific overrides committed by accident
48
+ codex-switch.local.*
49
+
50
+ # Secrets / local auth snapshots
51
+ .env
52
+ .env.*
53
+ auth.json
54
+ *.pem
55
+ *.p12
56
+ *.key
57
+
58
+ # Local Codex data copies accidentally brought into the repo
59
+ .codex/
60
+ .codex-accounts/
61
+
62
+ # Local databases and log exports used during debugging
63
+ *.db
64
+ *.sqlite
65
+ *.sqlite3
66
+ *.jsonl
@@ -0,0 +1,31 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] - 2026-05-30
11
+
12
+ Initial open-source release. The project began as a single-file Bash
13
+ script for personal use; this version is a from-scratch rewrite as a
14
+ clean Python package.
15
+
16
+ ### Added
17
+ - Python package `codex_switch` with stdlib-only dependencies.
18
+ - Subcommands: `list`, `current`, `info`, `save`, `use`, `init`, `note`,
19
+ `rename`, `delete`, `stats`, `quota`, `refresh`, `doctor`.
20
+ - Two swap modes (`AUTH` and `FULL`) selectable via `--no-share-sessions`.
21
+ - Glob-based file matching (`state_*.sqlite`, `logs_*.sqlite`) so Codex
22
+ schema bumps no longer require code changes.
23
+ - Account-name validation against `^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$`.
24
+ - Automatic `chmod 0700` on accounts home and per-account directories.
25
+ - LaunchAgent template for the daily `refresh` cron job.
26
+ - Shell completions for bash and zsh.
27
+ - Pytest suite with isolated `CODEX_HOME` / `CODEX_SWITCH_HOME` fixtures.
28
+ - GitHub Actions CI matrix on macOS and Ubuntu.
29
+
30
+ [Unreleased]: https://github.com/wikty/codex-accounts/compare/v0.1.0...HEAD
31
+ [0.1.0]: https://github.com/wikty/codex-accounts/releases/tag/v0.1.0
@@ -0,0 +1,29 @@
1
+ # Code of Conduct
2
+
3
+ This project follows version 2.1 of the **Contributor Covenant**, which is
4
+ the de-facto community standard for open-source projects.
5
+
6
+ The full text is available at:
7
+ <https://www.contributor-covenant.org/version/2/1/code_of_conduct/>
8
+
9
+ ## TL;DR
10
+
11
+ - Be welcoming, patient, and respectful in every interaction — issues,
12
+ pull requests, discussions, code reviews, chat.
13
+ - Critique code, not contributors. Assume good intent and ask for
14
+ clarification before escalating.
15
+ - Off-topic, personal, or hostile content has no place in this
16
+ repository.
17
+
18
+ ## Reporting
19
+
20
+ If you believe someone has acted contrary to this Code of Conduct, please
21
+ open a private report through GitHub's "Report content" flow on the
22
+ relevant issue, comment, or pull request. Maintainers will review and
23
+ respond as quickly as we can.
24
+
25
+ ## Enforcement
26
+
27
+ Maintainers may, at their discretion, remove comments, close issues or
28
+ pull requests, or block contributors who repeatedly violate this Code of
29
+ Conduct after a warning.
@@ -0,0 +1,97 @@
1
+ # Contributing to codex-accounts
2
+
3
+ Thanks for considering a contribution! This project is small enough that
4
+ process can stay light — please follow the conventions below and we'll
5
+ keep moving fast.
6
+
7
+ ## Quick dev loop
8
+
9
+ ```bash
10
+ git clone https://github.com/wikty/codex-accounts.git
11
+ cd codex-accounts
12
+
13
+ # Set up a virtualenv and install in editable mode with dev extras
14
+ python3 -m venv .venv
15
+ source .venv/bin/activate
16
+ pip install -e ".[dev]"
17
+
18
+ # Install git hooks
19
+ pre-commit install
20
+
21
+ # Run the test suite
22
+ pytest
23
+
24
+ # Lint
25
+ ruff check .
26
+ ruff format --check .
27
+
28
+ # Run the full local gate (including secret scanning)
29
+ pre-commit run --all-files
30
+ ```
31
+
32
+ The CLI is then available as `codex-accounts` inside the venv. It reads
33
+ its paths from `CODEX_HOME` and `CODEX_SWITCH_HOME` env vars, so you can
34
+ point it at a sandbox while iterating:
35
+
36
+ ```bash
37
+ export CODEX_HOME=/tmp/cs-sandbox/codex
38
+ export CODEX_SWITCH_HOME=/tmp/cs-sandbox/accounts
39
+ mkdir -p "$CODEX_HOME" "$CODEX_SWITCH_HOME"
40
+ codex-accounts doctor
41
+ ```
42
+
43
+ ## Code style
44
+
45
+ - **Python 3.9+** with `from __future__ import annotations`.
46
+ - **stdlib only** in the runtime package. Dev-time deps belong in the
47
+ `dev` extra of `pyproject.toml`.
48
+ - Type hints on every public function. Internal helpers are encouraged
49
+ to have them too.
50
+ - Run `ruff check` and `ruff format` before opening a PR.
51
+ - Run `pre-commit run --all-files` before opening a PR when you've touched
52
+ config, docs, or shell scripts.
53
+ - Comments explain *why*, not *what*. The reviewer can read the code.
54
+
55
+ ## Tests
56
+
57
+ - Every behavioural change ships with a test. There's no formal coverage
58
+ threshold, but new modules should land with smoke tests at minimum.
59
+ - Tests must not touch a real `~/.codex/` — use the `codex_env` fixture
60
+ defined in `tests/conftest.py`, which isolates `CODEX_HOME` and
61
+ `CODEX_SWITCH_HOME` under a `tmp_path`.
62
+ - Avoid network calls in tests. The `api` module is intentionally a thin
63
+ wrapper around `urllib` so it can be stubbed with `monkeypatch`.
64
+ - Never commit real `auth.json`, SQLite snapshots, JSONL exports, or any
65
+ sample copied from `~/.codex/` or `~/.codex-accounts/`. Keep real debug
66
+ data outside the repository and use redacted fixtures only.
67
+
68
+ ## Commits & pull requests
69
+
70
+ - Keep commits scoped and reviewable. "WIP" commits get squashed.
71
+ - Reference an issue number in the PR description when relevant.
72
+ - The PR description should answer:
73
+ 1. **What** changed?
74
+ 2. **Why** is the change needed?
75
+ 3. **How** was it verified (commands run, scenarios tested)?
76
+
77
+ ## Areas where help is especially welcome
78
+
79
+ - **Linux compatibility.** The code paths are mostly portable but
80
+ `is_codex_running()` and the install scripts are macOS-tuned. Anyone
81
+ running the Codex Linux client: please open issues with concrete
82
+ reproductions.
83
+ - **Codex schema watchdog.** When OpenAI bumps the SQLite schema or
84
+ rotates the private API path, the integration breaks silently. PRs
85
+ that add detection or fallbacks are very welcome.
86
+ - **Documentation translations.** We currently ship English and
87
+ Simplified Chinese READMEs; other languages welcome.
88
+
89
+ ## Releasing (maintainers)
90
+
91
+ 1. Update `CHANGELOG.md` — move `[Unreleased]` into a dated section.
92
+ 2. Bump `version` in `pyproject.toml` and `src/codex_switch/__init__.py`.
93
+ 3. Tag `vX.Y.Z`, push, let CI build & publish.
94
+
95
+ ## Code of Conduct
96
+
97
+ Participation is governed by the [Contributor Covenant](./CODE_OF_CONDUCT.md).
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 wikty and codex-switch contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,238 @@
1
+ Metadata-Version: 2.4
2
+ Name: codex-accounts
3
+ Version: 0.1.0
4
+ Summary: Multi-account CLI manager for the OpenAI Codex desktop app
5
+ Project-URL: Homepage, https://github.com/wikty/codex-accounts
6
+ Project-URL: Documentation, https://github.com/wikty/codex-accounts#readme
7
+ Project-URL: Issues, https://github.com/wikty/codex-accounts/issues
8
+ Project-URL: Source, https://github.com/wikty/codex-accounts
9
+ Project-URL: Changelog, https://github.com/wikty/codex-accounts/blob/main/CHANGELOG.md
10
+ Author: codex-accounts contributors
11
+ License: MIT License
12
+
13
+ Copyright (c) 2026 wikty and codex-switch contributors
14
+
15
+ Permission is hereby granted, free of charge, to any person obtaining a copy
16
+ of this software and associated documentation files (the "Software"), to deal
17
+ in the Software without restriction, including without limitation the rights
18
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19
+ copies of the Software, and to permit persons to whom the Software is
20
+ furnished to do so, subject to the following conditions:
21
+
22
+ The above copyright notice and this permission notice shall be included in all
23
+ copies or substantial portions of the Software.
24
+
25
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31
+ SOFTWARE.
32
+ License-File: LICENSE
33
+ Keywords: account-switcher,chatgpt,cli,codex,multi-account,openai
34
+ Classifier: Development Status :: 4 - Beta
35
+ Classifier: Environment :: Console
36
+ Classifier: Intended Audience :: Developers
37
+ Classifier: License :: OSI Approved :: MIT License
38
+ Classifier: Operating System :: MacOS
39
+ Classifier: Operating System :: POSIX :: Linux
40
+ Classifier: Programming Language :: Python :: 3
41
+ Classifier: Programming Language :: Python :: 3.9
42
+ Classifier: Programming Language :: Python :: 3.10
43
+ Classifier: Programming Language :: Python :: 3.11
44
+ Classifier: Programming Language :: Python :: 3.12
45
+ Classifier: Topic :: Utilities
46
+ Requires-Python: >=3.9
47
+ Provides-Extra: dev
48
+ Requires-Dist: pre-commit>=4.0; extra == 'dev'
49
+ Requires-Dist: pytest-cov>=4.0; extra == 'dev'
50
+ Requires-Dist: pytest>=7.0; extra == 'dev'
51
+ Requires-Dist: ruff>=0.5; extra == 'dev'
52
+ Description-Content-Type: text/markdown
53
+
54
+ <!-- markdownlint-disable MD041 -->
55
+ <h1 align="center">codex-accounts</h1>
56
+
57
+ <p align="center">
58
+ <em>A multi-account CLI manager for the OpenAI Codex desktop app.</em>
59
+ </p>
60
+
61
+ <p align="center">
62
+ <a href="https://github.com/wikty/codex-accounts/actions/workflows/ci.yml"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/wikty/codex-accounts/ci.yml?branch=main&label=tests"></a>
63
+ <a href="https://pypi.org/project/codex-accounts/"><img alt="PyPI" src="https://img.shields.io/pypi/v/codex-accounts.svg"></a>
64
+ <a href="https://pypi.org/project/codex-accounts/"><img alt="Python" src="https://img.shields.io/pypi/pyversions/codex-accounts.svg"></a>
65
+ <a href="./LICENSE"><img alt="License" src="https://img.shields.io/badge/license-MIT-blue.svg"></a>
66
+ </p>
67
+
68
+ <p align="center">
69
+ <a href="./README.zh-CN.md">中文文档</a> · <a href="./docs/installation.md">Install</a> · <a href="./docs/add-account.md">Add an account</a> · <a href="./docs/faq.md">FAQ</a>
70
+ </p>
71
+
72
+ ---
73
+
74
+ The OpenAI Codex desktop app stores all sessions, logs, and UI state in
75
+ `~/.codex/` — and the underlying SQLite database has **no notion of which
76
+ account a row belongs to**. The moment you switch to a different ChatGPT
77
+ account, every previous session disappears from the sidebar.
78
+
79
+ **codex-accounts** fixes this by swapping the relevant files in and out of
80
+ `~/.codex/`, giving you clean multi-account isolation with a single command:
81
+
82
+ ```console
83
+ $ codex-accounts use work
84
+ ✓ switched to: work (auth mode)
85
+
86
+ $ codex-accounts list
87
+ Accounts (/Users/you/.codex-accounts):
88
+
89
+ ▶ work work@example.com Plus 5d left 2h ago ← current
90
+ personal personal@me.io Plus 9d left yesterday
91
+ research lab@university.edu Pro 1d left ⚠ 3d ago
92
+ ```
93
+
94
+ ## Features
95
+
96
+ - **One-command switching** — `codex-accounts use <name>` saves the current
97
+ account and activates the target in a single step.
98
+ - **Two isolation modes** — share session history across all accounts
99
+ (default) or fully isolate sessions, history, and shell snapshots per
100
+ account (`--no-share-sessions`).
101
+ - **Live quota** — `quota` and `list -a` query the same private endpoint
102
+ the Codex client uses for its 5h/weekly progress bars.
103
+ - **Local usage stats** — `stats` reads the Codex SQLite database directly
104
+ for offline token-usage breakdowns.
105
+ - **Auto-refresh** — `refresh` opens the 5-hour window across every
106
+ account so a sliding daily allotment never goes unused (see
107
+ [docs/auto-refresh.md](./docs/auto-refresh.md)).
108
+ - **Zero dependencies** — pure stdlib Python; ships as a single console
109
+ script.
110
+
111
+ ## Requirements
112
+
113
+ | | Supported |
114
+ |---|---|
115
+ | **OS** | macOS 12+ (primary), Linux (best-effort, PRs welcome) |
116
+ | **Python** | 3.9+ |
117
+ | **Codex desktop app** | already installed and signed in at least once |
118
+
119
+ > Windows is not currently supported. The path conventions and process
120
+ > detection in `codex_switch.utils` would need to be extended; PRs welcome.
121
+
122
+ ## Install
123
+
124
+ ```bash
125
+ # Recommended: isolated install with pipx
126
+ pipx install codex-accounts
127
+
128
+ # Or with pip
129
+ pip install --user codex-accounts
130
+ ```
131
+
132
+ For a no-package-manager install of the bundled launcher script, see
133
+ [`docs/installation.md`](./docs/installation.md).
134
+
135
+ ## Quick start
136
+
137
+ ```bash
138
+ # 1. Snapshot the account you're already logged in to
139
+ codex-accounts save work
140
+
141
+ # 2. Add a second account (interactive)
142
+ codex-accounts init personal # placeholder dir
143
+ codex-accounts use personal # clears auth.json so Codex prompts you to log in
144
+ open -a Codex # finish OAuth in the browser
145
+ codex-accounts save personal # capture the new account's data
146
+
147
+ # 3. Day-to-day
148
+ codex-accounts list # see everything at a glance
149
+ codex-accounts use work # switch back
150
+ codex-accounts quota # check 5h / weekly limits
151
+ codex-accounts stats # local token usage
152
+ ```
153
+
154
+ See [docs/add-account.md](./docs/add-account.md) for a full walkthrough.
155
+
156
+ ## Commands
157
+
158
+ | Command | What it does |
159
+ |---|---|
160
+ | `list [-a]` | List saved accounts (`-a` adds live quota) |
161
+ | `current` | Print the active account |
162
+ | `info [name]` | Email, plan, token expiry, notes |
163
+ | `save <name> [--auth-only]` | Snapshot current Codex state under `<name>` |
164
+ | `use <name> [--no-share-sessions]` | Activate `<name>` (auto-saves the current one first) |
165
+ | `init <name>` | Create an empty snapshot directory (no copy) |
166
+ | `note <name> <text>` | Attach a free-text note |
167
+ | `rename <old> <new>` | Rename an account snapshot |
168
+ | `delete <name>` | Remove a snapshot directory |
169
+ | `stats [name]` | Token usage from local SQLite |
170
+ | `quota [name]` | Live quota via private API (requires network) |
171
+ | `refresh` | Open the 5h window on every account (cron-friendly) |
172
+ | `doctor` | Environment dump for bug reports |
173
+
174
+ Run `codex-accounts <cmd> --help` for command-specific options.
175
+
176
+ ## How it works
177
+
178
+ ```
179
+ ~/.codex/ ~/.codex-accounts/work/
180
+ ├── auth.json <─ swap ─> ├── auth.json
181
+ ├── state_*.sqlite <─ swap ─> ├── state_*.sqlite (FULL mode only)
182
+ ├── sessions/ <─ swap ─> ├── dirs/sessions/ (FULL mode only)
183
+ ├── config.toml └── meta.json (notes, timestamps)
184
+ ├── skills/ rules/ memories/ (shared across all accounts — never swapped)
185
+ └── installation_id
186
+ ```
187
+
188
+ - **AUTH mode** (default for `use`) — only `auth.json` is swapped. Sessions
189
+ and history live in `~/.codex/` and are visible from every account. This
190
+ is what most people want.
191
+ - **FULL mode** (`use --no-share-sessions`) — session DBs, log DBs, JSONL
192
+ index, the `sessions/`/`archived_sessions/`/`shell_snapshots/`
193
+ directories, and the global UI state file are all swapped. Use this when
194
+ you genuinely want separate session sidebars per account.
195
+
196
+ The exact file list lives in
197
+ [`src/codex_switch/config.py`](./src/codex_switch/config.py) and uses
198
+ **glob patterns** (`state_*.sqlite`, `logs_*.sqlite`) so future Codex
199
+ schema bumps don't silently miss files.
200
+
201
+ ## Security & privacy
202
+
203
+ - `~/.codex-accounts/` and every snapshot directory inside it are created
204
+ with mode `0700`.
205
+ - Account names are validated against `^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$`
206
+ to prevent path traversal.
207
+ - `auth.json` is the same plaintext OAuth bundle the Codex client itself
208
+ stores. Treat snapshot directories with the same care you'd treat
209
+ `~/.codex/` — back them up, but do not check them into git or sync them
210
+ to anywhere unencrypted.
211
+ - `quota`, `list -a`, and `refresh` make network calls to
212
+ `chatgpt.com/backend-api`. All other commands are fully offline.
213
+ - See [`SECURITY.md`](./SECURITY.md) for vulnerability reporting.
214
+
215
+ ## Disclaimers
216
+
217
+ - This project is **not affiliated with OpenAI** in any way.
218
+ - `quota`, `list -a`, and `refresh` rely on private endpoints
219
+ (`/backend-api/wham/usage` and `/backend-api/codex/responses`) that were
220
+ located by reverse-engineering the Codex desktop client. They can change
221
+ at any time. See
222
+ [`docs/internals/codex-app-internals.md`](./docs/internals/codex-app-internals.md)
223
+ for the methodology used to re-discover them when a Codex update breaks
224
+ the integration.
225
+ - `refresh` sends low-cost API requests on your behalf. Read
226
+ [`docs/auto-refresh.md`](./docs/auto-refresh.md) — including the
227
+ rate-limit and abuse-prevention caveats — before enabling the cron job.
228
+
229
+ ## Contributing
230
+
231
+ Pull requests, bug reports, and "I tried it on Linux and X broke" notes
232
+ are all welcome. See [`CONTRIBUTING.md`](./CONTRIBUTING.md) for the dev
233
+ loop, and [`CODE_OF_CONDUCT.md`](./CODE_OF_CONDUCT.md) for community
234
+ expectations.
235
+
236
+ ## License
237
+
238
+ [MIT](./LICENSE) © codex-accounts contributors.
@@ -0,0 +1,185 @@
1
+ <!-- markdownlint-disable MD041 -->
2
+ <h1 align="center">codex-accounts</h1>
3
+
4
+ <p align="center">
5
+ <em>A multi-account CLI manager for the OpenAI Codex desktop app.</em>
6
+ </p>
7
+
8
+ <p align="center">
9
+ <a href="https://github.com/wikty/codex-accounts/actions/workflows/ci.yml"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/wikty/codex-accounts/ci.yml?branch=main&label=tests"></a>
10
+ <a href="https://pypi.org/project/codex-accounts/"><img alt="PyPI" src="https://img.shields.io/pypi/v/codex-accounts.svg"></a>
11
+ <a href="https://pypi.org/project/codex-accounts/"><img alt="Python" src="https://img.shields.io/pypi/pyversions/codex-accounts.svg"></a>
12
+ <a href="./LICENSE"><img alt="License" src="https://img.shields.io/badge/license-MIT-blue.svg"></a>
13
+ </p>
14
+
15
+ <p align="center">
16
+ <a href="./README.zh-CN.md">中文文档</a> · <a href="./docs/installation.md">Install</a> · <a href="./docs/add-account.md">Add an account</a> · <a href="./docs/faq.md">FAQ</a>
17
+ </p>
18
+
19
+ ---
20
+
21
+ The OpenAI Codex desktop app stores all sessions, logs, and UI state in
22
+ `~/.codex/` — and the underlying SQLite database has **no notion of which
23
+ account a row belongs to**. The moment you switch to a different ChatGPT
24
+ account, every previous session disappears from the sidebar.
25
+
26
+ **codex-accounts** fixes this by swapping the relevant files in and out of
27
+ `~/.codex/`, giving you clean multi-account isolation with a single command:
28
+
29
+ ```console
30
+ $ codex-accounts use work
31
+ ✓ switched to: work (auth mode)
32
+
33
+ $ codex-accounts list
34
+ Accounts (/Users/you/.codex-accounts):
35
+
36
+ ▶ work work@example.com Plus 5d left 2h ago ← current
37
+ personal personal@me.io Plus 9d left yesterday
38
+ research lab@university.edu Pro 1d left ⚠ 3d ago
39
+ ```
40
+
41
+ ## Features
42
+
43
+ - **One-command switching** — `codex-accounts use <name>` saves the current
44
+ account and activates the target in a single step.
45
+ - **Two isolation modes** — share session history across all accounts
46
+ (default) or fully isolate sessions, history, and shell snapshots per
47
+ account (`--no-share-sessions`).
48
+ - **Live quota** — `quota` and `list -a` query the same private endpoint
49
+ the Codex client uses for its 5h/weekly progress bars.
50
+ - **Local usage stats** — `stats` reads the Codex SQLite database directly
51
+ for offline token-usage breakdowns.
52
+ - **Auto-refresh** — `refresh` opens the 5-hour window across every
53
+ account so a sliding daily allotment never goes unused (see
54
+ [docs/auto-refresh.md](./docs/auto-refresh.md)).
55
+ - **Zero dependencies** — pure stdlib Python; ships as a single console
56
+ script.
57
+
58
+ ## Requirements
59
+
60
+ | | Supported |
61
+ |---|---|
62
+ | **OS** | macOS 12+ (primary), Linux (best-effort, PRs welcome) |
63
+ | **Python** | 3.9+ |
64
+ | **Codex desktop app** | already installed and signed in at least once |
65
+
66
+ > Windows is not currently supported. The path conventions and process
67
+ > detection in `codex_switch.utils` would need to be extended; PRs welcome.
68
+
69
+ ## Install
70
+
71
+ ```bash
72
+ # Recommended: isolated install with pipx
73
+ pipx install codex-accounts
74
+
75
+ # Or with pip
76
+ pip install --user codex-accounts
77
+ ```
78
+
79
+ For a no-package-manager install of the bundled launcher script, see
80
+ [`docs/installation.md`](./docs/installation.md).
81
+
82
+ ## Quick start
83
+
84
+ ```bash
85
+ # 1. Snapshot the account you're already logged in to
86
+ codex-accounts save work
87
+
88
+ # 2. Add a second account (interactive)
89
+ codex-accounts init personal # placeholder dir
90
+ codex-accounts use personal # clears auth.json so Codex prompts you to log in
91
+ open -a Codex # finish OAuth in the browser
92
+ codex-accounts save personal # capture the new account's data
93
+
94
+ # 3. Day-to-day
95
+ codex-accounts list # see everything at a glance
96
+ codex-accounts use work # switch back
97
+ codex-accounts quota # check 5h / weekly limits
98
+ codex-accounts stats # local token usage
99
+ ```
100
+
101
+ See [docs/add-account.md](./docs/add-account.md) for a full walkthrough.
102
+
103
+ ## Commands
104
+
105
+ | Command | What it does |
106
+ |---|---|
107
+ | `list [-a]` | List saved accounts (`-a` adds live quota) |
108
+ | `current` | Print the active account |
109
+ | `info [name]` | Email, plan, token expiry, notes |
110
+ | `save <name> [--auth-only]` | Snapshot current Codex state under `<name>` |
111
+ | `use <name> [--no-share-sessions]` | Activate `<name>` (auto-saves the current one first) |
112
+ | `init <name>` | Create an empty snapshot directory (no copy) |
113
+ | `note <name> <text>` | Attach a free-text note |
114
+ | `rename <old> <new>` | Rename an account snapshot |
115
+ | `delete <name>` | Remove a snapshot directory |
116
+ | `stats [name]` | Token usage from local SQLite |
117
+ | `quota [name]` | Live quota via private API (requires network) |
118
+ | `refresh` | Open the 5h window on every account (cron-friendly) |
119
+ | `doctor` | Environment dump for bug reports |
120
+
121
+ Run `codex-accounts <cmd> --help` for command-specific options.
122
+
123
+ ## How it works
124
+
125
+ ```
126
+ ~/.codex/ ~/.codex-accounts/work/
127
+ ├── auth.json <─ swap ─> ├── auth.json
128
+ ├── state_*.sqlite <─ swap ─> ├── state_*.sqlite (FULL mode only)
129
+ ├── sessions/ <─ swap ─> ├── dirs/sessions/ (FULL mode only)
130
+ ├── config.toml └── meta.json (notes, timestamps)
131
+ ├── skills/ rules/ memories/ (shared across all accounts — never swapped)
132
+ └── installation_id
133
+ ```
134
+
135
+ - **AUTH mode** (default for `use`) — only `auth.json` is swapped. Sessions
136
+ and history live in `~/.codex/` and are visible from every account. This
137
+ is what most people want.
138
+ - **FULL mode** (`use --no-share-sessions`) — session DBs, log DBs, JSONL
139
+ index, the `sessions/`/`archived_sessions/`/`shell_snapshots/`
140
+ directories, and the global UI state file are all swapped. Use this when
141
+ you genuinely want separate session sidebars per account.
142
+
143
+ The exact file list lives in
144
+ [`src/codex_switch/config.py`](./src/codex_switch/config.py) and uses
145
+ **glob patterns** (`state_*.sqlite`, `logs_*.sqlite`) so future Codex
146
+ schema bumps don't silently miss files.
147
+
148
+ ## Security & privacy
149
+
150
+ - `~/.codex-accounts/` and every snapshot directory inside it are created
151
+ with mode `0700`.
152
+ - Account names are validated against `^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$`
153
+ to prevent path traversal.
154
+ - `auth.json` is the same plaintext OAuth bundle the Codex client itself
155
+ stores. Treat snapshot directories with the same care you'd treat
156
+ `~/.codex/` — back them up, but do not check them into git or sync them
157
+ to anywhere unencrypted.
158
+ - `quota`, `list -a`, and `refresh` make network calls to
159
+ `chatgpt.com/backend-api`. All other commands are fully offline.
160
+ - See [`SECURITY.md`](./SECURITY.md) for vulnerability reporting.
161
+
162
+ ## Disclaimers
163
+
164
+ - This project is **not affiliated with OpenAI** in any way.
165
+ - `quota`, `list -a`, and `refresh` rely on private endpoints
166
+ (`/backend-api/wham/usage` and `/backend-api/codex/responses`) that were
167
+ located by reverse-engineering the Codex desktop client. They can change
168
+ at any time. See
169
+ [`docs/internals/codex-app-internals.md`](./docs/internals/codex-app-internals.md)
170
+ for the methodology used to re-discover them when a Codex update breaks
171
+ the integration.
172
+ - `refresh` sends low-cost API requests on your behalf. Read
173
+ [`docs/auto-refresh.md`](./docs/auto-refresh.md) — including the
174
+ rate-limit and abuse-prevention caveats — before enabling the cron job.
175
+
176
+ ## Contributing
177
+
178
+ Pull requests, bug reports, and "I tried it on Linux and X broke" notes
179
+ are all welcome. See [`CONTRIBUTING.md`](./CONTRIBUTING.md) for the dev
180
+ loop, and [`CODE_OF_CONDUCT.md`](./CODE_OF_CONDUCT.md) for community
181
+ expectations.
182
+
183
+ ## License
184
+
185
+ [MIT](./LICENSE) © codex-accounts contributors.