codex-token-tracker 0.1.1 → 0.2.1
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/CHANGELOG.md +110 -0
- package/README.md +100 -8
- package/dist/cli.js +664 -80
- package/dist/main.js +604 -89
- package/dist/preload.js +3 -0
- package/dist/renderer/renderer.js +235 -5
- package/dist/renderer/styles.css +129 -0
- package/package.json +5 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `codex-token-tracker`. This project follows [Semantic Versioning](https://semver.org/).
|
|
4
|
+
|
|
5
|
+
## 0.2.1 — 2026-09-01
|
|
6
|
+
|
|
7
|
+
A manual **Sync** button that recalibrates this device's numbers on the dashboard.
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **Full sync.** The popover header gets a **⟳** button (also *Sync now* in the Account card and the tray
|
|
12
|
+
menu, and `codex-token-tracker sync` on the CLI). Unlike the background upload — which every 60 s pushes
|
|
13
|
+
only the hour buckets and sessions that changed — a full sync throws away every cache on the way:
|
|
14
|
+
1. re-reads the config, so agents enabled since start-up are picked up;
|
|
15
|
+
2. re-discovers every session directory and re-parses every transcript from scratch — Codex plus the
|
|
16
|
+
coding agents running on your Codex subscription (pi, OpenCode, Cline / Roo / Kilo, Hermes) and any
|
|
17
|
+
configured `extraSessionDirs` — instead of skipping files whose size and mtime are unchanged;
|
|
18
|
+
3. recomputes the aggregates with the current pricing table;
|
|
19
|
+
4. re-uploads **everything**, so the dashboard's totals for this device are replaced by the freshly
|
|
20
|
+
computed ones;
|
|
21
|
+
5. pulls the other devices' rows and the live rate limits back down.
|
|
22
|
+
|
|
23
|
+
Use it when a machine's numbers look wrong, after installing a new agent, or after an update that
|
|
24
|
+
changes the pricing table. It is manual only — never on a timer — because it re-sends the whole history.
|
|
25
|
+
- A banner in the popover reports the phase while a sync runs (*Rescanning every agent's transcripts…*,
|
|
26
|
+
*Re-uploading this device's history…*) and then the result, e.g. `Synced codex, pi · 75 files ·
|
|
27
|
+
75 sessions · 70 hours re-uploaded`. Signed out, the rescan still runs and nothing leaves the machine.
|
|
28
|
+
- `codex-token-tracker sync` prints the same summary and exits non-zero if the sync failed.
|
|
29
|
+
|
|
30
|
+
- **Dev builds target the dev environment.** A build now carries its channel, stamped by
|
|
31
|
+
`scripts/build.mjs`: only `--release` (what `prepack` runs) produces a production build, so every
|
|
32
|
+
published tarball is prod and every local `pnpm build` / `pnpm dev` is dev. A dev build
|
|
33
|
+
- defaults to the local dashboard `http://localhost:3000` instead of `https://codex.chenli.dev`, and
|
|
34
|
+
therefore uploads to whatever Convex deployment that dashboard advertises — the dev one;
|
|
35
|
+
- keeps its config, device token and upload state in `~/.codex-tracker-dev`, so a local run can
|
|
36
|
+
never overwrite the production token or the record of what was already pushed to production;
|
|
37
|
+
- defaults `checkUpdates` to `false` and refuses `codex-token-tracker update`, which would otherwise
|
|
38
|
+
install the published package over the checkout;
|
|
39
|
+
- runs as `Codex Tracker (dev)` with its own Electron userData directory and macOS LaunchAgent, so it
|
|
40
|
+
can run **beside** an installed copy instead of fighting it for the single-instance lock;
|
|
41
|
+
- shows an orange **DEV** badge in the popover header and names its dashboard and config directory in
|
|
42
|
+
`--version`, `status` and `paths`.
|
|
43
|
+
|
|
44
|
+
`--dashboard <url>`, `config set dashboardUrl` and `CODEX_TRACKER_HOME` still override all of it.
|
|
45
|
+
|
|
46
|
+
### Changed
|
|
47
|
+
|
|
48
|
+
- `Uploader.pushAll()` takes a `{ full }` option that clears the pushed-buckets/pushed-sessions record
|
|
49
|
+
before building the payload, and waits for an in-flight incremental push instead of skipping the call.
|
|
50
|
+
- `SessionStore.reset()` drops the parsed-file index so a following deep refresh re-reads everything.
|
|
51
|
+
- Packaging scripts: `build:release` builds with the prod channel; `prepack` runs it (so `npm pack` and
|
|
52
|
+
`npm publish` always ship a prod build) and `postpack` restores the dev build in `dist/`.
|
|
53
|
+
`prepublishOnly` now only typechecks.
|
|
54
|
+
- `app.setName()` moved ahead of `requestSingleInstanceLock()` — the lock is keyed on the userData
|
|
55
|
+
directory, which is derived from the name.
|
|
56
|
+
|
|
57
|
+
## 0.2.0 — 2026-09-01
|
|
58
|
+
|
|
59
|
+
Pricing accuracy, an honest tokens/s number, and self-update.
|
|
60
|
+
|
|
61
|
+
### Added
|
|
62
|
+
|
|
63
|
+
- **`codex-token-tracker` command.** Installing globally now puts **two** equivalent executables on your
|
|
64
|
+
PATH — `codex-token-tracker` (matching the package name) and the existing `codex-tracker` alias. Both
|
|
65
|
+
run the same CLI; nothing you already scripted breaks.
|
|
66
|
+
- **Self-update.** `codex-token-tracker update` checks the npm registry and installs the newest release
|
|
67
|
+
with the package manager this copy came from (npm / pnpm / yarn / bun). `--check` reports without
|
|
68
|
+
installing. The menu bar app shows an **Update** banner and a *Check for updates* item in the tray
|
|
69
|
+
menu; installing from there asks you to restart to apply.
|
|
70
|
+
- Checks are cached for 6 h in `~/.codex-tracker/update.json` and send no usage data or identifiers.
|
|
71
|
+
- Disable with `config set checkUpdates false`; point at a mirror with `CODEX_TRACKER_REGISTRY`.
|
|
72
|
+
- `codex-tracker status` prints a one-line notice when a newer version exists.
|
|
73
|
+
- **Long-context pricing tiers.** Models that OpenAI bills at a higher rate above 272K input tokens
|
|
74
|
+
(`gpt-5.4`, `gpt-5.5`, the `gpt-5.6-*` family and their `-pro` variants) are now priced per request at
|
|
75
|
+
the correct tier instead of always at the standard rate.
|
|
76
|
+
- New config key `checkUpdates` (default `true`).
|
|
77
|
+
|
|
78
|
+
### Changed
|
|
79
|
+
|
|
80
|
+
- **Pricing table rebuilt** from <https://developers.openai.com/api/docs/pricing>. Adds `gpt-5.6-sol`,
|
|
81
|
+
`gpt-5.6-terra`, `gpt-5.6-luna`, `gpt-5.6-cyber`, `gpt-5.5`, `gpt-5.5-pro`, `gpt-5.5-cyber`, `gpt-5.4`,
|
|
82
|
+
`gpt-5.4-mini`, `gpt-5.4-nano`, `gpt-5.4-pro`, `gpt-5.3-codex`, `gpt-5-search-api` and `chat-latest`,
|
|
83
|
+
plus explicit `-codex` entries so Codex CLI model ids resolve exactly rather than through the family
|
|
84
|
+
fallback. Models in current use — `gpt-5.6-sol` above all — are now exact matches and lose the *est.*
|
|
85
|
+
badge. The catch-all fallback moved from `gpt-5.2` to `gpt-5.3-codex`.
|
|
86
|
+
- **Codex-only accounting.** Usage on non-OpenAI models is dropped from totals, cost, the model mix, the
|
|
87
|
+
heatmap and uploads. Sources such as Cline/Roo/Kilo and OpenCode can drive Anthropic, Google or local
|
|
88
|
+
models; costing those against an OpenAI price table produced meaningless dollars. The dashboard also
|
|
89
|
+
filters rows and sessions uploaded by older clients.
|
|
90
|
+
|
|
91
|
+
### Fixed
|
|
92
|
+
|
|
93
|
+
- **Live tokens/s was wildly overstated** (6,000+ tok/s where the real rate is tens). Each request's
|
|
94
|
+
`input` counts the *entire prompt re-sent for that turn* — hundreds of thousands of context tokens —
|
|
95
|
+
so summing `total` over a 60 s window measured context replay, not generation. The rate is now
|
|
96
|
+
**output tokens only**, and the divisor is clamped to the part of the window the session has actually
|
|
97
|
+
existed for, so a session seconds old is not diluted by time that never happened. The 10 s burst
|
|
98
|
+
figure is computed the same way.
|
|
99
|
+
|
|
100
|
+
## 0.1.1 — 2026-08-31
|
|
101
|
+
|
|
102
|
+
### Fixed
|
|
103
|
+
|
|
104
|
+
- Self-install the Electron runtime on first run when npm ≥ 11 / pnpm ≥ 10 skipped its install script.
|
|
105
|
+
|
|
106
|
+
## 0.1.0 — 2026-08-31
|
|
107
|
+
|
|
108
|
+
First public release: macOS menu bar app, Windows tray app, headless `agent` mode, Codex/pi/OpenCode/
|
|
109
|
+
Cline/Roo/Kilo/Hermes session readers, live rate limits, activity heatmap, device-code login and
|
|
110
|
+
dashboard sync.
|
package/README.md
CHANGED
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
Menu bar / system tray app **and** headless agent that tracks your [OpenAI Codex](https://github.com/openai/codex) usage — tokens, cache hit rate, model mix, tokens per second of the running session, subscription rate limits and the **API-equivalent cost in dollars** — and syncs it to your team's Codex Tracker dashboard (Next.js + Clerk + Convex).
|
|
4
4
|
|
|
5
5
|
- macOS menu bar app and native Windows tray app (Electron)
|
|
6
|
-
- `codex-tracker agent` headless mode for **WSL2**, Linux and servers
|
|
6
|
+
- `codex-token-tracker agent` headless mode for **WSL2**, Linux and servers
|
|
7
|
+
- Self-update: `codex-token-tracker update`, plus an in-app "Update" button when a newer version is published
|
|
7
8
|
- Reads Codex CLI / Codex Desktop rollout logs (`~/.codex/sessions`) locally — no API keys, no proxies
|
|
8
|
-
- Real-time: today's totals,
|
|
9
|
+
- Real-time: today's totals, the live session's generation speed (tokens/s), context window use, weekly / 5-hour rate limits
|
|
9
10
|
- Activity heatmap merged from **local data + your other devices** (realtime database)
|
|
10
11
|
- English / 中文, follows your OS language and can be switched and persisted
|
|
11
12
|
- Light / dark follows the system theme
|
|
@@ -20,6 +21,12 @@ npm install -g codex-token-tracker
|
|
|
20
21
|
npx codex-token-tracker
|
|
21
22
|
```
|
|
22
23
|
|
|
24
|
+
This installs two equivalent commands on your PATH: **`codex-token-tracker`** and the shorter alias
|
|
25
|
+
`codex-tracker`. Every example below works with either name.
|
|
26
|
+
|
|
27
|
+
Already installed? `codex-token-tracker update` fetches the newest published version and installs it
|
|
28
|
+
with whichever package manager you used (npm / pnpm / yarn / bun).
|
|
29
|
+
|
|
23
30
|
> **npm 11+ / pnpm 10+ block Electron's install script by default.** That's fine: the first `codex-tracker` run downloads the Electron runtime itself (~100 MB, once). To do it during install instead: `npm install -g codex-token-tracker --allow-scripts=electron`.
|
|
24
31
|
|
|
25
32
|
Node.js 20+ is required. Electron is an *optional* dependency: if its binary cannot be downloaded (locked-down servers, WSL without a desktop), the package still installs and runs in agent mode.
|
|
@@ -54,18 +61,46 @@ The tracker discovers the Convex deployment through `<dashboard>/api/config`.
|
|
|
54
61
|
| `codex-tracker login [--dashboard <url>]` | Device-code login |
|
|
55
62
|
| `codex-tracker logout` | Forget the device token (local data stays) |
|
|
56
63
|
| `codex-tracker status [--json]` | Today / 7d / 30d usage, live session, rate limits, models |
|
|
64
|
+
| `codex-tracker sync` | Full sync: rescan every agent and re-upload this device's whole history |
|
|
57
65
|
| `codex-tracker paths` | Detected Codex session directories |
|
|
58
66
|
| `codex-tracker config get [key]` / `config set <key> <value>` | Settings (see below) |
|
|
59
67
|
| `codex-tracker lang <en\|zh\|auto>` | Display language |
|
|
68
|
+
| `codex-tracker update [--check]` | Install the newest published version; `--check` only reports it |
|
|
60
69
|
| `codex-tracker --version` / `--help` | |
|
|
61
70
|
|
|
62
71
|
## Menu bar app
|
|
63
72
|
|
|
64
73
|
- Tray title shows today's tokens (`12.4k`) — `config set trayTitle tokens|cost|none`
|
|
65
74
|
- Click: popover with Today, Live session (tokens/s, context window, rate limits), Activity heatmap, Models, Account
|
|
66
|
-
- Right-click: Open dashboard, Sign in/out, Language, Launch at login, Refresh, Quit
|
|
75
|
+
- Right-click: Open dashboard, Sign in/out, Language, Launch at login, Refresh, **Sync now**, Check for updates, Quit
|
|
76
|
+
- A banner appears at the top of the popover when a newer version is published; **Update** installs it and the app asks you to restart
|
|
67
77
|
- Launch at login uses a LaunchAgent on macOS and the registry run key on Windows
|
|
68
78
|
|
|
79
|
+
## Sync
|
|
80
|
+
|
|
81
|
+
The tracker uploads continuously in the background: every 60 s it sends the hour buckets and sessions
|
|
82
|
+
that *changed* since the last push. **Sync** does the full version instead — use it when the dashboard's
|
|
83
|
+
numbers for this machine look wrong, after you install a new agent, or after an update that changes the
|
|
84
|
+
pricing table.
|
|
85
|
+
|
|
86
|
+
Press the **⟳** button in the popover header (or *Sync now* in the Account card and the tray menu, or run
|
|
87
|
+
`codex-tracker sync`). It:
|
|
88
|
+
|
|
89
|
+
1. re-reads the config, so agents enabled since the app started are picked up;
|
|
90
|
+
2. re-discovers **every** session directory and re-parses **every** transcript from scratch — Codex plus
|
|
91
|
+
the coding agents running on your Codex subscription (pi, OpenCode, Cline / Roo / Kilo, Hermes) and any
|
|
92
|
+
`extraSessionDirs` you configured — instead of skipping files whose size and mtime are unchanged;
|
|
93
|
+
3. recomputes all aggregates with the current pricing table;
|
|
94
|
+
4. re-uploads **everything**, not just what changed, so the dashboard's totals for this device are
|
|
95
|
+
replaced by the freshly computed ones — this is the calibration step;
|
|
96
|
+
5. pulls the other devices' rows and the live rate limits back down.
|
|
97
|
+
|
|
98
|
+
A banner reports the phase while it runs and then what it found (`Synced codex, pi · 75 files ·
|
|
99
|
+
75 sessions · 70 hours re-uploaded`). Signed out, steps 1-3 still run and nothing leaves the machine.
|
|
100
|
+
|
|
101
|
+
A full sync re-sends your whole history, so it costs more bandwidth than a normal push — it is a manual
|
|
102
|
+
action, never on a timer.
|
|
103
|
+
|
|
69
104
|
## Windows and WSL2
|
|
70
105
|
|
|
71
106
|
**Native Windows**: `npm i -g codex-token-tracker` in PowerShell, then `codex-tracker`. The tray app also scans every WSL distro (`\\wsl$\<distro>\home\*\.codex\sessions`) so sessions run inside WSL are counted.
|
|
@@ -102,16 +137,38 @@ Config lives in `~/.codex-tracker/` (override with `CODEX_TRACKER_HOME`):
|
|
|
102
137
|
| `extraSessionDirs` | `[]` | Extra session folders (comma-separated in `config set`) |
|
|
103
138
|
| `launchAtLogin` | `false` | macOS / Windows |
|
|
104
139
|
| `trayTitle` | `tokens` | `tokens`, `cost` or `none` |
|
|
140
|
+
| `checkUpdates` | `true` | Ask the npm registry (once per 6 h) whether a newer version exists |
|
|
105
141
|
|
|
106
142
|
`CODEX_HOME` is honoured when locating `sessions/` and `archived_sessions/`.
|
|
107
143
|
|
|
108
|
-
###
|
|
144
|
+
### Updates
|
|
145
|
+
|
|
146
|
+
`checkUpdates` (default on) asks `registry.npmjs.org` for the package's `latest` dist-tag at most once
|
|
147
|
+
every 6 hours and caches the answer in `~/.codex-tracker/update.json`. Nothing else is sent — the request
|
|
148
|
+
carries no usage data and no identifiers. Turn it off with `codex-tracker config set checkUpdates false`;
|
|
149
|
+
`codex-tracker update` still works on demand. Set `CODEX_TRACKER_REGISTRY` (or `npm_config_registry`) to use
|
|
150
|
+
a mirror.
|
|
151
|
+
|
|
152
|
+
Global installs can fail for reasons the app cannot fix — a root-owned npm prefix, a proxy, a read-only
|
|
153
|
+
volume. When that happens the exact command is shown so you can run it yourself.
|
|
154
|
+
|
|
155
|
+
### Pricing
|
|
156
|
+
|
|
157
|
+
Costs are "API-equivalent" — [standard OpenAI list prices](https://developers.openai.com/api/docs/pricing)
|
|
158
|
+
per 1M tokens (input, cached input, output; reasoning tokens are billed as output). Models with a
|
|
159
|
+
long-context tier are billed at the higher rate for requests whose prompt exceeds 272K tokens. `-codex`
|
|
160
|
+
variants are priced at their base model's rate.
|
|
109
161
|
|
|
110
|
-
|
|
162
|
+
**Codex only.** Some supported sources (Cline/Roo/Kilo, OpenCode) can also drive Anthropic, Google or local
|
|
163
|
+
models. That usage is *not* counted: this tool reports Codex consumption, and pricing a Claude request
|
|
164
|
+
against an OpenAI table would be meaningless.
|
|
165
|
+
|
|
166
|
+
Models missing from the built-in table are priced by family and marked **est.** Override or add prices in
|
|
167
|
+
`~/.codex-tracker/pricing.json`:
|
|
111
168
|
|
|
112
169
|
```json
|
|
113
170
|
{
|
|
114
|
-
"gpt-5.
|
|
171
|
+
"gpt-5.7-nova": { "input": 1.75, "cachedInput": 0.175, "output": 14 }
|
|
115
172
|
}
|
|
116
173
|
```
|
|
117
174
|
|
|
@@ -120,7 +177,7 @@ Costs are "API-equivalent" — standard OpenAI list prices per 1M tokens (input,
|
|
|
120
177
|
The tracker reads the local transcripts of every agent that can use a Codex subscription (ChatGPT login) and
|
|
121
178
|
attributes usage to an **agent** (shown as "Sources" chips in the popover, a `Sources` line in `codex-tracker status`,
|
|
122
179
|
and as a tag on live sessions / model rows). Only Codex-subscription providers are counted unless
|
|
123
|
-
`trackAllProviders` is `true
|
|
180
|
+
`trackAllProviders` is `true`, and **only OpenAI models are counted at all** — see [Pricing](#pricing).
|
|
124
181
|
|
|
125
182
|
| Source | Where it looks | Notes |
|
|
126
183
|
|---|---|---|
|
|
@@ -168,7 +225,42 @@ CODEX_TRACKER_DEVTOOLS=1 ... # op
|
|
|
168
225
|
pnpm --filter codex-token-tracker build:icons # regenerate tray icons
|
|
169
226
|
```
|
|
170
227
|
|
|
171
|
-
|
|
228
|
+
### Dev builds vs published builds
|
|
229
|
+
|
|
230
|
+
A build knows which environment it belongs to, so a local test run can never write into production.
|
|
231
|
+
`scripts/build.mjs` stamps the channel at bundle time: **only `--release` produces a prod build**, which
|
|
232
|
+
is what `prepack` runs — so every tarball and every `npm publish` is prod, and every `pnpm build`,
|
|
233
|
+
`pnpm dev` and watch-mode rebuild is dev.
|
|
234
|
+
|
|
235
|
+
| | dev build (`pnpm build`) | published build (`npm i -g codex-token-tracker`) |
|
|
236
|
+
| --- | --- | --- |
|
|
237
|
+
| Dashboard default | `http://localhost:3000` | `https://codex.chenli.dev` |
|
|
238
|
+
| Convex deployment | whatever the local dashboard's `/api/config` advertises — the **dev** one | production |
|
|
239
|
+
| Config, device token, upload state | `~/.codex-tracker-dev` | `~/.codex-tracker` |
|
|
240
|
+
| `checkUpdates` default | `false` (`update` refuses to run) | `true` |
|
|
241
|
+
| App name / Electron userData | `Codex Tracker (dev)` | `Codex Tracker` |
|
|
242
|
+
| macOS LaunchAgent | `dev.codex-tracker.menubar.dev` | `dev.codex-tracker.menubar` |
|
|
243
|
+
| Popover | orange **DEV** badge in the header | — |
|
|
244
|
+
|
|
245
|
+
Because the two differ in app name and config directory, **a dev build and an installed one can run at
|
|
246
|
+
the same time**, each with its own tray icon, device token and upload state.
|
|
247
|
+
|
|
248
|
+
To test against a dev environment, start the dashboard and Convex, then run the local build:
|
|
249
|
+
|
|
250
|
+
```bash
|
|
251
|
+
cd apps/dashboard && npx convex dev # terminal 1
|
|
252
|
+
pnpm dev # terminal 2 — http://localhost:3000
|
|
253
|
+
pnpm --filter codex-token-tracker build # terminal 3
|
|
254
|
+
node packages/menubar/bin/codex-tracker.js login # → localhost:3000, no --dashboard needed
|
|
255
|
+
node packages/menubar/bin/codex-tracker.js menubar
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Both defaults are only *defaults*: `--dashboard <url>` and `config set dashboardUrl <url>` still point
|
|
259
|
+
either build anywhere, and `CODEX_TRACKER_HOME` still overrides the config directory.
|
|
260
|
+
|
|
261
|
+
Publishing (from the repo root): `pnpm release:menubar` — `prepublishOnly` typechecks and `prepack`
|
|
262
|
+
makes the release build, so a published tarball is never accidentally a dev build. `postpack` restores
|
|
263
|
+
the dev build in `dist/` afterwards, so your working copy keeps pointing at localhost.
|
|
172
264
|
|
|
173
265
|
## License
|
|
174
266
|
|