oc-go-usage-display 1.0.2 → 2.0.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 (41) hide show
  1. package/README.md +249 -68
  2. package/bin/lib.js +433 -29
  3. package/bin/oc-go-usage-display-init.js +42 -13
  4. package/bin/oc-go-usage-display-remove.js +38 -0
  5. package/bin/oc-go-usage-display-show.js +47 -39
  6. package/bin/oc-go-usage-display-status.js +33 -42
  7. package/bin/oc-go-usage-display-update.js +27 -14
  8. package/dist/helpers.d.ts +116 -0
  9. package/dist/helpers.d.ts.map +1 -0
  10. package/dist/helpers.js +568 -0
  11. package/dist/helpers.js.map +1 -0
  12. package/dist/index.d.ts +5 -9
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +258 -278
  15. package/dist/index.js.map +1 -1
  16. package/dist/plugins/oc-go-usage-display.kilo.ts +678 -0
  17. package/dist/plugins/oc-go-usage-display.kilo.tsx +1272 -0
  18. package/dist/plugins/oc-go-usage-display.ts +678 -0
  19. package/dist/plugins/oc-go-usage-display.tsx +1018 -0
  20. package/dist/shared.d.ts +96 -0
  21. package/dist/shared.d.ts.map +1 -0
  22. package/dist/shared.js +575 -0
  23. package/dist/shared.js.map +1 -0
  24. package/dist/tui-shared.d.ts +109 -0
  25. package/dist/tui-shared.d.ts.map +1 -0
  26. package/dist/tui-shared.js +372 -0
  27. package/dist/tui-shared.js.map +1 -0
  28. package/dist/tui.d.ts.map +1 -1
  29. package/dist/tui.js +226 -377
  30. package/dist/tui.js.map +1 -1
  31. package/dist/tui.kilo.d.ts +8 -0
  32. package/dist/tui.kilo.d.ts.map +1 -0
  33. package/dist/tui.kilo.js +502 -0
  34. package/dist/tui.kilo.js.map +1 -0
  35. package/package.json +47 -13
  36. package/src/helpers.ts +733 -0
  37. package/src/index.ts +331 -304
  38. package/src/shared.ts +696 -0
  39. package/src/tui-shared.tsx +705 -0
  40. package/src/tui.kilo.tsx +816 -0
  41. package/src/tui.tsx +356 -465
package/README.md CHANGED
@@ -2,112 +2,293 @@
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/oc-go-usage-display.svg)](https://www.npmjs.com/package/oc-go-usage-display)
4
4
 
5
- OpenCode Go subscription usage plugin (dual target):
5
+ OpenCode Go subscription usage for [opencode](https://opencode.ai) and Kilo:
6
6
 
7
- - **server** (`src/index.ts`): `go_usage` tool (manual query: `Go 5h … | 7d … | 30d …`).
8
- - **tui** (`src/tui.tsx`): `Go Usage` sidebar block (muted `5h`/`7d`/`30d` rows) + `session_prompt_right` statusline.
7
+ | Target | Bundled entry | Surface |
8
+ | ------ | ------------- | ------- |
9
+ | server | `dist/plugins/oc-go-usage-display.ts` | `go_usage` tool (`Go 5h 42% (reset 3h12m) \| 7d 15% \| 30d 61%`) |
10
+ | tui | `dist/plugins/oc-go-usage-display.tsx` | `Go Usage` sidebar + `session_prompt_right` statusline (opencode) |
11
+ | server (kilo) | `dist/plugins/oc-go-usage-display.kilo.ts` | `go_usage` tool for Kilo; reads Kilo's own auth store |
12
+ | tui (kilo) | `dist/plugins/oc-go-usage-display.kilo.tsx` | same TUI surfaces for Kilo |
9
13
 
10
- ![Go Usage sidebar and statusline showing 5h, 7d, and 30d subscription usage](docs/screenshot.png)
14
+ `shared.ts` is inlined at build time. Requires Node >= 22 and opencode >= 1.18.
15
+ All four bundles ship in the one npm package and one version; the build fails if
16
+ either host's bundle is missing.
17
+
18
+ ![Go Usage sidebar and statusline](docs/screenshot.png)
11
19
 
12
20
  ## Install (npm)
13
21
 
14
- ```sh
15
- npm install oc-go-usage-display
16
- npx oc-go-usage-display-init
17
- ```
22
+ | Mode | Command |
23
+ | ---- | ------- |
24
+ | Persistent (recommended) | `npm install oc-go-usage-display@latest && npx oc-go-usage-display-init --copy` |
25
+ | One-shot (npx) | `npx -p oc-go-usage-display@latest oc-go-usage-display-init --copy` |
26
+ | Project scope | `npx -p oc-go-usage-display@latest oc-go-usage-display-init --copy --config-dir .opencode` |
18
27
 
19
- Or one-shot without installing:
28
+ `--copy` is the default and self-contained; `--symlink` is dev-only (rebuild +
29
+ restart). Restart opencode afterwards. Pin the version (`@latest`, not
30
+ `@latest`) so installs stay reproducible; copy-first requires >= latest.
20
31
 
21
- ```sh
22
- npx -y oc-go-usage-display@latest oc-go-usage-display-init
32
+ Alternative — no files copied: declare the versioned package and let opencode
33
+ resolve it at startup:
34
+
35
+ ```jsonc
36
+ // opencode.jsonc — server target (go_usage tool)
37
+ { "plugin": ["oc-go-usage-display@latest"] }
38
+ // tui.json — TUI target (sidebar + statusline)
39
+ { "plugin": [["oc-go-usage-display@latest", { "sidebar": true, "statusline": true }]] }
23
40
  ```
24
41
 
25
- This links `src/*` into `~/.config/opencode/plugins/*` and registers the
26
- `opencode.jsonc` + `tui.json` entries. Restart opencode afterwards.
27
- No secrets are touched. Requires Node >= 22.
42
+ From a checkout: `./install.sh` (copy install; add `--target kilo` for Kilo),
43
+ `./install.sh --symlink` (dev-only), `./install-dev.sh` (latest `develop`
44
+ dev-tgz + config snapshot; there is no auto-restore — it prints the restore
45
+ command).
28
46
 
29
- ## Installation scope
47
+ ### Kilo
30
48
 
31
- | Scope | Command | Writes to | Notes |
32
- | ----- | ------- | --------- | ----- |
33
- | Global | `npx oc-go-usage-display-init` (or `bunx oc-go-usage-display-init`) | `~/.config/opencode/plugins/*` + `opencode.jsonc` + `tui.json` | Restart opencode afterwards |
34
- | Project | `npx oc-go-usage-display-init --scope project` (or manual: `.opencode/plugins/*` + `opencode.json`/`tui.json` in repo) | Repo-local `.opencode/` + `opencode.json`/`tui.json` | Restart opencode afterwards |
35
- | Bun | `bunx oc-go-usage-display-init` + `bunx oc-go-usage-display-show` | Same as global (`~/.config/opencode/…`) | `show` prints effective config (secrets redacted) |
49
+ Kilo is a separate target: `npx oc-go-usage-display-init --target kilo` copies
50
+ `oc-go-usage-display.kilo.{ts,tsx}` into `$KILO_CONFIG_DIR` /
51
+ `$XDG_CONFIG_HOME/kilo` / `~/.config/kilo` and registers `kilo.json` +
52
+ `tui.json`. Kilo's `tui.json` rejects `sidebar`/`statusline`, so its entry is a
53
+ plain plugin spec (both surfaces default on), and Kilo does not resolve
54
+ `./...` against its config dir, so the entries are absolute paths to the
55
+ installed copies. Without `--target`, hosts are detected by binary on PATH or
56
+ config dir, so brew/npm/curl/source installs all count: one detected host
57
+ installs silently, two or more offer a numbered multiselect, and nothing
58
+ detected installs both.
36
59
 
37
- Project-scope manual fallback: copy `src/index.ts` → `.opencode/plugins/oc-go-usage-display.ts`
38
- and `src/tui.tsx` → `.opencode/plugins/oc-go-usage-display.tsx`, then register the
39
- `opencode.json` (server) + `tui.json` (TUI) entries from the manual section below.
60
+ ## Commands
40
61
 
41
- ## Install (manual plugin entries)
62
+ After `npm install` the names below are on PATH; from a checkout use
63
+ `node ./bin/<bin>.js`.
42
64
 
43
- If you prefer to wire the plugin by hand (e.g. npm / OpenDock managed
44
- plugins), add the package to your config and restart opencode:
65
+ | Command | What it does |
66
+ | ------- | ------------ |
67
+ | `oc-go-usage-display-init` | install + register; `--target opencode\|kilo\|all` (default: detected hosts, else all) |
68
+ | `oc-go-usage-display-remove` | uninstall files + config entries (secrets untouched) |
69
+ | `oc-go-usage-display-show` | print effective install per host; `--json` for machine output |
70
+ | `oc-go-usage-display-status` | health check; exit 0 healthy, 1 with reasons |
71
+ | `oc-go-usage-display-update` | re-install + `git pull --ff-only` when a remote exists |
45
72
 
46
- ```jsonc
47
- // opencode.jsonc — server target (go_usage tool)
48
- {
49
- "plugin": ["oc-go-usage-display"]
50
- }
73
+ Flags: `--config-dir <path>` (opencode; default `$OPENCODE_CONFIG_DIR` or
74
+ `~/.config/opencode`), `--kilo-config-dir <path>` (default `$KILO_CONFIG_DIR`
75
+ or `~/.config/kilo`), `--target`, `--repo <path>`, `--copy`/`--symlink`,
76
+ `--sidebar=0/1`, `--statusline=0/1` (opencode only), `--json` (show).
77
+
78
+ ## Display toggles
79
+
80
+ Three axes, all defaulting to on/integrated. Each is a command in the palette,
81
+ persisted per surface, and it applies to whichever sidebar mode is active:
82
+
83
+ | Axis | Command | Also settable as |
84
+ | ---- | ------- | ---------------- |
85
+ | sidebar on/off | `Go usage: toggle sidebar` | `sidebar` option, `OPENCODE_OC_GO_SIDEBAR` / `KILO_OC_GO_SIDEBAR` |
86
+ | statusline on/off | `Go usage: toggle statusline` | `statusline` option, `OPENCODE_OC_GO_STATUSLINE` / `KILO_OC_GO_STATUSLINE` |
87
+ | display mode (Kilo) | `Go usage: toggle sidebar mode` | `sidebar_mode` option, `KILO_OC_GO_SIDEBAR_MODE` |
88
+
89
+ ```json
90
+ { "plugin": ["./plugins/oc-go-usage-display.tsx", { "sidebar": true, "statusline": true }] }
51
91
  ```
52
92
 
53
- ```jsonc
54
- // tui.json — TUI target (Go Usage sidebar + statusline)
55
- {
56
- "plugin": [["oc-go-usage-display", { "sidebar": true, "statusline": true }]]
57
- }
93
+ Hiding the sidebar hides it in either mode; the mode decides *what* it draws, not
94
+ whether it is there. Environment variables and the legacy `display` option apply
95
+ only when the `tui.json` toggles are absent. Restart the host after changing
96
+ static config. Kilo's `tui.json` rejects the `sidebar`/`statusline` options, so
97
+ on that host the palette and the env vars are the way to set them.
98
+
99
+ ## What the sidebar shows
100
+
101
+ One shared implementation renders the block on both hosts; only the sidebar's
102
+ width differs (~30 cells on opencode, ~40 on Kilo), and that is what decides the
103
+ layout. Both screenshots below are real captures of the pinned hosts, taken by
104
+ `scripts/capture-shots.mjs` (mocked usage, no subscription touched).
105
+
106
+ | opencode | Kilo (integrated) |
107
+ | -------- | ----------------- |
108
+ | ![opencode sidebar](docs/sidebar-opencode.png) | ![Kilo sidebar](docs/sidebar-kilo.png) |
109
+
110
+ **opencode** — the plan as meters, with the next reset on its own line, and a
111
+ model section that starts collapsed:
112
+
113
+ ```
114
+ Go Usage
115
+ 5h resets in 2h5m
116
+ 5h ████░░░░░░ 42%
117
+ 7d ██░░░░░░░░ 15%
118
+ 30d ██████░░░░ 61%
119
+
120
+ ▶ Top Go models (7)
121
+ mimo 59%·qwen 25%
58
122
  ```
59
123
 
60
- The `oc-plugin: ["server", "tui"]` manifest auto-discovers both targets
61
- from the published package (`dist/`). Set `OPENCODE_GO_API_KEY` (Bearer for
62
- `GET https://opencode.ai/zen/go/v1/usage`) or sign in via the `opencode-go`
63
- provider so `auth.json` supplies the key.
124
+ Fold the section open (the header is a disclosure control, like the host's own
125
+ `MCP` / `Models` sections) for one row per model:
64
126
 
65
- ## Install (local repo, easy update)
127
+ ```
128
+ ▾ Top Go models (7)
129
+ mimo-v2.6-p █████░ 59%
130
+ qwen3-max ███░░░░░ 25%
131
+ gpt-5.1 █░░░░░░ 12%
132
+ 2.31M of 2.4M Go tokens
133
+ 161 steps · $1.51
134
+ ```
66
135
 
67
- ```sh
68
- ./install.sh
136
+ A model's **weight** is its share of the Go tokens spent in this session, taken
137
+ from the host's own message store over the rendered session — the same scope as
138
+ opencode's `Context` panel next to it. It is a share of tokens: never a share of
139
+ the plan, a quota, or a price, because the plan's absolute limits are not
140
+ client-visible. Bars use the plan's threshold coloring (muted < 75% ≤ warning <
141
+ 90% ≤ error), and a capped window is always the error color however low its
142
+ percent reads.
143
+
144
+ Both hosts draw the plan the same way: the next reset on one line, then three
145
+ stacked meters whose bars share a left edge and whose percents share a right
146
+ edge.
147
+
148
+ **Kilo** — `sidebar_mode` picks what the block is:
149
+
150
+ - **integrated** (default): the block takes over the host's own `Token Usage`
151
+ band, retires that panel, and renders `Session Tokens` / `Models`. The plan is
152
+ drawn **once**, as the `Go Plan` meters inside the `OpenCode Go` group, and
153
+ every Go model row carries its `Go share`. There is deliberately no separate
154
+ `Go Usage` block saying the same three numbers again.
155
+ - **standalone**: our block in a free band above the host's panel, and the host
156
+ panel stays.
157
+
158
+ ## Auth and config
159
+
160
+ First match wins (secrets are never logged); each host reads only its own
161
+ credential store:
162
+
163
+ | # | Source | Behavior |
164
+ | - | ------ | -------- |
165
+ | 1 | `OPENCODE_OC_GO_MOCK=1` | deterministic mock snapshot (never cached) |
166
+ | 2 | `OPENCODE_OC_GO_API_KEY` | `GET https://opencode.ai/zen/go/v1/usage` with `Authorization: Bearer <key>` |
167
+ | 3 | provider `auth.json` | same Bearer path; `opencode-go` key, else `opencode`. opencode: `$XDG_DATA_HOME/opencode/auth.json` (`~/.local/share/opencode/auth.json`), then `~/.config/opencode/auth.json`. Kilo: the same files under `kilo` (`$KILO_CONFIG_DIR` / `$XDG_CONFIG_HOME/kilo`) |
168
+ | 4 | workspace + cookie | scrape `GET https://opencode.ai/workspace/{workspaceId}/go` with the `auth` cookie; file config from the host's config dir |
169
+ | 5 | none | unavailable snapshot (`not configured (set OPENCODE_OC_GO_API_KEY)`) |
170
+
171
+ File config (`oc-go-usage-display.json` in the host's config dir, e.g.
172
+ `~/.config/opencode` or `~/.config/kilo`):
173
+
174
+ ```jsonc
175
+ { "workspaceId": "...", "authCookie": "..." }
69
176
  ```
70
177
 
71
- This symlinks `src/*` into `~/.config/opencode/plugins/*` and registers the
72
- `opencode.jsonc` + `tui.json` entries. Edits in this repo apply after an
73
- opencode restart. No secrets are touched.
178
+ Successful snapshots cache 60s (memory + `oc-go-usage-display-cache.json` in
179
+ the host's config dir); failures are never cached. ### Environment variables
74
180
 
75
- ## Commands
181
+ Every variable this plugin reads is **scoped to the coding agent that reads it**,
182
+ so one shell can drive the two hosts independently:
183
+
184
+ | Suffix | opencode | Kilo |
185
+ | ------ | -------- | ---- |
186
+ | `API_KEY` | `OPENCODE_OC_GO_API_KEY` | `KILO_OC_GO_API_KEY` |
187
+ | `WORKSPACE_ID` | `OPENCODE_OC_GO_WORKSPACE_ID` | `KILO_OC_GO_WORKSPACE_ID` |
188
+ | `AUTH_COOKIE` | `OPENCODE_OC_GO_AUTH_COOKIE` | `KILO_OC_GO_AUTH_COOKIE` |
189
+ | `MOCK` | `OPENCODE_OC_GO_MOCK` | `KILO_OC_GO_MOCK` |
190
+ | `SIDEBAR` | `OPENCODE_OC_GO_SIDEBAR` | `KILO_OC_GO_SIDEBAR` |
191
+ | `STATUSLINE` | `OPENCODE_OC_GO_STATUSLINE` | `KILO_OC_GO_STATUSLINE` |
192
+ | `DISPLAY` (legacy) | `OPENCODE_OC_GO_DISPLAY` | `KILO_OC_GO_DISPLAY` |
193
+ | `SIDEBAR_MODE` | `OPENCODE_OC_GO_SIDEBAR_MODE` | `KILO_OC_GO_SIDEBAR_MODE` |
194
+
195
+ A Kilo build only reads `KILO_OC_GO_*`, so an `OPENCODE_OC_GO_*` name can never
196
+ steer it — the two hosts keep separate auth stores and config dirs for the same
197
+ reason.
76
198
 
77
199
  ```sh
78
- node ./bin/oc-go-usage-display-init.js # (re-)install
79
- node ./bin/oc-go-usage-display-show.js # show effective config (secrets redacted)
80
- node ./bin/oc-go-usage-display-status.js # health check (exit 0/1)
81
- node ./bin/oc-go-usage-display-update.js # re-link (+ git pull when a remote exists)
200
+ # a different surface selection per host, from one shell
201
+ OPENCODE_OC_GO_SIDEBAR=1 KILO_OC_GO_SIDEBAR=0 opencode
82
202
  ```
83
203
 
84
- After installing the package, the commands are also available as
85
- `oc-go-usage-display-init|show|status|update`.
204
+ The pre-2.0 unscoped `OPENCODE_GO_*` spelling is **no longer read**. It was
205
+ removed rather than deprecated: a fallback would keep one shared variable steering
206
+ both hosts after the split, which is the exact ambiguity the prefixes exist to
207
+ remove. If you configured credentials through it, move them to the host-scoped
208
+ name you actually run.
86
209
 
87
- ## Display toggles
210
+ `OPENCODE_CONFIG_DIR` / `KILO_CONFIG_DIR` are read by the install CLIs, not by
211
+ the plugin entry modules.
88
212
 
89
- Both surfaces default on and are independent:
213
+ ## Development
90
214
 
91
- ```json
92
- ["./plugins/oc-go-usage-display.tsx", { "sidebar": true, "statusline": true }]
215
+ ```sh
216
+ bun install
217
+ bun run build # tsc -> dist/ + esbuild -> dist/plugins/* (both hosts)
218
+ bun run check # typecheck only
93
219
  ```
94
220
 
95
- `OPENCODE_GO_SIDEBAR` / `OPENCODE_GO_STATUSLINE` env vars override when the
96
- toggles are absent. Restart opencode after changing them.
221
+ `bun run build` fails unless all four bundles exist, are self-contained and
222
+ export only the default module (`scripts/verify-bundles.mjs`); packed tarballs
223
+ can be checked with `node scripts/verify-tarball.mjs <file.tgz>`.
97
224
 
98
- ## Build
225
+ To refresh the README screenshots (boots both hosts in tmux, writes the panes
226
+ with their colors intact to `tmp/`):
99
227
 
100
228
  ```sh
101
- npm install
102
- npm run build # tsc -> dist/
103
- npm run check # typecheck only
229
+ docker compose run --rm -v "$PWD":/workspaces/oc-go-usage-display -v "$PWD/tmp:/out" \
230
+ test bun scripts/capture-shots.mjs
104
231
  ```
105
232
 
233
+ | Test command | Tier |
234
+ | ------------ | ---- |
235
+ | `bun run test` | build + READONLY unit tier (host/CI) |
236
+ | `bun run test:unit` | helper tests + the live usage **shape** check — the one place an API key is used (a single GET; skips without `OPENCODE_OC_GO_API_KEY`) |
237
+ | `bun run test:docker` | authoritative gate: integration + e2e, incl. the real opencode/kilo TUI display checks and the per-model mix rendered against a local fake provider |
238
+ | `bun run test:integration` / `bun run test:e2e` | container-only tiers |
239
+
240
+ Unit tests are readonly by construction (`scripts/check-unit-purity.mjs` rejects
241
+ fs writes, tmp usage, child processes and sockets). Integration and e2e run only
242
+ inside the container image; host-runnable tests redirect HOME/XDG and force
243
+ `OPENCODE_OC_GO_MOCK=1`, so they never touch the real `~/.config/opencode`.
244
+
245
+ **The API key buys one thing:** a shape check that the live usage payload is
246
+ still what we parse. Every TUI display test runs on the mock instead, because it
247
+ asserts layout, which does not need live numbers — so the container gate is
248
+ hermetic and needs no secret at all.
249
+
250
+ ## CI
251
+
252
+ | Workflow | Trigger | Jobs |
253
+ | -------- | ------- | ---- |
254
+ | `test.yml` | push, PR, weekly (Mon 06:00 UTC) | `unit` always; `container-e2e` (Docker gate) only on `main` pushes, the schedule, and non-draft PRs |
255
+ | `bump-deps.yml` | weekly (Mon 12:30 UTC), manual | `bun update` within the declared ranges, the Dockerfile host pins moved with the SDKs, the Docker gate on the bumped tree, then the commit — nothing is committed unless the gate is green |
256
+ | `dev-build.yml` | push to `develop` | `dev-tgz` artifact (90 days), used by `install-dev.sh` |
257
+ | `publish.yml` | push to `main` | gate -> release-please Release PR -> OIDC provenance publish; the release carries the tarball, all four plugin bundles and `SHA256SUMS`, and the registry tarball is re-verified after publish |
258
+
259
+ Releases are cut by [release-please](https://github.com/googleapis/release-please):
260
+ merging `develop` into `main` opens/updates a `chore(main): release X.Y.Z` PR
261
+ (`feat` -> minor, `fix` -> patch, breaking change -> major; `chore`/`docs`/`ci`/
262
+ `test`/`refactor`/`style`/`build`/`perf` never cut a release on their own).
263
+ Merging that PR tags `vX.Y.Z`, creates the GitHub release, and publishes to npm
264
+ after the containerized gate. To force a version, add a `Release-As: X.Y.Z`
265
+ footer to a commit merged to `main`.
266
+
106
267
  ## Troubleshooting
107
268
 
108
- ### Pre-rename files removed in 1.0.x
269
+ - **Plugin didn't load**: check `npx oc-go-usage-display-show` / `status`, then
270
+ restart the host (`opencode debug config` shows the resolved plugin list;
271
+ `opencode --pure` skips plugins, so it is not a valid check).
272
+ - **No API key or subscription**: surfaces show `Go n/a (…)`; set
273
+ `OPENCODE_OC_GO_API_KEY` or `KILO_OC_GO_API_KEY` for the host you are
274
+ running, sign in through the
275
+ `opencode-go` provider in the host you are running, or configure workspace +
276
+ cookie. Each host reads only its own `auth.json`, so a Kilo login does not
277
+ feed the opencode plugin and vice versa.
278
+ - **Kilo only**: `npx oc-go-usage-display-init --target kilo`; Kilo ignores
279
+ `sidebar`/`statusline` options, so toggle surfaces with the command palette
280
+ instead.
281
+ - **Stale copy install**: copy installs never auto-update; re-run
282
+ `npx oc-go-usage-display-init --copy` and restart.
283
+
284
+ ## Uninstall
285
+
286
+ ```sh
287
+ npx oc-go-usage-display-remove
288
+ npm uninstall oc-go-usage-display
289
+ ```
109
290
 
110
- Pre-rename `opencode-go-usage.*` shims were removed in 1.0.x. The installer and
111
- plugin now use only `oc-go-usage-display.*` plugin files, config entries, and
112
- the `oc-go-usage-display.json` file config. Delete any leftover
113
- `opencode-go-usage.*` files by hand if they remain from an older install.
291
+ Removes the plugin files and the server + `tui.json` entries from every
292
+ installed host (`--target` or `--config-dir`/`--kilo-config-dir` narrows it).
293
+ Secrets are never touched: env vars, `auth.json`, and
294
+ `oc-go-usage-display.json` stay in place.