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.
@@ -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
- `codex-usage-analyzer` is the local usage analysis package that emits `UsageSnapshot v2` JSON.
3
+ [![npm package](https://img.shields.io/npm/v/codex-usage-analyzer)](https://www.npmjs.com/package/codex-usage-analyzer)
4
+ [![CI](https://github.com/postmelee/codex-usage-analyzer/actions/workflows/ci.yml/badge.svg)](https://github.com/postmelee/codex-usage-analyzer/actions/workflows/ci.yml)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
4
6
 
5
- The package is designed to be reused by product-specific CLIs and web services. It analyzes local usage sources and returns a validated snapshot; account identity, submit tokens, public profile URLs, and rendered cards belong to the product that wraps it.
7
+ Read the account usage shown by Codex through the official app-server protocol, from one small CLI.
6
8
 
7
- ## CLI
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
- The published CLI entry point is:
11
+ ## Quick start
10
12
 
11
13
  ```bash
12
- npx codex-usage-analyzer@latest analyze --json
14
+ npx --yes codex-usage-analyzer@latest
13
15
  ```
14
16
 
15
- The `--json` mode writes a single `UsageSnapshot v2` object to stdout. Errors and usage text are written to stderr.
17
+ Human-readable output:
16
18
 
17
- The production `analyze --json` path reads local Codex session JSONL files from the Codex home directory. It uses `--codex-home <path>` when provided, otherwise `CODEX_HOME`, otherwise the default Codex home. When the session source is missing or unreadable, the command still emits a valid snapshot: required numeric totals are zero, unavailable usage details are `null` or empty arrays, and `extensions["codexUsageAnalyzer.diagnostics"]` explains the unavailable source. The production path does not return the sample fixture.
19
+ ```text
20
+ Codex account usage
18
21
 
19
- The parser currently derives token totals, daily token buckets, model ranking, skill/plugin ranking, longest task duration, streaks, reasoning effort, and total thread count from allowlisted session event fields. Skill/plugin rankings are counted only from actual invocation events that can be classified by session tool catalog metadata; catalog or enabled-tool lists alone do not increment usage. Custom/local skill and plugin names may appear in `topSkills` and `topPlugins`, but the analyzer does not emit raw local file paths, raw JSONL lines, session ids, prompts, responses, tool input, or tool output.
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
- Streak fields are local-only analyzer results. The current parser treats a UTC date as active when local session JSONL contains positive `last_token_usage` for that date.
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
- Parser fixture smoke command:
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
- Asset fixture smoke command:
34
+ For machine-readable output:
44
35
 
45
36
  ```bash
46
- node bin/codex-usage-analyzer.js analyze --json --codex-home src/__tests__/fixtures/assets
37
+ npx --yes codex-usage-analyzer@latest --json
47
38
  ```
48
39
 
49
- Development fixture command:
50
-
51
- ```bash
52
- node bin/codex-usage-analyzer.js analyze --json --fixture-sample
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
- The `--fixture-sample` mode is for tests, examples, and contract inspection only. It returns the packaged sample snapshot and must not be treated as real local Codex usage.
60
+ ## Why this CLI
56
61
 
57
- ## Profile Parity Smoke (Repository Only)
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
- Use the profile smoke helper from a repository checkout when you want to compare
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
- The helper is not published as an npm package binary. It is a maintainer QA
65
- tool for release and parser parity checks.
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
- Create a production snapshot:
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
- ```bash
70
- node bin/codex-usage-analyzer.js analyze --json > <local-snapshot.json>
71
- ```
80
+ ## Requirements
72
81
 
73
- Create a redacted baseline using
74
- `src/__tests__/fixtures/profile-baseline/redacted-baseline.json` as the shape
75
- reference, then compare:
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
- ```bash
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
- Mismatch reasons distinguish parser-bug candidates from expected source
91
- differences:
88
+ ## CLI reference
92
89
 
93
- - `numeric_mismatch`, `value_mismatch`, `actual_field_absent`, and ranking
94
- shape reasons mean a comparable field differed.
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
- Use optional baseline `sourcePolicy` metadata to keep a field comparable while
103
- labeling source-driven differences:
104
-
105
- ```json
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
- `sourcePolicy` belongs only to the redacted smoke baseline. It is not part of
116
- `UsageSnapshot v2`, and the analyzer output schema does not change. A
117
- source-aware mismatch still makes the smoke command exit nonzero; the field
118
- reason is what separates source differences from likely parser regressions.
119
-
120
- Known mismatch reasons:
121
-
122
- - Codex Desktop profile values can come from a remote account-level source,
123
- while this analyzer reads local session files and local Codex metadata.
124
- - Local cleanup, migration, archiving, deletion, or another device can make the
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
- analyzeUsage,
148
- assertUsageSnapshotV2,
149
- createSampleUsageSnapshotV2,
150
- validateUsageSnapshotV2
114
+ ACCOUNT_USAGE_CONTRACT_VERSION,
115
+ CodexUsageError,
116
+ readAccountUsage
151
117
  } from "codex-usage-analyzer";
152
118
 
153
- const snapshot = await analyzeUsage();
154
- assertUsageSnapshotV2(snapshot);
155
- ```
156
-
157
- `analyzeUsage()` returns the production analyzer result. You can pass `codexHome` for deterministic tests or custom Codex home discovery:
158
-
159
- ```js
160
- const snapshot = await analyzeUsage({
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
- When a local source is unavailable, fields use zero, `null`, empty arrays, and a namespaced diagnostic extension rather than sample values.
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
- Public exports:
131
+ ## How it works
170
132
 
171
- - `analyzeUsage(options?)`
172
- - `createSampleUsageSnapshotV2(overrides?)`
173
- - `validateUsageSnapshotV2(value)`
174
- - `assertUsageSnapshotV2(value)`
175
- - `isUsageSnapshotV2(value)`
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
- ## Package Contents
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
- The npm package includes the CLI entry point, runtime analyzer source, parser
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
- ## Ownership Boundary
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
- The analyzer owns local usage fields such as token totals, token breakdown, model usage, skill usage, plugin usage, activity statistics, and safe Codex pet logical references.
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
- Web products own GitHub login, display name, avatar URL, bio, profile visibility, submit tokens, devices, public URLs, rendered cards, and any uploaded or web-served pet image assets.
147
+ ## Privacy and Security
191
148
 
192
- Product-specific wrappers can call this SDK and submit the resulting snapshot to their own service:
149
+ The default CLI does not directly read or emit:
193
150
 
194
- ```js
195
- import {
196
- analyzeUsage,
197
- assertUsageSnapshotV2
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
- const snapshot = assertUsageSnapshotV2(await analyzeUsage());
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
- Wrapper metadata such as bearer tokens, device ids, account handles, visibility, GitHub bio, GitHub avatar URLs, custom pet upload URLs, and card-only rendering hints must stay outside the analyzer snapshot.
158
+ For vulnerability reporting and supported versions, see [SECURITY.md](SECURITY.md).
205
159
 
206
- ## Tests
160
+ ## Troubleshooting
207
161
 
208
- ```bash
209
- npm test
210
- node bin/codex-usage-analyzer.js analyze --json
211
- node bin/codex-usage-analyzer.js analyze --json --codex-home src/__tests__/fixtures/parser
212
- node bin/codex-usage-analyzer.js analyze --json --codex-home src/__tests__/fixtures/assets
213
- node bin/codex-usage-analyzer.js analyze --json --fixture-sample
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
- ## Release Checklist
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
- Before publishing:
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
- After the package is published:
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
- ```bash
232
- npx --yes codex-usage-analyzer@latest analyze --json
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
- Do not paste raw production snapshot output into release notes, PR bodies, or
236
- issue comments. Record only structural pass/fail results, exit codes, and
237
- package metadata needed for release verification.
185
+ ## Support
238
186
 
239
- ## Non-Goals
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
- This package does not:
189
+ ## License
242
190
 
243
- - perform GitHub OAuth
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
- ## Status
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 repository is the standalone home for the analyzer package. The production analyzer path is separated from the packaged sample fixture, and the release checklist above is the maintainer path for npm publishing and npx verification. Broader parity work against Codex Desktop profile data remains outside the npm release flow.
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 (error) {
8
- console.error(error instanceof Error ? error.message : String(error));
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.