cmd-usage 0.7.14

Live Command Code (commandcode.ai) usage dashboard: credits, 5-hour and weekly windows, plan limits. Watch mode or one-shot.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
.TH CMDUSE 1 "2026-10" "cmd-usage 0.7.8" "User Commands"
.SH NAME
cmduse \- live Command Code (commandcode.ai) usage dashboard and reporter
.br
ocuse \- OpenCode Go/Zen usage (Go's usage endpoint plus local opencode data)
.SH SYNOPSIS
.B cmduse
[\fIOPTIONS\fR]
.br
.B cmduse \-1
[\fIOPTIONS\fR]
.br
.B cmduse daily
[\fB\-\-days\fR \fIn\fR] [\fB\-\-json\fR] [\fB\-\-csv\fR] [\fB\-\-local\fR]
.br
.B cmduse hourly
[\fB\-\-hours\fR \fIn\fR] [\fB\-\-json\fR] [\fB\-\-csv\fR] [\fB\-\-local\fR]
.br
.B cmduse model
[\fB\-\-days\fR \fIn\fR | \fB\-\-since\fR \fIISO\fR]
[\fB\-\-json\fR] [\fB\-\-csv\fR]
.br
.B cmduse session
[\fB\-\-days\fR \fIn\fR | \fB\-\-since\fR \fIISO\fR]
[\fB\-\-json\fR] [\fB\-\-csv\fR]
.br
.B cmduse models
[\fB\-\-json\fR] [\fB\-\-gated\fR]
.br
.B cmduse plans
[\fB\-\-json\fR]
.br
.B cmduse statusline
[\fB\-\-json\fR]
.br
.B cmduse mcp
.br
.B cmduse config set
\fIkey\fR=\fIvalue\fR [\fIkey\fR=\fIvalue\fR ...]
.br
.B cmduse \-V
.br
.B cmduse \-h
.br
.B ocuse
[\fIOPTIONS\fR]
.SH DESCRIPTION
.B cmduse
is a terminal client for the Command Code (commandcode.ai) metered AI API.  It
fetches the account's plan, remaining monthly credits, and the 5\-hour and
weekly rolling spending windows, and renders them as a live in\-place
dashboard.  It also produces account\-wide usage reports (all harnesses, via
the usage API), offline reports from local CLI logs, a template\-driven
statusline for prompts, and a listing of live models.  The same crate also
ships a second binary,
.BR ocuse ,
which tracks OpenCode Go and OpenCode Zen; it shares this manual's
presentation and is documented under
.BR OCUSE .
.PP
Authentication is read from
.IR ~/.commandcode/auth.json ,
the login state written by the official Command Code CLI (\fBcmd login\fR).
The file is a JSON object containing an \fBapiKey\fR field.  There is no
separate cmduse login; without that file every network command fails with an
error naming the missing key.
.SH EXIT STATUS
.TP
0
Success.
.TP
1
Runtime failure (network, auth, config write, report fetch).
.TP
2
Argument parse error; a message was printed to stderr.
.SH SUBCOMMANDS
With no subcommand, \fBcmduse\fR runs the live dashboard in watch mode.  With
\fB\-1\fR it fetches once and prints.
.TP
.B daily
Account usage by UTC day for the last \fI\-\-days\fR N days (default 7, max
365, today included).  Account\-wide means all harnesses (CLI, IDE, web,
API) that spent against the same account.  Days are derived by fetching the
cumulative summary at each UTC midnight and differencing adjacent
boundaries; requests are pooled 8 at a time in parallel.  With
\fB\-\-local\fR it instead reads only this machine's CLI sessions from
.IR ~/.commandcode/projects
(offline, no API key required, misses other harnesses).  Days are bucketed
in UTC unless \fB\-\-tz\fR is given, which applies to both the API and the
local path.  \fB\-\-json\fR emits one object
\fI{"scope","total","days"}\fR where \fIdays\fR maps each date to its totals.
\fB\-\-csv\fR emits
\fIday,requests,tokens_in,tokens_out,cache_read,cache_write,cost_usd\fR
with a final \fItotal\fR row.
.TP
.B hourly
Same cumulative\-differencing method as \fBdaily\fR but over hour
boundaries (UTC unless \fB\-\-tz\fR) for the last \fI\-\-hours\fR N hours
(default 24, max 168).  \fB\-\-local\fR reads CLI\-log hour buckets offline
and honors \fB\-\-tz\fR.  \fB\-\-json\fR emits one object
\fI{"scope","source","hours"}\fR; \fB\-\-csv\fR emits
\fIhour,requests,tokens_in,tokens_out,cost_usd\fR.
.TP
.B model
Local usage grouped by model, read from
.IR ~/.commandcode/projects
(offline; the usage API exposes no per\-model split).  All\-time by default:
\fB\-\-days\fR \fIn\fR or \fB\-\-since\fR \fIISO\fR bounds the window, and
\fB\-\-json\fR reports \fIsource\fR + \fIsince\fR alongside \fImodels\fR.
\fB\-\-json\fR and \fB\-\-csv\fR supported; the \fITokens\fR column sums
input, output, cache read, and cache write.
.TP
.B session
Local usage grouped by project/session directory, same offline file.
\fB\-\-json\fR and \fB\-\-csv\fR supported.
.TP
.B models
Live model list from the provider endpoint
.I GET https://api.commandcode.ai/provider/v1/models
\-\- the same source the account plan gating uses.  Unfiltered by plan
unless \fB\-\-gated\fR is given, in which case only the current plan's
allowed models are shown (see the OPTIONS entry for \fB\-\-gated\fR).
Text rows are sorted by display name as
.IR "NAME  CONTEXT  ID" ,
where CONTEXT is a human K/M count or "\-" when the API omits it.
\fB\-\-json\fR prints one JSON object per model per line with keys id, name,
context_length, owned_by.
.TP
.B plans
Print the plan comparison table (name, price, monthly credits, 5\-hour and
weekly caps), marking the current plan with a leading "*" matched by exact
display name, so "individual\-goat" does not mark the Go row.  The current
plan is fetched best\-effort; with no key or network no row is marked.
For the JSON form, see \fB\-\-json\fR under OPTIONS.
.TP
.B statusline
Fetch once and print a single compact line (no trailing newline) built from
the configured statusline template.  Suitable for shell prompts, tmux
status, and headless scripts.  On any API error prints
.I "cmduse: <error>"
to stdout and exits 1.  \fB\-\-json\fR prints one JSON object:
plan, monthlyRemaining, monthlyCap, fiveHourUsed, fiveHourCap, weeklyUsed,
weeklyCap (all dollars as JSON numbers; plan is the human name such as
"GOAT").
.TP
.B mcp
Run an MCP (Model Context Protocol) stdio server: newline\-delimited
JSON\-RPC on stdin/stdout, diagnostics on stderr.  Exposes seven tools \(
usage, plans, models, daily, hourly, session, model \) whose output is the same
text the corresponding subcommands print.  Tool execution errors are returned as
results with isError true, not JSON\-RPC errors.  Intended for MCP hosts
such as Zed's context_servers ("command": "cmduse", "args": ["mcp"]).
.TP
.B config set \fIkey\fR=\fIvalue\fR ...
Merge the given settings into
.I ~/.config/cmd\-usage/config.json
(or
.IR $XDG_CONFIG_HOME/cmd\-usage/config.json )
and print the resulting values.  Keys and valid ranges:
.RS
.TP
interval=\fIs\fR
refresh seconds, 1\(en86400.
.TP
width=\fIn\fR
bar width, 5\(en200.
.TP
burst_on=\fIbool\fR
show the spend\-burst sparkline row in watch mode (default true).
.TP
burst=\fIn\fR
sparkline sample count, 5\(en240 (default 40).
.TP
sl=\fIstring\fR
statusline template, see STATUSLINE.
.TP
sl_colors=\fIbool\fR
ANSI colors in the statusline (default true).
.TP
sl_ascii=\fIbool\fR
use "#\-" bars instead of the "\[ha]"/dash glyphs in the statusline (default
false).
.RE
Unknown keys, non\-numeric values, and out\-of\-range values abort with a
message and exit 2; nothing is written.
.SH OPTIONS
Options accept \fB\-\-name value\fR, \fB\-\-name=value\fR, and an attached short
value (\fB\-i30\fR, \fB\-w40\fR).
.TP
.B \-1, \-\-once
Fetch once, print, exit.  Without this, watch mode runs forever until
Ctrl\-C.  With \fB\-\-json\fR it prints one JSON object (plan, status,
periodEnd, monthlyCredits, monthlyCap, purchasedCredits, freeCredits,
fiveHour, weekly, summary, error) instead of the text dashboard.
.TP
.B \-p, \-\-plain
No ANSI colors and no live redraw (used with \fB\-1\fR for scripts/pipes).
In watch mode it keeps the plain text render but still redraws in place.
Colors are also dropped automatically on a non\-terminal stdout or when
\fBNO_COLOR\fR is set.
The plain render carries the same fields as the colored dashboard: period end,
monthly quota (remaining / cap), a Monthly allowance row with its
"$X by now" pro\-rata figure, "window N% elapsed" on every window row, and the
"on pace to hit cap in ..." burn\-rate warning when the current rate reaches
the cap before the window resets.
.TP
.B \-i, \-\-interval \fIdur\fR
Refresh interval (1\(en86400 seconds).  Accepts a unit suffix:
.I 30s ", " 5m ", " 1h ", " 2d
(bare number = seconds).  Overrides config \fBinterval_secs\fR.
.TP
.B \-w, \-\-bar\-width \fIn\fR
Progress bar width (5\(en200).  Overrides config \fBbar_width\fR.
.TP
.B \-b, \-\-bursts \fIn\fR
Show the spend\-burst sparkline for this run with N samples (5\(en240);
implies it on regardless of config.
.TP
.B \-\-tz \fI\(+-HH:MM\fR
.BR daily " / " hourly :
bucket by this fixed UTC offset instead of UTC.  Applies to the account API
path and the \fB\-\-local\fR log path alike.  Accepts
.I +05:30 ", " -08:00 ", " +0530 ", " -8 .
.TP
.B \-\-days, \-\-last, \-l \fIn\fR
.BR daily : number of days back (1\(en365).
.TP
.B \-\-hours \fIn\fR
.BR hourly : number of hours back (1\(en168).
.TP
.B \-\-json
Machine\-readable output where the subcommand supports it.  Conflicts with
\fB\-\-csv\fR (supplying both exits 2).
.TP
.B \-\-csv
CSV output for \fBdaily\fR, \fBhourly\fR, \fBmodel\fR, and \fBsession\fR.
Fields containing a comma, quote, or newline are quoted per RFC 4180.
.TP
.B \-\-gated
.BR models :
keep only models the current plan may use.  Uses the plan id plus purchased
and free credits; purchased/free credits unlock everything, an unknown plan
shows everything.  The gate is a close approximation of the API's (the
server enforces the real limit), so a misclassification could show or hide
one model.  With \fB\-\-json\fR it does not filter: every model is emitted
with additional \fBallowed\fR (bool) and \fBreason\fR (string) fields.  If the
bundled gating snapshot is older than 30 days a warning is printed to stderr.
.TP
.B \-\-dismiss\-update
Acknowledge the current update notice: records the newest crates.io version
(same as
.BR "config set dismissed_update=<ver>" )
and exits.  The notice stays hidden until an even newer version appears.
.TP
.B \-W, \-\-watch
Force watch mode (the default).  Conflicts with
.BR \-1 ;
supplying both exits 2.
.TP
.B watch
Bare\-word alias for
.BR \-W .
.TP
.B \-\-local
.BR daily " / " hourly :
read only this machine's CLI logs; no network.
.TP
.B \-V, \-\-version
Print \fBcmduse <version>\fR and exit 0.
.TP
.B \-h, \-\-help
Print usage and exit 0.  Accepts "help" as a bare word too.
.TP
.B config
Config subcommand; see SUBCOMMANDS.
.SH THE LIVE DASHBOARD
With no subcommand, \fBcmduse\fR renders a frame and rewrites it in place
every interval.  All line content is clipped to the terminal width and the
frame never exceeds what the window holds, so it cannot wrap or scroll
during normal operation.
.SS Layout (full mode)
The frame is, top to bottom:
.RS
.nf
Command Code Usage . GOAT . active
Period ends 2026-09-27

Credits $44.15 / $70.00 monthly . $0.00 purchased . $0.00 free

Usage windows
 Monthly   36.9% <bar> $25.85 / $70.00 . resets in 18d 0h . window 42% elapsed . $29.40 by now
 5-hour    11.1% <bar> $1.55  / $14.00 . resets in 2h 22m . window 59% elapsed
 Weekly    55.7% <bar> $19.61 / $35.00 . resets in 1d 18h . window 75% elapsed

This billing period
 Requests 2.7K . Cost $26.63 . Tokens 402.1M in / 721.2K out . Success 100%
.fi
.RE
When enabled and there was nonzero spend in the last samples, an extra
spend\-burst row precedes the last (status) line.
.PP
Line semantics:
.TP
Header
Plan display name (see below) and subscription status.
.TP
Period ends
The UTC billing cycle end date, from the subscription's
\fBcurrentPeriodEnd\fR.  Exactly the first 10 characters (YYYY\-MM\-DD).
.TP
Credits
Remaining monthly credits, purchased credits, and free credits.  The cap
shown is from the local plan table (see PLAN TABLE), not from the API.
.TP
Usage windows
Three rows.  Bar fill is used/cap; the percentage is used/cap; "used / cap"
is in dollars; "resets in" is wall time until the window rolls;
"window N% elapsed" is time since the window start divided by its length.
Monthly also carries "$X by now": the monthly cap pro\-rated to that elapsed
share (cap x elapsed%), i.e. what an even burn would have consumed by this
point \- compare it against the actual used figure.  It is Monthly\-only: the
5\-hour and weekly caps are throttles rather than budgets, so a pro\-rata
figure there would read as a spend target.
Monthly's used is derived: monthly cap minus remaining credits.  Its cap and
period come from the plan table and the subscription period.  5\-hour and
weekly data (used, cap, resetAt) come verbatim from the API
\fBwindowLimits\fR response and are never derived.
.TP
On pace warning
When a window is at least 10% elapsed AND the current spend rate
(used since window start, divided by seconds since window start) projects
hitting the cap before the window resets, the row gains
\fI. on pace to hit cap in <Xh Ym>\fR.  Under 10% elapsed no projection is
shown (a flat extrapolation from minutes of data is noise).  The projection
assumes a flat spend rate; bursty sessions shift it.
.TP
This billing period
Cumulative request count, cost, input/output tokens (human K/M compact) and
success rate, from the usage summary endpoint.
.SS Window math (exact)
A window of length L seconds ends at instant R (epoch ms, from the API or,
for monthly, the subscription period end parsed as ISO 8601 UTC).  Its start
is R \- L.  Elapsed percent is
.IR "(now \- start) / L ",
clamped to 0\(en100, rounded to a whole percent.  "Resets in" is R \- now,
rendered as "Nd Nh" when a day or more, "Nh Nm" when an hour or more, "Nm"
when a minute or more, else "<1m".  When now >= R it renders "resetting..."
(the next fetch carries the fresh window).  Pace ETA is
.IR "used / (now \- start) ",
giving a dollars\-per\-second rate; seconds\-to\-cap is
.IR "(cap \- used) / rate";
it is shown only when that lands before R and the 10% gate passes.  ISO
dates parse as UTC when suffixed with Z or lacking a suffix, and honor an
explicit +HH:MM or \-HH:MM (or basic +HHMM) offset by shifting the civil
reading; a time with no offset is read as UTC.
.SS Compact mode
The terminal size is re\-queried every refresh.  When the window is smaller
than 40 columns by 16 rows the full frame is replaced by a single content
line:
.RS
.nf
GOAT $44.15/$70.00 . 5h $1.55
.fi
.RE
followed by the status line.  When the window is resized back over the
threshold the full frame returns, in place.  Even a very small window (a few
columns) keeps redrawing the clipped compact line stably; there is no exit
and no shredding.
.SS Status line and countdown
The final frame line is the status line:
.I "refreshing every <N>s . ctrl-c to quit"
Between refreshes, each second the line rewrites in place as
.I "refreshing every <N>s . next refresh in <K>s . ctrl-c to quit"
.IR "K" " = N\-1 .. 1".
Both lines are clipped to the terminal width if needed; a line exactly at
the width is legal (no wrap), longer content is truncated at the width.
.SS Spend\-burst sparkline
On by default; disabled with
.BR "config set burst_on=false" .
It is one row, labeled
.I "spend bursts (<N>s samples) "
followed by the history rendered as an 8\-level bar chart.  Each bar is the
dollar delta of the 5\-hour window's cumulative used between two consecutive
refreshes, so a tall bar means spend during that interval and a flat line
means idle.  Sample count is config \fBburst_samples\fR (default 40) or
\fB\-b\fR on the command line; at a 5s interval 40 samples is about 3
minutes.  The row is hidden while every retained delta is zero, so idle
screens stay quiet.  History is session\-only: it starts empty each run and
never shows spend from earlier sessions.  Zero scale renders an all\-low
row.
.SH PLAN TABLE
Plan detection lowercases the API plan id and matches substrings in this
order: "enterprise" -> Enterprise, "provider" -> Provider,
"team" -> Team Pro, "max" with "20" -> Max 20x, "max" without
-> Max 10x, "goat" -> GOAT, "pro" -> Pro, "go" -> Go,
anything else -> Free.
.PP
Monthly credit pool by plan (single shared pool, verified empirically; the
docs' per\-model allowances are not what the API meters):
.IP Go
$10
.IP GOAT
$70
.IP Pro
$80
.IP Max 10x
$150
.IP Max 20x
$300
.IP Team Pro
$40
.IP Enterprise / Provider
none (pay\-as\-you\-go; no monthly cap row)
.PP
The 5\-hour and weekly caps (e.g. $14 / $35 on GOAT) are NOT in this table;
they come from the API
.B windowLimits
response and must not be derived client\-side.
.SH STATUSLINE
The statusline template supports the placeholders
.I {plan} {credits} {cap} {credits_bar} {5h_bar} {5h_pct} {5h_used} {5h_cap} {5h_eta}
.I {wk_bar} {wk_pct} {wk_used} {wk_cap} {wk_eta}
. Unknown placeholders are dropped; an unclosed brace passes through;
multi\-line templates are allowed.  \fBsl_colors=false\fR strips ANSI after
rendering; \fBsl_ascii=true\fR renders bars with "#" and "\-" instead of the
box glyphs.  {credits} is remaining monthly credits, {cap} the plan monthly
cap.  {5h_eta} and {wk_eta} render the pace warning text ("on pace to hit cap
in 2h 3m") or an empty string when no warning applies.  The same template
engine renders both the statusline subcommand and any statusline template in
a shell prompt.
.SH API ENDPOINTS
All requests go to
.IR https://api.commandcode.ai ,
with header
.I Authorization: Bearer <apiKey>
and Accept: application/json.  Endpoints:
.IP "GET /alpha/billing/subscriptions"
plan id, status, current period start/end.
.IP "GET /alpha/billing/credits"
credits object (monthly/purchased/free) and windowLimits (fiveHour, weekly;
each with used, cap, resetAt in ms).
.IP "GET /alpha/usage/summary"
cumulative totals: count, cost, tokens in/out, success rate.
.IP "GET /alpha/usage/summary?since=<ISO>"
same shape, cumulative since the ISO instant (used by daily/hourly
differencing).
.IP "GET /provider/v1/models"
live model list; each entry has id, and may have name, context_length,
owned_by.
.PP
Transient failures (TLS handshake drops, timeouts, EOF, 429, and any 5xx)
are retried up to 5 times with an exponential backoff (1s base, 8s cap,
jitter); a hard 15s per\-attempt timeout applies.  A 429's numeric
\fBRetry\-After\fR is honored (capped at 60s) in place of the computed backoff.  A watch\-mode fetch that
still fails renders a minimal error frame:
.RS
.nf
Command Code Usage . fetch failed
error: <joined per-endpoint errors>
retrying on next refresh
.fi
.RE
and the next interval retries; no fake zero data is shown.
.SH FILES
.TP
.I ~/.commandcode/auth.json
Read; API key.  Written by the Command Code CLI.
.TP
.I ~/.commandcode/projects
Read; per\-project CLI usage logs used by \fBdaily\fR/\fBhourly\fR
\fB\-\-local\fR, \fBmodel\fR, \fBsession\fR.  JSON lines.
.TP
.I ~/.cache/cmd\-usage/last\-check
Written; JSON recording the last update\-check time and newest known version.
Deleting it forces a fresh check on the next run.
.TP
.I ~/.config/cmd\-usage/config.json
Config, or
.I $XDG_CONFIG_HOME/cmd\-usage/config.json
when XDG_CONFIG_HOME is set.  Missing/corrupt files silently fall back to
defaults (a corrupt file prints a warning to stderr).  Keys:
.RS
.TP
interval_secs
integer 1\(en86400, default 5.
.TP
bar_width
integer 5\(en200, default 20.
.TP
burst_enabled
boolean, default true.
.TP
burst_samples
integer 5\(en240, default 40.
.TP
notify_on_cap
boolean, default true.  In watch mode fire a desktop notification once when a
window crosses into overflow.
.TP
statusline_template
string, default "{plan} {credits}/{cap} . 5h {5h_bar} . wk {wk_bar}".
.TP
statusline_colors
boolean, default true.
.TP
statusline_ascii
boolean, default false.
.TP
check_updates
boolean, default true.  When false, never contact crates.io to check for a
newer \fBcmd\-usage\fR.
.TP
dismissed_update
version string or null.  Suppresses the update notice for exactly this
version; a newer release shows again.
.RE
Unknown keys are preserved on config set (the file is rewritten from the
merged struct, so unknown keys are actually dropped on the next
.I "config set"
write; hand\-editing extra keys is tolerated until a config set rewrites the
file).
.SH ENVIRONMENT
.TP
.B XDG_CONFIG_HOME
Base for the config file when set.
.TP
.B HOME
Base for auth, projects, config (fallback), and cache paths when
XDG_CONFIG_HOME is unset.
.TP
.B NO_COLOR
When set to a non\-empty value, ANSI colors are suppressed (no\-color.org).
Colors are also suppressed automatically when stdout is not a terminal, so
piping a report or `cmduse \-1` never leaks SGR escapes.
.SH EXAMPLES
.nf
cmduse                     # live dashboard, 5s refresh
cmduse -1                  # one shot
cmduse -1 -p               # plain one shot (scripts)
cmduse -i 30 -w 40         # slower refresh, wider bars
cmduse -b 120              # sparkline with 120 samples
cmduse daily --days 14     # account usage, two weeks
cmduse daily --local       # this machine only
cmduse hourly --hours 6
cmduse models
cmduse statusline
cmduse config set interval=10 burst_on=false
.fi
.SH BUGS / NOTES
Rendering edge cases were observed against real terminals:
.IP \(bu
A frame taller than the terminal scrolls on refresh; that is why watch mode
switches to compact mode under 40x16 and clips every line to the width.
.IP \(bu
Never add a trailing newline after the frame's last line and never write a
bare newline at the very bottom row of the window; both desync the in\-place
redraw in real terminals.
.IP \(bu
Account and local dailies/hourlies bucket in UTC by default; pass
\fB\-\-tz\fR to bucket by a fixed offset.  Without it, a session near a UTC
midnight boundary splits across two day rows.
.IP \(bu
If the API returns a plan id not in the local plan table, the dashboard labels
it "Free" with no monthly cap and prints a one\-time warning to stderr; update
\fIcore/plans.json\fR to teach it the new plan.
.SH OCUSE
The same crate also ships a second binary,
.BR ocuse ,
which tracks OpenCode Go (the Go subscription) and OpenCode Zen
(pay\-as\-you\-go) with the same CLI shape as \fBcmduse\fR.  OpenCode Go
exposes the console's own usage endpoint,
.IR GET\ /zen/go/v1/usage ,
which reports the three account meters \(em
.I rolling
(5\-hour),
.IR weekly ,
and
.I monthly
\(em each a percent of its limit and a reset instant, so
.B ocuse
reads those for its window rows (the credential from
.IR $OCUSE_API_KEY ", " $OPENCODE_API_KEY ,
else the
.I opencode\-go
entry of opencode's
.IR auth.json ).
It reports what actually ran on this machine from opencode's own store for
everything the endpoint does not carry \(em the per\-model table,
\fBdaily\fR/\fBhourly\fR, tokens \(em priced by opencode itself, against the
token rates and per\-model limits the OpenCode docs publish (the generated
catalogue
.IR core/zen.json ).
The endpoint's figures win wherever both exist: the server's 5\-hour window is
a block with its own reset, its week is anchored to Monday 00:00 UTC, its month
is the subscription anniversary, and it meters with its own price basis, none
of which is reproducible from the store.  With no key, no network, or
\fB\-\-no\-api\fR, the windows fall back to a local estimate and the dashboard
labels them as such \(em and names the reason under the \fBGO\fR heading when
there is one (\fIusage API: HTTP 401 api_key_expired\fR), because the estimate
alone cannot tell a missing key from an expired one.  The same line rides in
\fB\-\-json\fR as \fIaccountError\fR (\fBnull\fR when the endpoint answered, and
for \fB\-\-no\-api\fR, which is a choice rather than a fault).  An expired Go
key is not renewed by signing in again: it has to be replaced in the OpenCode
console.
.PP
Go meters per model: each model has a monthly dollar limit, and its 5\-hour,
weekly, and monthly windows are fixed shares of that limit (20%, 50%, and
100%).  Go ships as two plans that share one token price list but grant
different per\-model limits: Go and Go Plus.  Neither the store nor the usage
endpoint names the plan the account is on, so the plan is explicit
(\fB\-\-plan\fR) and defaults to
.BR go .
.SS ocuse synopsis
.B ocuse
[\fIOPTIONS\fR]
.br
.B ocuse \-1
[\fB\-\-json\fR] [\fIOPTIONS\fR]
.br
.B ocuse model
[\fIid\fR] [\fB\-\-since\fR \fIISO\fR] [\fB\-\-json\fR | \fB\-\-csv\fR] [\fIOPTIONS\fR]
.br
.B ocuse daily
[\fB\-\-days\fR \fIn\fR] [\fB\-\-json\fR | \fB\-\-csv\fR] [\fIOPTIONS\fR]
.br
.B ocuse hourly
[\fB\-\-hours\fR \fIn\fR] [\fB\-\-json\fR | \fB\-\-csv\fR] [\fIOPTIONS\fR]
.br
.B ocuse session
[\fB\-\-since\fR \fIISO\fR] [\fB\-\-json\fR | \fB\-\-csv\fR]
.br
.B ocuse models
[\fB\-\-gated\fR] [\fB\-\-json\fR]
.br
.B ocuse plans
[\fB\-\-json\fR]
.br
.B ocuse statusline
[\fB\-\-json\fR] [\fIOPTIONS\fR]
.br
.B ocuse mcp
.br
.B ocuse \-V
.br
.B ocuse \-h
.SS ocuse commands
.TP
.B (no command)
Run the live dashboard in watch mode: a frame redrawn in place every 10
seconds (colour, severity gauges, and the spend\-burst sparkline) until
Ctrl\-C.  The frame and countdown reuse \fBcmduse\fR's in\-place redraw
contract, so a shrinking frame never scrolls.
.TP
.B \-1, \-\-once
Fetch once, print, exit.  With \fB\-\-json\fR it prints the JSON projection
instead of the text dashboard.
.TP
.B \-\-json
Machine\-readable projection (one object): \fIsource\fR, \fIgeneratedAt\fR,
\fIperiodStart\fR (and its alias \fIperiodStartAt\fR, both epoch ms),
\fIperiodEndAt\fR (the resolved end of the period in epoch ms, \fBnull\fR for
\fB\-\-window all\fR, whose range has no boundary), \fIperiodInferred\fR,
\fIaccount\fR (the three account meters from Go's usage endpoint \(em
\fIrolling\fR, \fIweekly\fR, \fImonthly\fR, each \fI{status, percent,
resetsAt}\fR with \fIresetsAt\fR in epoch ms \(em or \fBnull\fR when the
endpoint was not reached), \fItotals\fR (each of month, fiveHour,
weekly carrying cost, requests, and tokens), and the per\-model breakdown
\fImodels\fR.  A bare \fB\-\-json\fR also leaves the watch loop, so it prints
and exits rather than redrawing.
.TP
.B model [\fIid\fR]
Local usage grouped by model.  With no \fIid\fR, the full model table; with an
\fIid\fR, that model's limit, its month/5\-hour/weekly spend, and its share of
period spend.  An unused model prints that it has no usage in the period.
\fB\-\-since\fR \fIISO\fR pins the window start (an exact instant, outranking
\fB\-\-window\fR and \fB\-\-period\-start\fR).  \fB\-\-json\fR emits one object
\fI{"scope","source","sinceMs","models"}\fR whose \fImodels\fR map each id to
requests, tokensIn, tokensOut, cacheRead, costUsd and its limit; \fB\-\-csv\fR
emits \fImodel,requests,tokens_in,tokens_out,cache_read,cost_usd\fR.
.TP
.B daily
Spend per day (oldest first) over the read window (\fB\-\-days\fR), bucketed in
the display timezone (\fB\-\-tz\fR).  \fB\-\-json\fR emits
\fI{"scope","source","total","days"}\fR; \fB\-\-csv\fR emits
\fIday,requests,tokens_in,tokens_out,cache_read,cost_usd\fR with a final
\fItotal\fR row.
.TP
.B hourly
Spend per hour, same bucketing as \fBdaily\fR but over the last \fB\-\-hours\fR
N hours (default 24, max 168).  \fB\-\-json\fR emits
\fI{"scope","source","total","hours"}\fR; \fB\-\-csv\fR emits
\fIhour,requests,tokens_in,tokens_out,cache_read,cost_usd\fR with a final
\fItotal\fR row.
.TP
.B session
Spend per session, newest first (top 20).  \fB\-\-since\fR \fIISO\fR pins the
window start.  \fB\-\-json\fR emits \fI{"scope","source","sessions"}\fR (each
entry adding the last\-used instant and the distinct\-model count);
\fB\-\-csv\fR emits
\fIsession,requests,tokens_in,tokens_out,cache_read,cost_usd\fR.
.TP
.B models
The Go catalogue for the selected plan: each model's name, id, \fB$\fR/1M
in/out/cache\-read rates, the plan's monthly limit, and a \fIGRANTED\fR column.
Without \fB\-\-gated\fR every catalogued model is listed and marked;
\fB\-\-gated\fR keeps only the models the plan grants (present in the plan's
allowance map).  \fB\-\-json\fR prints one JSON object per line with keys id,
name, input, output, cacheRead, limit (null when not granted) and granted.
Needs no database; works offline.
.TP
.B plans
Print the Go/Zen catalogue: both Go plans (label, price, and each model's
monthly limit) beside the shared token rates, then a line for the Zen
pay\-as\-you\-go models.  \fB\-\-json\fR emits one object with
\fIextractedAt\fR, \fIwindows\fR (the 5\-hour/weekly/monthly shares),
\fIplans\fR (id, label, priceUsd, allowanceByModel), and the Go and Zen rate
tables.  Needs no database; works offline.
.TP
.B statusline
Print one compact line: month spend, 5\-hour spend, and the top model.
\fB\-\-json\fR prints one object: plan, period, monthSpent, monthCap,
fiveHourSpent, fiveHourCap, weeklySpent, weeklyCap, model.
.TP
.B mcp
Run an MCP stdio server; see \fBocuse mcp server\fR below.
.TP
.B \-V, \-\-version
Print \fBocuse <version>\fR and exit 0.
.TP
.B \-h, \-\-help
Print usage and exit 0.
.SS ocuse options
.TP
.B \-\-db \fIpath\fR
opencode store path.  Default \fBOPENCODE_DB\fR, else
.IR ~/.local/share/opencode/opencode.db .
Opened read\-only, so a running opencode is unaffected; a missing or
unreadable store exits 1 with a hint.
.TP
.B \-\-plan \fIid\fR
Which Go plan to measure against: \fBgo\fR (default) or \fBgo-plus\fR.  There
is deliberately no auto\-detection: the usage endpoint reports percentages
rather than a plan id, and the local store records no subscription, so the plan
must be given.  An unknown id exits 2 and lists the known ids.
.TP
.B \-\-no\-api
Do not call OpenCode Go's usage endpoint: report the local estimate only.
Useful offline, or to compare the local windows against the account's.
.TP
.B \-\-days \fIn\fR
Days of history to read (default 120).  Bounds the
\fBdaily\fR window and the range the MCP tools scan.
.TP
.B \-\-hours \fIn\fR
Hours of history for \fBhourly\fR (default 24, max 168).
.TP
.B \-\-gated
models: keep only the models the selected plan grants.
.TP
.B \-\-window \fIw\fR
Reporting window for the dashboard and statusline: \fBmonth\fR (default, the
calendar month in UTC), \fBall\fR, or \fI<n>d\fR.  Anything else exits 2.
.TP
.B \-\-period-start \fIYYYY\-MM\-DD\fR
Pin the period start (midnight UTC) instead of deriving it from
\fB\-\-window\fR.
.TP
.B \-\-infer\-anniversary
Infer the period start from the first Go request ever seen, instead of the
calendar month.  Opt\-in, because sparse history infers badly; ignored when
\fB\-\-period-start\fR or \fB\-\-since\fR is given.  The JSON's
\fIperiodInferred\fR reports which
was used.
.TP
.B \-\-since \fIISO\fR
Window start for \fBmodel\fR/\fBsession\fR as an exact ISO\-8601 instant
(\fI2026\-08\-27T00:00:00Z\fR).  Outranks \fB\-\-window\fR and
\fB\-\-period\-start\fR; an unparseable value exits 2.
.TP
.B \-\-json
Machine\-readable output for every subcommand that has one: the dashboard
(\fB\-1\fR), \fBdaily\fR, \fBhourly\fR, \fBmodel\fR, \fBsession\fR,
\fBmodels\fR, \fBplans\fR, \fBstatusline\fR.  Never coloured.
.TP
.B \-\-csv
CSV output for \fBdaily\fR, \fBhourly\fR, \fBmodel\fR and \fBsession\fR
(the columns carry the store's fields; there is no cache\-write column).
Never coloured.  Supplying both \fB\-\-json\fR and \fB\-\-csv\fR exits 2.
.TP
.B \-\-rows \fIn\fR
Table rows to print (default 15).
.TP
.B \-\-plain
No colour and no gauges.  Colour is also dropped automatically on a
non\-terminal stdout or when \fBNO_COLOR\fR is set.
.TP
.B \-\-tz \fI\(+-HH:MM\fR
Display timezone for the \fBdaily\fR/\fBhourly\fR buckets.  Accepts
.IR +05:30 ", " -08:00 ", " +0530 .
Anything else exits 2.
.SS ocuse data and windows
When Go's usage endpoint answers, the header's three window lines are the
account's own meters (the shares and resets \fBopencode.ai/console\fR shows),
each with this store's own spend beside them \(em the two need not divide to
each other, so the share carries an \fIof limit\fR label \(em and the billing period comes from the endpoint's monthly reset instant \(em
the subscription anniversary, which is why the period line reads
\fIGo billing month\fR.  There is no money pair, pace or pro\-rata figure:
Go grants limits per model, so no account\-wide pool exists to divide by.
Each model's table row still compares its own spend
against its monthly limit; the table's \fI5H\fR/\fIWK\fR columns are local
rolling windows (this model's spend over the last 5 hours / 7 days), and the
dashboard says so rather than letting them read as a second opinion.
.TP
Without the endpoint \(em no Go key, no network, or \fB\-\-no\-api\fR \(em the
window lines are a local estimate and are labelled as one: the rows carry
spend alone, since limits are per model and no account\-wide pool exists to
divide by.  Only the monthly period has a real end, so that row alone gains
a reset countdown and its \fIwindow N% elapsed\fR share; the rolling 5\-hour
and weekly rows show no countdown.  The period defaults to the calendar month, with
\fB\-\-period\-start\fR pinning the real anniversary and
\fB\-\-infer\-anniversary\fR guessing it from history.  The header splits period tokens
\fIin / out\fR and names the resolved end date.  A model whose spend
crosses its limit is flagged \fILIMIT EXCEEDED\fR.  There is no
\fISuccess N%\fR figure \(em opencode's store records no per\-request success
or error signal.  Limits and rates come from
.IR core/zen.json ,
regenerated from OpenCode's own docs sources with
.BR "bun scripts/extract\-zen.ts" .
.SS ocuse mcp server
\fBocuse mcp\fR runs an MCP stdio server (newline\-delimited JSON\-RPC on
stdin/stdout, diagnostics on stderr) exposing seven tools \( \fIusage\fR,
\fIplans\fR, \fImodels\fR, \fIdaily\fR, \fIhourly\fR, \fIsession\fR,
\fImodel\fR \) whose output matches the corresponding subcommands.  Tool
execution errors are returned as results with \fIisError\fR true, never as
JSON\-RPC errors.  stdout carries protocol traffic only.
.SS ocuse files
.TP
.I ~/.local/share/opencode/opencode.db
Read\-only; opencode's own message store (v1 \fBmessage\fR, or v2
\fBsession_message\fR after the migration), the only per\-model cost source.
.TP
.I $OPENCODE_DB
Overrides the store path (equivalently, \fB\-\-db\fR).
.TP
.I ~/.local/share/opencode/auth.json
Read (never written) for the
.I opencode\-go
key, the credential \fB/connect\fR stored; \fB$OCUSE_API_KEY\fR and
\fB$OPENCODE_API_KEY\fR override it.
.SH SEE ALSO
.BR cmd (1),
the Command Code CLI for login and authentication.
.br
.BR ocuse ,
this crate's OpenCode Go/Zen twin, documented above under
.BR OCUSE .