codex-usage-analyzer 0.1.0 → 0.2.0
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.
- package/CONTRIBUTING.md +54 -0
- package/LICENSE +21 -0
- package/README.md +125 -185
- package/SECURITY.md +44 -0
- package/bin/codex-usage-analyzer.js +4 -2
- package/docs/account-usage-contract.md +85 -0
- package/docs/account-usage.schema.json +99 -0
- package/docs/downstream-integration.md +195 -0
- package/package.json +20 -8
- package/src/account-usage.js +115 -0
- package/src/app-server-client.js +229 -0
- package/src/cli.js +64 -51
- package/src/errors.js +46 -0
- package/src/format-account-usage.js +81 -0
- package/src/index.d.ts +63 -33
- package/src/index.js +10 -14
- package/src/analyze.js +0 -239
- package/src/fixtures/sample-v2-snapshot.js +0 -103
- package/src/parser/activity-aggregate.js +0 -264
- package/src/parser/asset-aggregate.js +0 -363
- package/src/parser/codex-home.js +0 -37
- package/src/parser/model-aggregate.js +0 -204
- package/src/parser/session-jsonl.js +0 -231
- package/src/parser/skill-plugin-aggregate.js +0 -228
- package/src/parser/token-aggregate.js +0 -229
- package/src/snapshot/index.js +0 -6
- package/src/snapshot/v2-schema.js +0 -519
- package/src/snapshot/v2-types.d.ts +0 -109
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Contributions to `codex-usage-analyzer` should be small, reviewable, and tied to a concrete user or integration need.
|
|
4
|
+
|
|
5
|
+
## Before you start
|
|
6
|
+
|
|
7
|
+
1. Search the [issue tracker](https://github.com/postmelee/codex-usage-analyzer/issues) for an existing task.
|
|
8
|
+
2. Open an issue for a bug, feature, public contract change, or structural change before editing source.
|
|
9
|
+
3. Wait for a maintainer to confirm the scope. This repository uses an issue-first Hyper-Waterfall workflow, so implementation stages cross explicit approval boundaries.
|
|
10
|
+
|
|
11
|
+
Security reports do not belong in public issues. Follow [SECURITY.md](SECURITY.md).
|
|
12
|
+
|
|
13
|
+
## Development requirements
|
|
14
|
+
|
|
15
|
+
- Node.js 20 or newer
|
|
16
|
+
- No runtime dependency additions without prior scope approval
|
|
17
|
+
- Synthetic fixtures and fake transports for automated tests
|
|
18
|
+
|
|
19
|
+
Run the local checks:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm test
|
|
23
|
+
npm pack --dry-run
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Automated tests must not require a real account, network access, a local Codex installation, or private credentials. Never commit or paste raw account usage, tokens, account identifiers, prompts, responses, app-server stderr, or machine-specific paths.
|
|
27
|
+
|
|
28
|
+
## Change guidelines
|
|
29
|
+
|
|
30
|
+
- Keep the default path on the official app-server `account/usage/read` method.
|
|
31
|
+
- Preserve the identity-free output boundary.
|
|
32
|
+
- Keep fields allowlisted and validate all upstream values before returning them.
|
|
33
|
+
- Update implementation, tests, TypeScript declarations, JSON Schema, and public documentation together when a public surface changes.
|
|
34
|
+
- Treat contract shape, meaning, or nullability changes as compatibility work requiring consumer-impact review.
|
|
35
|
+
- Keep private or undocumented endpoint experiments out of the default command and package contract.
|
|
36
|
+
- Avoid unrelated formatting, dependency, or repository metadata changes.
|
|
37
|
+
|
|
38
|
+
External contributors normally do not need to edit `mydocs/`; it contains the maintainer's workflow records and manuals. A maintainer will coordinate any required internal documentation.
|
|
39
|
+
|
|
40
|
+
## Pull requests
|
|
41
|
+
|
|
42
|
+
A pull request should include:
|
|
43
|
+
|
|
44
|
+
- the linked issue and approved scope
|
|
45
|
+
- a concise behavior summary
|
|
46
|
+
- focused tests for success, failure, and privacy boundaries
|
|
47
|
+
- commands used for verification
|
|
48
|
+
- compatibility or downstream impact, when applicable
|
|
49
|
+
|
|
50
|
+
Before requesting review, confirm that tests pass, the package dry-run contains only intended artifacts, generated output is absent, and the diff contains no secrets or private data.
|
|
51
|
+
|
|
52
|
+
## Collaboration
|
|
53
|
+
|
|
54
|
+
Keep discussion technical and specific. Explain tradeoffs, respond to review findings with code or evidence, and split work when a change becomes broader than its approved issue.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 postmelee
|
|
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.
|
package/README.md
CHANGED
|
@@ -1,255 +1,195 @@
|
|
|
1
1
|
# codex-usage-analyzer
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/codex-usage-analyzer)
|
|
4
|
+
[](https://github.com/postmelee/codex-usage-analyzer/actions/workflows/ci.yml)
|
|
5
|
+
[](LICENSE)
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
Read the account usage shown by Codex through the official app-server protocol, from one small CLI.
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
`codex-usage-analyzer` starts your installed Codex CLI, calls `account/usage/read`, and emits a stable, identity-free contract. It does not scan local sessions or directly read authentication files, tokens, keychains, prompts, or responses.
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
## Quick start
|
|
10
12
|
|
|
11
13
|
```bash
|
|
12
|
-
npx codex-usage-analyzer@latest
|
|
14
|
+
npx --yes codex-usage-analyzer@latest
|
|
13
15
|
```
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
Human-readable output:
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
```text
|
|
20
|
+
Codex account usage
|
|
18
21
|
|
|
19
|
-
|
|
22
|
+
Lifetime tokens 1.23B
|
|
23
|
+
Peak daily tokens 45.6M
|
|
24
|
+
Longest turn 12m 34s
|
|
25
|
+
Current streak 3 days
|
|
26
|
+
Longest streak 21 days
|
|
27
|
+
Daily buckets 30 days
|
|
20
28
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
Codex Desktop's profile screen is backed by its remote profile data and may include account-level usage that is no longer present in local session files, usage from another device, or data retained after local cleanup. For that reason, `activity.currentStreakDays` and `activity.longestStreakDays` are not guaranteed to match the Codex Desktop profile. The diagnostic extension includes `profileComparison.parity: "not_guaranteed"` when the analyzer has not compared against a remote profile baseline.
|
|
24
|
-
|
|
25
|
-
The analyzer does not call Codex Desktop remote profile APIs or plugin-store APIs. `skills` and `plugins` are local session-derived fields, so they are unavailable when actual invocation source events are absent.
|
|
26
|
-
|
|
27
|
-
`codexAssets.pet` is a safe logical reference, not an image export. The analyzer can report the Codex Desktop built-in pet catalog and the selected pet id when that setting is available. If no selected pet setting is persisted, it follows Codex Desktop's default and reports the built-in `codex` pet as `codex-built-in:pet:codex`. When a selected custom pet is found under `pets/<id>/pet.json` with an allowlisted spritesheet extension, the analyzer reports `codex-local:pet:custom-selected`.
|
|
28
|
-
|
|
29
|
-
The default analyzer output does not include local file paths, custom pet directory names, image bytes, data URLs, or generated image artifacts. Files under `generated_images/` are treated as private generated artifacts and are not promoted to `codexAssets`. A wrapper that wants to render custom pet images in a web application must provide its own opt-in asset export, upload, or local serving layer.
|
|
30
|
-
|
|
31
|
-
Local repository smoke command:
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
node bin/codex-usage-analyzer.js analyze --json
|
|
29
|
+
Captured at 2026-07-11T00:00:00.000Z
|
|
35
30
|
```
|
|
36
31
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
node bin/codex-usage-analyzer.js analyze --json --codex-home src/__tests__/fixtures/parser
|
|
41
|
-
```
|
|
32
|
+
The values above are synthetic. Your command reads the usage available to the currently signed-in Codex account.
|
|
42
33
|
|
|
43
|
-
|
|
34
|
+
For machine-readable output:
|
|
44
35
|
|
|
45
36
|
```bash
|
|
46
|
-
|
|
37
|
+
npx --yes codex-usage-analyzer@latest --json
|
|
47
38
|
```
|
|
48
39
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"contractVersion": 1,
|
|
43
|
+
"capturedAt": "2026-07-11T00:00:00.000Z",
|
|
44
|
+
"summary": {
|
|
45
|
+
"lifetimeTokens": 1234567890,
|
|
46
|
+
"peakDailyTokens": 45600000,
|
|
47
|
+
"longestRunningTurnSec": 754,
|
|
48
|
+
"currentStreakDays": 3,
|
|
49
|
+
"longestStreakDays": 21
|
|
50
|
+
},
|
|
51
|
+
"dailyUsageBuckets": [
|
|
52
|
+
{
|
|
53
|
+
"startDate": "2026-07-10",
|
|
54
|
+
"tokens": 123456
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
}
|
|
53
58
|
```
|
|
54
59
|
|
|
55
|
-
|
|
60
|
+
## Why this CLI
|
|
56
61
|
|
|
57
|
-
|
|
62
|
+
- **Account-level source:** use the same app-server method intended for Codex account usage instead of estimating from retained local files.
|
|
63
|
+
- **Privacy-first boundary:** receive usage metrics without adding names, usernames, avatars, emails, account identifiers, or credentials to the output.
|
|
64
|
+
- **Stable integration:** consume a versioned JSON contract with allowlisted fields and explicit `null` semantics.
|
|
65
|
+
- **Small runtime:** use Node.js built-ins and the Codex CLI already installed on your machine; there are no runtime package dependencies.
|
|
58
66
|
|
|
59
|
-
|
|
60
|
-
a local analyzer result with values manually copied from Codex Desktop's profile
|
|
61
|
-
UI. The comparison uses a redacted baseline file; do not commit a baseline copied
|
|
62
|
-
from a real account.
|
|
67
|
+
## Supported metrics
|
|
63
68
|
|
|
64
|
-
|
|
65
|
-
|
|
69
|
+
| Field | Meaning |
|
|
70
|
+
|---|---|
|
|
71
|
+
| `summary.lifetimeTokens` | Lifetime token usage |
|
|
72
|
+
| `summary.peakDailyTokens` | Highest token usage reported for one day |
|
|
73
|
+
| `summary.longestRunningTurnSec` | Longest-running turn, in seconds |
|
|
74
|
+
| `summary.currentStreakDays` | Current activity streak, in days |
|
|
75
|
+
| `summary.longestStreakDays` | Longest activity streak, in days |
|
|
76
|
+
| `dailyUsageBuckets` | Source-dated daily token buckets, when available |
|
|
66
77
|
|
|
67
|
-
|
|
78
|
+
Every summary field is present. A value of `null` means the upstream method did not provide that metric; it does not mean zero. Daily buckets can likewise be `null`, an empty array, or an array of dated values.
|
|
68
79
|
|
|
69
|
-
|
|
70
|
-
node bin/codex-usage-analyzer.js analyze --json > <local-snapshot.json>
|
|
71
|
-
```
|
|
80
|
+
## Requirements
|
|
72
81
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
82
|
+
- Node.js 20 or newer
|
|
83
|
+
- A recent Codex CLI available as `codex` on `PATH`
|
|
84
|
+
- A ChatGPT-backed Codex sign-in that supports `account/usage/read`
|
|
76
85
|
|
|
77
|
-
|
|
78
|
-
node scripts/profile-smoke.js --baseline <redacted-baseline.json> --snapshot <local-snapshot.json>
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
The smoke output is a field-level summary. Result statuses mean:
|
|
82
|
-
|
|
83
|
-
- `match`: expected and actual values are equal.
|
|
84
|
-
- `within_tolerance`: numeric values differ only within the baseline tolerance.
|
|
85
|
-
- `mismatch`: the field is comparable and differs outside tolerance.
|
|
86
|
-
- `not_comparable`: the baseline intentionally marks the field as visible in
|
|
87
|
-
profile UI but not comparable to local analyzer data.
|
|
88
|
-
- `skipped`: the baseline did not include that expected field.
|
|
86
|
+
API-key-only and Bedrock authentication do not provide this account usage method. Sign in through the installed Codex CLI before running the analyzer. The package delegates authentication to Codex and never asks you to paste a token.
|
|
89
87
|
|
|
90
|
-
|
|
91
|
-
differences:
|
|
88
|
+
## CLI reference
|
|
92
89
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
- `source_mismatch` means the baseline author marked that field as comparing
|
|
96
|
-
different sources, such as remote profile data versus local analyzer data.
|
|
97
|
-
- `profile_parity_not_guaranteed` means the local snapshot itself reports that
|
|
98
|
-
remote profile parity is not guaranteed, and the field is source-sensitive.
|
|
99
|
-
- `remote_profile_source_differs` is used with `not_comparable` fields that
|
|
100
|
-
should be visible in the profile baseline but intentionally not compared.
|
|
90
|
+
```text
|
|
91
|
+
codex-usage-analyzer - Read your Codex account usage
|
|
101
92
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
{
|
|
107
|
-
"sourcePolicy": {
|
|
108
|
-
"activity.totalThreads": "source_mismatch",
|
|
109
|
-
"skills.topSkills": "source_mismatch",
|
|
110
|
-
"plugins.topPlugins": "source_mismatch"
|
|
111
|
-
}
|
|
112
|
-
}
|
|
93
|
+
Usage:
|
|
94
|
+
codex-usage-analyzer [usage] [--json]
|
|
95
|
+
codex-usage-analyzer [usage] --help
|
|
96
|
+
codex-usage-analyzer --version
|
|
113
97
|
```
|
|
114
98
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
profile UI and local analyzer cover different source ranges.
|
|
126
|
-
- Streaks use the analyzer's UTC date buckets from local token events; profile
|
|
127
|
-
UI can use remote activity data.
|
|
128
|
-
- Activity insights and thread counts can differ when the profile UI aggregates
|
|
129
|
-
remote account-level data and the analyzer reads retained local sessions.
|
|
130
|
-
- Top skills/plugins require actual local invocation events. Catalog, enabled
|
|
131
|
-
tool lists, or remote profile rankings alone are not counted.
|
|
132
|
-
- `--fixture-sample` snapshots are rejected by the profile smoke helper, so a
|
|
133
|
-
packaged example cannot pass as a real profile parity check.
|
|
134
|
-
|
|
135
|
-
Redaction rules for real local baselines:
|
|
136
|
-
|
|
137
|
-
- Keep only profile-visible numbers, model ids, ranking ids, and explicit
|
|
138
|
-
tolerance values needed for comparison.
|
|
139
|
-
- Do not include real account handles, emails, local private paths, credential
|
|
140
|
-
material, conversation identifiers, conversation titles, prompts, responses,
|
|
141
|
-
tool input/output bodies, image captures, or unredacted session JSONL.
|
|
99
|
+
| Command | Output |
|
|
100
|
+
|---|---|
|
|
101
|
+
| `codex-usage-analyzer` | Human-readable account usage |
|
|
102
|
+
| `codex-usage-analyzer usage` | Same human-readable output |
|
|
103
|
+
| `codex-usage-analyzer --json` | Account Usage Contract JSON |
|
|
104
|
+
| `codex-usage-analyzer usage --json` | Same JSON output |
|
|
105
|
+
| `codex-usage-analyzer --help` | Help without starting app-server |
|
|
106
|
+
| `codex-usage-analyzer --version` | Package version without starting app-server |
|
|
107
|
+
|
|
108
|
+
Successful output is written to stdout. Failures are written to stderr as a stable error code and a safe message, without raw RPC data or app-server stderr.
|
|
142
109
|
|
|
143
110
|
## SDK
|
|
144
111
|
|
|
145
112
|
```js
|
|
146
113
|
import {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
validateUsageSnapshotV2
|
|
114
|
+
ACCOUNT_USAGE_CONTRACT_VERSION,
|
|
115
|
+
CodexUsageError,
|
|
116
|
+
readAccountUsage
|
|
151
117
|
} from "codex-usage-analyzer";
|
|
152
118
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
codexHome: "/path/to/codex-home"
|
|
162
|
-
});
|
|
119
|
+
try {
|
|
120
|
+
const usage = await readAccountUsage({ timeoutMs: 15_000 });
|
|
121
|
+
console.log(usage.contractVersion === ACCOUNT_USAGE_CONTRACT_VERSION);
|
|
122
|
+
} catch (error) {
|
|
123
|
+
if (error instanceof CodexUsageError) {
|
|
124
|
+
console.error(error.code);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
163
127
|
```
|
|
164
128
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
Use `createSampleUsageSnapshotV2()` only for examples, tests, and contract inspection.
|
|
129
|
+
The SDK returns the same document as CLI `--json`. See the [Account Usage Contract](docs/account-usage-contract.md) and [JSON Schema](docs/account-usage.schema.json) for field and compatibility rules.
|
|
168
130
|
|
|
169
|
-
|
|
131
|
+
## How it works
|
|
170
132
|
|
|
171
|
-
|
|
172
|
-
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
- `USAGE_SNAPSHOT_V2_SCHEMA_VERSION`
|
|
177
|
-
- `sampleUsageSnapshotV2`
|
|
133
|
+
1. Spawn `codex app-server` without a shell.
|
|
134
|
+
2. Complete the stable app-server initialization handshake.
|
|
135
|
+
3. Call `account/usage/read`.
|
|
136
|
+
4. Allowlist and validate the supported fields.
|
|
137
|
+
5. Stop the child process and return the normalized document.
|
|
178
138
|
|
|
179
|
-
|
|
139
|
+
The package has no direct credential reader and no private profile endpoint fallback. Authentication and service communication remain inside the installed Codex process.
|
|
180
140
|
|
|
181
|
-
|
|
182
|
-
modules, snapshot validators, type declarations, and the sample snapshot fixture
|
|
183
|
-
used by the SDK. It excludes repository tests, parser fixtures, working docs,
|
|
184
|
-
and repository-only smoke helper scripts.
|
|
141
|
+
## Downstream integrations
|
|
185
142
|
|
|
186
|
-
|
|
143
|
+
Profile sites, README cards, and other services can accept the identity-free JSON contract and combine it with identity they manage separately. The [Downstream Integration Guide](docs/downstream-integration.md) defines recommended field names, ownership, submit-token, validation, rendering, caching, and deletion boundaries.
|
|
187
144
|
|
|
188
|
-
|
|
145
|
+
Do not add identity fields to the account usage document. A downstream service should resolve GitHub identity from its own authenticated account binding, not trust a display name or avatar submitted by this CLI.
|
|
189
146
|
|
|
190
|
-
|
|
147
|
+
## Privacy and Security
|
|
191
148
|
|
|
192
|
-
|
|
149
|
+
The default CLI does not directly read or emit:
|
|
193
150
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
} from "codex-usage-analyzer";
|
|
151
|
+
- access tokens, refresh tokens, cookies, or keychain entries
|
|
152
|
+
- names, usernames, avatars, emails, or account identifiers
|
|
153
|
+
- prompts, responses, tool input, tool output, or local session files
|
|
154
|
+
- local filesystem paths, raw RPC responses, or raw app-server stderr
|
|
199
155
|
|
|
200
|
-
|
|
201
|
-
await submitToProductService({ snapshot });
|
|
202
|
-
```
|
|
156
|
+
Treat account usage as private data even though the contract excludes identity. Review a downstream service's retention and visibility policy before submitting output anywhere.
|
|
203
157
|
|
|
204
|
-
|
|
158
|
+
For vulnerability reporting and supported versions, see [SECURITY.md](SECURITY.md).
|
|
205
159
|
|
|
206
|
-
##
|
|
160
|
+
## Troubleshooting
|
|
207
161
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
The test suite validates the SDK exports, production parser behavior, asset safe output behavior, fixture-only CLI behavior, and `UsageSnapshot v2` schema rules.
|
|
162
|
+
| Error code | What to check |
|
|
163
|
+
|---|---|
|
|
164
|
+
| `CODEX_NOT_FOUND` | Install or update Codex and confirm `codex` is on `PATH`. |
|
|
165
|
+
| `APP_SERVER_START_FAILED` or `APP_SERVER_EXITED` | Confirm the installed Codex CLI can start and that your environment permits child processes. |
|
|
166
|
+
| `APP_SERVER_TIMEOUT` | Retry after checking connectivity; SDK callers can set `timeoutMs` up to 120000. |
|
|
167
|
+
| `APP_SERVER_RPC_ERROR` | Update Codex and confirm a compatible ChatGPT-backed sign-in. |
|
|
168
|
+
| `APP_SERVER_PROTOCOL_ERROR` or `INVALID_ACCOUNT_USAGE_RESPONSE` | Update both Codex and this package; the upstream response was not safe to normalize. |
|
|
217
169
|
|
|
218
|
-
|
|
170
|
+
The CLI intentionally suppresses raw upstream details. When reporting a bug, include the package version, Codex version, Node.js version, platform, command shape, and error code only.
|
|
219
171
|
|
|
220
|
-
|
|
172
|
+
## Development
|
|
221
173
|
|
|
222
174
|
```bash
|
|
223
175
|
npm test
|
|
224
176
|
npm pack --dry-run
|
|
225
|
-
node bin/codex-usage-analyzer.js analyze --json
|
|
226
|
-
npx --yes github:postmelee/codex-usage-analyzer analyze --json
|
|
227
177
|
```
|
|
228
178
|
|
|
229
|
-
|
|
179
|
+
Maintainers should use the repository's [npm release guide](mydocs/manual/npm_release_guide.md) for release operations; those steps are intentionally kept out of the user guide.
|
|
230
180
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
181
|
+
## Contributing
|
|
182
|
+
|
|
183
|
+
Read [CONTRIBUTING.md](CONTRIBUTING.md) before opening a pull request. Changes to the public contract need an issue and explicit consumer-impact review.
|
|
234
184
|
|
|
235
|
-
|
|
236
|
-
issue comments. Record only structural pass/fail results, exit codes, and
|
|
237
|
-
package metadata needed for release verification.
|
|
185
|
+
## Support
|
|
238
186
|
|
|
239
|
-
|
|
187
|
+
Use [GitHub Issues](https://github.com/postmelee/codex-usage-analyzer/issues) for reproducible bugs and focused feature requests. Use GitHub's private vulnerability reporting path for security-sensitive reports.
|
|
240
188
|
|
|
241
|
-
|
|
189
|
+
## License
|
|
242
190
|
|
|
243
|
-
|
|
244
|
-
- use private Codex Desktop profile endpoints
|
|
245
|
-
- export custom pet image files by default
|
|
246
|
-
- issue or store submit tokens
|
|
247
|
-
- own public profile handles
|
|
248
|
-
- render cards or images
|
|
249
|
-
- update GitHub README files
|
|
250
|
-
- upload raw credential files
|
|
251
|
-
- expose local private paths
|
|
191
|
+
Copyright (c) postmelee. Released under the [MIT License](LICENSE).
|
|
252
192
|
|
|
253
|
-
|
|
193
|
+
This license covers only this repository's code and documentation. It does not grant rights to OpenAI services, Codex assets, user data, model outputs, trademarks, or third-party content.
|
|
254
194
|
|
|
255
|
-
This
|
|
195
|
+
This independent project is not affiliated with, endorsed by, or sponsored by OpenAI. OpenAI and Codex names and trademarks belong to their respective owners.
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported versions
|
|
4
|
+
|
|
5
|
+
| Version | Supported |
|
|
6
|
+
|---|---|
|
|
7
|
+
| Latest published npm release | Yes |
|
|
8
|
+
| `main` | Development branch; not a supported release |
|
|
9
|
+
| Older npm releases | No |
|
|
10
|
+
|
|
11
|
+
Security fixes are released on the latest package line. Users should update to the newest published version before reporting an issue that may already be fixed.
|
|
12
|
+
|
|
13
|
+
## Reporting a vulnerability
|
|
14
|
+
|
|
15
|
+
Use [GitHub private vulnerability reporting](https://github.com/postmelee/codex-usage-analyzer/security/advisories/new) so maintainers can investigate without exposing users.
|
|
16
|
+
|
|
17
|
+
If private reporting is unavailable, open a minimal public issue asking for a secure contact channel. Do not include exploit details or sensitive data in that issue.
|
|
18
|
+
|
|
19
|
+
Include only the information needed to reproduce the security boundary:
|
|
20
|
+
|
|
21
|
+
- affected package and Codex CLI versions
|
|
22
|
+
- Node.js version and operating system
|
|
23
|
+
- command shape and safe error code
|
|
24
|
+
- impact and minimal reproduction using synthetic data
|
|
25
|
+
- whether the issue affects command execution, response validation, logging, persistence, or package integrity
|
|
26
|
+
|
|
27
|
+
Never submit authentication tokens, cookies, account identifiers, raw account usage, raw app-server responses or stderr, prompts, responses, local filesystem paths, private repository links, or private keys.
|
|
28
|
+
|
|
29
|
+
## Security scope
|
|
30
|
+
|
|
31
|
+
Reports are especially useful when they involve:
|
|
32
|
+
|
|
33
|
+
- unexpected command or shell execution
|
|
34
|
+
- credential, account identifier, or private data exposure
|
|
35
|
+
- unsafe handling of app-server protocol messages
|
|
36
|
+
- validation bypass in the public contract
|
|
37
|
+
- sensitive information written to stdout, stderr, logs, or package artifacts
|
|
38
|
+
- npm package, dependency, workflow, or trusted-publishing supply-chain risk
|
|
39
|
+
|
|
40
|
+
The CLI intentionally delegates sign-in to the installed Codex process. It does not directly read authentication files or keychains and does not accept pasted OpenAI credentials. A downstream service that accepts this package's output has its own authentication, storage, rendering, visibility, retention, and deletion responsibilities.
|
|
41
|
+
|
|
42
|
+
## Disclosure
|
|
43
|
+
|
|
44
|
+
Please allow maintainers to confirm the issue and prepare a fix before public disclosure. The project will credit reporters when requested and appropriate, but it does not promise a fixed response or remediation timeline.
|
|
@@ -4,7 +4,9 @@ import { runCli } from "../src/cli.js";
|
|
|
4
4
|
try {
|
|
5
5
|
const exitCode = await runCli(process.argv.slice(2));
|
|
6
6
|
process.exitCode = exitCode;
|
|
7
|
-
} catch
|
|
8
|
-
|
|
7
|
+
} catch {
|
|
8
|
+
process.stderr.write(
|
|
9
|
+
"codex-usage-analyzer: Unexpected failure. [UNEXPECTED_ERROR]\n"
|
|
10
|
+
);
|
|
9
11
|
process.exitCode = 1;
|
|
10
12
|
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Account Usage Contract
|
|
2
|
+
|
|
3
|
+
`codex-usage-analyzer --json` and the JavaScript `readAccountUsage()` API return the same Account Usage Contract. The current contract version is `1`.
|
|
4
|
+
|
|
5
|
+
The contract is a minimal, stable projection of the official Codex app-server `account/usage/read` result. It never includes a name, username, avatar, email, account identifier, or authentication material.
|
|
6
|
+
|
|
7
|
+
The machine-readable source of truth is [`account-usage.schema.json`](account-usage.schema.json).
|
|
8
|
+
|
|
9
|
+
## Shape
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"contractVersion": 1,
|
|
14
|
+
"capturedAt": "2026-07-11T00:00:00.000Z",
|
|
15
|
+
"summary": {
|
|
16
|
+
"lifetimeTokens": 1234567890,
|
|
17
|
+
"peakDailyTokens": 45600000,
|
|
18
|
+
"longestRunningTurnSec": 754,
|
|
19
|
+
"currentStreakDays": 3,
|
|
20
|
+
"longestStreakDays": 21
|
|
21
|
+
},
|
|
22
|
+
"dailyUsageBuckets": [
|
|
23
|
+
{
|
|
24
|
+
"startDate": "2026-07-10",
|
|
25
|
+
"tokens": 123456
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
All example values are synthetic and do not represent a real account.
|
|
32
|
+
|
|
33
|
+
## Root fields
|
|
34
|
+
|
|
35
|
+
| Field | Type | Meaning |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| `contractVersion` | integer, constant `1` | Version of this downstream contract |
|
|
38
|
+
| `capturedAt` | ISO 8601 UTC string | Time at which the app-server response was received |
|
|
39
|
+
| `summary` | object | Account-level token and activity summary |
|
|
40
|
+
| `dailyUsageBuckets` | array or `null` | Daily token buckets; `null` means unavailable upstream |
|
|
41
|
+
|
|
42
|
+
## Summary fields
|
|
43
|
+
|
|
44
|
+
Every summary field is always present. Each value is either a non-negative safe integer or `null`.
|
|
45
|
+
|
|
46
|
+
| Field | Meaning |
|
|
47
|
+
|---|---|
|
|
48
|
+
| `lifetimeTokens` | Lifetime token usage |
|
|
49
|
+
| `peakDailyTokens` | Highest token usage reported for one day |
|
|
50
|
+
| `longestRunningTurnSec` | Longest-running turn duration, in seconds |
|
|
51
|
+
| `currentStreakDays` | Current activity streak, in days |
|
|
52
|
+
| `longestStreakDays` | Longest activity streak, in days |
|
|
53
|
+
|
|
54
|
+
When the upstream method omits a metric or returns `null`, the wrapper preserves `null`. Downstream consumers must treat `null` as unavailable, not zero.
|
|
55
|
+
|
|
56
|
+
## Daily buckets
|
|
57
|
+
|
|
58
|
+
- `dailyUsageBuckets: null` means the upstream method did not provide buckets.
|
|
59
|
+
- `dailyUsageBuckets: []` means the bucket source was present but contained no rows.
|
|
60
|
+
- Each row contains only `startDate` and `tokens`.
|
|
61
|
+
- `startDate` is a `YYYY-MM-DD` date-only string. Consumers must preserve it as the source date instead of applying timezone rebucketing.
|
|
62
|
+
- `tokens` is a non-negative safe integer.
|
|
63
|
+
|
|
64
|
+
## Forward compatibility
|
|
65
|
+
|
|
66
|
+
The wrapper emits allowlisted fields only. New fields added by app-server do not automatically enter contract version 1. Changing an existing field's meaning, nullability, or root shape requires a new contract version and a consumer-impact review.
|
|
67
|
+
|
|
68
|
+
Version 1 objects reject unknown fields because `additionalProperties` is false throughout the schema. Validate `contractVersion` before accepting a document and reject unsupported versions explicitly.
|
|
69
|
+
|
|
70
|
+
## Privacy boundary
|
|
71
|
+
|
|
72
|
+
The contract excludes:
|
|
73
|
+
|
|
74
|
+
- display name, username, avatar, email, and account identifier
|
|
75
|
+
- access or refresh tokens, cookies, and credential paths
|
|
76
|
+
- local Codex session content and local filesystem paths
|
|
77
|
+
- raw app-server responses, stderr, and RPC error messages
|
|
78
|
+
|
|
79
|
+
Identity, submit tokens, storage, card rendering, cache policy, and deletion belong to the downstream service. See the [Downstream Integration Guide](downstream-integration.md).
|
|
80
|
+
|
|
81
|
+
## Upstream
|
|
82
|
+
|
|
83
|
+
- [OpenAI Codex App Server](https://developers.openai.com/codex/app-server)
|
|
84
|
+
- Method: `account/usage/read`
|
|
85
|
+
- API-key-only and Bedrock authentication are not supported by this method.
|