@slkiser/opencode-quota 3.0.2 → 3.1.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.
Files changed (120) hide show
  1. package/README.md +206 -143
  2. package/dist/lib/anthropic.d.ts +4 -5
  3. package/dist/lib/anthropic.d.ts.map +1 -1
  4. package/dist/lib/anthropic.js +230 -18
  5. package/dist/lib/anthropic.js.map +1 -1
  6. package/dist/lib/api-key-resolver.d.ts +1 -1
  7. package/dist/lib/api-key-resolver.d.ts.map +1 -1
  8. package/dist/lib/api-key-resolver.js +11 -13
  9. package/dist/lib/api-key-resolver.js.map +1 -1
  10. package/dist/lib/config.d.ts.map +1 -1
  11. package/dist/lib/config.js +6 -0
  12. package/dist/lib/config.js.map +1 -1
  13. package/dist/lib/cursor-detection.d.ts.map +1 -1
  14. package/dist/lib/cursor-detection.js +14 -5
  15. package/dist/lib/cursor-detection.js.map +1 -1
  16. package/dist/lib/cursor-usage.d.ts.map +1 -1
  17. package/dist/lib/cursor-usage.js +18 -14
  18. package/dist/lib/cursor-usage.js.map +1 -1
  19. package/dist/lib/entries.d.ts +1 -1
  20. package/dist/lib/entries.d.ts.map +1 -1
  21. package/dist/lib/entries.js.map +1 -1
  22. package/dist/lib/format-utils.d.ts +8 -0
  23. package/dist/lib/format-utils.d.ts.map +1 -1
  24. package/dist/lib/format-utils.js +13 -0
  25. package/dist/lib/format-utils.js.map +1 -1
  26. package/dist/lib/format.d.ts +2 -0
  27. package/dist/lib/format.d.ts.map +1 -1
  28. package/dist/lib/format.js +14 -9
  29. package/dist/lib/format.js.map +1 -1
  30. package/dist/lib/init-installer.d.ts +1 -0
  31. package/dist/lib/init-installer.d.ts.map +1 -1
  32. package/dist/lib/init-installer.js +15 -0
  33. package/dist/lib/init-installer.js.map +1 -1
  34. package/dist/lib/kimi-auth.d.ts +38 -0
  35. package/dist/lib/kimi-auth.d.ts.map +1 -0
  36. package/dist/lib/kimi-auth.js +104 -0
  37. package/dist/lib/kimi-auth.js.map +1 -0
  38. package/dist/lib/kimi.d.ts +3 -0
  39. package/dist/lib/kimi.d.ts.map +1 -0
  40. package/dist/lib/kimi.js +206 -0
  41. package/dist/lib/kimi.js.map +1 -0
  42. package/dist/lib/opencode-sqlite.d.ts.map +1 -1
  43. package/dist/lib/opencode-sqlite.js +9 -12
  44. package/dist/lib/opencode-sqlite.js.map +1 -1
  45. package/dist/lib/opencode-storage.d.ts.map +1 -1
  46. package/dist/lib/opencode-storage.js +9 -5
  47. package/dist/lib/opencode-storage.js.map +1 -1
  48. package/dist/lib/provider-metadata.d.ts +1 -1
  49. package/dist/lib/provider-metadata.d.ts.map +1 -1
  50. package/dist/lib/provider-metadata.js +17 -4
  51. package/dist/lib/provider-metadata.js.map +1 -1
  52. package/dist/lib/quota-render-data.d.ts.map +1 -1
  53. package/dist/lib/quota-render-data.js +1 -4
  54. package/dist/lib/quota-render-data.js.map +1 -1
  55. package/dist/lib/quota-status.d.ts.map +1 -1
  56. package/dist/lib/quota-status.js +46 -7
  57. package/dist/lib/quota-status.js.map +1 -1
  58. package/dist/lib/synthetic-config.d.ts +41 -0
  59. package/dist/lib/synthetic-config.d.ts.map +1 -0
  60. package/dist/lib/synthetic-config.js +57 -0
  61. package/dist/lib/synthetic-config.js.map +1 -0
  62. package/dist/lib/synthetic.d.ts +17 -0
  63. package/dist/lib/synthetic.d.ts.map +1 -0
  64. package/dist/lib/synthetic.js +85 -0
  65. package/dist/lib/synthetic.js.map +1 -0
  66. package/dist/lib/toast-format-grouped.d.ts +2 -0
  67. package/dist/lib/toast-format-grouped.d.ts.map +1 -1
  68. package/dist/lib/toast-format-grouped.js +9 -6
  69. package/dist/lib/toast-format-grouped.js.map +1 -1
  70. package/dist/lib/tui-config-diagnostics.d.ts.map +1 -1
  71. package/dist/lib/tui-config-diagnostics.js +13 -9
  72. package/dist/lib/tui-config-diagnostics.js.map +1 -1
  73. package/dist/lib/tui-panel-state.d.ts.map +1 -1
  74. package/dist/lib/tui-panel-state.js +10 -5
  75. package/dist/lib/tui-panel-state.js.map +1 -1
  76. package/dist/lib/tui-sidebar-format.d.ts +1 -1
  77. package/dist/lib/tui-sidebar-format.d.ts.map +1 -1
  78. package/dist/lib/tui-sidebar-format.js +1 -0
  79. package/dist/lib/tui-sidebar-format.js.map +1 -1
  80. package/dist/lib/types.d.ts +37 -4
  81. package/dist/lib/types.d.ts.map +1 -1
  82. package/dist/lib/types.js +1 -0
  83. package/dist/lib/types.js.map +1 -1
  84. package/dist/plugin.d.ts.map +1 -1
  85. package/dist/plugin.js +1 -0
  86. package/dist/plugin.js.map +1 -1
  87. package/dist/providers/anthropic.js +1 -1
  88. package/dist/providers/anthropic.js.map +1 -1
  89. package/dist/providers/copilot.d.ts.map +1 -1
  90. package/dist/providers/copilot.js +2 -1
  91. package/dist/providers/copilot.js.map +1 -1
  92. package/dist/providers/cursor.d.ts.map +1 -1
  93. package/dist/providers/cursor.js +2 -1
  94. package/dist/providers/cursor.js.map +1 -1
  95. package/dist/providers/google-antigravity.d.ts.map +1 -1
  96. package/dist/providers/google-antigravity.js +2 -1
  97. package/dist/providers/google-antigravity.js.map +1 -1
  98. package/dist/providers/kimi-code.d.ts +3 -0
  99. package/dist/providers/kimi-code.d.ts.map +1 -0
  100. package/dist/providers/kimi-code.js +71 -0
  101. package/dist/providers/kimi-code.js.map +1 -0
  102. package/dist/providers/registry.d.ts.map +1 -1
  103. package/dist/providers/registry.js +4 -2
  104. package/dist/providers/registry.js.map +1 -1
  105. package/dist/providers/synthetic.d.ts +6 -0
  106. package/dist/providers/synthetic.d.ts.map +1 -0
  107. package/dist/providers/{firmware.js → synthetic.js} +13 -15
  108. package/dist/providers/synthetic.js.map +1 -0
  109. package/package.json +2 -2
  110. package/dist/lib/firmware-config.d.ts +0 -41
  111. package/dist/lib/firmware-config.d.ts.map +0 -1
  112. package/dist/lib/firmware-config.js +0 -60
  113. package/dist/lib/firmware-config.js.map +0 -1
  114. package/dist/lib/firmware.d.ts +0 -22
  115. package/dist/lib/firmware.d.ts.map +0 -1
  116. package/dist/lib/firmware.js +0 -62
  117. package/dist/lib/firmware.js.map +0 -1
  118. package/dist/providers/firmware.d.ts +0 -6
  119. package/dist/providers/firmware.d.ts.map +0 -1
  120. package/dist/providers/firmware.js.map +0 -1
package/README.md CHANGED
@@ -1,20 +1,20 @@
1
1
  # OpenCode Quota
2
+
2
3
  [![npm version](https://img.shields.io/npm/v/%40slkiser%2Fopencode-quota)](https://www.npmjs.com/package/@slkiser/opencode-quota)
3
4
  [![npm downloads](https://img.shields.io/npm/dm/%40slkiser%2Fopencode-quota)](https://www.npmjs.com/package/@slkiser/opencode-quota)
4
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)
5
6
  [![CI](https://img.shields.io/github/actions/workflow/status/slkiser/opencode-quota/ci.yml?branch=main&label=CI)](https://github.com/slkiser/opencode-quota/actions/workflows/ci.yml)
6
7
  [![Node >=18](https://img.shields.io/badge/node-%3E%3D18-339933)](./package.json)
7
8
 
8
-
9
9
  `opencode-quota` adds usage quota and token visibility to OpenCode with zero context-window pollution.
10
10
 
11
11
  What you get:
12
12
 
13
- - TUI sidebar panel with quota
13
+ - TUI sidebar panel with quota
14
14
  - popup quota toasts after assistant responses
15
15
  - manual `/quota`, `/quota_status`, and `/tokens_*` commands
16
16
 
17
- **Quota providers**: Anthropic (Claude), GitHub Copilot, OpenAI (Plus/Pro), Cursor, Qwen Code, Alibaba Coding Plan, MiniMax Coding Plan, Chutes AI, Firmware AI, Google Antigravity, Z.ai Coding Plan, NanoGPT, and OpenCode Go.
17
+ **Quota providers**: Anthropic (Claude), GitHub Copilot, OpenAI (Plus/Pro), Cursor, Qwen Code, Alibaba Coding Plan, MiniMax Coding Plan, Kimi Code, Chutes AI, Synthetic, Google Antigravity, Z.ai Coding Plan, NanoGPT, and OpenCode Go.
18
18
 
19
19
  **Token reports**: All models and providers in [models.dev](https://models.dev), plus deterministic local pricing for Cursor Auto/Composer and Cursor model aliases that are not on models.dev.
20
20
 
@@ -45,15 +45,17 @@ What you get:
45
45
  </tr>
46
46
  </table>
47
47
 
48
- OpenCode `>= 1.4.3` is required.
48
+ OpenCode `>= 1.4.3` is required.
49
49
 
50
50
  If you are coming back later:
51
+
51
52
  - see [Provider Setup At A Glance](#provider-setup-at-a-glance) for provider-specific setup needs
52
53
  - see [Commands](#commands) for the slash commands
53
54
  - see [Configuration Reference](#configuration-reference) when you want to customize behavior
54
55
  - see [Troubleshooting](#troubleshooting) if something does not appear or auto-detect correctly
55
56
 
56
57
  ## Installation
58
+
57
59
  ### Automatic setup (recommended)
58
60
 
59
61
  ```sh
@@ -62,23 +64,23 @@ npx @slkiser/opencode-quota init
62
64
 
63
65
  The installer (append-only, preserves existing values) asks for:
64
66
 
65
- - **Scope**: `Project` or `Global`
67
+ - **Scope**: `Project` or `Global`
66
68
  - **Quota UI**: `Toast`, `Sidebar`, `Toast + Sidebar`, or `None (manual /quota and /tokens_* only)`
67
- - **Provider mode**: `Auto-detect` or `Manual select`
68
- - **Layout style**: `classic` or `grouped`
69
- - **Show session input/output tokens**: `Yes` or `No`
69
+ - **Provider mode**: `Auto-detect` or `Manual select`
70
+ - **Layout style**: `classic` or `grouped`
71
+ - **Percent display (toast/sidebar only)**: `remaining` or `used`
72
+ - **Show session input/output tokens**: `Yes` or `No`
70
73
 
71
74
  All quota settings live in `opencode.json` or `opencode.jsonc`. `tui.json` or `tui.jsonc` is only for loading the sidebar plugin.
72
75
 
73
-
74
- ### After install
76
+ ### After install
75
77
 
76
78
  1. Restart OpenCode.
77
79
  2. Run `/quota_status`.
78
80
  3. Run `/quota`.
79
81
  4. If you chose `Sidebar` or `Toast + Sidebar`, open the session sidebar and confirm the `Quota` panel appears.
80
82
 
81
- ### Manual setup
83
+ ### Manual setup
82
84
 
83
85
  You can install manually, but the installer is easier and safer.
84
86
 
@@ -87,7 +89,7 @@ You can install manually, but the installer is easier and safer.
87
89
  ```jsonc
88
90
  {
89
91
  "$schema": "https://opencode.ai/config.json",
90
- "plugin": ["@slkiser/opencode-quota"]
92
+ "plugin": ["@slkiser/opencode-quota"],
91
93
  }
92
94
  ```
93
95
 
@@ -96,7 +98,7 @@ You can install manually, but the installer is easier and safer.
96
98
  ```jsonc
97
99
  {
98
100
  "$schema": "https://opencode.ai/tui.json",
99
- "plugin": ["@slkiser/opencode-quota"]
101
+ "plugin": ["@slkiser/opencode-quota"],
100
102
  }
101
103
  ```
102
104
 
@@ -115,9 +117,9 @@ Keep the `tui.json` or `tui.jsonc` entry above and disable toasts in `opencode.j
115
117
  "plugin": ["@slkiser/opencode-quota"],
116
118
  "experimental": {
117
119
  "quotaToast": {
118
- "enableToast": false
119
- }
120
- }
120
+ "enableToast": false,
121
+ },
122
+ },
121
123
  }
122
124
  ```
123
125
 
@@ -130,9 +132,9 @@ Keep the `tui.json` or `tui.jsonc` entry above and disable toasts in `opencode.j
130
132
  {
131
133
  "experimental": {
132
134
  "quotaToast": {
133
- "enabledProviders": ["copilot", "openai", "google-antigravity"]
134
- }
135
- }
135
+ "enabledProviders": ["copilot", "openai", "google-antigravity"],
136
+ },
137
+ },
136
138
  }
137
139
  ```
138
140
 
@@ -145,55 +147,74 @@ Keep the `tui.json` or `tui.jsonc` entry above and disable toasts in `opencode.j
145
147
  {
146
148
  "experimental": {
147
149
  "quotaToast": {
148
- "formatStyle": "grouped"
149
- }
150
- }
150
+ "formatStyle": "grouped",
151
+ },
152
+ },
151
153
  }
152
154
  ```
153
155
 
154
156
  </details>
155
157
 
156
- ## Provider Setup At A Glance
158
+ <details>
159
+ <summary><strong>Example: Show percent used instead of percent remaining in toasts and the sidebar</strong></summary>
157
160
 
158
- | Provider | Auto setup | Authentication | Quota |
159
- | --- | --- | --- | --- |
160
- | **Anthropic (Claude)** | Needs [quick setup](#anthropic-quick-setup) | Local CLI auth | Local CLI report |
161
- | **GitHub Copilot** | Usually | OpenCode auth or PAT | Remote API |
162
- | **OpenAI** | Yes | OpenCode auth | Remote API |
163
- | **Cursor** | Needs [quick setup](#cursor-quick-setup) | Companion auth | Local runtime accounting |
164
- | **Qwen Code** | Needs [quick setup](#qwen-code-quick-setup) | Companion auth | Local estimation |
165
- | **Alibaba Coding Plan** | Yes | OpenCode auth/global config/env | Local estimation |
166
- | **Firmware AI** | Usually | OpenCode auth/global config/env | Remote API |
167
- | **Chutes AI** | Usually | OpenCode auth/global config/env | Remote API |
168
- | **Google Antigravity** | Needs [quick setup](#google-antigravity-quick-setup) | Companion auth | Remote API |
169
- | **Z.ai** | Yes | OpenCode auth/global config/env | Remote API |
170
- | **NanoGPT** | Usually | OpenCode auth/global config/env | Remote API |
171
- | **MiniMax Coding Plan** | Yes | OpenCode auth/global config/env | Remote API |
172
- | **OpenCode Go** | Needs [quick setup](#opencode-go-quick-setup) | Env/config auth | Dashboard scraping |
161
+ ```jsonc
162
+ {
163
+ "experimental": {
164
+ "quotaToast": {
165
+ "percentDisplayMode": "used",
166
+ },
167
+ },
168
+ }
169
+ ```
170
+
171
+ </details>
172
+
173
+ ## Provider Setup At A Glance
173
174
 
175
+ | Provider | Auto setup | Authentication | Quota |
176
+ | ----------------------- | ---------------------------------------------------- | ------------------------------- | ------------------------ |
177
+ | **Anthropic (Claude)** | Needs [quick setup](#anthropic-quick-setup) | Local CLI auth | Local CLI report, OAuth fallback |
178
+ | **GitHub Copilot** | Usually | OpenCode auth or PAT | Remote API |
179
+ | **OpenAI** | Yes | OpenCode auth | Remote API |
180
+ | **Cursor** | Needs [quick setup](#cursor-quick-setup) | Companion auth | Local runtime accounting |
181
+ | **Qwen Code** | Needs [quick setup](#qwen-code-quick-setup) | Companion auth | Local estimation |
182
+ | **Alibaba Coding Plan** | Yes | OpenCode auth/global config/env | Local estimation |
183
+ | **Synthetic** | Yes | OpenCode auth/global config/env | Remote API |
184
+ | **Chutes AI** | Usually | OpenCode auth/global config/env | Remote API |
185
+ | **Google Antigravity** | Needs [quick setup](#google-antigravity-quick-setup) | Companion auth | Remote API |
186
+ | **Z.ai** | Yes | OpenCode auth/global config/env | Remote API |
187
+ | **NanoGPT** | Usually | OpenCode auth/global config/env | Remote API |
188
+ | **MiniMax Coding Plan** | Yes | OpenCode auth/global config/env | Remote API |
189
+ | **Kimi Code** | Yes | OpenCode auth/global config/env | Remote API |
190
+ | **OpenCode Go** | Needs [quick setup](#opencode-go-quick-setup) | Env/config auth | Dashboard scraping |
174
191
 
175
192
  <a id="anthropic-quick-setup"></a>
193
+
176
194
  <details>
177
195
  <summary><strong>Quick setup: Anthropic (Claude)</strong></summary>
178
196
 
179
- Anthropic quota support now checks the local Claude CLI instead of passing Claude consumer OAuth tokens directly to Anthropic APIs.
197
+ Anthropic quota support is local-first: it checks the local Claude CLI first, and if Claude auth is confirmed but local quota windows are missing, it falls back to Claude's local credentials file plus the Anthropic OAuth usage API.
180
198
 
181
199
  If Claude Code is already installed and authenticated, this usually works automatically. Otherwise:
182
200
 
183
201
  1. Install Claude Code so `claude` is available on your `PATH`.
184
202
  2. Run `claude auth login`.
185
- 3. Confirm `claude auth status` succeeds locally.
203
+ 3. Confirm `claude auth status --json` or `claude auth status` succeeds locally.
186
204
  4. Confirm OpenCode is configured with the `anthropic` provider.
187
205
 
188
206
  If Claude lives at a custom path, set `experimental.quotaToast.anthropicBinaryPath`. The default is `claude`.
189
207
 
190
- If you use Anthropic via API key in OpenCode, model usage still works normally. This plugin only shows Anthropic quota rows when the local Claude CLI exposes quota windows.
208
+ When local CLI auth is present but local windows are missing, the plugin reads `~/.claude/.credentials.json`, extracts `claudeAiOauth.accessToken`, and queries Anthropic's OAuth usage endpoint. No manual Claude consumer token config is required.
209
+
210
+ If you use Anthropic via API key in OpenCode, model usage still works normally. This plugin only shows Anthropic quota rows when local Claude auth is present and either the CLI or the Claude OAuth fallback can provide quota windows. If Claude auth is present but both quota probes fail, `/quota`, toasts, and the sidebar surface a sanitized Anthropic error instead of silently skipping the provider.
191
211
 
192
212
  For behavior details and troubleshooting, see [Anthropic notes](#anthropic-notes).
193
213
 
194
214
  </details>
195
215
 
196
216
  <a id="cursor-quick-setup"></a>
217
+
197
218
  <details>
198
219
  <summary><strong>Quick setup: Cursor</strong></summary>
199
220
 
@@ -205,15 +226,15 @@ Cursor quota support requires the `@playwo/opencode-cursor-oauth` [plugin](https
205
226
  "plugin": ["@playwo/opencode-cursor-oauth", "@slkiser/opencode-quota"],
206
227
  "provider": {
207
228
  "cursor": {
208
- "name": "Cursor"
209
- }
229
+ "name": "Cursor",
230
+ },
210
231
  },
211
232
  "experimental": {
212
233
  "quotaToast": {
213
234
  "cursorPlan": "pro",
214
- "cursorBillingCycleStartDay": 7
215
- }
216
- }
235
+ "cursorBillingCycleStartDay": 7,
236
+ },
237
+ },
217
238
  }
218
239
  ```
219
240
 
@@ -228,6 +249,7 @@ For behavior details and troubleshooting, see [Cursor notes](#cursor-notes).
228
249
  </details>
229
250
 
230
251
  <a id="google-antigravity-quick-setup"></a>
252
+
231
253
  <details>
232
254
  <summary><strong>Quick setup: Google Antigravity</strong></summary>
233
255
 
@@ -235,7 +257,7 @@ Google quota support requires the `opencode-antigravity-auth` [plugin](https://g
235
257
 
236
258
  ```jsonc
237
259
  {
238
- "plugin": ["opencode-antigravity-auth", "@slkiser/opencode-quota"]
260
+ "plugin": ["opencode-antigravity-auth", "@slkiser/opencode-quota"],
239
261
  }
240
262
  ```
241
263
 
@@ -244,6 +266,7 @@ For behavior details and troubleshooting, see [Google Antigravity notes](#google
244
266
  </details>
245
267
 
246
268
  <a id="qwen-code-quick-setup"></a>
269
+
247
270
  <details>
248
271
  <summary><strong>Quick setup: Qwen Code</strong></summary>
249
272
 
@@ -251,7 +274,7 @@ Qwen quota support requires the `opencode-qwencode-auth` [plugin](https://github
251
274
 
252
275
  ```jsonc
253
276
  {
254
- "plugin": ["opencode-qwencode-auth", "@slkiser/opencode-quota"]
277
+ "plugin": ["opencode-qwencode-auth", "@slkiser/opencode-quota"],
255
278
  }
256
279
  ```
257
280
 
@@ -260,6 +283,7 @@ For behavior details and troubleshooting, see [Qwen Code notes](#qwen-code-notes
260
283
  </details>
261
284
 
262
285
  <a id="opencode-go-quick-setup"></a>
286
+
263
287
  <details>
264
288
  <summary><strong>Quick setup: OpenCode Go</strong></summary>
265
289
 
@@ -292,44 +316,51 @@ Environment variables take precedence over the config file. Run `/quota_status`
292
316
 
293
317
  ## Commands
294
318
 
295
- | Command | What it shows |
296
- | --- | --- |
297
- | `/quota` | Manual grouped quota report with a local call timestamp |
298
- | `/quota_status` | Concise diagnostics for config, TUI setup, provider availability, account detection, and pricing snapshot health |
299
- | `/pricing_refresh` | Pull the local runtime pricing snapshot from `models.dev` on demand |
300
- | `/tokens_today` | Tokens used today (calendar day) |
301
- | `/tokens_daily` | Tokens used in the last 24 hours |
302
- | `/tokens_weekly` | Tokens used in the last 7 days |
303
- | `/tokens_monthly` | Tokens used in the last 30 days, including pricing sections |
304
- | `/tokens_all` | Tokens used across all local history |
305
- | `/tokens_session` | Tokens used in the current session only |
306
- | `/tokens_session_all` | Tokens used in the current session plus all descendant child/subagent sessions |
307
- | `/tokens_between` | Tokens used between two dates: `YYYY-MM-DD YYYY-MM-DD` |
308
-
319
+ | Command | What it shows |
320
+ | --------------------- | ---------------------------------------------------------------------------------------------------------------- |
321
+ | `/quota` | Manual grouped quota report with a local call timestamp |
322
+ | `/quota_status` | Concise diagnostics for config, TUI setup, provider availability, account detection, and pricing snapshot health |
323
+ | `/pricing_refresh` | Pull the local runtime pricing snapshot from `models.dev` on demand |
324
+ | `/tokens_today` | Tokens used today (calendar day) |
325
+ | `/tokens_daily` | Tokens used in the last 24 hours |
326
+ | `/tokens_weekly` | Tokens used in the last 7 days |
327
+ | `/tokens_monthly` | Tokens used in the last 30 days, including pricing sections |
328
+ | `/tokens_all` | Tokens used across all local history |
329
+ | `/tokens_session` | Tokens used in the current session only |
330
+ | `/tokens_session_all` | Tokens used in the current session plus all descendant child/subagent sessions |
331
+ | `/tokens_between` | Tokens used between two dates: `YYYY-MM-DD YYYY-MM-DD` |
309
332
 
310
333
  ## Provider-Specific Notes
311
334
 
312
335
  <a id="anthropic-notes"></a>
336
+
313
337
  <details>
314
338
  <summary><strong>Anthropic (Claude)</strong></summary>
315
339
 
316
- The plugin probes the local Claude CLI with `anthropicBinaryPath --version` and `anthropicBinaryPath auth status`. By default `anthropicBinaryPath` is `claude`, so standard installs work without extra config. It does not pass Claude Free/Pro/Max OAuth tokens directly to Anthropic endpoints.
340
+ The plugin probes the local Claude CLI with `anthropicBinaryPath --version` and `anthropicBinaryPath auth status --json` first. By default `anthropicBinaryPath` is `claude`, so standard installs work without extra config.
341
+
342
+ If the Claude CLI exposes 5-hour and 7-day quota windows in local structured output, the plugin shows them directly. If the CLI only exposes auth state, the plugin falls back to `~/.claude/.credentials.json` and Anthropic's OAuth usage endpoint. When Claude is authenticated but both quota probes fail, `/quota`, toasts, and the sidebar surface a sanitized Anthropic error instead of silently skipping the provider.
317
343
 
318
- If the Claude CLI exposes 5-hour and 7-day quota windows in local structured output, the plugin shows them. If the CLI only exposes auth state, Anthropic quota rows are skipped and `/quota_status` explains why.
344
+ - Provider availability remains local-only: Anthropic is considered available when the local Claude CLI is installed and authenticated.
345
+ - `experimental.quotaToast.anthropicBinaryPath` only changes CLI probing. It does not change the fallback credentials-file location.
346
+ - `/quota_status` shows `quota_source` as either `claude-auth-status-json`, `claude-credentials-oauth-api`, or `(none)`.
319
347
 
320
348
  **Troubleshooting:**
321
349
 
322
- | Problem | Solution |
323
- | --- | --- |
324
- | `claude` not found | Install Claude Code and make sure `claude` is on your `PATH` |
325
- | Claude installed at a custom path | Set `experimental.quotaToast.anthropicBinaryPath` to the Claude executable path |
326
- | Not authenticated | Run `claude auth login`, then confirm `claude auth status` works |
327
- | Authenticated but no quota rows | Your local Claude CLI version did not expose quota windows; run `/quota_status` for the exact probe result |
328
- | Plugin not detected | Confirm OpenCode is configured with the `anthropic` provider |
350
+ | Problem | Solution |
351
+ | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
352
+ | `claude` not found | Install Claude Code and make sure `claude` is on your `PATH` |
353
+ | Claude installed at a custom path | Set `experimental.quotaToast.anthropicBinaryPath` to the Claude executable path |
354
+ | Not authenticated | Run `claude auth login`, then confirm `claude auth status --json` or `claude auth status` works |
355
+ | Authenticated but no quota rows | Run `/quota_status` and check `quota_source` plus `message` to see whether the local CLI, the fallback credentials file, or the fallback API failed |
356
+ | Missing or invalid `~/.claude/.credentials.json` | Re-authenticate Claude Code so it rewrites the local credentials file, then rerun `/quota_status` |
357
+ | Fallback API error or no quota response | Check `/quota_status` for the sanitized fallback error detail and retry after Claude Code refreshes local auth |
358
+ | Plugin not detected | Confirm OpenCode is configured with the `anthropic` provider |
329
359
 
330
360
  </details>
331
361
 
332
362
  <a id="github-copilot-notes"></a>
363
+
333
364
  <details>
334
365
  <summary><strong>GitHub Copilot</strong></summary>
335
366
 
@@ -364,6 +395,7 @@ Example `copilot-quota-token.json`:
364
395
  </details>
365
396
 
366
397
  <a id="cursor-notes"></a>
398
+
367
399
  <details>
368
400
  <summary><strong>Cursor</strong></summary>
369
401
 
@@ -382,15 +414,16 @@ Example override:
382
414
  "experimental": {
383
415
  "quotaToast": {
384
416
  "cursorPlan": "none",
385
- "cursorIncludedApiUsd": 120
386
- }
387
- }
417
+ "cursorIncludedApiUsd": 120,
418
+ },
419
+ },
388
420
  }
389
421
  ```
390
422
 
391
423
  </details>
392
424
 
393
425
  <a id="openai-notes"></a>
426
+
394
427
  <details>
395
428
  <summary><strong>OpenAI</strong></summary>
396
429
 
@@ -403,6 +436,7 @@ OpenAI uses native OpenCode OAuth from `auth.json`. The canonical auth family is
403
436
  </details>
404
437
 
405
438
  <a id="qwen-code-notes"></a>
439
+
406
440
  <details>
407
441
  <summary><strong>Qwen Code</strong></summary>
408
442
 
@@ -417,6 +451,7 @@ See [Qwen Code quick setup](#qwen-code-quick-setup) for auth. Usage is local-onl
417
451
  </details>
418
452
 
419
453
  <a id="alibaba-coding-plan-notes"></a>
454
+
420
455
  <details>
421
456
  <summary><strong>Alibaba Coding Plan</strong></summary>
422
457
 
@@ -438,16 +473,16 @@ Example fallback tier:
438
473
  {
439
474
  "experimental": {
440
475
  "quotaToast": {
441
- "alibabaCodingPlanTier": "lite"
442
- }
443
- }
476
+ "alibabaCodingPlanTier": "lite",
477
+ },
478
+ },
444
479
  }
445
480
  ```
446
481
 
447
482
  </details>
448
483
 
449
-
450
484
  <a id="minimax-coding-plan-notes"></a>
485
+
451
486
  <details>
452
487
  <summary><strong>MiniMax Coding Plan</strong></summary>
453
488
 
@@ -462,7 +497,23 @@ MiniMax Coding Plan uses trusted env vars or trusted user/global OpenCode config
462
497
 
463
498
  </details>
464
499
 
500
+ <a id="kimi-code-notes"></a>
501
+
502
+ <details>
503
+ <summary><strong>Kimi Code</strong></summary>
504
+
505
+ Kimi Code uses trusted env vars or trusted user/global OpenCode config first, then native OpenCode auth from `auth.json["kimi-for-coding"]` or `auth.json["kimi-code"]`. No additional plugin is required.
506
+
507
+ - API key sources are `KIMI_API_KEY`, `KIMI_CODE_API_KEY`, trusted user/global `provider["kimi-for-coding"].options.apiKey` or `provider["kimi-code"].options.apiKey`, then `auth.json`.
508
+ - Repo-local `opencode.json` / `opencode.jsonc` is ignored for Kimi secrets.
509
+ - Allowed env templates are limited to `{env:KIMI_API_KEY}` and `{env:KIMI_CODE_API_KEY}`.
510
+ - The plugin calls `https://api.kimi.com/coding/v1/usages`.
511
+ - `/quota_status` shows auth detection, API-key diagnostics, live quota state, and endpoint errors.
512
+
513
+ </details>
514
+
465
515
  <a id="zai-notes"></a>
516
+
466
517
  <details>
467
518
  <summary><strong>Z.ai</strong></summary>
468
519
 
@@ -476,33 +527,40 @@ Z.ai uses trusted env vars or trusted user/global OpenCode config first, then na
476
527
 
477
528
  </details>
478
529
 
479
- <a id="firmware-ai-notes"></a>
530
+ <a id="synthetic-notes"></a>
531
+
480
532
  <details>
481
- <summary><strong>Firmware AI</strong></summary>
533
+ <summary><strong>Synthetic</strong></summary>
482
534
 
483
- If OpenCode already has Firmware configured, it usually works automatically. Optional API key: `provider.firmware.options.apiKey`.
535
+ If OpenCode already has Synthetic configured, it should work automatically. Optional API key: `provider.synthetic.options.apiKey`.
484
536
 
485
- For security, provider secrets are read from environment variables or your user/global OpenCode config only. Repo-local `opencode.json` / `opencode.jsonc` is ignored for `provider.firmware.options.apiKey`.
537
+ For security, provider secrets are read from `SYNTHETIC_API_KEY`, your user/global OpenCode config, or `auth.json.synthetic` only. Repo-local `opencode.json` / `opencode.jsonc` is ignored for `provider.synthetic.options.apiKey`.
486
538
 
487
- Allowed env templates are limited to `{env:FIRMWARE_AI_API_KEY}` and `{env:FIRMWARE_API_KEY}`.
539
+ - The plugin calls `GET https://api.synthetic.new/v2/quotas`.
540
+ - It reads `subscription.limit`, `subscription.requests`, and `subscription.renewsAt`.
541
+ - Synthetic currently expects numeric JSON values for `subscription.limit` and `subscription.requests`; malformed or stringified values are treated as API-shape errors. Invalid `subscription.renewsAt` values are ignored.
542
+ - `/quota`, toasts, and the sidebar show one Synthetic row with remaining percent plus the same compact `used/limit` summary used by other percent-based providers when that row data is available.
543
+ - `/quota_status` shows a `synthetic` section with API-key diagnostics only; it does not do a live Synthetic fetch there.
544
+ - Allowed env templates are limited to `{env:SYNTHETIC_API_KEY}`.
488
545
 
489
546
  Example user/global config (`~/.config/opencode/opencode.jsonc` on Linux/macOS):
490
547
 
491
548
  ```jsonc
492
549
  {
493
550
  "provider": {
494
- "firmware": {
551
+ "synthetic": {
495
552
  "options": {
496
- "apiKey": "{env:FIRMWARE_API_KEY}"
497
- }
498
- }
499
- }
553
+ "apiKey": "{env:SYNTHETIC_API_KEY}",
554
+ },
555
+ },
556
+ },
500
557
  }
501
558
  ```
502
559
 
503
560
  </details>
504
561
 
505
562
  <a id="chutes-ai-notes"></a>
563
+
506
564
  <details>
507
565
  <summary><strong>Chutes AI</strong></summary>
508
566
 
@@ -519,16 +577,17 @@ Example user/global config (`~/.config/opencode/opencode.jsonc` on Linux/macOS):
519
577
  "provider": {
520
578
  "chutes": {
521
579
  "options": {
522
- "apiKey": "{env:CHUTES_API_KEY}"
523
- }
524
- }
525
- }
580
+ "apiKey": "{env:CHUTES_API_KEY}",
581
+ },
582
+ },
583
+ },
526
584
  }
527
585
  ```
528
586
 
529
587
  </details>
530
588
 
531
589
  <a id="google-antigravity-notes"></a>
590
+
532
591
  <details>
533
592
  <summary><strong>Google Antigravity</strong></summary>
534
593
 
@@ -541,6 +600,7 @@ See [Google Antigravity quick setup](#google-antigravity-quick-setup). This comp
541
600
  </details>
542
601
 
543
602
  <a id="nanogpt-notes"></a>
603
+
544
604
  <details>
545
605
  <summary><strong>NanoGPT</strong></summary>
546
606
 
@@ -560,16 +620,17 @@ Example user/global config (`~/.config/opencode/opencode.jsonc` on Linux/macOS):
560
620
  "provider": {
561
621
  "nanogpt": {
562
622
  "options": {
563
- "apiKey": "{env:NANOGPT_API_KEY}"
564
- }
565
- }
566
- }
623
+ "apiKey": "{env:NANOGPT_API_KEY}",
624
+ },
625
+ },
626
+ },
567
627
  }
568
628
  ```
569
629
 
570
630
  </details>
571
631
 
572
632
  <a id="opencode-go-notes"></a>
633
+
573
634
  <details>
574
635
  <summary><strong>OpenCode Go</strong></summary>
575
636
 
@@ -585,49 +646,51 @@ OpenCode Go quota scrapes the OpenCode Go dashboard at `https://opencode.ai/work
585
646
 
586
647
  **Troubleshooting:**
587
648
 
588
- | Problem | Solution |
589
- | --- | --- |
590
- | Config not detected | Confirm `OPENCODE_GO_WORKSPACE_ID` and `OPENCODE_GO_AUTH_COOKIE` are set, then use `/quota_status` to inspect the exact config paths checked on your machine |
591
- | Incomplete config | Both `workspaceId` and `authCookie` are required; check `/quota_status` for which field is missing |
592
- | Scrape returns no data | The auth cookie may have expired; get a fresh one from your browser |
593
- | Dashboard format changed | The SolidJS SSR pattern may have changed; file an issue or wait for the official API |
649
+ | Problem | Solution |
650
+ | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
651
+ | Config not detected | Confirm `OPENCODE_GO_WORKSPACE_ID` and `OPENCODE_GO_AUTH_COOKIE` are set, then use `/quota_status` to inspect the exact config paths checked on your machine |
652
+ | Incomplete config | Both `workspaceId` and `authCookie` are required; check `/quota_status` for which field is missing |
653
+ | Scrape returns no data | The auth cookie may have expired; get a fresh one from your browser |
654
+ | Dashboard format changed | The SolidJS SSR pattern may have changed; file an issue or wait for the official API |
594
655
 
595
656
  </details>
596
657
 
597
658
  ## Configuration Reference
598
659
 
599
- All quota plugin settings live under `experimental.quotaToast` in `opencode.json` or `opencode.jsonc`. The sidebar install step is separate: add the package to `tui.json` or `tui.jsonc`, or choose `Sidebar` or `Toast + Sidebar` in `npx @slkiser/opencode-quota init`.
660
+ All quota plugin settings live under `experimental.quotaToast` in `opencode.json` or `opencode.jsonc`.
600
661
 
601
- When both are present, user/global config provides defaults. Project/workspace config may override display-oriented settings for that project, but user/global config remains authoritative for automatic/network-affecting settings such as `enabled`, `enabledProviders`, `minIntervalMs`, `pricingSnapshot.*`, `showOnIdle`, `showOnQuestion`, `showOnCompact`, and `showOnBothFail`. SDK config is only used when no config files are found.
662
+ Project/workspace config may override display-oriented settings for that project, but user/global config remains authoritative for automatic/network-affecting settings such as `enabled`, `enabledProviders`, `minIntervalMs`, `pricingSnapshot.*`, `showOnIdle`, `showOnQuestion`, `showOnCompact`, and `showOnBothFail`. SDK config is only used when no config files are found.
602
663
 
603
664
  ### Core/shared settings
604
665
 
605
- | Option | Default | Meaning |
606
- | --- | --- | --- |
607
- | `enabled` | `true` | Master switch for quota collection and handled slash commands. When `false`, `/quota`, `/quota_status`, `/pricing_refresh`, and `/tokens_*` are handled as no-ops. |
608
- | `enabledProviders` | `"auto"` | Auto-detect providers, or set an explicit provider list. |
609
- | `minIntervalMs` | `300000` | Minimum fetch interval between provider updates. |
610
- | `formatStyle` | `classic` | Shared quota-row style for popup toasts and the TUI sidebar: `classic` or `grouped`. Legacy `toastStyle` is still accepted on read for backward compatibility, but `formatStyle` is the canonical key. |
611
- | `onlyCurrentModel` | `false` | Filter quota rows to the current model/provider when that session selection can be resolved. |
612
- | `showSessionTokens` | `true` | Show the `Session input/output tokens` section in quota displays when session token data is available. Toasts and `/quota` show per-model input/output rows; the TUI sidebar shows a one-line total summary. |
613
- | `pricingSnapshot.source` | `"auto"` | Token pricing snapshot selection for `/tokens_*`: `auto`, `bundled`, or `runtime`. |
614
- | `pricingSnapshot.autoRefresh` | `7` | Refresh stale local pricing data after this many days. |
666
+ | Option | Default | Meaning |
667
+ | ----------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
668
+ | `enabled` | `true` | Master switch for quota collection and handled slash commands. When `false`, `/quota`, `/quota_status`, `/pricing_refresh`, and `/tokens_*` are handled as no-ops. |
669
+ | `enabledProviders` | `"auto"` | Auto-detect providers, or set an explicit provider list. |
670
+ | `minIntervalMs` | `300000` | Minimum fetch interval between provider updates. |
671
+ | `formatStyle` | `classic` | Shared quota-row style for popup toasts and the TUI sidebar: `classic` or `grouped`. Legacy `toastStyle` is still accepted on read for backward compatibility, but `formatStyle` is the canonical key. |
672
+ | `percentDisplayMode` | `remaining` | Shared percent meaning for popup toasts and the TUI sidebar: `remaining` renders labels like `81% left`, while `used` renders labels like `19% used`; the bar fill always matches the shown meaning. |
673
+ | `onlyCurrentModel` | `false` | Filter quota rows to the current model/provider when that session selection can be resolved. |
674
+ | `showSessionTokens` | `true` | Show the `Session input/output tokens` section in quota displays when session token data is available. Toasts and `/quota` show per-model input/output rows; the TUI sidebar shows a one-line total summary. |
675
+ | `pricingSnapshot.source` | `"auto"` | Token pricing snapshot selection for `/tokens_*`: `auto`, `bundled`, or `runtime`. |
676
+ | `pricingSnapshot.autoRefresh` | `7` | Refresh stale local pricing data after this many days. |
615
677
 
678
+ `percentDisplayMode` affects popup toasts and the TUI sidebar only. `/quota` keeps its existing remaining-oriented percentage output. Value-only rows such as spend or used/limit summaries are unchanged.
616
679
 
617
680
  ### Toast settings
618
681
 
619
- | Option | Default | Meaning |
620
- | --- | --- | --- |
621
- | `enableToast` | `true` | Show popup toasts. Disabling this does not disable `/quota` or the TUI sidebar. |
622
- | `toastDurationMs` | `9000` | Toast duration in milliseconds. |
623
- | `showOnIdle` | `true` | Show a toast on the idle trigger. |
624
- | `showOnQuestion` | `true` | Show a toast after a question/assistant response. |
625
- | `showOnCompact` | `true` | Show a toast after session compaction. |
626
- | `showOnBothFail` | `true` | Show a fallback toast when providers attempted quota reads and all failed. |
627
- | `layout.maxWidth` | `50` | Toast formatting width target. Ignored by the TUI sidebar. |
628
- | `layout.narrowAt` | `42` | Toast compact-layout breakpoint. Ignored by the TUI sidebar. |
629
- | `layout.tinyAt` | `32` | Toast tiny-layout breakpoint. Ignored by the TUI sidebar. |
630
- | `debug` | `false` | Append toast debug context when troubleshooting. |
682
+ | Option | Default | Meaning |
683
+ | ----------------- | ------- | ------------------------------------------------------------------------------- |
684
+ | `enableToast` | `true` | Show popup toasts. Disabling this does not disable `/quota` or the TUI sidebar. |
685
+ | `toastDurationMs` | `9000` | Toast duration in milliseconds. |
686
+ | `showOnIdle` | `true` | Show a toast on the idle trigger. |
687
+ | `showOnQuestion` | `true` | Show a toast after a question/assistant response. |
688
+ | `showOnCompact` | `true` | Show a toast after session compaction. |
689
+ | `showOnBothFail` | `true` | Show a fallback toast when providers attempted quota reads and all failed. |
690
+ | `layout.maxWidth` | `50` | Toast formatting width target. Ignored by the TUI sidebar. |
691
+ | `layout.narrowAt` | `42` | Toast compact-layout breakpoint. Ignored by the TUI sidebar. |
692
+ | `layout.tinyAt` | `32` | Toast tiny-layout breakpoint. Ignored by the TUI sidebar. |
693
+ | `debug` | `false` | Append toast debug context when troubleshooting. |
631
694
 
632
695
  ### TUI sidebar setup
633
696
 
@@ -638,31 +701,31 @@ If you want the `Quota` sidebar panel, you need **two files**:
638
701
 
639
702
  **Important:** `experimental.quotaToast.*` settings do **not** go in `tui.json`. `tui.json` is only for loading the TUI plugin.
640
703
 
641
- | File | What goes there | Needed for sidebar? |
642
- | --- | --- | --- |
643
- | `tui.json` / `tui.jsonc` | `plugin: ["@slkiser/opencode-quota"]` | Yes |
644
- | `opencode.json` / `opencode.jsonc` | All `experimental.quotaToast.*` settings | Yes |
704
+ | File | What goes there | Needed for sidebar? |
705
+ | ---------------------------------- | ---------------------------------------- | ------------------- |
706
+ | `tui.json` / `tui.jsonc` | `plugin: ["@slkiser/opencode-quota"]` | Yes |
707
+ | `opencode.json` / `opencode.jsonc` | All `experimental.quotaToast.*` settings | Yes |
645
708
 
646
709
  ### Provider-specific settings
647
710
 
648
- | Option | Default | Meaning |
649
- | --- | --- | --- |
650
- | `anthropicBinaryPath` | `"claude"` | Command/path used for local Claude CLI probing; override this for custom installs or shim locations. |
651
- | `googleModels` | `["CLAUDE"]` | Google model keys to query: `CLAUDE`, `G3PRO`, `G3FLASH`, `G3IMAGE`. |
652
- | `alibabaCodingPlanTier` | `"lite"` | Fallback Alibaba Coding Plan tier when auth does not include `tier`. |
653
- | `cursorPlan` | `"none"` | Cursor included API budget preset: `none`, `pro`, `pro-plus`, `ultra`. |
654
- | `cursorIncludedApiUsd` | unset | Override Cursor monthly included API budget in USD. |
655
- | `cursorBillingCycleStartDay` | unset | Local billing-cycle anchor day `1..28`; when unset, Cursor usage resets on the local calendar month. |
711
+ | Option | Default | Meaning |
712
+ | ---------------------------- | ------------ | ---------------------------------------------------------------------------------------------------- |
713
+ | `anthropicBinaryPath` | `"claude"` | Command/path used for local Claude CLI probing; override this for custom installs or shim locations. |
714
+ | `googleModels` | `["CLAUDE"]` | Google model keys to query: `CLAUDE`, `G3PRO`, `G3FLASH`, `G3IMAGE`. |
715
+ | `alibabaCodingPlanTier` | `"lite"` | Fallback Alibaba Coding Plan tier when auth does not include `tier`. |
716
+ | `cursorPlan` | `"none"` | Cursor included API budget preset: `none`, `pro`, `pro-plus`, `ultra`. |
717
+ | `cursorIncludedApiUsd` | unset | Override Cursor monthly included API budget in USD. |
718
+ | `cursorBillingCycleStartDay` | unset | Local billing-cycle anchor day `1..28`; when unset, Cursor usage resets on the local calendar month. |
656
719
 
657
720
  ## Token Pricing Snapshot
658
721
 
659
722
  `/tokens_*` uses a local `models.dev` pricing snapshot. A bundled snapshot ships for offline use, and Cursor `auto` and `composer*` pricing stays bundled because those ids are not on `models.dev`.
660
723
 
661
- | `pricingSnapshot.source` | Active pricing behavior |
662
- | --- | --- |
663
- | `auto` | Newer runtime snapshot wins; otherwise bundled pricing stays active. |
664
- | `bundled` | Packaged bundled snapshot stays active. |
665
- | `runtime` | Runtime snapshot stays active when present; bundled pricing is fallback until one exists. |
724
+ | `pricingSnapshot.source` | Active pricing behavior |
725
+ | ------------------------ | ----------------------------------------------------------------------------------------- |
726
+ | `auto` | Newer runtime snapshot wins; otherwise bundled pricing stays active. |
727
+ | `bundled` | Packaged bundled snapshot stays active. |
728
+ | `runtime` | Runtime snapshot stays active when present; bundled pricing is fallback until one exists. |
666
729
 
667
730
  - See [Configuration Reference](#configuration-reference) for option defaults.
668
731
  - `pricingSnapshot.autoRefresh` controls how many days a runtime snapshot can age before background refresh.