Skip to content

About

Safety reviews and optional one-time auto-approval for OpenCode shell and edit permissions

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

OpenCode Reviewer

Reviews pending permissions in the OpenCode sidebar using a separate LLM. Covers shell commands, file edits, MCP calls, custom tools, and external-directory access. Supports streaming explanations, auto-approval, and Linux desktop notifications with distinct sounds.

Requires OpenCode 1.18.35 or newer on Linux.

Install and config

Add this entry to ~/.config/opencode/tui.json or .opencode/tui.json. OpenCode installs the npm package.

{
  "$schema": "https://opencode.ai/tui.json",
  "plugin": [
    [
      "opencode-reviewer@latest",
      {
        "baseURL": "https://openrouter.ai/api/v1",
        "model": "your-model",
        "apiKey": "your-api-key",
        "apiKeyEnv": "OPENCODE_REVIEWER_API_KEY",
        "instructions": "/absolute/path/to/reviewer-prompts",
        "stream": false,
        "reviewBash": true,
        "reviewEdits": true,
        "reviewMcp": false,
        "reviewCustomTools": false,
        "reviewExternalDirectories": false,
        "autoApprove": false,
        "extraCareful": true,
        "autoApproveDelaySeconds": 15,
        "notify": true,
        "notifySound": true,
        "notificationSoundDirectory": "/absolute/path/to/notification-sounds",
        "formatRetries": 1,
        "timeoutMs": 30000,
        "maxFiles": 6,
        "maxEvidenceBytes": 131072
      }
    ]
  ]
}

Only baseURL and model are required. Use any OpenAI-compatible Chat Completions endpoint: /chat/completions is appended to the base URL. Choose a model available at that endpoint.

Replace apiKey, or remove it and set the variable named by apiKeyEnv before launching OpenCode. The inline key takes precedence. Omit both for an unauthenticated endpoint. Remove instructions to use the built-in prompts and notificationSoundDirectory to use the bundled sounds.

The remaining values above are the defaults. Restart OpenCode after changing configuration. Reviews run when OpenCode asks for permission, so set the relevant rules to ask in opencode.json. Existing allow rules skip review.

Options reference

Option Behavior
stream Show the rating and explanation as they arrive. Requires SSE support from the endpoint.
reviewBash Review native shell commands.
reviewEdits Review native edit, write, and apply-patch requests.
reviewMcp Review identifiable MCP tool and resource permissions.
reviewCustomTools Review permissions requested by registered custom tools.
reviewExternalDirectories Review directory access independently of the other switches. Directory approval can resume the operation without another prompt.
autoApprove Allow completed Safe reviews once after the visible countdown.
extraCareful Include the extra-careful prompt in auto-mode reviews. Defaults to true; set false to omit it.
autoApproveDelaySeconds Countdown duration, 0–3600 seconds.
notify Linux desktop notifications and sounds. Defaults to true; set false to disable both.
notifySound Play notification sounds. Defaults to true; set false to keep banners silent.
notificationSoundDirectory Absolute custom sound directory. Use attention, approved, error, and ended basenames with .wav or .mp3; WAV takes precedence. Missing or unusable files fall back to bundled sounds.
formatRetries Additional attempts to correct malformed assessment JSON, 0–100.
timeoutMs Total review deadline, 1–3,600,000 ms.
maxFiles File limit per review, 1–1,000.
maxEvidenceBytes Evidence limit, 1–16,777,216 bytes. Whole files or diffs may be omitted; oversized mandatory arguments fail review.
instructions Absolute directory containing overrides for the prompt templates. Missing templates use the built-ins.

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.

Usage The sidebar shows Safe, Unsafe, or Analysis unavailable. Explanations support Markdown and scrolling. If the sidebar is hidden, use OpenCode's Show sidebar command.

With streaming enabled, Evaluating and its spinner disappear when a rating arrives. The rating remains provisional until the full response is validated. A format retry clears the preview and restores the loading indicator. Auto-approval starts only after the full response is validated and rendered.

Transient connection failures and HTTP 408/429/500/502/503/504 responses get up to two internal retries within timeoutMs, honoring server cooldowns. A stream that has already delivered assessment text is not restarted. This is separate from formatRetries; no additional setting is needed. Retried requests can incur additional provider charges, and unreported usage remains unknown.

During an auto-approval countdown, click the countdown to allow once immediately, or Cancel to leave the request manual. Hiding or covering the panel also cancels that request's countdown. Cancel before using native Allow always or rejection forms; those forms alone do not stop the countdown. Positive countdowns hold their configured starting number for one extra second before counting down. A zero-second setting still approves without that hold.

/reviewer-disable and /reviewer-enable control the current conversation and its descendants. The setting is saved for resume. Both commands are also in the command palette. Disabling stops current reviews and countdowns while native permission controls remain available.

Token and cost totals appear below completed reports when available. Open Reviewer: Lifetime usage in the command palette for cumulative totals. OpenRouter costs use reported charges; other endpoints use available catalog estimates. Received usage counts even if a review fails or is interrupted. Unreported charges are missing from the totals.

The lifetime dialog shows completed reviews, retries, tokens, cost, Safe/Unsafe percentages, confirmed auto-approvals, and average time to a rating and full report. Percentages use recorded completed reviews as their denominator. Each validated review counts once, even without usage data; a fresh review after re-enabling counts again. Retries count extra API attempts actually dispatched, including format corrections and transport recovery. Manual approvals are not auto-approvals. Timings run from evaluation start, including evidence and retries, to the accepted attempt's first rating and final validated response, excluding rendering/countdown time. Non-streaming reviews use the final response time for both measurements. Only running averages and sample counts are stored, not individual timings. Totals persist across restarts. New metrics show partial history when older records lack them; averages include measured reviews only. Earlier unrecorded values cannot be reconstructed.

Reviews send the pending request, latest user prompt, project context, and relevant file snapshots, diffs, or tool arguments to your endpoint before approval. Shell file snapshots can follow symlinks outside the project. Missing evidence is noted in the report; ratings are advice based on the supplied evidence.

Desktop notifications Transient banners have an **Opencode (Session name)** heading and a small status icon: green checkmark for approvals, orange exclamation mark for attention, red X for errors, and a neutral code mark for completed responses. GNOME controls the heading's font weight. The event message appears beneath it, even while the terminal is focused:
  • Session needs attention: questions and manual permissions. Reviewed requests wait for a final validated assessment; failures, canceled automation, and a Safe review blocked from starting its countdown also notify. Unreviewed requests notify immediately, including when conversation review is disabled.
  • Reviewer approved a permission: sent with the approval sound after confirmed automatic approval, for both positive and zero delays. The countdown is silent. Approval sounds are limited to one every two seconds; every eligible banner is retained for delivery.
  • Session error: an unrecovered session/provider failure, not a review failure.
  • Session ended: a completed root-agent response, not a question/permission pause or an explicit user interruption.

Notifications cover conversations visited in this terminal and their descendants. Existing pending requests at startup/resume are not replayed. Clicking can select the originating GNOME Terminal tab and root conversation. Native input prompts cover root/direct-child requests in the supported host. Open dialogs are left intact; other terminals still receive banners and sounds. Desktop policies control expiry/history and whether activation actually brings a window forward. GNOME Terminal clicks use the desktop activation token to bring the correct tab forward across workspaces. GNOME may attribute the notification source to Terminal; the banner heading remains Opencode.

Linux delivery uses notify-send, stdbuf, and gdbus; audio uses paplay or pw-play. On Ubuntu, libnotify-bin, coreutils, libglib2.0-bin, and pulseaudio-utils provide these utilities. The MP3 decoder and four default sounds are bundled; FFmpeg is not required. MP3 and mono/stereo PCM/float WAV files up to 4 MiB and 10 seconds are normalized toward -20 dBFS RMS with a -3 dBFS peak ceiling before playback. Custom sounds are loaded on first use; restart after replacing them. Audio is prepared before showing its banner and played from the normalized cache with a low-latency buffer; preparation never blocks permission approval. stdbuf makes delivery acknowledgements immediate instead of waiting for notify-send to flush its output when the banner closes. Disable overlapping notification plugins to avoid duplicate alerts.

Development

Use Node.js 24.15.0+ within 24.x, or 22.22.2+ within 22.x, and npm. Run npm ci --ignore-scripts, then npm run check for typechecking, source tests, pure-helper tests and the build. npm run test:helpers runs the helper checks without building or starting OpenCode. Pull-request CI checks both Node versions. See AGENTS.md for runtime tests and the tag-driven release process.

About

Safety reviews and optional one-time auto-approval for OpenCode shell and edit permissions

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Contributors

Languages