tledger 0.2.1 → 0.3.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/README.md +150 -136
- package/bin/token-ledger-cache-image.mjs +1150 -0
- package/bin/token-ledger-rates.mjs +4 -1
- package/bin/token-ledger-terminal.mjs +89 -29
- package/bin/token-ledger-trend-image.mjs +1527 -584
- package/bin/token-ledger-trend-terminal.mjs +73 -28
- package/bin/token-ledger-trend.mjs +25 -11
- package/bin/token-ledger-tui.mjs +7 -3
- package/bin/token-ledger.mjs +303 -92
- package/docs/token-ledger-cli-week.png +0 -0
- package/docs/token-ledger-report-7-day.png +0 -0
- package/lib/token-ledger-importer.mjs +589 -279
- package/lib/token-ledger-snapshot.mjs +267 -0
- package/lib/token-ledger-usage.mjs +524 -0
- package/package.json +10 -5
package/README.md
CHANGED
|
@@ -1,171 +1,189 @@
|
|
|
1
1
|
# Token Ledger
|
|
2
2
|
|
|
3
|
-
Token Ledger is a
|
|
4
|
-
shows ranked project bars, model mix, usage type, cache coverage, and reset
|
|
5
|
-
cycle context without sending your data anywhere.
|
|
3
|
+
Token Ledger is a local-only Codex usage dashboard with two outputs:
|
|
6
4
|
|
|
7
|
-
|
|
5
|
+
- a generated PNG report for trends, model composition, and weekly-meter
|
|
6
|
+
context;
|
|
7
|
+
- a terminal dashboard for a fast project and token summary.
|
|
8
|
+
|
|
9
|
+
This README describes the local checkout. It does not assume a hosted report
|
|
10
|
+
or a published npm package.
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
## Install
|
|
10
13
|
|
|
11
|
-
|
|
14
|
+
Requires Node.js 22.13 or newer. From this checkout:
|
|
12
15
|
|
|
13
16
|
```bash
|
|
14
|
-
npm install
|
|
17
|
+
npm install
|
|
18
|
+
npm install -g .
|
|
15
19
|
```
|
|
16
20
|
|
|
17
|
-
|
|
21
|
+
The second command installs `tledger` on your PATH. From the checkout, you can
|
|
22
|
+
use `npx tledger` instead.
|
|
23
|
+
|
|
24
|
+
## Basics
|
|
25
|
+
|
|
26
|
+
| What you need | Command |
|
|
27
|
+
| --- | --- |
|
|
28
|
+
| Quick guide | `tledger` |
|
|
29
|
+
| Last 24 hours | `tledger 1d` |
|
|
30
|
+
| Last 7 calendar days | `tledger week` |
|
|
31
|
+
| Rolling 30 days | `tledger 30d` |
|
|
32
|
+
| 7-day PNG report | `tledger report 7d` |
|
|
33
|
+
| Cache-only PNG report | `tledger report 7d --cache-rate` |
|
|
34
|
+
|
|
35
|
+
The main options are:
|
|
36
|
+
|
|
37
|
+
- `--static` prints once instead of opening the terminal dashboard.
|
|
38
|
+
- `--refresh` rebuilds the local usage cache.
|
|
39
|
+
- `--image-output <file>` chooses where to save a PNG.
|
|
40
|
+
- `--no-open` writes a PNG without opening it.
|
|
41
|
+
- `--help-all` shows the complete command and option reference.
|
|
42
|
+
|
|
43
|
+
`week` covers seven local calendar days ending on the selected day. `1d` is a
|
|
44
|
+
rolling 24-hour view ending when the command starts. In a TTY, the project
|
|
45
|
+
dashboard is interactive. `j`/`k` select a project; `q`, `Q`, `Esc`, or
|
|
46
|
+
`Ctrl-C` exits. Enter does not inspect a project, and `d` / `w` / `m` do not
|
|
47
|
+
change the range; choose the range in the command.
|
|
48
|
+
|
|
49
|
+
## Cache and input controls
|
|
50
|
+
|
|
51
|
+
`tledger report [Nd|Nw] --cache-rate` writes a separate, purpose-built cache
|
|
52
|
+
report to `token-ledger-cache-report-<period>.png`. Its primary view is the
|
|
53
|
+
input-token-weighted cache rate (`cached input / measured input`), shown
|
|
54
|
+
across the selected period with input-volume context. A smaller model breakout
|
|
55
|
+
shows which models account for that input and their individual cache rates.
|
|
56
|
+
The cache report intentionally omits the general report's project, quota-meter,
|
|
57
|
+
runway, and output-token sections. Cached input is clamped to input per event,
|
|
58
|
+
and the report states how much token volume had a usable component breakdown.
|
|
59
|
+
Use `--image-output`, `--image-width`, `--date`, `--tz`, and `--no-open` the
|
|
60
|
+
same way as on the standard report.
|
|
61
|
+
|
|
62
|
+
The default privacy-reduced snapshot is
|
|
63
|
+
`~/.token-ledger/token-ledger-snapshot-v2.json.gz`. It is gzip-compressed,
|
|
64
|
+
written atomically with mode `0600`, targets 12 MiB, and has a hard 16 MiB
|
|
65
|
+
on-disk limit. Its expanded JSON representation also targets 48 MiB and has a
|
|
66
|
+
64 MiB safety limit, so the old 93 MiB raw-cache behavior cannot recur on the
|
|
67
|
+
default production path. Reads check the compressed size before loading and
|
|
68
|
+
bound gzip expansion to the same 64 MiB JSON limit. The collector de-duplicates
|
|
69
|
+
through a private temporary SQLite spool, then keeps exact recent calls while
|
|
70
|
+
rolling older history into minute, hour, and day buckets. If a dense history
|
|
71
|
+
approaches the target, it increases the bucket resolution automatically while
|
|
72
|
+
preserving additive token, model, project, cache, tool-call, and thread totals.
|
|
73
|
+
When a compacted bucket crosses a requested range or chart boundary, Token
|
|
74
|
+
Ledger allocates its additive values proportionally across the overlap and
|
|
75
|
+
marks the terminal result as estimated; exact recent calls remain exact. The
|
|
76
|
+
temporary spool is removed when collection completes or exits with a handled
|
|
77
|
+
error.
|
|
78
|
+
|
|
79
|
+
If even the coarsest bounded representation exceeds the hard limit, Token
|
|
80
|
+
Ledger preserves the previous cache and asks you to reduce the source with
|
|
81
|
+
`--no-archived` or the collector's `--since` option. It never replaces the
|
|
82
|
+
production cache with an oversized or partial file. On a normal default-path
|
|
83
|
+
run, a snapshot whose mtime is in the past and less than one hour old skips the
|
|
84
|
+
source walk. An exact-hour or future mtime is not fresh; an older snapshot is
|
|
85
|
+
checked against local source mtimes before it is reused or rebuilt.
|
|
18
86
|
|
|
19
87
|
```bash
|
|
20
|
-
|
|
88
|
+
# Force a rebuild from CODEX_HOME or ~/.codex
|
|
89
|
+
tledger week --refresh
|
|
90
|
+
|
|
91
|
+
# Read the existing default snapshot without a source-freshness check
|
|
92
|
+
tledger week --no-refresh
|
|
93
|
+
|
|
94
|
+
# Read an explicit snapshot without automatic freshness checks
|
|
95
|
+
tledger week --input /path/to/token-ledger-snapshot-v2.json.gz
|
|
21
96
|
```
|
|
22
97
|
|
|
23
|
-
|
|
98
|
+
`--refresh` rebuilds the default snapshot and cannot be combined with
|
|
99
|
+
`--input` in this checkout. `--no-archived` excludes `archived_sessions` when a
|
|
100
|
+
refresh occurs. The collector can also be run directly:
|
|
24
101
|
|
|
25
102
|
```bash
|
|
26
|
-
|
|
27
|
-
cd token-ledger
|
|
28
|
-
npm install -g .
|
|
103
|
+
node lib/token-ledger-importer.mjs --output /path/to/token-ledger-snapshot-v2.json.gz
|
|
29
104
|
```
|
|
30
105
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
106
|
+
Explicit `.json` snapshots remain readable for fixtures and deliberate exports,
|
|
107
|
+
but `.json.gz` is the bounded production cache format. After an upgrade, the
|
|
108
|
+
new cache does not read or delete schema-v1 cache files; remove an old generated
|
|
109
|
+
cache separately once the v2 cache is proven.
|
|
35
110
|
|
|
36
|
-
|
|
111
|
+
## Report versus CLI
|
|
37
112
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
113
|
+
| | Generated report | Terminal dashboard |
|
|
114
|
+
| --- | --- | --- |
|
|
115
|
+
| Command | `tledger report 7d` or `tledger trend 7d --image` | `tledger week`, `tledger 1d`, or `tledger day <date>` |
|
|
116
|
+
| Output | One PNG with a stat quad, weekly-meter pace/runway, daily token columns, an aligned cache-rate strip, top projects, and per-model cache rates | Interactive or static project rows with totals, shares, thread counts, model mix, usage type, cache split, and reset-cycle context |
|
|
117
|
+
| Range | A selected local-calendar-day trend window, such as 7d or 2w | A calendar day/week or a rolling 24-hour/`Nd`/`Nw` window |
|
|
118
|
+
| Estimate surface | Meter-derived burn and runway are called out; cache coverage comes from measured token breakdowns | The sidebar can show derived `View burn`; project detail includes rate-card credit shares when available |
|
|
41
119
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
is interactive; press `q` or `esc` to exit.
|
|
120
|
+
The report is the broader visual summary. The CLI does not open or generate a
|
|
121
|
+
report unless you request the `report`, `trend --image`, or `--image` form.
|
|
45
122
|
|
|
46
|
-
|
|
123
|
+
## Examples
|
|
47
124
|
|
|
48
|
-
|
|
49
|
-
tledger 1d
|
|
50
|
-
tledger 1d --static
|
|
51
|
-
tledger day 2026-08-05
|
|
52
|
-
tledger week --top 5
|
|
53
|
-
tledger week --static
|
|
54
|
-
tledger trend 7d --static
|
|
55
|
-
tledger trend 7d --image --image-output artifacts/token-ledger-trend-7d.png
|
|
56
|
-
tledger report 7d
|
|
57
|
-
```
|
|
125
|
+
### Seven-day report
|
|
58
126
|
|
|
59
|
-
|
|
60
|
-
ending when the command starts. It is different from `tledger day today`, which
|
|
61
|
-
covers the current calendar day from local midnight.
|
|
62
|
-
|
|
63
|
-
`tledger report [7d|14d|30d]` is the one-step report output: it writes the
|
|
64
|
-
dashboard PNG (identical to `trend --image`) to
|
|
65
|
-
`token-ledger-report-<period>.png` in the current directory. It accepts the
|
|
66
|
-
same flags as the trend view (`--drain`, `--date`, `--tz`, `--image-output`,
|
|
67
|
-
`--image-width`) and prints progress while rendering and encoding the image.
|
|
68
|
-
|
|
69
|
-
The terminal trend view is a compact approximation of the image view. For the
|
|
70
|
-
full chart grammar, use `--image`: it writes a PNG with two aligned panels
|
|
71
|
-
sharing one time axis — the observed weekly meter as a line on its own 0–100%
|
|
72
|
-
panel on top, and calendar-day columns of local token volume stacked by model
|
|
73
|
-
below, each annotated with the observed drop ("−18.1%" means the meter fell
|
|
74
|
-
18.1 points across that column's days). The drain numbers come straight from
|
|
75
|
-
the meter — no pricing model involved — so token volume and actual limit
|
|
76
|
-
consumption can be compared per day at a glance.
|
|
77
|
-
|
|
78
|
-
Turns run in fast mode (service tier "priority") are drawn as a darker shade
|
|
79
|
-
at the top of their model's segment, with each model's fast share in the
|
|
80
|
-
legend; fast-mode turns are weighted 1.5× in the credit estimate because they
|
|
81
|
-
debit the plan limit at a higher rate.
|
|
82
|
-
|
|
83
|
-
Pass `--drain` to flip the columns into limit-drain units instead: each column
|
|
84
|
-
becomes the weekly limit percentage the meter dropped, stacked by model using
|
|
85
|
-
rate-card credit weights (an estimate — the official card is the best
|
|
86
|
-
available proxy for per-model debit, but subscription limits are not billed
|
|
87
|
-
per token), on the same percent scale as the meter line.
|
|
88
|
-
|
|
89
|
-
Meter windows are keyed by their server-reported reset timestamp, so a fresh
|
|
90
|
-
window that starts days early (a provider-initiated limit restart) is drawn as
|
|
91
|
-
its own cycle and labeled `restart`, while a true weekly expiry is labeled
|
|
92
|
-
`reset`.
|
|
93
|
-
Stale readings from sessions still reporting a superseded window are dropped
|
|
94
|
-
instead of being fused into the line as phantom drain. Drops observed after a
|
|
95
|
-
sparse meter gap (over 36 hours) are spread across the covered days and marked
|
|
96
|
-
with `≈`. When a range has no usable meter drain, columns fall back to raw
|
|
97
|
-
local token counts and the chart says so.
|
|
98
|
-
|
|
99
|
-
`--image` defaults to `token-ledger-trend-7d.png` in the current directory.
|
|
100
|
-
Use `--image-output <file.png>` to choose the path and `--image-width <px>` to
|
|
101
|
-
choose a width from 900 to 2400 pixels.
|
|
102
|
-
|
|
103
|
-
Use `trend 14d` for daily columns across two weeks. At 30 days, the terminal
|
|
104
|
-
uses readable multi-day bins: three-day bins at ordinary widths and two-day
|
|
105
|
-
bins on wider terminals. The image view uses the same readable multi-day
|
|
106
|
-
binning at 30 days. The image also reports the separate local rate-card credit
|
|
107
|
-
estimate when token breakdowns are available; that estimate is an absolute
|
|
108
|
-
credit count and never rescales the observed-drain columns.
|
|
109
|
-
|
|
110
|
-
The CLI automatically checks the local Codex source files before rendering. If
|
|
111
|
-
they are newer than the local cache, it rebuilds the privacy-reduced snapshot.
|
|
112
|
-
The first refresh may scan historical rollout files; later runs use the cache
|
|
113
|
-
for one hour before checking source freshness again. Use `--refresh` when you
|
|
114
|
-
need to force an immediate rebuild.
|
|
115
|
-
|
|
116
|
-
The `1d` project dashboard shows a compact snapshot-age line such as
|
|
117
|
-
`SNAPSHOT · fresh · 12m old`. `fresh` means the snapshot is within the
|
|
118
|
-
one-hour cache window, `stale` means it is older, and `age unknown` means the
|
|
119
|
-
snapshot has no usable capture-time metadata. The indicator does not print a
|
|
120
|
-
local path or trigger another source scan.
|
|
121
|
-
|
|
122
|
-
Useful overrides:
|
|
127
|
+

|
|
123
128
|
|
|
124
|
-
|
|
125
|
-
# Use another timezone instead of the computer's local timezone
|
|
126
|
-
tledger week --tz America/New_York
|
|
129
|
+
### Non-report CLI output
|
|
127
130
|
|
|
128
|
-
|
|
129
|
-
tledger week --refresh
|
|
131
|
+

|
|
130
132
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
+
The terminal capture was made from a local privacy-reduced snapshot after
|
|
134
|
+
replacing project and thread labels with neutral names. It contains no prompts,
|
|
135
|
+
responses, secrets, home paths, or project names.
|
|
133
136
|
|
|
134
|
-
|
|
135
|
-
tledger week --input /path/to/token-ledger-snapshot.json
|
|
136
|
-
```
|
|
137
|
+
## What is observed
|
|
137
138
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
139
|
+
The collector reads local rollout JSONL under `sessions/` and, unless disabled,
|
|
140
|
+
`archived_sessions/`, plus `session_index.jsonl` and read-only `state_5.sqlite`
|
|
141
|
+
metadata. It retains positive `last_token_usage` model-call events and their
|
|
142
|
+
timestamps, turn IDs, model/source attribution, and token categories.
|
|
141
143
|
|
|
142
|
-
|
|
144
|
+
Observed totals are the sum of globally de-duplicated retained events. Events
|
|
145
|
+
with turn IDs use the turn plus cumulative/last-usage/context signatures;
|
|
146
|
+
legacy events without turn IDs use a high-specificity usage signature and are
|
|
147
|
+
marked as heuristic. State database token counters are kept as non-additive
|
|
148
|
+
reference values because forks and subagents inherit cumulative history.
|
|
143
149
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
150
|
+
Input, cached-input, output, and reasoning are stored as separate categories:
|
|
151
|
+
cached input is a subset of input, and reasoning is a subset of output. Any
|
|
152
|
+
composition that presents them together subtracts those subsets to avoid
|
|
153
|
+
double counting. Models are attributed from turn context/settings and local
|
|
154
|
+
thread metadata, then normalized for display.
|
|
147
155
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
156
|
+
The weekly meter uses local rate-limit observations for the account-wide
|
|
157
|
+
weekly window. Reset timestamps identify windows; stale readings and separate
|
|
158
|
+
named pools are not stitched into that meter. Remaining percentage,
|
|
159
|
+
observation time, and the selected window are local observations; the reset
|
|
160
|
+
type (weekly expiry versus restart) is derived by comparing the prior window's
|
|
161
|
+
reset timestamp with the first reading of the new window. None of this is an
|
|
162
|
+
official account-wide quota or billing record.
|
|
151
163
|
|
|
152
|
-
The
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
164
|
+
The exported snapshot contains token metadata, model/use-type labels, project
|
|
165
|
+
labels, and display titles. It omits message bodies, reasoning text, tool
|
|
166
|
+
arguments/results, credential fields, and full local paths. Display titles and
|
|
167
|
+
project labels are user-written or local metadata and should be reviewed before
|
|
168
|
+
sharing. Normal successful dashboard output is privacy-reduced, but diagnostics
|
|
169
|
+
or explicit PNG writes may echo configured snapshot, Codex, or output path
|
|
170
|
+
labels.
|
|
158
171
|
|
|
159
|
-
##
|
|
172
|
+
## What is estimated
|
|
160
173
|
|
|
161
|
-
|
|
174
|
+
Credit values use the hardcoded rate card dated **2026-08-17**. Cached input is
|
|
175
|
+
priced separately, priority/fast-mode events use the 1.5× multiplier, and
|
|
176
|
+
events without a detailed breakdown or known model rate are unrated. These are
|
|
177
|
+
rate-card estimates, not provider billing totals.
|
|
162
178
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
179
|
+
When meter observations are available, report bars in `--drain` mode represent
|
|
180
|
+
observed meter drops; model attribution within a drop uses rate-card weights
|
|
181
|
+
when possible and token weights as a fallback. Long observation gaps are
|
|
182
|
+
spread across local calendar days as estimates. Tokens-per-meter-point,
|
|
183
|
+
model-split burn, runway, and CLI `View burn` are derived estimates. None is
|
|
184
|
+
official billing, quota, or account-completeness truth.
|
|
167
185
|
|
|
168
|
-
## Verify
|
|
186
|
+
## Verify
|
|
169
187
|
|
|
170
188
|
```bash
|
|
171
189
|
npm test
|
|
@@ -173,7 +191,3 @@ npm run lint
|
|
|
173
191
|
npm run verify:release
|
|
174
192
|
npm pack --dry-run --json
|
|
175
193
|
```
|
|
176
|
-
|
|
177
|
-
`npm run verify:release` packs the allowlisted artifact, installs that tarball
|
|
178
|
-
in a clean temporary directory with no network or Codex data access, and runs
|
|
179
|
-
the installed `tledger --help` and synthetic `tledger 1d --static` smoke checks.
|