opencode-reviewer 0.6.1 → 0.8.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/README.md +159 -32
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/dist/tui.js +3064 -990
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
# OpenCode
|
|
1
|
+
# OpenCode Reviewer
|
|
2
2
|
|
|
3
3
|
Reviews pending permissions in the OpenCode sidebar using a separate LLM. Covers
|
|
4
4
|
shell commands, file edits, MCP calls, custom tools, and external-directory access.
|
|
5
|
-
Supports streaming explanations,
|
|
6
|
-
|
|
5
|
+
Supports streaming explanations, saved report history, auto-approval, and Linux
|
|
6
|
+
desktop notifications with distinct sounds.
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+

|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Requires OpenCode 1.18.35 or newer on Linux.
|
|
11
|
+
|
|
12
|
+
## Install and config
|
|
11
13
|
|
|
12
14
|
Add this entry to `~/.config/opencode/tui.json` or `.opencode/tui.json`.
|
|
13
15
|
OpenCode installs the [npm package](https://www.npmjs.com/package/opencode-reviewer).
|
|
@@ -35,8 +37,18 @@ OpenCode installs the [npm package](https://www.npmjs.com/package/opencode-revie
|
|
|
35
37
|
"autoApproveDelaySeconds": 15,
|
|
36
38
|
"notify": true,
|
|
37
39
|
"notifySound": true,
|
|
40
|
+
"staleReminderSeconds": 60,
|
|
41
|
+
"notifications": {
|
|
42
|
+
"attention": { "banner": true, "sound": true },
|
|
43
|
+
"unsafe": { "banner": true, "sound": true },
|
|
44
|
+
"question": { "banner": true, "sound": true },
|
|
45
|
+
"approved": { "banner": true, "sound": true },
|
|
46
|
+
"error": { "banner": true, "sound": true },
|
|
47
|
+
"ended": { "banner": true, "sound": true }
|
|
48
|
+
},
|
|
38
49
|
"notificationSoundDirectory": "/absolute/path/to/notification-sounds",
|
|
39
50
|
"formatRetries": 1,
|
|
51
|
+
"maxOutputTokens": 2048,
|
|
40
52
|
"timeoutMs": 30000,
|
|
41
53
|
"maxFiles": 6,
|
|
42
54
|
"maxEvidenceBytes": 131072
|
|
@@ -47,7 +59,7 @@ OpenCode installs the [npm package](https://www.npmjs.com/package/opencode-revie
|
|
|
47
59
|
```
|
|
48
60
|
|
|
49
61
|
Only `baseURL` and `model` are required. Use any OpenAI-compatible Chat Completions
|
|
50
|
-
endpoint
|
|
62
|
+
endpoint: `/chat/completions` is appended to the base URL. Choose a model available
|
|
51
63
|
at that endpoint.
|
|
52
64
|
|
|
53
65
|
Replace `apiKey`, or remove it and set the variable named by `apiKeyEnv` before
|
|
@@ -59,7 +71,7 @@ The remaining values above are the defaults. Restart OpenCode after changing
|
|
|
59
71
|
configuration. Reviews run when OpenCode asks for permission, so set the relevant
|
|
60
72
|
rules to `ask` in `opencode.json`. Existing `allow` rules skip review.
|
|
61
73
|
|
|
62
|
-
## Options
|
|
74
|
+
## Options reference
|
|
63
75
|
|
|
64
76
|
| Option | Behavior |
|
|
65
77
|
| --- | --- |
|
|
@@ -69,38 +81,50 @@ rules to `ask` in `opencode.json`. Existing `allow` rules skip review.
|
|
|
69
81
|
| `reviewMcp` | Review identifiable MCP tool and resource permissions. |
|
|
70
82
|
| `reviewCustomTools` | Review permissions requested by registered custom tools. |
|
|
71
83
|
| `reviewExternalDirectories` | Review directory access independently of the other switches. Directory approval can resume the operation without another prompt. |
|
|
72
|
-
| `autoApprove` | Allow completed Safe reviews once after
|
|
84
|
+
| `autoApprove` | Allow completed Safe reviews once after their countdown, including behind report history. |
|
|
73
85
|
| `extraCareful` | Include the extra-careful prompt in auto-mode reviews. Defaults to `true`; set `false` to omit it. |
|
|
74
86
|
| `autoApproveDelaySeconds` | Countdown duration, 0–3600 seconds. |
|
|
75
87
|
| `notify` | Linux desktop notifications and sounds. Defaults to `true`; set `false` to disable both. |
|
|
76
88
|
| `notifySound` | Play notification sounds. Defaults to `true`; set `false` to keep banners silent. |
|
|
77
|
-
| `
|
|
89
|
+
| `staleReminderSeconds` | Repeat pending human-interaction notifications every 60 seconds by default. Nonnegative safe integer seconds; `0` disables reminders. Only the front-of-queue blocker per conversation repeats. |
|
|
90
|
+
| `notifications` | Per-type `banner` and `sound` booleans for `attention`, `unsafe`, `question`, `approved`, `error`, and `ended`. Omitted types and fields default to `true`. |
|
|
91
|
+
| `notificationSoundDirectory` | Absolute custom sound directory. Use any of the six notification type names as basenames with `.wav` or `.mp3`; WAV takes precedence. Missing or unusable files fall back to that type's bundled sound. |
|
|
78
92
|
| `formatRetries` | Additional attempts to correct malformed assessment JSON, 0–100. |
|
|
93
|
+
| `maxOutputTokens` | Provider output-token limit, sent as `max_tokens`. Defaults to 2,048; accepts positive safe integers within your provider/model's supported range. Retries keep the same limit. |
|
|
79
94
|
| `timeoutMs` | Total review deadline, 1–3,600,000 ms. |
|
|
80
95
|
| `maxFiles` | File limit per review, 1–1,000. |
|
|
81
96
|
| `maxEvidenceBytes` | Evidence limit, 1–16,777,216 bytes. Whole files or diffs may be omitted; oversized mandatory arguments fail review. |
|
|
82
97
|
| `instructions` | Absolute directory containing overrides for the [prompt templates](https://github.com/mightykatun/opencode-reviewer/tree/main/prompts). Missing templates use the built-ins. |
|
|
83
98
|
|
|
84
|
-
|
|
99
|
+
My LLMs insist on writing a bunch of useless text to my README, so I collapsed them here in case anyone wants to inflict themselves (or more likely their agent) the pain of reading it.
|
|
85
100
|
|
|
101
|
+
<details>
|
|
102
|
+
<summary>Usage</summary>
|
|
86
103
|
The sidebar shows Safe, Unsafe, or Analysis unavailable. Explanations support
|
|
87
104
|
Markdown and scrolling. If the sidebar is hidden, use OpenCode's Show sidebar
|
|
88
105
|
command.
|
|
89
106
|
|
|
90
107
|
With streaming enabled, Evaluating and its spinner disappear when a rating arrives.
|
|
91
|
-
The rating remains provisional until the full response is validated. A
|
|
108
|
+
The rating remains provisional until the full response is validated. A retry
|
|
92
109
|
clears the preview and restores the loading indicator. Auto-approval
|
|
93
110
|
starts only after the full response is validated and rendered.
|
|
94
111
|
|
|
95
|
-
Transient connection failures
|
|
96
|
-
two internal retries within `timeoutMs`, honoring
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
112
|
+
Transient connection failures, HTTP 408/429/500/502/503/504 responses, and rejected
|
|
113
|
+
assessment streams share up to two internal retries within `timeoutMs`, honoring
|
|
114
|
+
server cooldowns. Stream protocol failures and output-token truncation regenerate
|
|
115
|
+
the report from a fresh, identical request; previous previews are cleared and never
|
|
116
|
+
joined to the next response. Socket failures after text starts, provider error/refusal
|
|
117
|
+
events, tool calls, invalid JSON/UTF-8, incomplete SSE framing and resource-limit
|
|
118
|
+
failures remain terminal. This recovery is separate from `formatRetries`.
|
|
119
|
+
If token-limit errors persist, increase `maxOutputTokens` within your model's limits.
|
|
120
|
+
Providers enforce this limit and may include reasoning tokens; the plugin's byte
|
|
121
|
+
limits and overall timeout still apply. Retried requests can incur additional
|
|
122
|
+
provider charges, and unreported usage remains unknown.
|
|
100
123
|
|
|
101
124
|
During an auto-approval countdown, click the countdown to allow once immediately,
|
|
102
125
|
or Cancel to leave the request manual. Hiding or covering the panel also cancels
|
|
103
|
-
that request's countdown
|
|
126
|
+
that request's countdown, except when covered by this plugin's report history.
|
|
127
|
+
Cancel before using native Allow always or rejection
|
|
104
128
|
forms; those forms alone do not stop the countdown.
|
|
105
129
|
Positive countdowns hold their configured starting number for one extra second
|
|
106
130
|
before counting down. A zero-second setting still approves without that hold.
|
|
@@ -110,35 +134,103 @@ descendants. The setting is saved for resume. Both commands are also in the comm
|
|
|
110
134
|
palette. Disabling stops current reviews and countdowns while native permission
|
|
111
135
|
controls remain available.
|
|
112
136
|
|
|
137
|
+
### Report history
|
|
138
|
+
|
|
139
|
+
Use `/reviewer-history` or **Reviewer: Report history** in the command palette to
|
|
140
|
+
open the newest saved report for the current conversation and its descendants.
|
|
141
|
+
Left/Right or the arrow buttons select older/newer entries; Up/Down and
|
|
142
|
+
PageUp/PageDown scroll. Close or Escape closes history. Repeating the command
|
|
143
|
+
returns to the newest report. History remains available with review disabled or
|
|
144
|
+
invalid reviewer configuration, and does not force a hidden sidebar open.
|
|
145
|
+
|
|
146
|
+
Each entry shows the original report, available usage, model, provider and outcome:
|
|
147
|
+
**Auto approved**, **Manually approved**, **Cancelled**, or **Rejected**. Cancelled
|
|
148
|
+
records a linked interruption or removed request after automation was cancelled;
|
|
149
|
+
it does not prove that the tool never ran. Ambiguous outcomes are omitted, including
|
|
150
|
+
native Allow once replies whose submitting client cannot be identified. History
|
|
151
|
+
keeps the latest completed report, which can differ from the report that caused
|
|
152
|
+
approval in another window.
|
|
153
|
+
|
|
154
|
+
History can cover an ongoing review without stopping its countdown. A newly
|
|
155
|
+
completed Safe review can also start its countdown beneath history after its full
|
|
156
|
+
report is rendered. Native dialogs, including the command palette, still cancel an
|
|
157
|
+
active countdown; opening history afterward cannot restart it. Browsing saved
|
|
158
|
+
reports never approves a request or replays notifications.
|
|
159
|
+
|
|
160
|
+
Reports are saved only after a qualifying permission resolution. Saved reports
|
|
161
|
+
can contain private text and are retained in OpenCode's local state directory
|
|
162
|
+
until their conversation is deleted. Deleting a root removes its descendants'
|
|
163
|
+
details; deletion missed while OpenCode was closed is reconciled when that host
|
|
164
|
+
scope is visited again. Windows using the same state directory share this history,
|
|
165
|
+
partitioned by host directory and root conversation. Uncommitted reports can be
|
|
166
|
+
lost on shutdown or prolonged storage failure.
|
|
167
|
+
|
|
168
|
+
### Usage totals
|
|
169
|
+
|
|
113
170
|
Token and cost totals appear below completed reports when available. Open
|
|
114
|
-
Reviewer:
|
|
171
|
+
**Reviewer: Statistics** in the command palette for **Lifetime** and **Conversation**
|
|
172
|
+
views. Use Tab or click a scope to switch. The dialog opens on Lifetime;
|
|
173
|
+
Conversation uses the session selected when opened, resolving its root and all
|
|
174
|
+
descendants, including subagents, within the current host-directory scope.
|
|
175
|
+
Opening from a descendant shows the same combined conversation totals.
|
|
176
|
+
OpenRouter
|
|
115
177
|
costs use reported charges; other endpoints use available catalog estimates.
|
|
116
178
|
Received usage counts even if a review fails or is interrupted. Unreported charges
|
|
117
179
|
are missing from the totals.
|
|
118
180
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
review,
|
|
123
|
-
|
|
181
|
+
Both views show completed reviews, retries, tokens, cost, Safe/Unsafe
|
|
182
|
+
percentages, confirmed auto-approvals, and average time to a rating and full report.
|
|
183
|
+
Percentages use recorded completed reviews as their denominator. Each validated
|
|
184
|
+
review counts once, even without usage data; a fresh review after re-enabling counts
|
|
185
|
+
again. Retries count extra API attempts actually dispatched, including format
|
|
186
|
+
corrections and transport recovery. Manual approvals are not auto-approvals.
|
|
187
|
+
Timings run from evaluation start, including evidence and retries, to the accepted
|
|
188
|
+
attempt's first rating and final validated response, excluding rendering/countdown
|
|
189
|
+
time. Non-streaming reviews use the final response time for both measurements.
|
|
190
|
+
Averages use running means and sample counts; stored review details also retain
|
|
191
|
+
their individual timings. Both scopes persist in the existing history database
|
|
192
|
+
across restart/resume. Conversation totals keep independent roots separate;
|
|
193
|
+
Lifetime combines activity across conversations and host directories using the
|
|
194
|
+
same state directory. Browsing and switching views do not add usage.
|
|
195
|
+
|
|
196
|
+
Older retained history can provide a **partial** conversation baseline. Previously
|
|
197
|
+
deleted details and usage predating history tracking cannot be attributed or
|
|
198
|
+
reconstructed from legacy lifetime aggregates. This limitation is labeled in the
|
|
199
|
+
dialog. Once recorded in conversation totals, deleting report details does not
|
|
200
|
+
reduce those totals or Lifetime. Storage failures show unavailable, not zero.
|
|
201
|
+
|
|
202
|
+
Tokens describe received provider usage, not just the visible explanation. One
|
|
203
|
+
report may sum several reviewer POSTs, including format corrections and transport
|
|
204
|
+
retries with received usage. Each POST can resend the prompt and evidence;
|
|
205
|
+
corrections also include the failed response and feedback. Cached input remains
|
|
206
|
+
part of the provider's input-token count. Lifetime and Conversation also retain
|
|
207
|
+
received usage from unsuccessful or interrupted reviews, which do not count as
|
|
208
|
+
completed reviews. Averages include measured reviews only.
|
|
124
209
|
|
|
125
210
|
Reviews send the pending request, latest user prompt, project context, and relevant
|
|
126
211
|
file snapshots, diffs, or tool arguments to your endpoint before approval. Shell
|
|
127
212
|
file snapshots can follow symlinks outside the project. Missing evidence is noted
|
|
128
213
|
in the report; ratings are advice based on the supplied evidence.
|
|
214
|
+
</details>
|
|
129
215
|
|
|
130
|
-
|
|
131
|
-
|
|
216
|
+
<details>
|
|
217
|
+
<summary>Desktop notifications</summary>
|
|
132
218
|
Transient banners have an **Opencode (Session name)** heading and a small status icon: green
|
|
133
|
-
checkmark for approvals, orange exclamation mark for attention, red
|
|
219
|
+
checkmark for approvals, orange exclamation mark for attention, red exclamation mark
|
|
220
|
+
for Unsafe reviews, purple question mark for questions, red X
|
|
134
221
|
for errors, and a neutral code mark for completed responses. GNOME controls the
|
|
135
222
|
heading's font weight. The event message appears beneath it, even while the
|
|
136
223
|
terminal is focused:
|
|
137
224
|
|
|
138
|
-
- **Session needs attention:**
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
225
|
+
- **Session needs attention:** manual permissions. Reviewed requests
|
|
226
|
+
stay silent during identification, report generation and retries. Final Safe
|
|
227
|
+
reports notify when auto-approval is disabled or canceled, or after failed approval
|
|
228
|
+
is confirmed to remain pending. Waiting for rendering, queue position or an
|
|
229
|
+
automatic countdown to start does not trigger attention. Disabled/unsupported
|
|
230
|
+
reviews and terminal analysis failures can notify without a report.
|
|
231
|
+
- **Unsafe permission needs human approval:** a completed, validated Unsafe review,
|
|
232
|
+
with its own sound. Provisional streamed ratings never notify.
|
|
233
|
+
- **Agent has a question:** a pending agent question, with its own sound.
|
|
142
234
|
- **Reviewer approved a permission:** sent with the approval sound after confirmed
|
|
143
235
|
automatic approval, for both positive and zero delays. The countdown is silent.
|
|
144
236
|
Approval sounds are limited to
|
|
@@ -147,8 +239,42 @@ terminal is focused:
|
|
|
147
239
|
- **Session ended:** a completed root-agent response, not a question/permission
|
|
148
240
|
pause or an explicit user interruption.
|
|
149
241
|
|
|
242
|
+
Permission attention and Unsafe notifications, including their reminders, apply
|
|
243
|
+
only to the current native permission blocker in each visited root conversation.
|
|
244
|
+
Requests queued behind it stay silent and are re-evaluated from their current
|
|
245
|
+
review/approval state when they become actionable. A sequence that proceeds
|
|
246
|
+
through automatic approval stays free of attention notifications. Losing the
|
|
247
|
+
actionable position, restarting analysis or entering automatic approval cancels
|
|
248
|
+
pending attention delivery and reminders.
|
|
249
|
+
|
|
250
|
+
Each type's `banner` and `sound` can be controlled independently. For example,
|
|
251
|
+
`notifications.approved.banner: false` keeps approval sounds without banners;
|
|
252
|
+
`notifications.question.sound: false` keeps question banners silent. Set both to
|
|
253
|
+
`false` to disable that type. `notify: false` overrides all types and disables
|
|
254
|
+
reminders too; `notifySound: false` silences all types and their reminders.
|
|
255
|
+
Sound-only delivery does not require a desktop banner or delivery acknowledgement.
|
|
256
|
+
Invalid notification settings disable notification work without disabling reviews.
|
|
257
|
+
|
|
258
|
+
Pending permissions and questions repeat after `staleReminderSeconds`, measured
|
|
259
|
+
from initial dispatch, even if desktop delivery fails. Reminders replace their
|
|
260
|
+
previous banner and append **(Reminder)** to the event text, reusing the same
|
|
261
|
+
sound, icon, session heading and click target. Only the native front-of-queue
|
|
262
|
+
interaction per root conversation repeats: permissions precede questions, with
|
|
263
|
+
the host's session/request ordering. Queued interactions wait; when the blocker
|
|
264
|
+
changes, its replacement waits a full interval. Independent visited conversations
|
|
265
|
+
can each remind. The supported host presents input for roots and direct children;
|
|
266
|
+
deeper descendants cannot become a native root-input permission notification or
|
|
267
|
+
reminder target. Their questions can still receive initial question notifications.
|
|
268
|
+
|
|
269
|
+
Answering/dismissing a question in OpenCode, resolving a permission, deleting its
|
|
270
|
+
session or closing the plugin stops its reminders. Closing/clicking a desktop
|
|
271
|
+
banner, activating the terminal or viewing a conversation does not. Countdown
|
|
272
|
+
and approval submission remain silent. Approval, error and completed-response
|
|
273
|
+
notifications never repeat. Setting `staleReminderSeconds: 0` disables all reminders.
|
|
274
|
+
|
|
150
275
|
Notifications cover conversations visited in this terminal and their descendants.
|
|
151
|
-
Existing pending requests at startup/resume are not replayed
|
|
276
|
+
Existing pending requests at startup/resume are not replayed or reminded, but still
|
|
277
|
+
participate in queue ordering. Clicking can select
|
|
152
278
|
the originating GNOME Terminal tab and root conversation. Native input prompts
|
|
153
279
|
cover root/direct-child requests in the supported host. Open dialogs are
|
|
154
280
|
left intact; other terminals still receive banners and sounds. Desktop policies
|
|
@@ -159,7 +285,7 @@ the banner heading remains Opencode.
|
|
|
159
285
|
|
|
160
286
|
Linux delivery uses `notify-send`, `stdbuf`, and `gdbus`; audio uses `paplay` or `pw-play`.
|
|
161
287
|
On Ubuntu, `libnotify-bin`, `coreutils`, `libglib2.0-bin`, and `pulseaudio-utils` provide these
|
|
162
|
-
utilities. The MP3 decoder and
|
|
288
|
+
utilities. The MP3 decoder and six default sounds are bundled; FFmpeg is not
|
|
163
289
|
required. MP3 and mono/stereo PCM/float WAV files up to 4 MiB and 10 seconds are
|
|
164
290
|
normalized toward -20 dBFS RMS with a -3 dBFS peak ceiling before playback.
|
|
165
291
|
Custom sounds are loaded on first use; restart after replacing them.
|
|
@@ -168,6 +294,7 @@ with a low-latency buffer; preparation never blocks permission approval.
|
|
|
168
294
|
`stdbuf` makes delivery acknowledgements immediate instead of waiting for
|
|
169
295
|
`notify-send` to flush its output when the banner closes.
|
|
170
296
|
Disable overlapping notification plugins to avoid duplicate alerts.
|
|
297
|
+
</details>
|
|
171
298
|
|
|
172
299
|
## Development
|
|
173
300
|
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -29,7 +29,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
29
29
|
|
|
30
30
|
# Bundled audio decoder and supplied sounds
|
|
31
31
|
|
|
32
|
-
The
|
|
32
|
+
The six notification MP3 files were supplied by the maintainer with
|
|
33
33
|
permission to redistribute them with this plugin. Their original bytes are
|
|
34
34
|
embedded in the bundle. Normalization occurs during playback preparation.
|
|
35
35
|
|