opencode-context-indicator 1.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.
- package/LICENSE +21 -0
- package/README.md +242 -0
- package/index.js +2367 -0
- package/lib/dedup.js +120 -0
- package/package.json +57 -0
- package/tui.tsx +180 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 opencode-context-indicator contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
# opencode-context-indicator
|
|
2
|
+
|
|
3
|
+
Real-time **context-window usage** indicator for [OpenCode](https://opencode.ai),
|
|
4
|
+
with a **per-category token breakdown** and an optional **terminal-UI sidebar**.
|
|
5
|
+
|
|
6
|
+
It tells you how full the current model's context window is, and *what* is
|
|
7
|
+
filling it: system prompt, tool schemas, user/assistant text, reasoning, tool
|
|
8
|
+
arguments and the residual "other" bucket.
|
|
9
|
+
|
|
10
|
+
The package ships a **dual V1 + V2 plugin** (one entry works in both OpenCode
|
|
11
|
+
generations) plus an optional TUI sidebar module exposed as the `./tui` entry.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## What it shows
|
|
16
|
+
|
|
17
|
+
### Per-category breakdown
|
|
18
|
+
|
|
19
|
+
For every served request the plugin estimates how the context window is split:
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
[2026-…] session=ses_abc model=… ctx=45.2k/120k (38%) … input=44.1k
|
|
23
|
+
user 4.2k (est tokens)
|
|
24
|
+
assistant 3.1k (est tokens)
|
|
25
|
+
reasoning 0.8k (est tokens) (exact 1.2k)
|
|
26
|
+
tool args 0.3k (est tokens, input only)
|
|
27
|
+
system 2.1k (est tokens)
|
|
28
|
+
tool schemas 1.4k (est tokens)
|
|
29
|
+
other 5.6k (= input - sum of estimates)
|
|
30
|
+
source context-hook
|
|
31
|
+
subagents 2 session(s): in=8.1k out=2.3k r=1.0k worst=12%
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
* Token counts are **estimates** from a unicode-aware heuristic
|
|
35
|
+
(Cyrillic ≈ 2.5, CJK ≈ 1.5, latin/ASCII ≈ 4 chars/token) — not a tokenizer.
|
|
36
|
+
`reasoning` also carries the exact value reported by the model when present.
|
|
37
|
+
* `other` is the residual (`input − sum of estimates`).
|
|
38
|
+
* Tool **results** are deliberately not counted; only tool **call arguments**
|
|
39
|
+
(results are not part of the sent prompt).
|
|
40
|
+
* `ctx` is OpenCode's native overflow count: `tokens.total` when present, else
|
|
41
|
+
`input + output + cache.read + cache.write`. Percentages are **not clamped**
|
|
42
|
+
at 100% — exceeding the window stays visible.
|
|
43
|
+
|
|
44
|
+
### Toast (V1 only)
|
|
45
|
+
|
|
46
|
+
On OpenCode 1.x, after each assistant message a throttled toast appears:
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
ctx 45.2k / 120k (38%) · r 1.2k · c 3.4k
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`r` = reasoning tokens, `c` = cache-read tokens (both only when nonzero); cost
|
|
53
|
+
is appended only when the model config carries explicit pricing.
|
|
54
|
+
|
|
55
|
+
### TUI sidebar (V2, terminal only)
|
|
56
|
+
|
|
57
|
+
On the OpenCode 2.x terminal TUI the `./tui` entry renders a compact sidebar
|
|
58
|
+
panel with the same breakdown:
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
Context
|
|
62
|
+
gpt-4o · 45.2k / 120k (38%)
|
|
63
|
+
user 4.2k 9%
|
|
64
|
+
assistant 3.1k 7%
|
|
65
|
+
reasoning 0.8k 2%
|
|
66
|
+
tool args 0.3k 1%
|
|
67
|
+
system 2.1k 5%
|
|
68
|
+
tool schemas 1.4k 3%
|
|
69
|
+
other 5.6k 12%
|
|
70
|
+
updated 12:30:01
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Surface matrix
|
|
76
|
+
|
|
77
|
+
| Surface | Toast | TUI sidebar | Breakdown log file |
|
|
78
|
+
| --- | :---: | :---: | :---: |
|
|
79
|
+
| OpenCode **1.x** — Desktop | ✅ | — | ✅ |
|
|
80
|
+
| OpenCode **1.x** — TUI | ✅ | — | ✅ |
|
|
81
|
+
| OpenCode **2.x** — TUI | — | ✅ | ✅ |
|
|
82
|
+
| OpenCode **2.x** — Desktop | — | — | ✅ |
|
|
83
|
+
|
|
84
|
+
Notes — these reflect what the plugin API actually exposes today:
|
|
85
|
+
|
|
86
|
+
* **V2 has no toast channel on the server side.** The V2 plugin API
|
|
87
|
+
(`ctx.*`) exposes no TUI/toast method (opencode issue `#49380`); the V2 path
|
|
88
|
+
therefore delivers everything through the log file and the TUI sidebar. The
|
|
89
|
+
sidebar is a TUI-process slot and does not exist in the Desktop app.
|
|
90
|
+
* **V1 has no sidebar.** The CLI-plugin / slot API (and the `./tui` entry) is a
|
|
91
|
+
V2 feature; OpenCode 1.x has no equivalent, so V1 is toast + log only.
|
|
92
|
+
* The Desktop app is TUI-less; its V2 surface is the log file only.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Log / state file locations
|
|
97
|
+
|
|
98
|
+
All paths use the OS temp directory (`os.tmpdir()`), i.e. `%TEMP%` on Windows
|
|
99
|
+
and `$TMPDIR` (usually `/tmp`) elsewhere:
|
|
100
|
+
|
|
101
|
+
| File | Purpose |
|
|
102
|
+
| --- | --- |
|
|
103
|
+
| `context-breakdown.log` | Human-readable live snapshot + bounded final summaries |
|
|
104
|
+
| `opencode-context-indicator-state.json` | Machine-readable snapshot consumed by the TUI sidebar |
|
|
105
|
+
| `context-events.log` | Raw event tap — **only** when `DEBUG_EVENTS` is flipped to `true` in the source (off by default) |
|
|
106
|
+
|
|
107
|
+
The live `context-breakdown.log` snapshot is **rewritten** (never grows); final
|
|
108
|
+
summaries (on `session.idle`) and compaction notes are **appended** — log writes
|
|
109
|
+
use plain `appendFileSync`, not atomic replacement. Only the machine-readable
|
|
110
|
+
`opencode-context-indicator-state.json` is written **atomically** (temp file +
|
|
111
|
+
rename), so concurrent plugin instances cannot corrupt it. Cross-instance
|
|
112
|
+
duplicate final summaries are prevented separately by an atomic claim marker
|
|
113
|
+
(see `lib/dedup.js`).
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Installation
|
|
118
|
+
|
|
119
|
+
### OpenCode 2.x (V2)
|
|
120
|
+
|
|
121
|
+
Per the [OpenCode v2 plugin docs](https://opencode.ai/v2/docs/plugins), npm
|
|
122
|
+
plugins are listed under the `plugins` (plural) config key. Use the CLI:
|
|
123
|
+
|
|
124
|
+
```sh
|
|
125
|
+
opencode plugin add opencode-context-indicator
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
or add it to `opencode.jsonc`:
|
|
129
|
+
|
|
130
|
+
```jsonc
|
|
131
|
+
{
|
|
132
|
+
"$schema": "https://opencode.ai/config.json",
|
|
133
|
+
"plugins": ["opencode-context-indicator"]
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
The `./tui` sidebar entry is loaded automatically alongside the main plugin in
|
|
138
|
+
the terminal TUI. For a CLI-only setup against remote servers, the package can
|
|
139
|
+
also be listed in [`cli.json`](https://opencode.ai/v2/docs/cli/plugins):
|
|
140
|
+
|
|
141
|
+
```json
|
|
142
|
+
{ "plugins": ["opencode-context-indicator"] }
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### OpenCode 1.x (V1)
|
|
146
|
+
|
|
147
|
+
Add the package name to the `plugin` array in your `opencode.json`:
|
|
148
|
+
|
|
149
|
+
```json
|
|
150
|
+
{
|
|
151
|
+
"plugin": ["opencode-context-indicator"]
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Local file (no npm)
|
|
156
|
+
|
|
157
|
+
Copy `index.js` and `lib/dedup.js` into `~/.config/opencode/plugins/`, keeping
|
|
158
|
+
the `lib/` subdirectory next to the plugin file so the plugin's `import` of the
|
|
159
|
+
helper resolves. The `lib/` folder is support code, not a separate plugin entry:
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
~/.config/opencode/plugins/context-indicator.js
|
|
163
|
+
~/.config/opencode/plugins/lib/dedup.js
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
To use the sidebar locally as well, place `tui.tsx` where your OpenCode
|
|
167
|
+
installation resolves the package's `./tui` entry (npm install is the
|
|
168
|
+
recommended path for the sidebar).
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Requirements
|
|
173
|
+
|
|
174
|
+
* **Node.js ≥ 18** (the main plugin uses only Node built-ins). `@opencode/plugin`
|
|
175
|
+
is an **optional** peer dependency: OpenCode resolves it at runtime, and
|
|
176
|
+
`index.js` itself does not import it (the V2 `define` helper is inlined).
|
|
177
|
+
* **OpenCode ≥ 1.18.29** for the V1 path. ⚠️ The V1 path relies on
|
|
178
|
+
`experimental.chat.*` hooks, which are **experimental** and may change or stop
|
|
179
|
+
firing in future OpenCode 1.x releases; if they do, the indicator degrades
|
|
180
|
+
gracefully (the breakdown falls back to throttled `session.messages` fetches
|
|
181
|
+
and toasts keep working).
|
|
182
|
+
* **OpenCode ≥ 2.0.16** for the V2 path (built and verified against
|
|
183
|
+
**2.0.18**).
|
|
184
|
+
* **TUI sidebar**: terminal TUI only, requires the OpenTUI rendering stack that
|
|
185
|
+
ships with OpenCode (`@opentui/core`, `@opentui/solid`, `solid-js`). These are
|
|
186
|
+
declared as **optional** peer dependencies, so the main plugin installs and
|
|
187
|
+
runs fine without them (the sidebar simply is not available).
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Configuration
|
|
192
|
+
|
|
193
|
+
There are **no user-facing plugin options**. The plugin reads the merged
|
|
194
|
+
OpenCode configuration only to *harvest* each model's context limits and
|
|
195
|
+
explicit pricing (the `config` hook on the V1 path; the model registry on the
|
|
196
|
+
V2 path). It does not register configurable keys of its own.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## How it works
|
|
201
|
+
|
|
202
|
+
The package default export is a dual plugin:
|
|
203
|
+
|
|
204
|
+
* `setup(ctx)` — V2 entry (OpenCode ≥ 2.0.16). Registers a `session.hook("context", …)`
|
|
205
|
+
to capture the final messages / system prompt / tool schemas right before each
|
|
206
|
+
model request, subscribes to the event stream (`session.created`,
|
|
207
|
+
`session.step.ended`, `session.idle`, `session.compacted`, failure events) and
|
|
208
|
+
records limits from the model registry. Read-only: the context is never
|
|
209
|
+
mutated.
|
|
210
|
+
* `server({ client })` — V1 entry (OpenCode ≥ 1.18.29). Classic event handler +
|
|
211
|
+
experimental transform hooks + toasts.
|
|
212
|
+
|
|
213
|
+
Both paths write the same breakdown log; the V2 path additionally feeds the
|
|
214
|
+
sidebar through `opencode-context-indicator-state.json`. Cross-instance
|
|
215
|
+
duplicate final summaries are suppressed with an atomic claim marker
|
|
216
|
+
(`lib/dedup.js`). Every file / estimate / subagent path is fault-tolerant: a
|
|
217
|
+
failure is logged and never breaks the main event or toast path.
|
|
218
|
+
|
|
219
|
+
This plugin does not touch `opencode-token-monitor`
|
|
220
|
+
(`token_stats` / `token_history` / `token_export` keep working unchanged).
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## Screenshots
|
|
225
|
+
|
|
226
|
+
<!-- TODO: add screenshots -->
|
|
227
|
+
|
|
228
|
+
_(to be added)_
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Contributing
|
|
233
|
+
|
|
234
|
+
Issues and pull requests are welcome. Please keep changes minimal and
|
|
235
|
+
fault-tolerant: any code on the event / hook path must never throw into the
|
|
236
|
+
caller.
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## License
|
|
241
|
+
|
|
242
|
+
[MIT](./LICENSE)
|