opencode-context-indicator 1.1.1 → 1.1.2

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 (3) hide show
  1. package/README.md +67 -8
  2. package/package.json +4 -6
  3. package/tui.tsx +40 -2
package/README.md CHANGED
@@ -73,6 +73,10 @@ other 5.6k 12%
73
73
  updated 12:30:01
74
74
  ```
75
75
 
76
+ > Requires a `file://` install from a path outside `node_modules`; on the npm
77
+ > path the sidebar is auto-disabled. See
78
+ > [Live sidebar: npm vs file:// install](#live-sidebar-npm-vs-file-install).
79
+
76
80
  ### Slash commands (V2)
77
81
 
78
82
  On OpenCode 2.x (Desktop **and** terminal TUI) the plugin registers two slash
@@ -225,6 +229,9 @@ Notes — these reflect what the plugin API actually exposes today:
225
229
  therefore delivers everything through the log file, the TUI sidebar and the
226
230
  `/context` / `/context-breakdown` slash commands. The sidebar is a TUI-process
227
231
  slot and does not exist in the Desktop app; the slash commands work in **both**.
232
+ The TUI sidebar is **live only for a `file://` install** from a path outside
233
+ `node_modules`; on the npm path it is auto-disabled (upstream `#33884`) — see
234
+ [Live sidebar: npm vs file:// install](#live-sidebar-npm-vs-file-install).
228
235
  * **V1 has no sidebar and no slash command.** The command/slot API (and the
229
236
  `./tui` entry) is a V2 feature; OpenCode 1.x has no equivalent, so V1 is
230
237
  toast + log only.
@@ -275,13 +282,55 @@ or add it to `opencode.jsonc`:
275
282
  ```
276
283
 
277
284
  The `./tui` sidebar entry is loaded automatically alongside the main plugin in
278
- the terminal TUI. For a CLI-only setup against remote servers, the package can
279
- also be listed in [`cli.json`](https://opencode.ai/v2/docs/cli/plugins):
285
+ the terminal TUI — but its live behaviour depends on the install method, see
286
+ [Live sidebar: npm vs file:// install](#live-sidebar-npm-vs-file-install) below.
287
+ For a CLI-only setup against remote servers, the package can also be listed in
288
+ [`cli.json`](https://opencode.ai/v2/docs/cli/plugins):
280
289
 
281
290
  ```json
282
291
  { "plugins": ["opencode-context-indicator"] }
283
292
  ```
284
293
 
294
+ ### Live sidebar: npm vs file:// install
295
+
296
+ The TUI sidebar is a **TUI-process slot**. On OpenCode 2.x it behaves
297
+ differently depending on **how the plugin was installed** — an upstream OpenCode
298
+ limitation (`anomalyco/opencode#33884`), not a plugin bug: OpenCode's TUI loader
299
+ skips the host Solid transform for any path inside a `node_modules` directory, so
300
+ a slot mounted from an npm install renders once and then never live-updates.
301
+
302
+ | Install | Desktop | TUI commands | TUI live sidebar |
303
+ | --- | :---: | :---: | :---: |
304
+ | npm (`opencode plugin add opencode-context-indicator`) | ✅ | ✅ | ❌ auto-disabled (upstream #33884) |
305
+ | `file://` (path **outside** any `node_modules`) | ✅ | ✅ | ✅ live |
306
+
307
+ On the **npm** path the plugin detects that it lives under `node_modules` and
308
+ **disables the sidebar gracefully** — it logs a single hint and registers no
309
+ slot, so you never see a frozen "no data yet" panel. The `/context` /
310
+ `/context-breakdown` slash commands and the breakdown log file keep working on
311
+ every install.
312
+
313
+ #### Getting the live sidebar (`file://` install)
314
+
315
+ 1. Put the package **outside** any `node_modules`: clone the repository, or
316
+ unpack the npm tarball (`npm pack opencode-context-indicator`, then extract
317
+ the `.tgz`) — e.g. into `C:\Users\you\plugins\opencode-context-indicator`.
318
+ Double-check that the chosen path contains **no `node_modules` segment**
319
+ (e.g. `C:\Users\you\plugins\...`, not `.../node_modules/...`).
320
+ 2. Point OpenCode at that directory in `~/.config/opencode/opencode.jsonc`:
321
+
322
+ ```jsonc
323
+ {
324
+ "plugins": ["file:///C:/Users/you/plugins/opencode-context-indicator"]
325
+ }
326
+ ```
327
+
328
+ 3. Restart OpenCode. The sidebar is now live and updates as context grows.
329
+
330
+ > ⚠️ The `file://` path must **not** contain a `node_modules` segment. If it
331
+ > does, OpenCode skips the Solid transform and the sidebar will not update; the
332
+ > plugin auto-disables it and logs the hint above.
333
+
285
334
  ### OpenCode 1.x (V1)
286
335
 
287
336
  Add the package name to the `plugin` array in your `opencode.json`:
@@ -303,9 +352,11 @@ helper resolves. The `lib/` folder is support code, not a separate plugin entry:
303
352
  ~/.config/opencode/plugins/lib/dedup.js
304
353
  ```
305
354
 
306
- To use the sidebar locally as well, place `tui.tsx` where your OpenCode
307
- installation resolves the package's `./tui` entry (npm install is the
308
- recommended path for the sidebar).
355
+ To use the sidebar locally as well, point OpenCode at a `file://` copy of the
356
+ package that lives **outside any `node_modules`** (see
357
+ [Live sidebar: npm vs file:// install](#live-sidebar-npm-vs-file-install)) — that
358
+ is the only install path that keeps the sidebar live. An npm install auto-disables
359
+ the sidebar instead.
309
360
 
310
361
  ---
311
362
 
@@ -322,9 +373,17 @@ recommended path for the sidebar).
322
373
  * **OpenCode ≥ 2.0.16** for the V2 path (built and verified against
323
374
  **2.0.19**).
324
375
  * **TUI sidebar**: terminal TUI only, requires the OpenTUI rendering stack that
325
- ships with OpenCode (`@opentui/core`, `@opentui/solid`, `solid-js`). These are
326
- declared as **optional** peer dependencies, so the main plugin installs and
327
- runs fine without them (the sidebar simply is not available).
376
+ ships with OpenCode. `@opentui/core` and `solid-js` are **optional** peer
377
+ dependencies resolved by OpenCode at runtime; the main plugin installs and runs
378
+ fine without them (the sidebar simply is not available). `@opentui/solid` is
379
+ instead shipped as a **pinned direct dependency** (exact `0.5.12`): OpenCode's
380
+ TUI loader does not expose a host instance of it, so for npm-installed plugins
381
+ the JSX pragma would otherwise fail to resolve `@opentui/solid/jsx-runtime`
382
+ (upstream: opencode issue #33884 — `node_modules` plugins are excluded from the
383
+ host Solid transform and get an isolated OpenTUI copy). Because of that same
384
+ upstream limitation, on the **npm** path the sidebar is **auto-disabled**
385
+ (the plugin logs one hint and registers no slot) — use a `file://` install for
386
+ the live sidebar, see [Live sidebar: npm vs file:// install](#live-sidebar-npm-vs-file-install).
328
387
 
329
388
  ---
330
389
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-context-indicator",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "Real-time OpenCode context-window usage indicator: per-category token breakdown written to a log file, plus an optional TUI sidebar. Dual V1 + V2 plugin entry.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -37,7 +37,6 @@
37
37
  "peerDependencies": {
38
38
  "@opencode/plugin": ">=2.0.16",
39
39
  "@opentui/core": ">=0.5.12",
40
- "@opentui/solid": ">=0.5.12",
41
40
  "solid-js": ">=1.9.0"
42
41
  },
43
42
  "peerDependenciesMeta": {
@@ -47,17 +46,16 @@
47
46
  "@opentui/core": {
48
47
  "optional": true
49
48
  },
50
- "@opentui/solid": {
51
- "optional": true
52
- },
53
49
  "solid-js": {
54
50
  "optional": true
55
51
  }
56
52
  },
53
+ "dependencies": {
54
+ "@opentui/solid": "0.5.12"
55
+ },
57
56
  "devDependencies": {
58
57
  "@opencode/plugin": "^2.0.19",
59
58
  "@opentui/core": "^0.5.12",
60
- "@opentui/solid": "^0.5.12",
61
59
  "solid-js": "^1.9.12"
62
60
  }
63
61
  }
package/tui.tsx CHANGED
@@ -23,8 +23,19 @@
23
23
  * file renders "no data yet". The main plugin never imports this file, so the
24
24
  * absence of the OpenTUI peers cannot break the server/V1 path.
25
25
  *
26
- * Peer requirements (declared optional in package.json): @opentui/core,
27
- * @opentui/solid, solid-js.
26
+ * Runtime requirements: @opentui/core and solid-js are optional peers resolved
27
+ * by OpenCode at runtime. @opentui/solid is a pinned direct dependency (exact
28
+ * 0.5.12): OpenCode's TUI loader does not expose a host instance of it, so for
29
+ * npm-installed plugins the JSX pragma would otherwise fail to resolve
30
+ * `@opentui/solid/jsx-runtime` (upstream opencode issue #33884).
31
+ *
32
+ * Graceful mode: when this file is loaded from an npm install (its own path is
33
+ * inside a `node_modules` directory), OpenCode skips the host Solid transform
34
+ * for `node_modules` paths, so a mounted slot renders once and then never
35
+ * live-updates (anomalyco/opencode#33884). Rather than freeze a permanent
36
+ * "no data yet" panel, the entry detects that case, logs a single hint and
37
+ * registers no slot. Install via `file://` from a path outside any
38
+ * `node_modules` for the live sidebar (see README → "Live sidebar").
28
39
  */
29
40
  import {Plugin, usePlugin} from "@opencode/plugin/tui"
30
41
  import {createSignal, Show} from "solid-js"
@@ -32,11 +43,25 @@ import type {ColorInput} from "@opentui/core"
32
43
  import {readFileSync} from "node:fs"
33
44
  import {tmpdir} from "node:os"
34
45
  import {join} from "node:path"
46
+ import {fileURLToPath} from "node:url"
35
47
 
36
48
  const STATE_FILE = join(tmpdir(), "opencode-context-indicator-state.json")
37
49
  const POLL_MS = 1000
38
50
  const LABEL_WIDTH = 12
39
51
 
52
+ // True when this module was loaded from an npm install, i.e. its own file path
53
+ // contains a `node_modules` segment (OpenCode's TUI loader skips the host Solid
54
+ // transform for such paths → slots mount once but never live-update; see the
55
+ // Graceful mode note above). Normalised to forward slashes for Windows paths.
56
+ function isNodeModulesInstall(): boolean {
57
+ try {
58
+ const selfPath = fileURLToPath(import.meta.url).replace(/\\/g, "/").toLowerCase()
59
+ return selfPath.includes("/node_modules/")
60
+ } catch {
61
+ return false
62
+ }
63
+ }
64
+
40
65
  type Categories = {
41
66
  user?: number
42
67
  assistant?: number
@@ -163,6 +188,19 @@ function Sidebar(props: { entry: () => StateEntry | null }) {
163
188
  export default Plugin.define({
164
189
  id: "context-indicator.tui",
165
190
  setup(context) {
191
+ // npm installs (path under node_modules) cannot get live slot updates on
192
+ // this OpenCode version. Stay inert and log a single hint instead of
193
+ // registering a slot that would freeze on "no data yet".
194
+ if (isNodeModulesInstall()) {
195
+ console.log(
196
+ "[context-indicator] TUI sidebar disabled: npm-installed plugins cannot get " +
197
+ "live updates on this OpenCode version (anomalyco/opencode#33884). " +
198
+ 'Install via file:// (see README → "Live sidebar") for the live sidebar. ' +
199
+ "Slash commands still work everywhere.",
200
+ )
201
+ return
202
+ }
203
+
166
204
  // Re-read the bridge file once per second and re-render reactively.
167
205
  const [tick, setTick] = createSignal(0)
168
206
  let currentSession: string | undefined