Skip to main content

Roboviewer

Automated code review for merge requests, running entirely on your machine.

Point it at two branches and it comes back with a ranked list of problems worth fixing — not a wall of style nitpicks.

roboviewer develop
▸ muse-glimmer-30b @ api.fireworks.ai
▸ nmc/albums_customisation → master: 32 files, 3 checklist items
▸ Started: Runtime behaviour
▸ Started: Contracts and structure
▸ Started: Risks and coverage
• Contracts and structure: 0 findings (ok) · 404015 tokens · 21s
• Risks and coverage: 0 findings (ok) · 56984 tokens · 26s
• Runtime behaviour: 5 findings (ok) · 57932 tokens · 39s
▸ After merge and deduplication: 5 findings
▸ Stage 1 of 2: checking 5 findings, one pass each
▸ Stage 2 of 2: ruling on 5 verified findings
▸ Confirmed 5 of 5

  F001  [Blocker] iOSClient/Albums/AlbumsViewController.swift:14 — @Environment used in a UIKit UIViewController
  F002  [Major] .../Details/AlbumDetailsViewModel.swift:128 — UI state mutated from a background callback in loadAlbumPhotos
  F004  [Major] .../Details/AlbumDetailsViewModel.swift:292 — isLoadingPopupVisible toggled per iteration in onPhotosSelected
  F003  [Minor] .../Details/PhotosGridView.swift:69 — Database write performed inside view code when building viewer metadata
  F005  [Minor] iOSClient/Albums/Domain/Models/Album.swift:55 — Fallback dates set to now when dateRange decoding fails

Confirmed 5 of 5 · 1927677 tokens · 99% from cache
Report: .roboviewer/runs/20260820-202715/report.md

A real run, not an illustration: muse-glimmer-30b over nextcloud/ios#4091. Four of those five findings are verified against the code, the fifth is unadjudicated — see Measurements.

Findings come back in English. --language ru asks the model for another one without touching the prompts — see Output language.

The problem

Review arrives late, and tired. A merge request waits hours or days, and by the time someone opens it they are on their fourth review of the afternoon. The blocker ships under three comments about whitespace.

Hosted reviewers want your code. CodeRabbit, Copilot and the rest do good work, but every one of them means uploading the repository to somebody else's infrastructure. Inside a corporate network that is where the conversation ends.

They also want your forge. They plug into GitHub or GitLab and review what is already a merge request. Looking over your own branch before you open it, or reviewing a mirror that lives nowhere but your laptop, is not something they do.

Pasting a diff into a chat window invents problems. Given a few lines of context, a model will confidently report a missing nil check that sits twenty lines above the hunk. Nothing is ranked, nothing is verified, and a real blocker arrives in the same flat list as a naming preference.

What you get

Your code stays where it is. Roboviewer talks to any OpenAI-compatible endpoint — including a corporate gateway — so reviews never leave the network you already trust. Nothing is uploaded anywhere else, and there is no service to sign up for.

Any git repository, no integration. It reads two branches through plain git. No app to install on your organisation, no webhooks, no permissions to request.

Review before you open the MR. Run it on your own branch, fix what it finds, and let the humans spend their attention on design instead of on the bug you would have caught yourself.

The change is the scope, not the file. It reports what the diff introduces and what the diff breaks, and it draws that line by consequence rather than by authorship. If the changed code now calls into something that was already broken, that call is a finding: the branch is what ships, and the code having been wrong before this MR does not make it work now. Long-standing problems the change does not touch stay out.

A ranked list you can act on. Findings carry a severity, a file and a line, and a final judge pass throws out the ones that do not survive a second look — between 6% and 54% of them, depending on how noisy the model is. What survives is not guaranteed right: see Measurements for the rate that has been verified against code.

Where it stands

Measured on nextcloud/ios#4091 — an Albums feature, 32 files and 3903 lines once the resource files are excluded — against 31 defects established by hand. This is a starting line, published so it can be argued with and moved; the full table, every setting and the caveats are in Measurements.

Recall. How many of the 31 known defects a configuration surfaced across its runs. One block is one defect.

                                  ┌───────────────────────────────┐ 31
nemotron-lightning-30b · 8 items  │██                             │  2   6%
muse-glimmer-30b · 3 items        │████████████                   │ 12  39%
muse-glimmer-30b · 8 items        │███████████████                │ 15  48%
claude-opus-5 · 1 item            │██████████████████████         │ 22  71%
                                  └───────────────────────────────┘

False positives. Of everything a configuration shipped, how much was verified wrong against the code. Solid is proven false; light is not yet adjudicated, so the real rate sits inside the bar.

                                  0%        10%       20%       30%
                                  ├─────────┼─────────┼─────────┤
nemotron-lightning-30b · 8 items  │██░░░░░░                     │   4%…15%
muse-glimmer-30b · 3 items        │██████░░░░                   │  12%…20%
muse-glimmer-30b · 8 items        │████░░░░░░░░░░░              │   8%…30%
claude-opus-5 · 1 item            │█░░░░░░░░░░                  │   2%…21%

A low rate can still be a bad report. Of the 48 findings the nemotron configuration shipped, 36 are one "this file has no tests" entry per file — formally correct, and one thought repeated thirty-six times. Counting findings rewards that; counting distinct defects does not, which is why the recall chart above is drawn per defect rather than per finding.

Three things this does not say. It is one merge request, so n = 1 at the repository level. Fifteen of the 31 defects entered the truth set by verifying one model's output, so that model is being graded partly on ground it defined — origin in benchmarks/references/ios-4091.toml marks which entries are independent. And Opus ran without the judge, as a ceiling to aim at rather than a configuration of this tool.

Requirements

  • Python 3.11+
  • git
  • An OpenAI-compatible endpoint with tool calling — the agents drive the review through tools, so a completions-only gateway will not work. roboviewer --check-provider tells you which side of that line yours is on.

Install

git clone git@github.com:axazeano/Roboviewer.git && cd Roboviewer
python3 -m venv .venv && .venv/bin/pip install -e .
ln -sf "$PWD/.venv/bin/roboviewer" ~/.local/bin/roboviewer

Docker

The image carries the tool and git. The repository under review, the config and the reports stay on your side, as mounts.

docker run --rm \
  -v "$PWD:/repo" \
  -v ~/.config/roboviewer/provider.toml:/provider.toml:ro \
  -v ~/.config/roboviewer/config.toml:/config.toml:ro \
  -v "$PWD/.roboviewer:/out" \
  -e ROBOVIEWER_API_KEY -e ROBOVIEWER_PROVIDER_CONFIG=/provider.toml \
  axazeano/roboviewer:latest develop --config /config.toml --output /out

Mount the repository with its history — a shallow clone has no merge base to diff against. The image runs as an unprivileged user; on Linux add --user "$(id -u):$(id -g)" so the reports it writes belong to you.

latest is what you want at a keyboard. A pipeline should name a release — axazeano/roboviewer:0.1.2 — so that a rerun of an old commit reviews it with the version it was reviewed with.

Configure

mkdir -p ~/.config/roboviewer
cp provider.example.toml ~/.config/roboviewer/provider.toml
cp config.example.toml   ~/.config/roboviewer/config.toml
export ROBOVIEWER_API_KEY=...
roboviewer --check-provider

Set provider.base_url and reviewer.model. Everything else has working defaults and is documented inline in provider.example.toml and config.example.toml.

The provider lives in its own file so the settings file stays safe to copy: a --config file carrying a [provider] section is refused. --check-provider makes a handful of targeted requests and names what is wrong — wrong auth scheme, a base_url missing /v1, a gateway that cannot do tool calling — instead of leaving you to infer it from eight agents failing at once.

The sections, the rule that --config replaces rather than layers, and what to do about rate limits: Configuration.

Use

roboviewer <target> [source]

The target branch is required. The source defaults to your current branch, and naming it explicitly lets you review someone else's branch without checking it out.

roboviewer develop                    # current branch into develop
roboviewer develop feature/login      # someone else's branch
roboviewer -C ~/projects/app develop  # a repository living elsewhere

Reports land in .roboviewer/runs/<timestamp>/, and --diff-only shows what would be reviewed without spending tokens. Every flag: Command line.

Documentation

Page What is in it
Configuration The config file, checking the gateway, rate limits
Command line Every flag and the environment variables behind them
How it works Whole files, the reference pre-pass, one agent per concern, the judge
Reports and output What a run writes, the four formats, overriding a template
Continuous integration Exit codes, and a job for GitLab and for GitHub
Customise the checklist Adding a concern without touching code
Output language Findings in a language other than English
Tuning Prompts, how many agents, thinking, the turn limit
Measurements What it finds and gets wrong, per model and checklist size
Watching a run What the agents did with the context: the log, the page, the command
The benchmark `benchmark list

docs/ also carries the map of the code, the tooling baseline and how the benchmark is built and run.

What it doesn't do

  • It does not post comments on your merge request, and does not talk to GitHub or GitLab at all. Output is files on disk; in CI it is the pipeline that publishes them, from formats the forge already understands.
  • It does not modify your code. The agents get read-only tools — read_file, grep, list_files, git_show — and nothing else.
  • It does not replace a human reviewer. On the merge request it was measured against it surfaced between 6% and 48% of the known defects depending on the model and the checklist, and it has no idea whether the feature was worth building.
  • It does not try to reproduce a human review, and nothing here measures how closely it agrees with one. Overlap with reviewer comments would measure similarity, not correctness — the two miss different things, and a run that matched a reviewer perfectly would have added nothing. It is measured against defects established in the code, not against what somebody happened to write in a comment thread.
  • It keeps no state between runs. Every run starts from the diff and nothing else, so in CI it reports the same findings again on every push — including the ones you have already read and decided to leave. Nothing in the tool suppresses a repeat, and that is the usual reason review bots get switched off. Until that changes, the honest place for it is a branch you run by hand.

License

MIT — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

roboviewer-0.3.0.tar.gz (222.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

roboviewer-0.3.0-py3-none-any.whl (200.1 kB view details)

Uploaded Python 3

File details

Details for the file roboviewer-0.3.0.tar.gz.

File metadata

  • Download URL: roboviewer-0.3.0.tar.gz
  • Upload date:
  • Size: 222.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for roboviewer-0.3.0.tar.gz
Algorithm Hash digest
SHA256 4df5d74fd90153d71a4db0c097621eec153ccc7459032b7ea012dcc8ba5441c5
MD5 ea7f889df89868833699e770ab588942
BLAKE2b-256 7a0d19bc8a78bccebf98f42508d06a8470eaf4400b995a512fa85dabeb23630e

See more details on using hashes here.

Provenance

The following attestation bundles were made for roboviewer-0.3.0.tar.gz:

Publisher: release.yml on axazeano/Roboviewer

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file roboviewer-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: roboviewer-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 200.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for roboviewer-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5acc66fe7bb51fa8a09f1bd665d7cafebf131999ad4d9448441a54b7f9389f1b
MD5 e2cbd9716f8a37910d5b192a4b0f813c
BLAKE2b-256 56560f10fe2b1adea54372a121c7fd78477d8bb737a61d6e10faded5b23d108c

See more details on using hashes here.

Provenance

The following attestation bundles were made for roboviewer-0.3.0-py3-none-any.whl:

Publisher: release.yml on axazeano/Roboviewer

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 files

0.2.0

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page