δΈζζζ‘£ | English
Multi-model AI code review for GitHub pull requests and GitLab merge requests.
mreviewer is built for a very simple first experience: install one binary, point it at a real PR, and get back something you can act on.
If you are trying it for the first time, start with the Personal CLI path. The goal is not to stand up infrastructure. The goal is to get one useful review in about five minutes.
mreviewer does not just dump model output. A first run gives you three layers:
- a short verdict such as
approvedorrequested_changes - a short
What To Fix Firstlist so you know where to start - inline comments on the exact changed lines when you publish back to GitHub
If your first run says requested_changes, that is not a setup failure. It means the tool found something concrete enough to block on.
The same review, broken out:
| CLI dry-run | GitHub brief |
|---|---|
![]() |
![]() |
| GitHub inline finding |
|---|
![]() |
What you are looking at:
- The CLI dry-run is the safest first step. It shows the verdict and the top findings before anything is posted back.
- The GitHub brief is the PR-level answer: should this merge as-is, or does it need work first?
- The inline comments are the useful part when you are actually fixing the PR. They point at the changed lines and explain why they matter.
- Personal CLI: one binary, local SQLite, no Docker. Best for your first run.
- Enterprise Webhook: automatic webhook review, history, queueing, and
/admin/.
Recommended:
curl -fsSL https://raw.githubusercontent.com/fakechris/mreviewer/main/scripts/install.sh | bashHomebrew is also supported:
brew tap fakechris/mreviewer https://github.com/fakechris/mreviewer
brew install mreviewerVerify the binary:
mreviewer versionmreviewer init --provider openaiThis writes config.yaml, creates .mreviewer/state/, and defaults to local SQLite. You do not need to hand-edit YAML to get started.
The generated OpenAI route defaults to output_mode: tool_call. json_schema is still available, but tool_call is the more robust default across OpenAI-compatible providers because the runtime already does local strict validation and one repair pass.
If you want to start with Zhipu GLM-5 instead of OpenAI:
mreviewer init --provider zhipuaiFor Zhipu GLM-5 / GLM-5.1, prefer tool_call routes. A live probe on 2026-04-10 showed intermittent 429/code=1305 congestion and non-schema responses under json_schema strict=true, so strict JSON-schema mode should not be treated as the primary production path on this endpoint (see the acceptance probe).
If you want to preview the generated config without writing files:
mreviewer init --provider openai --dry-runexport OPENAI_API_KEY=...
export GITHUB_TOKEN=...For Zhipu GLM-5, export ZHIPUAI_API_KEY instead of OPENAI_API_KEY:
export ZHIPUAI_API_KEY=...
export GITHUB_TOKEN=...GitLab is optional for the first run. Add it later if you want to review GitLab MRs too:
export GITLAB_BASE_URL=https://gitlab.example.com
export GITLAB_TOKEN=...mreviewer doctor --jsonThis validates config, database, model routing, and platform credentials up front.
If you want to verify a provider's structured-output contract before changing a route to output_mode: json_schema, run a live route probe first:
mreviewer structured-output-probe --config config.yaml --route <configured-route> --mode tool --runs 10
mreviewer structured-output-probe --config config.yaml --route <configured-route> --mode native --runs 5Treat json_schema as production-ready only after the provider-native route shows stable HTTP success, parse success, and local schema success under this probe.
The current reference matrix is tracked in docs/acceptance/2026-04-11-structured-output-probe-matrix.md.
mreviewer review \
--target https://github.com/acme/repo/pull/17 \
--dry-run \
--output both \
--reviewer-packs security,architecture,database \
-vvThis is the safest first experience. You see the verdict, the shortlist, and the exact packs that fired, but nothing is written back yet.
mreviewer review \
--target https://github.com/acme/repo/pull/17 \
--output both \
--reviewer-packs security,architecture,databaseBy default, this posts the review back to the PR. If you only want local artifacts, add --publish artifact-only.
What you get from a real run:
- a brief verdict you can scan in seconds
- a small list of the highest-priority findings
- inline comments for the changed lines that actually need work
- JSON output you can feed into scripts or other agents
mreviewer serveBy default this starts:
- local SQLite at
.mreviewer/state/mreviewer.db - GitLab webhook:
POST /webhook - GitHub webhook:
POST /github/webhook - local admin page:
/admin/
Use mreviewer serve --db file:/custom/path.db to override the local database path.
If you only want to validate the runtime plan:
mreviewer serve --dry-run -vvmreviewer init: generate a personal config templatemreviewer doctor: validate config, database, provider routes, and platform tokensmreviewer review: review one GitHub/GitLab targetmreviewer serve: run ingress + worker in one local process with embedded migrationsmreviewer help: show grouped top-level or subcommand helpmreviewer version: show the installed CLI version
Backward compatibility remains: mreviewer --target ... still works and maps to review.
# install
curl -fsSL https://raw.githubusercontent.com/fakechris/mreviewer/main/scripts/install.sh | bash
# generate config
mreviewer init --provider openai
# or use Zhipu GLM-5
mreviewer init --provider zhipuai
# Zhipu recommendation: keep output_mode=tool_call
# strict json_schema is not yet reliable on this endpoint
# validate setup
mreviewer doctor
# preview without side effects
mreviewer review --target <pr-or-mr-url> --dry-run -vv
# run for real
mreviewer review --target <pr-or-mr-url> --output both --publish artifact-onlyKey flags:
--target: GitHub PR or GitLab MR URL--targets: comma-separated GitHub/GitLab PR or MR URLs for multi-target review and aggregate comparison--output:markdown,json, orboth--dry-run/--dryrun: render the execution plan and output without publish or status side effects--verbose,-v,-vv,-vvv,-vvvv: increase trace detail--publish:full-review-comments,summary-only, orartifact-only--reviewer-packs: comma-separated reviewer packs--route: model or model-chain override--advisor-route: optional stronger second-opinion model or chain override--exit-mode:neverorrequested_changes; returns exit code3when the final verdict requests changes--compare-live: comma-separated reviewer IDs/kinds already present on the target PR/MR, for examplereviewer-a,reviewer-b--compare-artifacts: comma-separated JSON artifact paths to compare against the current review bundle
Related subcommand:
mreviewer structured-output-probe --route <configured-route> --mode tool --runs 10: live probe for route-level structured output behavior
JSON output includes:
review_briefjudge_verdictdecision_benchmarkcomparisonaggregate_comparisonadvisor_artifact
Markdown output starts with # Review Decision Brief and surfaces:
Final VerdictWhat To Fix FirstSpecialist SignalsReviewer Overlapwhen comparison is enabled
Runtime environment overrides:
REVIEW_PACKS: default reviewer packs for CLI/runtime processingREVIEW_MODEL_CHAIN: default review chain referenceREVIEW_ADVISOR_CHAIN: default stronger second-opinion chain referenceREVIEW_COMPARE_REVIEWERS: comma-separated external reviewer IDs to compare during runtime processing
Use the enterprise path when you need:
- automatic GitLab/GitHub webhook reviews
- MySQL-backed queueing and history
- separate
ingressandworkerservices - operator actions and dashboard visibility
cp .env.example .env
docker compose up -d --buildFor image-based deployment:
docker compose -f docker-compose.prod.yaml up -dFor custom routes or mounted config:
docker compose -f docker-compose.prod.yaml -f docker-compose.prod.config.yaml up -ddocker-compose.yaml is for local developer source builds. docker-compose.prod.yaml is for enterprise-style deployment. MySQL is the recommended enterprise default; SQLite remains fine for local single-machine usage.
- Go to GitLab project β Settings β Webhooks
- URL:
http://your-server:3100/webhook- For local-network testing, replace
your-serverwith your machine's LAN IP, for examplehttp://10.0.0.16:3100/webhook - Do not use
localhostunless GitLab and mreviewer are running on the same host
- For local-network testing, replace
- Secret: value from
GITLAB_WEBHOOK_SECRET - Trigger: check
Merge request events - Click
Add webhook
If GitLab rejects the hook with Invalid url given, ask a GitLab admin to enable Allow requests to the local network from web hooks and services, or use a public HTTPS tunnel instead of a LAN IP.
GitHub webhook path is POST /github/webhook and follows the same ingress/worker control plane.
π Detailed setup: WEBHOOK.md
Enterprise and local serve mode both expose /admin/.
Key API routes:
/admin/api/queue/admin/api/concurrency/admin/api/failures/admin/api/runs/admin/api/trends/admin/api/ownership/admin/api/identities
Set MREVIEWER_ADMIN_TOKEN or ADMIN_TOKEN to require Authorization: Bearer <token> on the admin routes.
Trigger a GitLab review without waiting for webhook delivery:
docker compose exec worker /app/manual-trigger \
--project-id 123 \
--mr-iid 456 \
--waitThe worker image also includes /app/mreviewer for direct CLI review.
GitLab β ingress (webhook) β MySQL/SQLite
β
worker β LLM Provider
β
GitLab (discussions)
- GitLab Webhook Setup - Three configuration methods (project/group/system)
- Docker Deployment - Build and deploy to production
- Enterprise Webhook Architecture - Queue semantics, concurrency model, and control-plane design
- Admin Dashboard Operations -
/admin/usage and bearer auth - Failure Playbook - How to triage provider, worker, and supersede failures
- Contributing Guide - How to contribute
- Configuration - Safe default runtime config
- Advanced Configuration Template - Multi-provider example with env expansion
See TODOS.md for current priorities.
MIT License - see LICENSE



