codex-quota 1.0.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.
@@ -0,0 +1,221 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py.cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ # Pipfile.lock
96
+
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ # uv.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ # poetry.lock
109
+ # poetry.toml
110
+
111
+ # pdm
112
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
113
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
114
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
115
+ # pdm.lock
116
+ # pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # pixi
121
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
122
+ # pixi.lock
123
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
124
+ # in the .venv directory. It is recommended not to include this directory in version control.
125
+ .pixi
126
+
127
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
128
+ __pypackages__/
129
+
130
+ # Celery stuff
131
+ celerybeat-schedule
132
+ celerybeat.pid
133
+
134
+ # Redis
135
+ *.rdb
136
+ *.aof
137
+ *.pid
138
+
139
+ # RabbitMQ
140
+ mnesia/
141
+ rabbitmq/
142
+ rabbitmq-data/
143
+
144
+ # ActiveMQ
145
+ activemq-data/
146
+
147
+ # SageMath parsed files
148
+ *.sage.py
149
+
150
+ # Environments
151
+ .env
152
+ .envrc
153
+ .venv
154
+ env/
155
+ venv/
156
+ ENV/
157
+ env.bak/
158
+ venv.bak/
159
+
160
+ # Spyder project settings
161
+ .spyderproject
162
+ .spyproject
163
+
164
+ # Rope project settings
165
+ .ropeproject
166
+
167
+ # mkdocs documentation
168
+ /site
169
+
170
+ # mypy
171
+ .mypy_cache/
172
+ .dmypy.json
173
+ dmypy.json
174
+
175
+ # Pyre type checker
176
+ .pyre/
177
+
178
+ # pytype static type analyzer
179
+ .pytype/
180
+
181
+ # Cython debug symbols
182
+ cython_debug/
183
+
184
+ # PyCharm
185
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
186
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
187
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
188
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
189
+ # .idea/
190
+
191
+ # Abstra
192
+ # Abstra is an AI-powered process automation framework.
193
+ # Ignore directories containing user credentials, local state, and settings.
194
+ # Learn more at https://abstra.io/docs
195
+ .abstra/
196
+
197
+ # Visual Studio Code
198
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
199
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
200
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
201
+ # you could uncomment the following to ignore the entire vscode folder
202
+ # .vscode/
203
+ # Temporary file for partial code execution
204
+ tempCodeRunnerFile.py
205
+
206
+ # Ruff stuff:
207
+ .ruff_cache/
208
+
209
+ # PyPI configuration file
210
+ .pypirc
211
+
212
+ # Marimo
213
+ marimo/_static/
214
+ marimo/_lsp/
215
+ __marimo__/
216
+
217
+ # Streamlit
218
+ .streamlit/secrets.toml
219
+
220
+ # System files
221
+ .DS_Store
@@ -0,0 +1,93 @@
1
+ # Changelog
2
+
3
+ ## 1.0.0 - 2026-06-04
4
+
5
+ ### Added
6
+
7
+ - `codex-quota login <profile> --device-auth` for device-code login on headless or remote machines.
8
+ - `codex-quota profile add <profile> --login --device-auth` to create and authenticate a profile in one step.
9
+ - TUI support for `login <profile> --device-auth`.
10
+
11
+ ### Fixed
12
+
13
+ - `profile add --device-auth` without `--login` now exits with a clear user-facing error.
14
+ - POSIX profile/config directories are now created and tightened with `0700` permissions.
15
+ - `exec` now respects user Codex config and rules by default.
16
+ - Hardened profile discovery so symlinked directories cannot be treated as external `CODEX_HOME` locations.
17
+ - Safe-by-default JSON status output avoids leaking path and quota metadata into CI logs.
18
+
19
+ ## 0.3.0 - 2026-06-03
20
+
21
+ ### Added
22
+
23
+ - Filesystem-based profile discovery under `~/.codex-quota/profiles`.
24
+ - Profile management commands: `profile list`, `profile add`, `profile remove`, and `profile path`.
25
+ - `codex-quota login <profile> --create`.
26
+ - `codex-quota init --verify`.
27
+ - Dedicated profile and App Server modules for safer path handling and quota reads.
28
+ - Stable `ok` field in JSON status output.
29
+
30
+ ### Changed
31
+
32
+ - `~/.codex-quota/profiles/<profile>/` became the source of truth for profile existence.
33
+ - Config no longer stores a static profile registry.
34
+ - `codex-quota init` now bootstraps and validates the environment only.
35
+ - status and check dynamically discover profiles from the filesystem.
36
+ - Config loading preserves unknown legacy keys while ignoring old profile registry data for discovery.
37
+ - TUI now uses dynamic profile discovery and shared service logic.
38
+
39
+ ### Fixed
40
+
41
+ - Long-path wrapping in profile path output.
42
+ - macOS temp-path and symlink-sensitive profile path handling.
43
+ - Per-profile status collection now continues when one profile fails.
44
+ - Missing Codex binary is represented as a per-profile status error where appropriate.
45
+ - Malformed config JSON now raises a clear config error.
46
+ - Malformed App Server responses now raise a clear app-server error.
47
+
48
+ ## 0.2.0 - 2026-06-03
49
+
50
+ ### Added
51
+
52
+ - Textual-based fullscreen TUI.
53
+ - `Refreshed at HH:MM DD.MM.YYYY` timestamp above the status table.
54
+ - `codex_ok` field in JSON status output.
55
+ - Safer unknown-profile validation for `status` and `check`.
56
+ - User-facing refresh/loading messages in TUI.
57
+ - Scroll-safe TUI input handling through Textual widgets.
58
+
59
+ ### Changed
60
+
61
+ - Replaced the old Rich `Live` + manual prompt TUI with Textual.
62
+ - Improved status table formatting, colors, widths, and percentage display.
63
+ - `service.collect_statuses()` now distinguishes missing Codex binary from profile/auth failures.
64
+ - TUI refresh now runs asynchronously and does not block the command input field.
65
+ - Manual refresh no longer leaves a persistent `Refreshed.` panel.
66
+
67
+ ### Fixed
68
+
69
+ - Mouse wheel escape-sequence pollution in the TUI command input.
70
+ - Refresh message panel persisting after manual refresh.
71
+ - Possible `KeyError` for unknown profile names in `status` and `check`.
72
+ - Date formatting from `DD:MM:YYYY` to `DD.MM.YYYY`.
73
+
74
+ ### Removed
75
+
76
+ - Old Rich `Live` fullscreen TUI implementation.
77
+ - Manual raw terminal input handling with `select` / `read(1)`.
78
+
79
+ ## 0.1.0 - 2026-06-03
80
+
81
+ Initial preview release.
82
+
83
+ ### Added
84
+
85
+ - Python package under `src/codex_quota`.
86
+ - Multi-profile config stored separately from Codex homes.
87
+ - Profile directory initialization.
88
+ - Official Codex login delegation per profile via `CODEX_HOME`.
89
+ - App Server JSON-RPC quota reader for `account/rateLimits/read`.
90
+ - Human-readable status table and JSON output.
91
+ - Automation-friendly `check` command.
92
+ - Minimal low-reasoning `codex exec` wrapper.
93
+ - Simple Rich-based TUI with refresh, login, exec, and quit commands.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ssh-den
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,389 @@
1
+ Metadata-Version: 2.4
2
+ Name: codex-quota
3
+ Version: 1.0.0
4
+ Summary: Multi-profile Codex CLI quota monitor with CLI and TUI
5
+ Project-URL: Homepage, https://github.com/ssh-den/codex-quota
6
+ Project-URL: Repository, https://github.com/ssh-den/codex-quota
7
+ Project-URL: Issues, https://github.com/ssh-den/codex-quota/issues
8
+ Project-URL: Changelog, https://github.com/ssh-den/codex-quota/blob/main/CHANGELOG.md
9
+ Author: ssh-den
10
+ License: MIT
11
+ License-File: LICENSE
12
+ Keywords: cli,codex,monitoring,quota,tui
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: MacOS
18
+ Classifier: Operating System :: POSIX :: Linux
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: System :: Monitoring
23
+ Classifier: Topic :: Utilities
24
+ Requires-Python: >=3.11
25
+ Requires-Dist: rich>=13.7.1
26
+ Requires-Dist: textual>=3.5.0
27
+ Requires-Dist: typer>=0.12.5
28
+ Provides-Extra: dev
29
+ Requires-Dist: mypy>=1.11; extra == 'dev'
30
+ Requires-Dist: pylint>=3.2; extra == 'dev'
31
+ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
32
+ Requires-Dist: pytest>=8.2; extra == 'dev'
33
+ Requires-Dist: ruff>=0.6; extra == 'dev'
34
+ Description-Content-Type: text/markdown
35
+
36
+ # codex-quota
37
+
38
+ A utility for managing isolated Codex CLI profiles and monitoring quota usage across multiple Codex environments.
39
+
40
+ Includes JSON output for automation and a live terminal dashboard.
41
+
42
+ > **Note:** This is an independent community tool. It is not affiliated with or endorsed by OpenAI.
43
+
44
+ ---
45
+
46
+ ## Requirements
47
+
48
+ - Python 3.11+
49
+ - Official Codex CLI available as `codex`
50
+
51
+ Install Codex CLI:
52
+
53
+ ```bash
54
+ npm install -g @openai/codex
55
+ ```
56
+
57
+ or
58
+
59
+ ```bash
60
+ brew install codex
61
+ ```
62
+
63
+ Tested with `codex-cli 0.136.0`.
64
+
65
+ ---
66
+
67
+ ## Installation
68
+
69
+ Install from PyPI:
70
+
71
+ ```bash
72
+ pip install codex-quota
73
+ ```
74
+
75
+ Install from source:
76
+
77
+ ```bash
78
+ git clone https://github.com/ssh-den/codex-quota.git
79
+ cd codex-quota
80
+ python -m venv .venv
81
+ source .venv/bin/activate # Windows: .venv\Scripts\activate
82
+ pip install -e .
83
+ ```
84
+
85
+ ---
86
+
87
+ ## Quick Start
88
+
89
+ ```bash
90
+ # Initialize (creates config and profiles directory)
91
+ codex-quota init
92
+
93
+ # Add a profile and log in
94
+ codex-quota profile add personal --login
95
+
96
+ # Check quota status
97
+ codex-quota status
98
+
99
+ # Launch the live terminal dashboard
100
+ codex-quota tui
101
+ ```
102
+
103
+ ---
104
+
105
+ ## Security
106
+
107
+ Authentication is fully delegated to the official Codex CLI. `codex-quota` never reads, stores, or transmits credentials. It sets `CODEX_HOME` and calls `codex` on your behalf.
108
+
109
+ Profile and config directories are created with `0700` permissions on POSIX systems so `auth.json` and related state are not exposed by a weak `umask` on multi-user machines.
110
+
111
+ ---
112
+
113
+ ## Script filesystem layout
114
+
115
+ ```
116
+ ~/.codex-quota/profiles/
117
+ ├── personal/
118
+ ├── work/
119
+ └── testing/
120
+
121
+ ~/.config/codex-quota/
122
+ └── config.json
123
+ ```
124
+
125
+ The filesystem is the source of truth. Profiles are discovered dynamically. The configuration file stores application settings only and does not maintain a profile registry.
126
+
127
+ ---
128
+
129
+ ## Configuration
130
+
131
+ Default configuration:
132
+
133
+ ```json
134
+ {
135
+ "profiles_dir": "~/.codex-quota/profiles",
136
+ "codex_bin": "codex",
137
+ "default_model": "gpt-5.4-mini",
138
+ "reasoning_effort": "low",
139
+ "refresh_seconds": 30.0
140
+ }
141
+ ```
142
+
143
+ Edit `~/.config/codex-quota/config.json` to change model defaults or reasoning effort.
144
+
145
+ ---
146
+
147
+ ## Initialization
148
+
149
+ ```bash
150
+ codex-quota init
151
+ ```
152
+
153
+ Behavior:
154
+
155
+ - Create config directory if missing
156
+ - Create profiles directory if missing
157
+ - Create `config.json` if missing
158
+ - Preserve existing configuration
159
+ - Verify Codex CLI installation
160
+ - Print detected Codex version
161
+ - Discover existing profiles by scanning `~/.codex-quota/profiles/*`
162
+
163
+ Overwrite configuration:
164
+
165
+ ```bash
166
+ codex-quota init --overwrite-config
167
+ ```
168
+
169
+ Run bootstrap plus quota verification (`--check` is an alias):
170
+
171
+ ```bash
172
+ codex-quota init --verify
173
+ ```
174
+
175
+ ---
176
+
177
+ ## Profile management
178
+
179
+ List profiles:
180
+
181
+ ```bash
182
+ codex-quota profile list
183
+ ```
184
+
185
+ Add profile:
186
+
187
+ ```bash
188
+ codex-quota profile add personal
189
+ ```
190
+
191
+ Create and login immediately:
192
+
193
+ ```bash
194
+ codex-quota profile add personal --login
195
+ ```
196
+
197
+ Create and force device-code auth on headless or remote machines:
198
+
199
+ ```bash
200
+ codex-quota profile add personal --login --device-auth
201
+ ```
202
+
203
+ Print profile path:
204
+
205
+ ```bash
206
+ codex-quota profile path personal
207
+ ```
208
+
209
+ Remove profile:
210
+
211
+ ```bash
212
+ codex-quota profile remove personal
213
+ ```
214
+
215
+ Force remove (non-interactive):
216
+
217
+ ```bash
218
+ codex-quota profile remove personal --yes
219
+ ```
220
+
221
+ Profile names are validated. Path traversal, path separators, absolute paths, whitespace, and suspicious characters are rejected.
222
+
223
+ ---
224
+
225
+ ## Login
226
+
227
+ ```bash
228
+ codex-quota login personal
229
+ ```
230
+
231
+ Equivalent to:
232
+
233
+ ```bash
234
+ CODEX_HOME="$HOME/.codex-quota/profiles/personal" codex login
235
+ ```
236
+
237
+ Use device authorization instead of the local browser callback flow:
238
+
239
+ ```bash
240
+ codex-quota login personal --device-auth
241
+ ```
242
+
243
+ Create the profile automatically if missing:
244
+
245
+ ```bash
246
+ codex-quota login personal --create
247
+ ```
248
+
249
+ Combine both when bootstrapping a remote profile in one step:
250
+
251
+ ```bash
252
+ codex-quota login personal --create --device-auth
253
+ ```
254
+
255
+ ---
256
+
257
+ ## Status
258
+
259
+ All profiles:
260
+
261
+ ```bash
262
+ codex-quota status
263
+ ```
264
+
265
+ Single profile:
266
+
267
+ ```bash
268
+ codex-quota status personal
269
+ ```
270
+
271
+ JSON output:
272
+
273
+ ```bash
274
+ codex-quota status --json
275
+ ```
276
+
277
+ Example human-readable output:
278
+
279
+ ```
280
+ Profile Status 5h Left Week Left
281
+ personal OK 99% 69%
282
+ work OK 74% 52%
283
+ ```
284
+
285
+ Default JSON is safe for CI logs and automation:
286
+
287
+ - No absolute profile paths
288
+ - No raw `rateLimits` payload
289
+ - No plan or credits metadata unless explicitly requested
290
+
291
+ Opt in to the extra fields only when you need them:
292
+
293
+ ```bash
294
+ codex-quota status --json --json-paths --json-raw
295
+ ```
296
+
297
+ Quota lockout detection uses `rateLimitReachedType != null`. The tool does not infer lockout solely from `usedPercent == 100`.
298
+
299
+ ---
300
+
301
+ ## Check command
302
+
303
+ Automation-oriented health check:
304
+
305
+ ```bash
306
+ codex-quota check
307
+ ```
308
+
309
+ Single profile:
310
+
311
+ ```bash
312
+ codex-quota check personal
313
+ ```
314
+
315
+ Exit codes:
316
+
317
+ | Code | Meaning |
318
+ |------|---------|
319
+ | 0 | Selected profiles are authenticated, readable, and not quota-blocked |
320
+ | 2 | Codex missing, auth missing/expired, app-server failure, quota block, or no selected profiles found |
321
+
322
+ ---
323
+
324
+ ## Exec
325
+
326
+ Run Codex under a selected profile:
327
+
328
+ ```bash
329
+ codex-quota exec personal "Reply with exactly: ok"
330
+ ```
331
+
332
+ Disable forced JSON output:
333
+
334
+ ```bash
335
+ codex-quota exec personal "Say hello" --raw
336
+ ```
337
+
338
+ `exec` now respects the user's existing Codex config and rules by default instead of disabling them.
339
+
340
+ ---
341
+
342
+ ## TUI
343
+
344
+ Launch:
345
+
346
+ ```bash
347
+ codex-quota tui
348
+ ```
349
+
350
+ Custom refresh interval:
351
+
352
+ ```bash
353
+ codex-quota tui --refresh 15
354
+ ```
355
+
356
+ The TUI uses Textual and dynamically discovers profiles from the filesystem.
357
+
358
+ Available commands:
359
+
360
+ ```
361
+ refresh
362
+ login <profile> [--device-auth]
363
+ exec <profile> <prompt>
364
+ quit
365
+ ```
366
+
367
+ ---
368
+
369
+ ## Internal quota API
370
+
371
+ Status collection launches:
372
+
373
+ ```bash
374
+ CODEX_HOME=<profile-home> codex app-server --stdio
375
+ ```
376
+
377
+ Then performs the following JSON-RPC sequence:
378
+
379
+ ```
380
+ 1. initialize
381
+ 2. initialized
382
+ 3. account/rateLimits/read
383
+ ```
384
+
385
+ Responses are normalized for display and safe JSON output. Raw API values are available only through explicit `--json-raw`.
386
+
387
+ ## License
388
+
389
+ MIT License