PeanutGallery 0.1.1
dotnet tool install --global PeanutGallery --version 0.1.1
dotnet new tool-manifest
dotnet tool install --local PeanutGallery --version 0.1.1
#tool dotnet:?package=PeanutGallery&version=0.1.1
nuke :add-package PeanutGallery --version 0.1.1
Peanut Gallery
A panel of opinionated code reviewers on your pull requests. Bring your own models.
Most review bots give you one reviewer with one opinion. Peanut Gallery convenes a panel — an architect, a bug-hunter, a contrarian who argues the change should not exist — each running on a model you choose, each posting a verdict that updates itself as you push.
Quickstart
Drop it into any repository's PR workflow:
# .github/workflows/review.yml
on:
pull_request:
types: [opened, reopened, synchronize, ready_for_review]
issue_comment:
types: [created] # so you can talk back to the panel — see below
permissions:
contents: read
pull-requests: write
jobs:
review:
# Comments land on issues as well as PRs, and the panel answers its own
# comments. Skip both rather than starting a job that has nothing to do.
if: >-
github.event_name != 'issue_comment' ||
(github.event.comment.user.type != 'Bot' && github.event.issue.pull_request)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: charles8051/peanut-gallery@959816696b48b1302cd1f7bbee27253f2587b3b0 # v0.1.0
with:
openrouter-api-key: ${{ secrets.OPENROUTER_API_KEY }}
That is the whole setup. With no config committed you get the default panel described below.
Pinned to a commit, with the release tag in a comment. This action runs with
pull-requests: writeand your model key, so a moving reference is a moving trust boundary — and a tag can be force-moved over a published release, which a commit cannot. That is what GitHub's hardening guidance recommends for third-party actions. Read the tag comment to see which version you are on; bump both together.
The default panel
Two reviewers always run: an architect and a bug-hunter. An orchestrator reads the diff when the PR opens and convenes up to two more aimed at what this particular change risks — then pins them for the life of the PR, so the panel does not churn between pushes.
They speak with one deduplicated comment rather than four, and they answer comments
addressed to @peanut-gallery with a single reconciliation call rather than a full
panel turn.
The two seeded reviewers run whether or not the orchestrator succeeds, so a planner failure leaves you with a review rather than an empty board.
Commit a peanut.json when you want to pin your own lenses.
Reviews are stateful
Each persona keeps its session — last SHA, running summary, open findings — inside its own PR comment. A new push sends only the delta, and the reviewer reports what changed and what got resolved rather than starting over.
A review runs on a push to the PR, and on a new PR comment — the latter needs the
issue_comment trigger in the quickstart above. A comment is how you talk back: explain
that a finding is intentional and the reviewer withdraws it. Editing an existing comment
does not trigger a review — types: [created] is deliberate, since fixing a typo in a
reply is not worth a full panel turn. Post a new comment instead.
What a comment costs is configurable via
conversation: a mentions gate so
only comments addressed to the panel count, and a mode of reconcile (one call decides
what comes off the board), panel (every persona takes a full turn), or off. The
bundled default uses reconcile with @peanut-gallery, so two humans talking in a PR
thread cost nothing.
Inputs
| Input | |
|---|---|
openrouter-api-key / fireworks-api-key |
convenience inputs for the two common providers |
provider-keys |
any other provider — one KEY=VALUE per line, exported before the review runs |
config |
repo-relative path to a config; omit for the default panel |
pr-number |
defaults to the triggering PR |
github-token |
defaults to the workflow token |
A config's provider block names only the environment variable its key lives in, never
the key itself. So any OpenAI-compatible provider works through provider-keys:
- uses: charles8051/peanut-gallery@959816696b48b1302cd1f7bbee27253f2587b3b0 # v0.1.0
with:
config: .github/peanut-gallery.json
provider-keys: |
NVIDIA_API_KEY=${{ secrets.NVIDIA_API_KEY }}
TOGETHER_API_KEY=${{ secrets.TOGETHER_API_KEY }}
Runner note: the action runs a prebuilt image from GHCR rather than building a Dockerfile per job, so
ubuntu-latestneeds no setup. Cross-repouses:also needs Settings → Actions → "Allow access from other repositories".
Documentation
docs/INDEX.md— the question → document map, and the place to startCONTRIBUTING.md— conventions, build and test, how to open a PRSECURITY.md— threat model and how to report a vulnerability privately
License
MIT. Copyright (c) 2026 Charles Lee.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
This package has no dependencies.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.1 | 33 | 8/30/2026 |
| 0.1.1-rc.1 | 33 | 8/29/2026 |
| 0.1.0 | 52 | 8/29/2026 |