PRsona — an AI pull-request reviewer trained on YOUR review history. Local-first Electron app: backfill your GitHub comments, calibrate to your style, draft PR reviews in your voice. You approve every comment. Bring your own keys: Claude, GPT, Ollama.
JavaScript
1
0 commits
updated Sep 24, 2026
PRsona learns a specific person's review style from their own GitHub comment history and drafts pull-request comments in that voice — running locally, with your own API keys, posting nothing you haven't approved.
Features · How it works · Quick start · Contributing

CodeRabbit, Copilot, and friends review like nobody in particular — generic comments from a generic model, tuned to nobody's standards, with your code sent to someone else's cloud.
PRsona inverts the model: your review history is the training data.
| Hosted review bots | PRsona | |
|---|---|---|
| Style | Generic, one-size-fits-all | Learned from your past reviews |
| Data | Sent to the vendor | Stays on your machine |
| Model | Locked to their choice | Any: Claude, GPT, local Ollama, OpenAI-compatible |
| Posting | Auto-comments on PRs | Human approves every comment |
| Calibration | None | Filters by your per-category history |
| Cost | Per-seat SaaS | Free, MIT, bring your own keys |
flowchart LR
A["<b>Backfill</b><br/>your past GitHub<br/>review comments"] --> B["<b>Embed + categorize</b><br/>fixed vocabulary,<br/>vector search in SQLite"]
B --> C["<b>Calibrate</b><br/>your per-category<br/>comment rates"]
C --> D["<b>Review a PR</b><br/>analysis pass,<br/>then style pass"]
D --> E{"You: accept /<br/>edit / reject"}
E -->|corrections| F["<b>Consolidate</b><br/>profile + rubric<br/>update (you approve)"]
F -.->|better profile| D
Everything lives in one local SQLite file + one JSON profile file per reviewer under the app's userData directory. No server, no external database, no inbound network exposure — the app polls GitHub, GitHub never calls it.
| Dashboard | Setup |
|---|---|
![]() | ![]() |
| Review |
|---|
![]() |
fetch; engines requires >=22.0.0 —
.nvmrc pins 24)ollama pull qwen2.5-coder:32b, or similar).repo scope (public-repo
reads need no scope at all), or fine-grained: Contents +
Pull requests, read and write. The write permission is only needed
to post pending reviews.git clone <this repo>
cd PRsona
npm install
npm start
Hit an install error (node-gyp, rimraf, better-sqlite3)? See
Troubleshooting.
On first launch, go to the Setup tab:
alice).http://localhost:11434./v1/chat/completions route.you ≠ Your Name).Then use the Pull Requests tab to load open PRs and trigger a review — it's the screen the app opens on, with a live status strip (reviewer, corpus size, sessions, pending feedback, model) so you can tell at a glance whether backfill has actually run. The Review tab accepts/edits/rejects drafts, and the Profile tab inspects the learned rubric/style and runs consolidation once you've accumulated some feedback.
npm test # offline: pipeline suite + wiring audit
npm run dist -- --dir # unpacked app in build/mac-arm64/
npm run dist # platform installers (dmg/zip on macOS)
The build is unsigned without a Developer ID, so macOS Gatekeeper will warn on first launch — right-click the app → Open to bypass.
~/Library/Application Support/pr-review-agent/config.json on macOS);
comments, embeddings, sessions, and corrections live in a local SQLite
database in the same directory; profiles are plain JSON files under
profiles/.A claude.ai Pro/Max/Team subscription does not include programmatic API
access — this app talks to the Anthropic Console API, which is billed
separately per token. If cost matters more than model quality, a local
model via Ollama has no per-token cost at all, at the expense of needing
decent hardware and generally weaker instruction-following than frontier
models (the analysis/style prompts include a strictness knob that helps
compensate for this — see src/pipeline/prompts.js).
electron/ main process (window, IPC handlers) + preload bridge
src/db/ SQLite schema + query helpers (better-sqlite3)
src/llm/ provider abstraction: anthropic / openai / ollama / openai_compat
src/github/ GitHub REST client (backfill, PR diff, posting reviews)
src/pipeline/ analysis → calibrate → style → consolidate + prompts
src/profile/ reviewer profile JSON store + diffing for approval UI
src/config/ local settings store (electron-store)
renderer/ plain HTML/CSS/JS UI — no framework, no build step
test/ offline test suites (npm test)
docs/ screenshots + troubleshooting guide
src/pipeline/categorize.js labels each new comment from
the fixed vocabulary in src/pipeline/categories.js. The analysis pass
uses the same vocabulary, so calibration can join the two sides on
category name. It only ever selects rows where category IS NULL, so
re-running backfill never re-processes already-labeled comments, and a
batch the model answers with unparseable JSON is left NULL for the next
run instead of being stamped uncategorized. You can also hand-edit a
reviewer's profile JSON directly (<userData>/profiles/<reviewer>.json)
to seed it faster.createPendingReview deliberately
omits the event field, which is the only way to get a PENDING
(unsubmitted) review: sending event: "COMMENT" would submit it
immediately (and additionally requires a top-level body). Nothing is
posted or notified until a human opens the PR and submits the review from
the GitHub UI as a final check. Comments are authored by whichever account
owns your token, not by the reviewer being modeled, and each one needs a
file path plus a line present in the diff — GitHub 422s otherwise, so the
submit button filters those out first.PRs welcome — see CONTRIBUTING.md for the dev setup,
the three-layer IPC contract the wiring test enforces, and the PR
checklist. npm test must be green (it's fully offline).
MIT © 2026 saril
If PRsona saves you review time, give it a ⭐ — it helps others find it.
JavaScript
82.6%
CSS
11.4%
HTML
6.0%
PRsona — an AI pull-request reviewer trained on YOUR review history. Local-first Electron app: backfill your GitHub comments, calibrate to your style, draft PR reviews in your voice. You approve every comment. Bring your own keys: Claude, GPT, Ollama.
JavaScript
1
0 commits
updated Sep 24, 2026
PRsona learns a specific person's review style from their own GitHub comment history and drafts pull-request comments in that voice — running locally, with your own API keys, posting nothing you haven't approved.
Features · How it works · Quick start · Contributing

CodeRabbit, Copilot, and friends review like nobody in particular — generic comments from a generic model, tuned to nobody's standards, with your code sent to someone else's cloud.
PRsona inverts the model: your review history is the training data.
| Hosted review bots | PRsona | |
|---|---|---|
| Style | Generic, one-size-fits-all | Learned from your past reviews |
| Data | Sent to the vendor | Stays on your machine |
| Model | Locked to their choice | Any: Claude, GPT, local Ollama, OpenAI-compatible |
| Posting | Auto-comments on PRs | Human approves every comment |
| Calibration | None | Filters by your per-category history |
| Cost | Per-seat SaaS | Free, MIT, bring your own keys |
flowchart LR
A["<b>Backfill</b><br/>your past GitHub<br/>review comments"] --> B["<b>Embed + categorize</b><br/>fixed vocabulary,<br/>vector search in SQLite"]
B --> C["<b>Calibrate</b><br/>your per-category<br/>comment rates"]
C --> D["<b>Review a PR</b><br/>analysis pass,<br/>then style pass"]
D --> E{"You: accept /<br/>edit / reject"}
E -->|corrections| F["<b>Consolidate</b><br/>profile + rubric<br/>update (you approve)"]
F -.->|better profile| D
Everything lives in one local SQLite file + one JSON profile file per reviewer under the app's userData directory. No server, no external database, no inbound network exposure — the app polls GitHub, GitHub never calls it.
| Dashboard | Setup |
|---|---|
![]() | ![]() |
| Review |
|---|
![]() |
fetch; engines requires >=22.0.0 —
.nvmrc pins 24)ollama pull qwen2.5-coder:32b, or similar).repo scope (public-repo
reads need no scope at all), or fine-grained: Contents +
Pull requests, read and write. The write permission is only needed
to post pending reviews.git clone <this repo>
cd PRsona
npm install
npm start
Hit an install error (node-gyp, rimraf, better-sqlite3)? See
Troubleshooting.
On first launch, go to the Setup tab:
alice).http://localhost:11434./v1/chat/completions route.you ≠ Your Name).Then use the Pull Requests tab to load open PRs and trigger a review — it's the screen the app opens on, with a live status strip (reviewer, corpus size, sessions, pending feedback, model) so you can tell at a glance whether backfill has actually run. The Review tab accepts/edits/rejects drafts, and the Profile tab inspects the learned rubric/style and runs consolidation once you've accumulated some feedback.
npm test # offline: pipeline suite + wiring audit
npm run dist -- --dir # unpacked app in build/mac-arm64/
npm run dist # platform installers (dmg/zip on macOS)
The build is unsigned without a Developer ID, so macOS Gatekeeper will warn on first launch — right-click the app → Open to bypass.
~/Library/Application Support/pr-review-agent/config.json on macOS);
comments, embeddings, sessions, and corrections live in a local SQLite
database in the same directory; profiles are plain JSON files under
profiles/.A claude.ai Pro/Max/Team subscription does not include programmatic API
access — this app talks to the Anthropic Console API, which is billed
separately per token. If cost matters more than model quality, a local
model via Ollama has no per-token cost at all, at the expense of needing
decent hardware and generally weaker instruction-following than frontier
models (the analysis/style prompts include a strictness knob that helps
compensate for this — see src/pipeline/prompts.js).
electron/ main process (window, IPC handlers) + preload bridge
src/db/ SQLite schema + query helpers (better-sqlite3)
src/llm/ provider abstraction: anthropic / openai / ollama / openai_compat
src/github/ GitHub REST client (backfill, PR diff, posting reviews)
src/pipeline/ analysis → calibrate → style → consolidate + prompts
src/profile/ reviewer profile JSON store + diffing for approval UI
src/config/ local settings store (electron-store)
renderer/ plain HTML/CSS/JS UI — no framework, no build step
test/ offline test suites (npm test)
docs/ screenshots + troubleshooting guide
src/pipeline/categorize.js labels each new comment from
the fixed vocabulary in src/pipeline/categories.js. The analysis pass
uses the same vocabulary, so calibration can join the two sides on
category name. It only ever selects rows where category IS NULL, so
re-running backfill never re-processes already-labeled comments, and a
batch the model answers with unparseable JSON is left NULL for the next
run instead of being stamped uncategorized. You can also hand-edit a
reviewer's profile JSON directly (<userData>/profiles/<reviewer>.json)
to seed it faster.createPendingReview deliberately
omits the event field, which is the only way to get a PENDING
(unsubmitted) review: sending event: "COMMENT" would submit it
immediately (and additionally requires a top-level body). Nothing is
posted or notified until a human opens the PR and submits the review from
the GitHub UI as a final check. Comments are authored by whichever account
owns your token, not by the reviewer being modeled, and each one needs a
file path plus a line present in the diff — GitHub 422s otherwise, so the
submit button filters those out first.PRs welcome — see CONTRIBUTING.md for the dev setup,
the three-layer IPC contract the wiring test enforces, and the PR
checklist. npm test must be green (it's fully offline).
MIT © 2026 saril
If PRsona saves you review time, give it a ⭐ — it helps others find it.
JavaScript
82.6%
CSS
11.4%
HTML
6.0%