@leo000001/opencode-quota-sidebar 4.0.5 → 4.0.11
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 +504 -446
- package/README.zh-CN.md +516 -458
- package/dist/cli.d.ts +38 -0
- package/dist/cli.js +153 -42
- package/dist/cli_render.d.ts +4 -4
- package/dist/cli_render.js +74 -74
- package/dist/cost.d.ts +21 -4
- package/dist/cost.js +493 -264
- package/dist/format.d.ts +5 -5
- package/dist/format.js +288 -287
- package/dist/history_usage.d.ts +15 -9
- package/dist/history_usage.js +28 -22
- package/dist/index.d.ts +3 -3
- package/dist/index.js +35 -34
- package/dist/models_dev_pricing.d.ts +6 -0
- package/dist/models_dev_pricing.js +226 -0
- package/dist/opencode_pricing.d.ts +14 -0
- package/dist/opencode_pricing.js +273 -0
- package/dist/storage.d.ts +3 -3
- package/dist/storage.js +27 -28
- package/dist/storage_parse.d.ts +1 -1
- package/dist/storage_parse.js +51 -45
- package/dist/storage_paths.d.ts +1 -0
- package/dist/storage_paths.js +26 -11
- package/dist/title_apply.d.ts +5 -22
- package/dist/title_apply.js +19 -61
- package/dist/tui.d.ts +1 -1
- package/dist/tui.tsx +481 -471
- package/dist/tui_helpers.d.ts +5 -3
- package/dist/tui_helpers.js +62 -34
- package/dist/types.d.ts +8 -10
- package/dist/usage.d.ts +9 -6
- package/dist/usage.js +27 -21
- package/dist/usage_service.d.ts +8 -7
- package/dist/usage_service.js +261 -150
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,446 +1,504 @@
|
|
|
1
|
-
# opencode-quota-sidebar
|
|
2
|
-
|
|
3
|
-
[](https://www.npmjs.com/package/@leo000001/opencode-quota-sidebar)
|
|
4
|
-
[](https://github.com/xihuai18/opencode-quota-sidebar/blob/main/LICENSE)
|
|
5
|
-
|
|
6
|
-
[简体中文](./README.zh-CN.md)
|
|
7
|
-
|
|
8
|
-
OpenCode plugin that shows token usage and provider quota in the TUI sidebar, while keeping the shared session title compact and readable across Desktop, Web, and TUI.
|
|
9
|
-
|
|
10
|
-

|
|
11
|
-
|
|
12
|
-
The screenshot above comes from [`./assets/OpenCode-Quota-Sidebar.png`](./assets/OpenCode-Quota-Sidebar.png) and shows the actual TUI sidebar layout this plugin renders.
|
|
13
|
-
|
|
14
|
-
## What It Does
|
|
15
|
-
|
|
16
|
-
- Renders dedicated `TITLE`, `USAGE`, and `QUOTA` blocks in the TUI sidebar
|
|
17
|
-
- Keeps the shared `session.title` on a compact single line instead of pushing multiline telemetry into every client
|
|
18
|
-
- Aggregates usage for `session`, `day`, `week`, and `month`
|
|
19
|
-
- Supports provider quota/balance fetchers for OpenAI, Copilot, Anthropic, Kimi, Zhipu, MiniMax, and RightCode
|
|
20
|
-
- Can include descendant subagent sessions in session-scoped usage/quota totals
|
|
21
|
-
- Exposes `quota_summary` and `quota_show` tools for reports and title toggling
|
|
22
|
-
|
|
23
|
-
## Architecture Overview
|
|
24
|
-
|
|
25
|
-
This repository is a pure plugin implementation. It does not modify OpenCode core.
|
|
26
|
-
|
|
27
|
-
- Server layer: aggregates usage, fetches quota snapshots, stores state, manages title refresh, and exposes tools
|
|
28
|
-
- TUI layer: renders the sidebar panel UI and reads persisted sidebar-panel payloads
|
|
29
|
-
- Persistence layer: stores global state plus day-partitioned session chunks so historical sessions can render without full rescans
|
|
30
|
-
- Provider adapter layer: maps each provider to a common `QuotaSnapshot` shape through a registry of adapters
|
|
31
|
-
|
|
32
|
-
The implementation is built on top of `@opencode-ai/plugin` and `@opencode-ai/sdk`.
|
|
33
|
-
|
|
34
|
-
## How It Works
|
|
35
|
-
|
|
36
|
-
This plugin has two display layers:
|
|
37
|
-
|
|
38
|
-
- TUI sidebar panel: renders structured `TITLE`, `USAGE`, and `QUOTA` blocks
|
|
39
|
-
- Shared session title: stays compact so Desktop, Web, and TUI can all read the same title cleanly
|
|
40
|
-
|
|
41
|
-
In `sidebar.titleMode="auto"`, the shared title remains a compact single line. The richer multiline layout is handled by the dedicated TUI plugin instead of being written into `session.title` for every client.
|
|
42
|
-
|
|
43
|
-
Session-scoped aggregation can include descendant subagent sessions when `sidebar.includeChildren=true`. Day/week/month summaries do not merge descendants.
|
|
44
|
-
|
|
45
|
-
## Supported Providers
|
|
46
|
-
|
|
47
|
-
Built-in quota adapters:
|
|
48
|
-
|
|
49
|
-
| Provider | Endpoint family | Auth | Quota shape | Notes |
|
|
50
|
-
| ------------------- | ---------------------------------------------------------- | ------- | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
|
51
|
-
| OpenAI Codex | `chatgpt.com/backend-api/wham/usage` | OAuth | Multi-window subscription | Reads ChatGPT usage windows such as short-term + weekly; Pro plans may also expose Codex Spark limits (`additional_rate_limits`) |
|
|
52
|
-
| GitHub Copilot | `api.github.com/copilot_internal/user` | OAuth | Monthly subscription | Uses the Copilot internal user endpoint |
|
|
53
|
-
| Anthropic | `api.anthropic.com/api/oauth/usage` | OAuth | Multi-window subscription | Supports plan-based usage windows |
|
|
54
|
-
| Kimi For Coding | `api.kimi.com/coding/v1/usages` | API key | Multi-window subscription | Typically `5h` + weekly windows |
|
|
55
|
-
| Zhipu Coding Plan | `bigmodel.cn/api/monitor/usage/quota/limit` | API key | Token quota | Coding-plan style quota window |
|
|
56
|
-
| MiniMax Coding Plan | `www.minimaxi.com/v1/api/openplatform/coding_plan/remains` | API key | Multi-window subscription | Typically `5h` + weekly windows |
|
|
57
|
-
| RightCode | `www.right.codes/account/summary` | API key | Daily quota and/or balance | Prefix-based subscription matching, with balance fallback |
|
|
58
|
-
|
|
59
|
-
Generic providers without a built-in quota endpoint can still contribute usage totals, but they will not show quota/balance unless an adapter exists.
|
|
60
|
-
|
|
61
|
-
Provider notes:
|
|
62
|
-
|
|
63
|
-
- OpenAI, Copilot, and Anthropic quota support is based on OAuth/session auth, not generic API-key billing endpoints
|
|
64
|
-
- **OpenAI Codex Spark**: OpenAI Pro subscriptions may expose additional per-feature windows (e.g. `GPT-5.3-Codex-Spark`) in the `additional_rate_limits` field of the `wham/usage` response. When present, the plugin automatically parses and renders these as extra windows under the OpenAI quota line. No extra config is required. Code review quota (`code_review_rate_limit`) is not displayed yet.
|
|
65
|
-
- RightCode can show both a daily allowance line and a balance line
|
|
66
|
-
- Copilot quota is supported, but API-equivalent cost is intentionally not shown because runtime pricing is not reliable enough
|
|
67
|
-
|
|
68
|
-
## Display Rules
|
|
69
|
-
|
|
70
|
-
- Sidebar quota lines show providers actually used in the current session and recognized by an adapter
|
|
71
|
-
- `quota_summary` fetches default quota providers even if they were not used in the current session
|
|
72
|
-
- The TUI sidebar reads persisted `sidebarPanel` / usage state first, so historical sessions can render quickly on open or resume
|
|
73
|
-
- Compact-title quota parsing is only a fallback path; the TUI panel prefers persisted structured data
|
|
74
|
-
- `quota_show` toggles title decoration on or off, but the TUI panel remains the main rich display path
|
|
75
|
-
|
|
76
|
-
## Install
|
|
77
|
-
|
|
78
|
-
OpenCode loads the server plugin from `opencode.json` and the TUI plugin from `tui.json`.
|
|
79
|
-
|
|
80
|
-
`opencode.json`
|
|
81
|
-
|
|
82
|
-
```json
|
|
83
|
-
{
|
|
84
|
-
"plugin": ["@leo000001/opencode-quota-sidebar@latest"]
|
|
85
|
-
}
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
`tui.json`
|
|
89
|
-
|
|
90
|
-
```json
|
|
91
|
-
{
|
|
92
|
-
"plugin": ["@leo000001/opencode-quota-sidebar@latest"]
|
|
93
|
-
}
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
For OpenCode `>=1.2.15`, keep server plugins in `opencode.json` and TUI plugins in `tui.json`.
|
|
97
|
-
|
|
98
|
-
## Sidebar Demo
|
|
99
|
-
|
|
100
|
-
Typical TUI sidebar layout (with Codex Spark windows):
|
|
101
|
-
|
|
102
|
-
```text
|
|
103
|
-
TITLE
|
|
104
|
-
Fix quota adapter matching
|
|
105
|
-
USAGE
|
|
106
|
-
R184 I189k O53.2k
|
|
107
|
-
CR31.4k CW3.2k Cd66%
|
|
108
|
-
|
|
109
|
-
QUOTA
|
|
110
|
-
OAI 5h80 R3h20m
|
|
111
|
-
W70 R2D04h
|
|
112
|
-
Sk5h100 R1h00m
|
|
113
|
-
SkW100 R3D04h
|
|
114
|
-
Cop M78 R12D00h
|
|
115
|
-
RC D$88.9/$60 E6D00h
|
|
116
|
-
B260
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
Compact shared title example:
|
|
120
|
-
|
|
121
|
-
```text
|
|
122
|
-
Fix quota adapter matching | OAI 5h80 R3h20m W70 R2D04h | RC D$88.9/$60 B260 | Cd66% |
|
|
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
|
-
-
|
|
1
|
+
# opencode-quota-sidebar
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@leo000001/opencode-quota-sidebar)
|
|
4
|
+
[](https://github.com/xihuai18/opencode-quota-sidebar/blob/main/LICENSE)
|
|
5
|
+
|
|
6
|
+
[简体中文](./README.zh-CN.md)
|
|
7
|
+
|
|
8
|
+
OpenCode plugin that shows token usage and provider quota in the TUI sidebar, while keeping the shared session title compact and readable across Desktop, Web, and TUI.
|
|
9
|
+
|
|
10
|
+

|
|
11
|
+
|
|
12
|
+
The screenshot above comes from [`./assets/OpenCode-Quota-Sidebar.png`](./assets/OpenCode-Quota-Sidebar.png) and shows the actual TUI sidebar layout this plugin renders.
|
|
13
|
+
|
|
14
|
+
## What It Does
|
|
15
|
+
|
|
16
|
+
- Renders dedicated `TITLE`, `USAGE`, and `QUOTA` blocks in the TUI sidebar
|
|
17
|
+
- Keeps the shared `session.title` on a compact single line instead of pushing multiline telemetry into every client
|
|
18
|
+
- Aggregates usage for `session`, `day`, `week`, and `month`
|
|
19
|
+
- Supports provider quota/balance fetchers for OpenAI, Copilot, Anthropic, Kimi, Zhipu, MiniMax, and RightCode
|
|
20
|
+
- Can include descendant subagent sessions in session-scoped usage/quota totals
|
|
21
|
+
- Exposes `quota_summary` and `quota_show` tools for reports and title toggling
|
|
22
|
+
|
|
23
|
+
## Architecture Overview
|
|
24
|
+
|
|
25
|
+
This repository is a pure plugin implementation. It does not modify OpenCode core.
|
|
26
|
+
|
|
27
|
+
- Server layer: aggregates usage, fetches quota snapshots, stores state, manages title refresh, and exposes tools
|
|
28
|
+
- TUI layer: renders the sidebar panel UI and reads persisted sidebar-panel payloads
|
|
29
|
+
- Persistence layer: stores global state plus day-partitioned session chunks so historical sessions can render without full rescans
|
|
30
|
+
- Provider adapter layer: maps each provider to a common `QuotaSnapshot` shape through a registry of adapters
|
|
31
|
+
|
|
32
|
+
The implementation is built on top of `@opencode-ai/plugin` and `@opencode-ai/sdk`.
|
|
33
|
+
|
|
34
|
+
## How It Works
|
|
35
|
+
|
|
36
|
+
This plugin has two display layers:
|
|
37
|
+
|
|
38
|
+
- TUI sidebar panel: renders structured `TITLE`, `USAGE`, and `QUOTA` blocks
|
|
39
|
+
- Shared session title: stays compact so Desktop, Web, and TUI can all read the same title cleanly
|
|
40
|
+
|
|
41
|
+
In `sidebar.titleMode="auto"`, the shared title remains a compact single line. The richer multiline layout is handled by the dedicated TUI plugin instead of being written into `session.title` for every client.
|
|
42
|
+
|
|
43
|
+
Session-scoped aggregation can include descendant subagent sessions when `sidebar.includeChildren=true`. Day/week/month summaries do not merge descendants.
|
|
44
|
+
|
|
45
|
+
## Supported Providers
|
|
46
|
+
|
|
47
|
+
Built-in quota adapters:
|
|
48
|
+
|
|
49
|
+
| Provider | Endpoint family | Auth | Quota shape | Notes |
|
|
50
|
+
| ------------------- | ---------------------------------------------------------- | ------- | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
|
51
|
+
| OpenAI Codex | `chatgpt.com/backend-api/wham/usage` | OAuth | Multi-window subscription | Reads ChatGPT usage windows such as short-term + weekly; Pro plans may also expose Codex Spark limits (`additional_rate_limits`) |
|
|
52
|
+
| GitHub Copilot | `api.github.com/copilot_internal/user` | OAuth | Monthly subscription | Uses the Copilot internal user endpoint |
|
|
53
|
+
| Anthropic | `api.anthropic.com/api/oauth/usage` | OAuth | Multi-window subscription | Supports plan-based usage windows |
|
|
54
|
+
| Kimi For Coding | `api.kimi.com/coding/v1/usages` | API key | Multi-window subscription | Typically `5h` + weekly windows |
|
|
55
|
+
| Zhipu Coding Plan | `bigmodel.cn/api/monitor/usage/quota/limit` | API key | Token quota | Coding-plan style quota window |
|
|
56
|
+
| MiniMax Coding Plan | `www.minimaxi.com/v1/api/openplatform/coding_plan/remains` | API key | Multi-window subscription | Typically `5h` + weekly windows |
|
|
57
|
+
| RightCode | `www.right.codes/account/summary` | API key | Daily quota and/or balance | Prefix-based subscription matching, with balance fallback |
|
|
58
|
+
|
|
59
|
+
Generic providers without a built-in quota endpoint can still contribute usage totals, but they will not show quota/balance unless an adapter exists.
|
|
60
|
+
|
|
61
|
+
Provider notes:
|
|
62
|
+
|
|
63
|
+
- OpenAI, Copilot, and Anthropic quota support is based on OAuth/session auth, not generic API-key billing endpoints
|
|
64
|
+
- **OpenAI Codex Spark**: OpenAI Pro subscriptions may expose additional per-feature windows (e.g. `GPT-5.3-Codex-Spark`) in the `additional_rate_limits` field of the `wham/usage` response. When present, the plugin automatically parses and renders these as extra windows under the OpenAI quota line. No extra config is required. Code review quota (`code_review_rate_limit`) is not displayed yet.
|
|
65
|
+
- RightCode can show both a daily allowance line and a balance line
|
|
66
|
+
- Copilot quota is supported, but API-equivalent cost is intentionally not shown because runtime pricing is not reliable enough
|
|
67
|
+
|
|
68
|
+
## Display Rules
|
|
69
|
+
|
|
70
|
+
- Sidebar quota lines show providers actually used in the current session and recognized by an adapter
|
|
71
|
+
- `quota_summary` fetches default quota providers even if they were not used in the current session
|
|
72
|
+
- The TUI sidebar reads persisted `sidebarPanel` / usage state first, so historical sessions can render quickly on open or resume
|
|
73
|
+
- Compact-title quota parsing is only a fallback path; the TUI panel prefers persisted structured data
|
|
74
|
+
- `quota_show` toggles title decoration on or off, but the TUI panel remains the main rich display path
|
|
75
|
+
|
|
76
|
+
## Install
|
|
77
|
+
|
|
78
|
+
OpenCode loads the server plugin from `opencode.json` and the TUI plugin from `tui.json`.
|
|
79
|
+
|
|
80
|
+
`opencode.json`
|
|
81
|
+
|
|
82
|
+
```json
|
|
83
|
+
{
|
|
84
|
+
"plugin": ["@leo000001/opencode-quota-sidebar@latest"]
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
`tui.json`
|
|
89
|
+
|
|
90
|
+
```json
|
|
91
|
+
{
|
|
92
|
+
"plugin": ["@leo000001/opencode-quota-sidebar@latest"]
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
For OpenCode `>=1.2.15`, keep server plugins in `opencode.json` and TUI plugins in `tui.json`.
|
|
97
|
+
|
|
98
|
+
## Sidebar Demo
|
|
99
|
+
|
|
100
|
+
Typical TUI sidebar layout (with Codex Spark windows):
|
|
101
|
+
|
|
102
|
+
```text
|
|
103
|
+
TITLE
|
|
104
|
+
Fix quota adapter matching
|
|
105
|
+
USAGE
|
|
106
|
+
R184 I189k O53.2k
|
|
107
|
+
CR31.4k CW3.2k Cd66%
|
|
108
|
+
API $12.8
|
|
109
|
+
QUOTA
|
|
110
|
+
OAI 5h80 R3h20m
|
|
111
|
+
W70 R2D04h
|
|
112
|
+
Sk5h100 R1h00m
|
|
113
|
+
SkW100 R3D04h
|
|
114
|
+
Cop M78 R12D00h
|
|
115
|
+
RC D$88.9/$60 E6D00h
|
|
116
|
+
B260
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Compact shared title example:
|
|
120
|
+
|
|
121
|
+
```text
|
|
122
|
+
Fix quota adapter matching | OAI 5h80 R3h20m W70 R2D04h | RC D$88.9/$60 B260 | Cd66% | API$12.8
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Pricing And API Cost
|
|
126
|
+
|
|
127
|
+
`API cost` is an API-equivalent estimate. It is not your subscription fee, not a provider invoice, and not necessarily what the upstream service actually billed.
|
|
128
|
+
|
|
129
|
+
Pricing source priority:
|
|
130
|
+
|
|
131
|
+
1. explicit model prices from your OpenCode main config (`opencode.jsonc` / `opencode.json`)
|
|
132
|
+
2. fast/tier prices derived from those explicit base-model prices
|
|
133
|
+
3. non-zero runtime prices from `provider.list()`
|
|
134
|
+
4. fast/tier prices derived from runtime metadata
|
|
135
|
+
5. `models.dev` remote model catalog pricing
|
|
136
|
+
6. bundled fallback pricing shipped by this plugin
|
|
137
|
+
|
|
138
|
+
Important notes:
|
|
139
|
+
|
|
140
|
+
- OpenAI / Anthropic OAuth runtime metadata often reports `cost: 0`, so runtime pricing is only a supplemental source
|
|
141
|
+
- `provider.list()` is a runtime metadata view of the models OpenCode currently exposes; it is useful when non-zero, but it is not a stable authoritative pricing API
|
|
142
|
+
- OpenCode main-config pricing layers merge field-by-field, so a later override can replace only `input` / `output` without discarding earlier `cache_*` or `context_over_200k` fields
|
|
143
|
+
- `models.dev` is used as a structured remote supplement only for runtime-discovered models that are still missing prices after config, runtime, and bundled sources are considered; this mainly helps newer models that are not in the plugin's bundled table yet
|
|
144
|
+
- if `models.dev` is unreachable, the plugin falls back to the higher-priority sources above; API cost may remain `0` for uncovered models until pricing becomes available again
|
|
145
|
+
- bundled pricing covers common models, so token usage and quota features do not require manual pricing config
|
|
146
|
+
- if you use a new or not-yet-bundled model and runtime pricing is still zero, `API cost` may stay `$0.00` until you add an explicit model price override in your OpenCode main config
|
|
147
|
+
|
|
148
|
+
To get complete `API cost` coverage for new models, at least one of these must be true:
|
|
149
|
+
|
|
150
|
+
1. the model already exists in the plugin's bundled pricing table
|
|
151
|
+
2. you configured that model's price in OpenCode main config
|
|
152
|
+
3. runtime `provider.list()` returns a non-zero price for it
|
|
153
|
+
4. runtime `provider.list()` exposes the model and `models.dev` has pricing for it
|
|
154
|
+
|
|
155
|
+
## Tool Report Demo
|
|
156
|
+
|
|
157
|
+
Example historical `quota_summary` markdown output shape:
|
|
158
|
+
|
|
159
|
+
```md
|
|
160
|
+
## Quota History - Daily since 2026-02-18
|
|
161
|
+
|
|
162
|
+
### Quota Status
|
|
163
|
+
|
|
164
|
+
- OpenAI: 5h | 80.0% | reset 3h20m; Weekly | 70.0% | reset 2D04h
|
|
165
|
+
- Copilot: Monthly | 78.0% | reset 12D00h
|
|
166
|
+
- RightCode: Daily $88.9/$60 | reset 6D00h
|
|
167
|
+
|
|
168
|
+
### Totals
|
|
169
|
+
|
|
170
|
+
| Metric | Total | Avg/Period |
|
|
171
|
+
| ------------ | ----: | ---------: |
|
|
172
|
+
| Requests | 184 | 26.3 |
|
|
173
|
+
| Total Tokens | 277k | 39.6k |
|
|
174
|
+
| Cache Hit | 63.1% | 58.4% |
|
|
175
|
+
| API Cost | $12.8 | $1.83 |
|
|
176
|
+
|
|
177
|
+
### Provider Breakdown
|
|
178
|
+
|
|
179
|
+
| Provider | Req | Input | Output | Total | Share | Cache Hit | API Cost |
|
|
180
|
+
| --------- | --: | ----: | -----: | ----: | ----: | --------: | -------: |
|
|
181
|
+
| OpenAI | 140 | 160k | 61k | 221k | 79.8% | 66.2% | $10.4 |
|
|
182
|
+
| Anthropic | 44 | 29k | 27.1k | 56.1k | 20.2% | 51.3% | $2.34 |
|
|
183
|
+
|
|
184
|
+
### Period Detail
|
|
185
|
+
|
|
186
|
+
| Period | Requests | Input | Output | Cache | Cache Hit | Total | API Cost |
|
|
187
|
+
| ------------ | -------: | ----: | -----: | ----: | --------: | ----: | -------: |
|
|
188
|
+
| 2026-02-18 | 12 | 18.3k | 4.2k | 8.9k | 32.7% | 31.4k | $1.12 |
|
|
189
|
+
| 2026-02-24\* | 17 | 8.1k | 2.0k | 3.4k | 66.0% | 13.5k | $0.88 |
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
The tool already returns full markdown. Clients should display that report directly instead of replacing it with a short summary.
|
|
193
|
+
|
|
194
|
+
Sidebar output uses compact tokens. Toasts and markdown reports keep fuller human-readable wording.
|
|
195
|
+
|
|
196
|
+
## Why The TUI Panel Exists
|
|
197
|
+
|
|
198
|
+
OpenCode renders the sidebar title as plain text inside a single styled title field. That means the shared title is great for compact telemetry, but not ideal for a rich multi-section layout.
|
|
199
|
+
|
|
200
|
+
This plugin therefore uses:
|
|
201
|
+
|
|
202
|
+
- shared compact titles for cross-client compatibility
|
|
203
|
+
- a dedicated TUI sidebar panel for the detailed block layout
|
|
204
|
+
|
|
205
|
+
That split avoids polluting Desktop/Web titles while still giving TUI users a readable quota dashboard.
|
|
206
|
+
|
|
207
|
+
## Abbreviations
|
|
208
|
+
|
|
209
|
+
Usage tokens:
|
|
210
|
+
|
|
211
|
+
- `R`: requests
|
|
212
|
+
- `I`: input tokens
|
|
213
|
+
- `O`: output tokens, including reasoning tokens
|
|
214
|
+
- `CR`: cache read tokens
|
|
215
|
+
- `CW`: cache write tokens
|
|
216
|
+
- `Cd`: cached ratio / cache coverage
|
|
217
|
+
- `API`: API-equivalent cost estimate
|
|
218
|
+
|
|
219
|
+
Quota tokens:
|
|
220
|
+
|
|
221
|
+
- `OAI`: OpenAI
|
|
222
|
+
- `Cop`: GitHub Copilot
|
|
223
|
+
- `Ant`: Anthropic
|
|
224
|
+
- `RC`: RightCode
|
|
225
|
+
- `B`: balance
|
|
226
|
+
- `D`: daily window
|
|
227
|
+
- `W`: weekly window
|
|
228
|
+
- `M`: monthly window
|
|
229
|
+
- `Sk5h`: OpenAI Codex Spark short window (e.g. 5h)
|
|
230
|
+
- `SkW`: OpenAI Codex Spark weekly window
|
|
231
|
+
- `R3h20m`: resets in `3h20m`
|
|
232
|
+
- `R2D04h`: resets in `2D04h`
|
|
233
|
+
- `E6D00h`: expires in `6D00h`
|
|
234
|
+
|
|
235
|
+
Example compact quota fragments:
|
|
236
|
+
|
|
237
|
+
- `OAI 5h80 R3h20m`: OpenAI short window, 80% remaining, resets in `3h20m`
|
|
238
|
+
- `OAI Sk5h100 R1h00m`: OpenAI Codex Spark 5h window, 100% remaining, resets in `1h00m`
|
|
239
|
+
- `OAI SkW100 R3D04h`: OpenAI Codex Spark weekly window, 100% remaining, resets in `3D04h`
|
|
240
|
+
- `Cop M78 R12D00h`: Copilot monthly quota, 78% remaining, resets in `12D00h`
|
|
241
|
+
- `RC D$88.9/$60 E6D00h B260`: RightCode daily quota plus balance
|
|
242
|
+
|
|
243
|
+
## Config
|
|
244
|
+
|
|
245
|
+
Recommended config file locations:
|
|
246
|
+
|
|
247
|
+
- `~/.config/opencode/quota-sidebar.config.json`
|
|
248
|
+
- `<worktree>/quota-sidebar.config.json`
|
|
249
|
+
- `<directory>/quota-sidebar.config.json`
|
|
250
|
+
- `<worktree>/.opencode/quota-sidebar.config.json`
|
|
251
|
+
- `<directory>/.opencode/quota-sidebar.config.json`
|
|
252
|
+
- `OPENCODE_QUOTA_CONFIG=/absolute/path/to/config.json`
|
|
253
|
+
|
|
254
|
+
Minimal example:
|
|
255
|
+
|
|
256
|
+
```json
|
|
257
|
+
{
|
|
258
|
+
"sidebar": {
|
|
259
|
+
"enabled": true,
|
|
260
|
+
"titleMode": "auto",
|
|
261
|
+
"showCost": true,
|
|
262
|
+
"showQuota": true,
|
|
263
|
+
"includeChildren": true
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
See [`quota-sidebar.config.example.json`](./quota-sidebar.config.example.json) for a fuller config example.
|
|
269
|
+
|
|
270
|
+
Important config notes:
|
|
271
|
+
|
|
272
|
+
- `sidebar.titleMode`: `auto`, `compact`, or `multiline`
|
|
273
|
+
- `sidebar.showCost`: controls API-equivalent cost in sidebar, title, markdown report, toast, and CLI output
|
|
274
|
+
- `sidebar.wrapQuotaLines`: wraps long quota lines with indentation instead of dropping fields
|
|
275
|
+
- `sidebar.includeChildren`: includes descendant subagent sessions for `period=session`
|
|
276
|
+
Config is layered. The later source overrides the earlier one:
|
|
277
|
+
|
|
278
|
+
1. global config
|
|
279
|
+
2. worktree config
|
|
280
|
+
3. directory config
|
|
281
|
+
4. worktree `.opencode` config
|
|
282
|
+
5. directory `.opencode` config
|
|
283
|
+
6. `OPENCODE_QUOTA_CONFIG`
|
|
284
|
+
|
|
285
|
+
OpenCode main pricing config candidates are read from these locations:
|
|
286
|
+
|
|
287
|
+
1. `~/.config/opencode/opencode.jsonc`
|
|
288
|
+
2. `~/.config/opencode/opencode.json`
|
|
289
|
+
3. `<worktree>/opencode.jsonc`
|
|
290
|
+
4. `<worktree>/opencode.json`
|
|
291
|
+
5. `<directory>/opencode.jsonc`
|
|
292
|
+
6. `<directory>/opencode.json`
|
|
293
|
+
7. `<worktree>/.opencode/opencode.jsonc`
|
|
294
|
+
8. `<worktree>/.opencode/opencode.json`
|
|
295
|
+
9. `<directory>/.opencode/opencode.jsonc`
|
|
296
|
+
10. `<directory>/.opencode/opencode.json`
|
|
297
|
+
|
|
298
|
+
## Linux CLI Notes
|
|
299
|
+
|
|
300
|
+
- `opencode-quota` will auto-start a temporary `opencode serve` when no local server is already reachable
|
|
301
|
+
- recent releases clean up that temporary server more aggressively on Linux/Unix so the CLI can exit normally after printing the report
|
|
302
|
+
- if the CLI still hangs on Linux, upgrade to a version that includes the server-process cleanup fix
|
|
303
|
+
|
|
304
|
+
## Persistence And Aggregation
|
|
305
|
+
|
|
306
|
+
The plugin stores:
|
|
307
|
+
|
|
308
|
+
- global state in `<opencode-data>/quota-sidebar.state.json`
|
|
309
|
+
- session chunks in `<opencode-data>/quota-sidebar-sessions/YYYY/MM/DD.json`
|
|
310
|
+
|
|
311
|
+
Those persisted chunks keep title state, cached usage, sidebar-panel payloads, and quota cache data. This lets the TUI sidebar render from stored structured state on session open/resume instead of depending entirely on live message scans.
|
|
312
|
+
|
|
313
|
+
Usage aggregation is incremental. The plugin tracks a cursor per session and processes only new messages when possible. If message history changes in a way that invalidates the incremental view, it can rescan and refresh persisted usage.
|
|
314
|
+
|
|
315
|
+
Pricing cache notes:
|
|
316
|
+
|
|
317
|
+
- newer releases persist a `pricingFingerprint` alongside cached session usage
|
|
318
|
+
- changing a model price from one non-zero value to another non-zero value now invalidates old cached API-cost totals automatically
|
|
319
|
+
- older plugin versions only keyed cache freshness on billing version, so historical session API-cost values could remain stale until a forced recompute
|
|
320
|
+
- legacy decorated titles that still contain `Est$...` are recognized during cleanup/restore, but newly rendered titles always use `API$...`
|
|
321
|
+
|
|
322
|
+
## Tools
|
|
323
|
+
|
|
324
|
+
- `quota_summary`: shows usage and quota for `session`, `day`, `week`, or `month`
|
|
325
|
+
- `quota_show`: toggles title decoration on or off
|
|
326
|
+
|
|
327
|
+
Behavior notes:
|
|
328
|
+
|
|
329
|
+
- `quota_summary` returns the full markdown report body
|
|
330
|
+
- `quota_summary` can show a toast in addition to returning markdown
|
|
331
|
+
- `quota_summary` accepts `period`, `since`, `last`, `toast`, and `includeChildren`
|
|
332
|
+
- `quota_summary(includeChildren=true)` only changes `period=session`
|
|
333
|
+
- `day/week/month` scans all sessions in the selected time range, so child sessions are included when they have activity in that range
|
|
334
|
+
- `day/week/month` does not do parent-tree rollup; child sessions are counted as independent sessions, not merged through `includeChildren`
|
|
335
|
+
- `since` and `last` are mutually exclusive
|
|
336
|
+
- `period=session` does not accept `since` or `last`
|
|
337
|
+
- `quota_show(enabled=true|false)` can explicitly force a state instead of toggling
|
|
338
|
+
- Historical reports support both absolute `since` and relative `last`
|
|
339
|
+
- `since` accepts `YYYY-MM` or `YYYY-MM-DD`
|
|
340
|
+
- `last` accepts a positive integer and is relative to the current period: `day=7`, `week=8`, `month=6`
|
|
341
|
+
- Empty `period=day|week|month` means the current natural day/week/month
|
|
342
|
+
|
|
343
|
+
Example command aliases:
|
|
344
|
+
|
|
345
|
+
For direct in-chat history output, define command aliases that call `quota_summary`.
|
|
346
|
+
The old TUI history popup path was removed; history now goes through the tool report directly.
|
|
347
|
+
These aliases are still OpenCode command templates, so they expand into prompt text before the model/tool chain runs. For the cleanest direct output path, prefer the standalone CLI.
|
|
348
|
+
|
|
349
|
+
Examples:
|
|
350
|
+
|
|
351
|
+
- `quota_summary(period=day)` -> today
|
|
352
|
+
- `quota_summary(period=week)` -> this week
|
|
353
|
+
- `quota_summary(period=month)` -> this month
|
|
354
|
+
- `quota_summary(period=day,last=7)` -> last 7 days
|
|
355
|
+
- `quota_summary(period=week,last=8)` -> last 8 weeks
|
|
356
|
+
- `quota_summary(period=month,last=6)` -> last 6 months
|
|
357
|
+
- `quota_summary(period=month,since=2026-01)` -> since Jan 2026
|
|
358
|
+
|
|
359
|
+
```json
|
|
360
|
+
{
|
|
361
|
+
"command": {
|
|
362
|
+
"qday": {
|
|
363
|
+
"description": "Today / last N days / since date",
|
|
364
|
+
"template": "Run /qday for opencode-quota-sidebar. Call tool quota_summary exactly once and return its full report directly. If `$ARGUMENTS` is empty: period=day, toast=true. If `$ARGUMENTS` is a positive integer: period=day, last=<that integer>, toast=true. If `$ARGUMENTS` matches YYYY-MM-DD: period=day, since=<that date>, toast=true. Otherwise briefly explain: empty, positive integer, or YYYY-MM-DD."
|
|
365
|
+
},
|
|
366
|
+
"qweek": {
|
|
367
|
+
"description": "This week / last N weeks / since date",
|
|
368
|
+
"template": "Run /qweek for opencode-quota-sidebar. Call tool quota_summary exactly once and return its full report directly. If `$ARGUMENTS` is empty: period=week, toast=true. If `$ARGUMENTS` is a positive integer: period=week, last=<that integer>, toast=true. If `$ARGUMENTS` matches YYYY-MM-DD: period=week, since=<that date>, toast=true. Otherwise briefly explain: empty, positive integer, or YYYY-MM-DD."
|
|
369
|
+
},
|
|
370
|
+
"qmonth": {
|
|
371
|
+
"description": "This month / last N months / since month",
|
|
372
|
+
"template": "Run /qmonth for opencode-quota-sidebar. Call tool quota_summary exactly once and return its full report directly. If `$ARGUMENTS` is empty: period=month, toast=true. If `$ARGUMENTS` is a positive integer: period=month, last=<that integer>, toast=true. If `$ARGUMENTS` matches YYYY-MM: period=month, since=<that month>, toast=true. Otherwise briefly explain: empty, positive integer, or YYYY-MM."
|
|
373
|
+
},
|
|
374
|
+
"qtoggle": {
|
|
375
|
+
"description": "Toggle sidebar usage display on/off",
|
|
376
|
+
"template": "Call tool quota_show (no arguments, it toggles)."
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
## CLI
|
|
383
|
+
|
|
384
|
+
The package exposes a standalone CLI dashboard. After installing globally or making the `bin` available:
|
|
385
|
+
|
|
386
|
+
```bash
|
|
387
|
+
npm install -g @leo000001/opencode-quota-sidebar
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
If you prefer not to install globally, you can also run it with `npx @leo000001/opencode-quota-sidebar <args>`.
|
|
391
|
+
|
|
392
|
+
```bash
|
|
393
|
+
# Current period (single snapshot)
|
|
394
|
+
opencode-quota day # today
|
|
395
|
+
opencode-quota week # this week (Monday-based)
|
|
396
|
+
opencode-quota month # this month
|
|
397
|
+
|
|
398
|
+
# Multi-period history
|
|
399
|
+
opencode-quota day 7 # last 7 days
|
|
400
|
+
opencode-quota week 8 # last 8 weeks
|
|
401
|
+
opencode-quota month 6 # last 6 months
|
|
402
|
+
|
|
403
|
+
# Absolute start date
|
|
404
|
+
opencode-quota day --since 2026-04-01
|
|
405
|
+
opencode-quota week --since 2026-04-01
|
|
406
|
+
opencode-quota month --since 2026-01
|
|
407
|
+
|
|
408
|
+
# Also accepted as positional (equivalent to --since)
|
|
409
|
+
opencode-quota day 2026-04-01
|
|
410
|
+
opencode-quota month 2026-01
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
When called without `last` or `--since`, the CLI renders a single-period snapshot (`QUOTA + TOTALS + PROVIDERS`). When called with `last` or `--since`, it renders multi-period history with a larger multi-line `TREND` block.
|
|
414
|
+
|
|
415
|
+
### CLI semantics
|
|
416
|
+
|
|
417
|
+
- `day` = current natural day; `week` = current natural week (Monday-based); `month` = current natural month
|
|
418
|
+
- A positional integer maps to `last=<N>` (number of periods back from now)
|
|
419
|
+
- A positional date string maps to `--since` (`YYYY-MM-DD` for day/week, `YYYY-MM` for month)
|
|
420
|
+
- `--since` and `--last` are mutually exclusive
|
|
421
|
+
- `last` is limited to 90 for day, reasonable ranges for week/month
|
|
422
|
+
|
|
423
|
+
### Trend section
|
|
424
|
+
|
|
425
|
+
The `TREND` block appears only in multi-period mode. Each metric (`Requests`, `Tokens`, `Cache`, `Cost`) is rendered as a small multi-line bar chart:
|
|
426
|
+
|
|
427
|
+
- one summary line: the current value only
|
|
428
|
+
- one bar row per visible period (latest 8 periods max), ordered oldest-to-newest
|
|
429
|
+
- the current period is marked with `*`
|
|
430
|
+
|
|
431
|
+
Interpretation example:
|
|
432
|
+
|
|
433
|
+
```text
|
|
434
|
+
Requests 12.3k
|
|
435
|
+
04-08 | ███░░░░░░░░░░░░░░░ | 4.1k
|
|
436
|
+
04-09 | ██████░░░░░░░░░░░░ | 8.2k
|
|
437
|
+
04-10* | █████████████░░░░░ | 12.3k
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
This means the current bucket has `12.3k` requests, and the bar rows below show the relative size of each visible bucket from oldest to newest.
|
|
441
|
+
|
|
442
|
+
### Connection behavior
|
|
443
|
+
|
|
444
|
+
- The CLI talks to the local OpenCode API at `http://localhost:4096` by default
|
|
445
|
+
- Set `OPENCODE_BASE_URL` to override (e.g. `http://192.168.1.10:4096`)
|
|
446
|
+
- If no server is running and `OPENCODE_BASE_URL` is not set, the CLI attempts to start one:
|
|
447
|
+
- **Linux/macOS**: runs `opencode serve --hostname=127.0.0.1 --port=4096`
|
|
448
|
+
- **Windows**: tries `opencode.cmd`, then `opencode` via `shell: true`, then `bash -lc opencode`
|
|
449
|
+
- The auto-start waits up to 10 seconds for the server to print `opencode server listening on <url>`
|
|
450
|
+
- If auto-start fails, check that `opencode` is in your `PATH`
|
|
451
|
+
- On Windows, the `shell: true` path is usually the most reliable when `opencode.cmd` is not directly spawnable from Node
|
|
452
|
+
|
|
453
|
+
### Platform notes
|
|
454
|
+
|
|
455
|
+
- **Terminal encoding**: the dashboard uses Unicode box-drawing and block elements (`█░`). Requires a UTF-8 capable terminal. Windows users should use Windows Terminal, PowerShell 7+, or a terminal that supports UTF-8. Classic cmd.exe with legacy codepages (CP437/CP850) may render garbled characters.
|
|
456
|
+
- **Alignment**: weekly/monthly trend labels can still be truncated when the visible label is very long (for example long absolute week ranges). This is a known presentation tradeoff in the current terminal renderer.
|
|
457
|
+
- **Windows PATH**: the CLI tries multiple command forms to find `opencode`. If none work, ensure `opencode` or `opencode.cmd` is on your PATH, or start the server manually and set `OPENCODE_BASE_URL`.
|
|
458
|
+
- **Node.js**: requires `>=18`
|
|
459
|
+
|
|
460
|
+
### Environment variables
|
|
461
|
+
|
|
462
|
+
| Variable | Default | Purpose |
|
|
463
|
+
| ---------------------------- | ------------------------- | -------------------------------------------------------------------------------- |
|
|
464
|
+
| `OPENCODE_BASE_URL` | `http://localhost:4096` | OpenCode API endpoint; set this if the server is remote or on a non-default port |
|
|
465
|
+
| `OPENCODE_QUOTA_CONFIG_HOME` | `~/.config/opencode` | Global config directory override |
|
|
466
|
+
| `OPENCODE_QUOTA_DATA_HOME` | `~/.local/share/opencode` | Global data directory override |
|
|
467
|
+
|
|
468
|
+
## Development
|
|
469
|
+
|
|
470
|
+
```bash
|
|
471
|
+
npm install
|
|
472
|
+
npm run build
|
|
473
|
+
npm test
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
For local development, load:
|
|
477
|
+
|
|
478
|
+
- `file:///ABSOLUTE/PATH/opencode-quota-sidebar/dist/index.js` in `opencode.json`
|
|
479
|
+
- `file:///ABSOLUTE/PATH/opencode-quota-sidebar/dist/tui.tsx` in `tui.json`
|
|
480
|
+
|
|
481
|
+
On Windows, use forward slashes in `file:///` URLs.
|
|
482
|
+
|
|
483
|
+
## Compatibility And Caveats
|
|
484
|
+
|
|
485
|
+
- Node.js `>=18`
|
|
486
|
+
- OpenCode plugin SDK `@opencode-ai/plugin` / `@opencode-ai/sdk` `^1.3.5`
|
|
487
|
+
- For OpenCode `>=1.2.15`, TUI config belongs in `tui.json`
|
|
488
|
+
- The shared title is still one `session.title` value for all clients
|
|
489
|
+
- The plugin avoids ANSI styling in sidebar titles to keep resize behavior stable
|
|
490
|
+
- Some providers expose true quota windows, others only expose balance data
|
|
491
|
+
|
|
492
|
+
## Contributing
|
|
493
|
+
|
|
494
|
+
- Changelog: [CHANGELOG.md](./CHANGELOG.md)
|
|
495
|
+
- Adapter and architecture notes: [CONTRIBUTING.md](./CONTRIBUTING.md)
|
|
496
|
+
- Security policy: [SECURITY.md](./SECURITY.md)
|
|
497
|
+
|
|
498
|
+
## Documentation Navigation
|
|
499
|
+
|
|
500
|
+
- English README: [`README.md`](./README.md)
|
|
501
|
+
- Simplified Chinese README: [`README.zh-CN.md`](./README.zh-CN.md)
|
|
502
|
+
- Changelog: [`CHANGELOG.md`](./CHANGELOG.md)
|
|
503
|
+
- Contributing guide: [`CONTRIBUTING.md`](./CONTRIBUTING.md)
|
|
504
|
+
- Security policy: [`SECURITY.md`](./SECURITY.md)
|