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.
- codex_accounts-0.1.0/.gitignore +66 -0
- codex_accounts-0.1.0/CHANGELOG.md +31 -0
- codex_accounts-0.1.0/CODE_OF_CONDUCT.md +29 -0
- codex_accounts-0.1.0/CONTRIBUTING.md +97 -0
- codex_accounts-0.1.0/LICENSE +21 -0
- codex_accounts-0.1.0/PKG-INFO +238 -0
- codex_accounts-0.1.0/README.md +185 -0
- codex_accounts-0.1.0/README.zh-CN.md +159 -0
- codex_accounts-0.1.0/SECURITY.md +54 -0
- codex_accounts-0.1.0/completions/_codex-accounts +84 -0
- codex_accounts-0.1.0/completions/codex-accounts.bash +57 -0
- codex_accounts-0.1.0/docs/add-account.md +156 -0
- codex_accounts-0.1.0/docs/auto-refresh.md +151 -0
- codex_accounts-0.1.0/docs/faq.md +121 -0
- codex_accounts-0.1.0/docs/installation.md +95 -0
- codex_accounts-0.1.0/docs/internals/codex-app-internals.md +244 -0
- codex_accounts-0.1.0/docs/internals/codex-rs-api-map.md +461 -0
- codex_accounts-0.1.0/install.sh +159 -0
- codex_accounts-0.1.0/packaging/com.codex-accounts.refresh.plist +51 -0
- codex_accounts-0.1.0/pyproject.toml +101 -0
- codex_accounts-0.1.0/scripts/install-launchagent.sh +46 -0
- codex_accounts-0.1.0/src/codex_switch/__init__.py +6 -0
- codex_accounts-0.1.0/src/codex_switch/__main__.py +8 -0
- codex_accounts-0.1.0/src/codex_switch/accounts.py +265 -0
- codex_accounts-0.1.0/src/codex_switch/api.py +144 -0
- codex_accounts-0.1.0/src/codex_switch/cli.py +532 -0
- codex_accounts-0.1.0/src/codex_switch/config.py +96 -0
- codex_accounts-0.1.0/src/codex_switch/stats.py +139 -0
- codex_accounts-0.1.0/src/codex_switch/utils.py +302 -0
- codex_accounts-0.1.0/tests/__init__.py +0 -0
- codex_accounts-0.1.0/tests/conftest.py +131 -0
- codex_accounts-0.1.0/tests/test_accounts.py +100 -0
- codex_accounts-0.1.0/tests/test_cli.py +68 -0
- 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.
|