op-reviewer is a tool that uses OpenCode to review the
latest pull-request commit and publish the result to GitHub. Executes in docker container, its not depending on any specific CI runner.
currently its meant for woodpecker CI
- Reads CI metadata and selects an OpenCode API key for the commit author.
- Clones
CI_REPO_URLinto./sourcewhen a checkout is not already present. - Checks out
CI_COMMIT_SHA. - Runs OpenCode in the checked-out repository and asks it to review the diff.
- Parses OpenCode's JSON response into a summary and optional inline comments.
- Publishes those review items with direct, argument-safe
gh apicalls.
The model never generates executable shell. Review text is validated as JSON and
passed to gh as arguments, so model prose cannot become a shell command.
The container includes the compiled reviewer binary, OpenCode, GitHub CLI, and Git. The repository being reviewed is fetched at runtime and is not included in the image.
Environment variables:
| Variable | Purpose |
|---|---|
CI_REPO_URL |
Repository URL used when cloning the review target. |
CI_COMMIT_SHA |
Commit to check out and review. |
CI_COMMIT_PULL_REQUEST |
Pull-request number used by GitHub API calls. |
CI_REPO |
GitHub repository in owner/name form. Optional when CI_REPO_URL is a GitHub URL. |
CI_COMMIT_AUTHOR |
Commit author's GitHub username, used to select an API key. |
OP_REVIEWER_MODEL |
OpenCode model identifier. |
OP_REVIEWER_GH_TOKEN |
GitHub token used to publish the review. |
Author-specific OpenCode keys use the form OP_REVIEWER_<author>. Underscores in
the suffix are treated as hyphens when matching GitHub usernames. For example:
CI_COMMIT_AUTHOR=antoni-ostrowski
OP_REVIEWER_antoni_ostrowski=<opencode-api-key>
review:
image: antost360/op-reviewer:latest
environment:
OP_REVIEWER_GH_TOKEN:
from_secret: OP_REVIEWER_GH_TOKEN
OP_REVIEWER_antoni_ostrowski:
from_secret: OP_REVIEWER_antoni_ostrowski
OP_REVIEWER_MODEL:
from_secret: OP_REVIEWER_MODEL
when:
- event: pull_request
Build the image:
docker build -t op-reviewer .Run it with CI variables and secrets:
docker run --rm --env-file .env.local op-reviewerThe image expects to start in /app; it creates the runtime checkout at
/app/source.
Install the Go version declared in mise.toml, then run:
mise run devBuild the binary locally:
mise run build