The Repowise PR bot is a GitHub App that runs the same intelligence layers as the CLI and dashboard against every pull request. It posts one short comment, with a checks section when coverage, security or docs have something to say, optional pass/fail checks a branch rule can require, and review threads on the lines that need them. Every push gets a Repowise review check with the commit it reviewed and its finding counts. In Signals, the default mode, the comment is deterministic and posts only when there is something worth saying: no model, no per-PR tokens, and free forever for public / OSS repos. AI review adds a model on every pull request that changes code and is part of Pro, billed from credits. Private repos need the Pro plan too. See review modes.
Install it from the GitHub App page: github.com/apps/repowise-bot. Pick individual repos or a whole org. There is also a marketing overview and you can manage installs from the dashboard.
Install
Install the GitHub App. Open github.com/apps/repowise-bot, choose the repos (or the whole org), and approve.
Connect the install to your account. GitHub sends you back to
repowise.dev/bot/installed, which shows a "Finishing setup" state while it
waits for GitHub's webhook to register the installation. It polls for that on
its own, up to eight times at 1.5-second intervals, and tells you if
registration is taking longer than expected. Two cases from there:
- Personal account install. Claimed automatically as soon as you are signed in. Nothing to click. If the claim fails the page says so and offers a retry button.
- Organization install. An organization admin has to confirm it. The page shows a "Confirm organization access" button, which needs a GitHub sign-in fresh enough to carry a provider token; without one the button is disabled and the page asks you to sign in with GitHub again.
If you are not signed in at all, comments still appear on pull requests. You just cannot manage the install or claim the indexed repos until you sign in.
Indexing starts. Once the install is connected, the default branch of each
covered repo is indexed through the same pipeline the hosted dashboard uses,
typically 3 to 10 minutes per repo. Until a repo's first snapshot exists the
page lists it as indexing.
Open a pull request. On opened / synchronize / reopened, the bot
re-parses the changed files, computes the health delta between base and head,
and decides whether to comment.
Read the report. The View on Repowise button on each comment opens
the pull request's page on repowise.dev (/pr/{owner}/{repo}/{number}),
with the full analysis, findings and tests to run. Pages for public repos need
no sign-in. Pages for private repos open for signed-in users with access to
the repo.
Permissions requested: Contents: Read · Pull requests: Write · Metadata: Read · Issues: Write (GitHub treats PR comments as issue comments) · Checks: Write, for the Repowise review check, the merge gate, pass/fail checks and annotations on lines. Grant Checks: Write: without it the bot still comments, but a clean pull request gets no comment, so nothing on it shows the review ran. The one-click coverage setup needs Contents: Read and write and Workflows: Read and write.
Review modes
The org policy picks the mode for every repo
in an installation, and a repo can override it (Settings → PR bot). The mode is
set only on the dashboard: the bot ignores review_mode in
.repowise/bot.yaml, so a pull request from a fork cannot turn on a paid pass.
| Mode | What it does | Plan | Cost |
|---|---|---|---|
| Signals | Comments when a contract breaks, a finding lands, or tests or companion files are missing. No model runs. | Free on public repos | None |
| AI review | Reviews every pull request that changes code, on every push. Docs-only and other non-code pull requests get Signals. | Pro | About 9 cents a pull request on average, every push included |
How AI review works
- Quick pass on every push. A model reads the diff with the evidence Signals already computed: callers, co-change partners, findings, tests.
- Fix pushes are incremental. A later push is read for what changed since the last reviewed commit. The review remembers its earlier points, so a point is never raised twice, and a point whose lines a push fixed is resolved on its thread.
- A verifier on risky claims. A claim that a caller breaks, a failure is silently swallowed, or a high-priority logic error is checked against the code before it posts.
- A deep review when the change warrants it. On a risky pull request,
where change risk, blast radius or hotspot history call for it, a deeper
review reads the code around the diff. It runs automatically once per pull
request, and on demand with depth
deepor/repowise review deep. - Tests in one thread. Changed code that no test reaches is listed once, in a single "Tests for this change" thread, edited in place as pushes land.
- Drafts. A draft pull request gets the quick pass. The deep review is considered when it is marked ready for review.
- On demand. Comment
/repowise review deepto run the deep review on the current commit.
Depth (review_depth) sets how far AI review goes:
| Depth | Runs |
|---|---|
light | The quick pass and the verifier. No deep review. |
auto | The default. Adds the deep review when the change warrants it. |
deep | The deep review on every push. |
AI review draws on the same credit balance as chat, docs and MCP, with no
per-seat review fee. Pro includes $5 of credits a month, about 55 reviewed
pull requests, and 100 pull requests cost about $9. Two caps bound the spend:
each pull request has a cap (ai_pr_cap_cents, 60 cents by default) and each
repository a monthly AI spend limit ($5 by default). When the plan does not
include AI review, the balance is empty, or the monthly limit is reached, the
bot posts only what Signals would, and the comment and the review check note
the pause. When a pull request's own cap is spent, later pushes get Signals and
the review check says the pull request's AI budget is spent.
When the bot comments
In Signals the bot stays silent unless there is a measurable signal worth interrupting a reviewer for. A pull request with no findings gets no comment at all. In AI review it also comments when the review has a point to raise. A clean quick pass posts no comment, and a clean deep review posts a short note that there is nothing to fix. Either way the Repowise review check reports every push, so a clean result is visible without a comment. When the bot does comment, improvements are shown alongside problems so cleanup gets credit. Signals posts when any of these fire:
- net repo health degrades, or any modified file's score drops;
- a hotspot file (high churn + many dependents) is touched;
- a top co-change partner of a modified file is missing from the PR;
- new dead code is introduced (or removed, which is a win);
- a modified file is on a declining-health trajectory;
- a changed file carries substantial recent bug-fix history;
- the diff's change-risk score lands in this repo's high band.
The bot edits its existing comment when new commits land instead of posting a wall of duplicates. If nothing is left to say after an earlier comment, the stale comment is deleted.
What's in the comment
The comment is short and leads with what the reviewer should do. Each part
renders only when it has something to say, and the full analysis is one click
away: the View on Repowise button opens the pull request's page
(/pr/{owner}/{repo}/{number}), and each review thread has a Details link
to its point on that page.
| Part | What it shows |
|---|---|
| Verdict and review actions | The evidence that made the bot post, as actions: a broken contract, a finding this PR introduced, a missing companion file, the tests to run. At most three. |
| Health line | The repo score and how this PR moved it (show_health). |
| Gate line | The merge gate's verdict, when the gate is on. |
| Coverage | One verdict line: patch coverage of the changed lines, the project delta, and the threshold when one is set. The uncovered changed lines are folded under it, per file, each range linked to its lines. Measured, and only when CI uploads a report (see coverage setup). Nothing renders while CI is still running. |
| Security | New findings on the lines the pull request adds, at or above security_shows_at. Secrets are masked. |
| Tests | Only when there is no coverage report and none is coming: the changed files no test reaches through the call or import graph. Inferred, so it never shows a percentage. |
| Doc drift | Opt-in (doc_drift). Refuted claims in docs the pull request edits. Documents that only name a changed file stay on the PR page and in the Repowise / doc drift check run. |
| Evidence | A folded table of what is known and unknown about the change: owners, components, provenance with its coverage. Standard detail only. |
| Reviewers | Suggested reviewers (show_ownership). Standard detail only. |
Coverage, security, tests and doc drift form the comment's checks section (see checks). In Signals nothing in the comment is written by a model, so every comment is reproducible. AI review writes its part with a model, and the pull request page names the model that wrote it.
Findings on lines
on_lines decides what lands on the changed lines themselves:
| Value | What it posts |
|---|---|
off | Nothing on the lines; the findings stay in the comment. |
annotations | Check Run annotations in Files changed: high and critical health findings on lines this PR added, and changed signatures that code outside the PR still calls. With the merge gate off they ride on a neutral check posted only when there is something to mark. |
threads | The default. The strongest findings as review threads you can reply to: leaked keys, breaking signature changes with outside callers, and AI review points. |
both | Annotations and threads. |
AI review points on code this PR wrote are capped by the review sensitivity.
The Repowise review check
Every push gets a GitHub check run named Repowise review. It is on by
default, and it tells people and coding agents whether the latest commit has
been reviewed and what the review found:
| State | Conclusion | Title |
|---|---|---|
| Review running | in_progress | Reviewing <short sha> |
| Waiting for the repo's first index | in_progress | Waiting for the first index |
| Clean | success | 0 findings, with the depth that ran |
| Findings | neutral | The open findings by priority, with the depth that ran, for example 3 findings: 1 P1, 2 P2 |
| Pull request's AI budget spent | neutral | The findings count, with a note that this pull request's AI budget is spent |
| Skipped | neutral | Not reviewed: <reason>, for a [skip repowise] title, a bot author, the bot turned off, a plan that does not cover the repo, a pull request too large, or no files to review |
| Superseded by a newer push | neutral | Superseded, with the newer commit |
| Did not finish | neutral | Comment /repowise recheck to run it again |
The title ends with the depth that ran, shown as a tier label: (T1) for the
quick pass, up to (T3) for the deep review. A run paused for credits or the
plan is a normal clean or findings run with a note line in its summary. The
summary names the reviewed commit and the base it was compared against.
The check concludes failure only when the merge gate is on
and blocking. Keep it out of required checks unless the gate is on.
For coding agents. The latest commit is reviewed when the
Repowise review check on the head SHA is completed. Read the check's
finding counts instead of comparing comment timestamps. When the bot posts a
comment, its hidden repowise-bot marker also carries the reviewed head SHA.
A clean pull request gets no comment, so on an install without Checks: Write
there is nothing to read: grant it.
To turn the check off for a repo, set review_check: false.
Commands
Comment on a pull request:
| Command | Does |
|---|---|
/repowise recheck | Runs the review again on the current commit. |
/repowise review deep | Runs the AI deep review on the current commit (AI review only). |
/repowise remember [path:<glob>] <text> | Saves a review preference the bot reads on later reviews. Works in review threads too. |
/repowise confirm | In a review thread: accepts the decision saved from it. Needs write access. |
/repowise forget | In a review thread: undoes what was saved from it. Needs write access. |
/repowise help | Lists the commands. |
Put [skip repowise] in a pull request title to skip it.
Teach the review
Reply on one of the review's findings to tell it what your team does, for example "we validate this at the API boundary, not here". The review saves the reply as a decision and applies it to later reviews, and answers on the thread with what it saved and a link to it.
- Write access accepts it. A reply from someone with write, maintain or admin access on the repository is accepted right away: "Saved as a decision (accepted: octocat has write access)". Anyone else's reply is saved for someone to accept.
- Accept from the thread. Reply
/repowise confirmon the thread to accept a saved decision, or confirm it on the repository's Decisions page. - Undo. Reply
/repowise forgeton the thread. The decision stops shaping reviews, and a finding the reply had quieted can be raised again.
The Learn from replies setting, in a repository's bot settings or the org policy, picks what a reply becomes:
| Option | Does |
|---|---|
| Accept automatically when the replier has write access | The default. Replies from people with write access are accepted, others are saved for someone to accept. |
| Save for someone to accept | Every reply is saved, and nothing shapes reviews until someone accepts it. |
| Don't learn from replies | Replies are not saved. |
What the review learned on a repository is listed under What it learned from your team in that repository's bot settings. Teammates who did not install the bot can see it there; only the person who installed the bot can change the setting.
The merge gate
Beyond commenting, the bot can post a GitHub Check Run named
Repowise / code health that a branch protection rule can require, turning
code health into a merge gate. It is off by default (health_gate.mode):
off: no check is created.advisory: always concludesneutral. The verdict is visible on the PR but never blocks. The safe default to start with.blocking: concludesfailurewhen a rule trips, which a required check will block the merge on.
The rules (evaluated only in blocking mode):
| Rule | Blocks when |
|---|---|
repo_drop_block | The repo health score drops by more than this many points (default 0.3). |
min_new_file_score | A changed file scores below this floor, out of 10. |
block_on_introduced | The PR introduces a finding in its added lines. |
block_at | With block_on_introduced, the lowest severity that fails: critical, high, medium or low. Unset means any severity. |
Or start from a named profile and nudge single knobs: health_gate.profile
accepts warn-only, block-new-file-floor or block-any-decline. The
profile seeds the rules; any explicit key set alongside it wins.
not_evaluated decides what every Repowise check run concludes when it
could not evaluate, for example no health score yet or no coverage report:
neutral (the default) passes a required check, failure holds the merge
until it can evaluate.
Because the bot already re-scores the repo at both the base and head commits, the gate needs no extra index; it reads the same per-PR analysis the comment is built from.
Checks
The comment's checks section carries what the tests, the security scan and the
docs say about the change (see what's in the comment).
checks_comment decides when it renders:
on_signal(the default): only when a check has something to say. Once shown it is always updated, to an all-clear line when the findings are gone, so a stale finding never lingers.always: on every pull request.off: never.
Pass/fail checks
Each check can also post its own GitHub check run, which a branch protection
rule can require. check_runs lists the ones that run. review (the
Repowise review check) is on by default, the
rest are off, and all work with or without the checks section:
check_runs entry | Check run | Fails when |
|---|---|---|
review | Repowise review | Only with a blocking merge gate. Otherwise success when clean and neutral with findings. |
coverage | Repowise / coverage | Patch coverage is below coverage_fail_under (a percent, 0 to 100). With no minimum it reports the figure and concludes neutral. |
security | Repowise / security | The pull request adds a finding at or above security_fail_on (high by default). |
doc_drift | Repowise / doc drift | A doc the pull request edits carries a claim the code refutes, at high confidence. |
A check that could not evaluate concludes as not_evaluated says.
Coverage setup
Measured coverage needs a coverage report from your CI. In the dashboard
(Settings → PR bot → a repo's settings → Checks), Set up coverage has
the bot open a draft pull request that adds
.github/workflows/repowise-coverage.yml: it runs your tests with coverage and
uploads the report with the step below. The bot detects the stack (Python,
Node, Go, Java with Maven or Gradle) and the pull request says how to adjust
the test command. If your
tests already run in another workflow, it explains how to move the upload step
there so they run once. Review it, mark it ready and merge it; the next pull
request carries a coverage line.
The one-click setup needs two extra repository permissions on the PR bot: Contents: Read and write and Workflows: Read and write. Existing installs see "Approve the new permission" in the dashboard, which links to the installation's settings on GitHub. Everything else (the checks section, check runs, uploads) works without them.
Or add it yourself. The dashboard shows the generated workflow, and the upload
step alone, to copy. Add the step to the job that runs your tests, after the
step that writes the coverage report, and give the job the id-token: write
permission:
jobs:
test:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write # lets the upload prove it comes from this repository
steps:
# ... check out, install, and run your tests with coverage ...
- name: Upload coverage to Repowise
if: always()
continue-on-error: true
env:
REPORTS: "coverage.xml" # space-separated paths or globs
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
PR_NUMBER: ${{ github.event.pull_request.number }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
shopt -s globstar nullglob
files=()
for pattern in $REPORTS; do for f in $pattern; do [ -f "$f" ] && files+=(-F "report=@$f"); done; done
if [ ${#files[@]} -eq 0 ]; then echo "::warning::Repowise: no coverage report found at: $REPORTS"; exit 0; fi
auth=()
if [ -n "${ACTIONS_ID_TOKEN_REQUEST_URL:-}" ]; then
token=$(curl -sS -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=repowise" | jq -r '.value // empty' || true)
[ -n "$token" ] && auth=(-H "Authorization: Bearer $token")
fi
curl -sS --fail-with-body --max-time 60 "${auth[@]}" "${files[@]}" \
-F "repository=$GITHUB_REPOSITORY" -F "head_sha=$HEAD_SHA" -F "pr_number=$PR_NUMBER" \
-F "event=$GITHUB_EVENT_NAME" -F "run_url=$RUN_URL" -F "workspace=$GITHUB_WORKSPACE" \
https://api.repowise.dev/ci/coverage \
|| echo "::warning::Repowise: coverage upload failed; see the message above."It is plain curl and jq, so it needs no extra action. It never fails the
job: a missing report or a failed upload is a warning in the log, and the
server's answer (including how many report paths did not match a file in the
repository) is printed there too.
REPORTS is a space-separated list of report paths or globs (** works),
relative to the repository root. Supported formats: LCOV, Cobertura XML,
JaCoCo XML, Clover XML, Go coverprofile, and the Repowise coverage JSON. The
format is detected from each file, and absolute paths in a report are made
relative to the checkout. Typical values:
| Stack | Test command (example) | REPORTS |
|---|---|---|
| Python | pytest --cov --cov-report=xml | coverage.xml |
| Node | npx vitest run --coverage --coverage.reporter=lcov | coverage/lcov.info |
| Go | go test ./... -coverprofile=coverage.out | coverage.out |
| Java (Maven) | mvn -B verify with the jacoco-maven-plugin report goal | target/site/jacoco/jacoco.xml |
| Java (Gradle) | ./gradlew test jacocoTestReport | build/reports/jacoco/test/jacocoTestReport.xml |
| Several or unsure | "coverage.xml coverage/lcov.info lcov.info coverage.out **/jacoco.xml **/cobertura*.xml **/clover.xml" |
Runners. GitHub-hosted runners have curl and jq installed.
Self-hosted runners need curl and jq; without jq the upload has no identity
and is refused.
Fork pull requests. The upload proves which repository it comes from with a short-lived identity token from the workflow, so no secret is needed. A pull request from a fork gets no such token. Its upload is accepted only when the repository is public and the upload is for the open pull request's current head commit; the comment then labels it "uploaded from a fork pull request without verified identity". Such an upload never replaces a verified one for the same commit. On a private repository, fork uploads are refused.
Getting coverage into hosted
Measured coverage reaches a repo's Tests page and the hosted MCP tools by one of two routes. Both read the same report formats your test runner already writes.
| Route | Where | Gives |
|---|---|---|
| CI upload | The upload step above, from a GitHub Actions job | File and line totals, plus the per-test map when a default-branch push run sends a report that carries it |
| Manual upload | The upload panel on the repo's Tests page | File and line totals, plus the per-test map when the report carries it |
Formats. The manual upload takes LCOV, Cobertura XML, Clover XML, the
Repowise coverage JSON, and a coverage.py .coverage file. The CI upload takes
the formats listed under REPORTS above, plus a .coverage file.
Default-branch pushes fill the Tests page. Only an upload from a push to
the default branch reaches the Tests page and the MCP tools. Uploads from pull
request runs feed the pull request coverage check and nothing else, so run the
coverage job on both events:
on:
push:
branches: [main] # your default branch
pull_request:The job needs permissions: id-token: write (and contents: read) so the
upload can prove which repository it comes from.
Per-test map. Knowing which tests to run for a change needs a report that
records which test covered each line. Produce it with
pytest --cov=<package> --cov-context=test (needs pytest-cov), which writes a
.coverage file, or as an LCOV report where each block carries a distinct
TN: test name. See
Building a per-test map.
Send it either way:
- Manual upload on the repo's Tests page.
- CI upload from a
pushrun on the default branch, with.coverageinREPORTS(the step sends it as-F report=@.coverage). The workflow the bot generates for a Python project sends it on push.
Pull request runs give totals for the pull request check only, even when they
send .coverage.
Where it shows. The Tests page shows per-file and per-module coverage,
untested hotspots, and the risk-versus-coverage view. Through the hosted MCP,
get_risk returns tests_to_run and
get_change_risk lists impacted tests, both from
the per-test map.
Checks settings
| Key | Default | Meaning |
|---|---|---|
checks_comment | on_signal | When the checks section renders: off, on_signal or always. |
coverage | show | Coverage in the comment: off or show. check_run shows it and also runs Repowise / coverage. |
tests_reach | true | Name the changed files no test reaches when there is no coverage report. |
show_security_check | true | Security in the comment. |
security_shows_at | med | Lowest severity shown: high, med or low. |
doc_drift | off | Doc drift in the comment: off, show, or a confidence (high, medium, low) at which a refuted claim alone posts the comment. |
check_runs | [review] | Check runs: any of review, coverage, security, doc_drift. |
review_check | true | The Repowise review check. false turns it off even when check_runs lists review. |
coverage_fail_under | none | Patch coverage percent below which Repowise / coverage fails. Empty reports only. |
security_fail_on | high | Lowest severity that fails Repowise / security: high, med or low. |
not_evaluated | neutral | What a check run concludes when it could not evaluate: neutral or failure. |
Configuration
Settings come from layers, lowest first; a higher layer wins for each key it sets:
- the bot's defaults;
- the org policy of the installation;
.repowise/bot.yamlin the repo;- the repo's own settings on the dashboard;
- the keys the org policy locks.
Policy keys decide a gate, so a pull request cannot loosen them from its own
branch: health_gate, check_runs, coverage_fail_under, security_fail_on,
not_evaluated, review_check, ignore_paths and apply_labels are read from
.repowise/bot.yaml on the base branch only. Paid keys (review_mode,
review_depth, ai_pr_cap_cents, ai_monthly_cap_cents) are read from the
dashboard only. ignore_paths is a
union across layers, so a layer can add scope but never un-ignore a path
another layer skips. A malformed value is skipped and the layer below stands.
Org policy and repo overrides
Settings → PR bot → an installation opens its org policy: the settings every repo it covers starts from. It offers three presets:
| Preset | Sets |
|---|---|
| Quiet | Posts only for critical findings. No pass/fail checks, no merge gate. |
| Standard | The bot's defaults: posts for high-severity findings, no pass/fail checks, no merge gate. |
| Strict gate | Posts from medium severity, check_runs: [coverage, security], a blocking merge gate, and not_evaluated: failure. |
No preset changes the review mode, which is a paid choice of its own. The page shows how many repos follow the preset (override none of its keys), and can make selected repos follow it: after a confirmation naming the repos and the settings, it clears their overrides of the preset's keys and leaves the rest.
Each policy row has a lock. A locked key wins over the repo's dashboard
settings and its .repowise/bot.yaml, so a repo cannot loosen it; the repo's
page shows the row read only. Locking a key the policy does not set yet pins
the value the repos get at that moment. The merge gate locks as one key.
A repo's page (Customise on the policy, or Settings on a repo row)
shows every setting with its value and where it comes from: Default,
Org default, Overridden or Locked by org. A change there overrides
the policy for that repo; Reset on a row, or Reset all to org default,
removes the override. The dashboard cannot see .repowise/bot.yaml, so a value
marked Default or Org default may still be changed by the repo's YAML.
.repowise/bot.yaml
Committed and versioned with the code:
bot:
enabled: true
comment_mode: on_signal # or "always" to post a clean bill of health
verbosity: standard # compact | standard
introduced: high # off | show | critical | high | medium | low
recent_decline: show # same values; "show" never posts on its own
change_risk: signal # off | signal (PR page) | comment
on_lines: threads # off | annotations | threads | both
apply_labels: false # opt in to repowise:* PR labels
ignore_paths:
- "vendor/**"
- "**/*.generated.*"
health_gate:
mode: advisory # off | advisory | blocking
repo_drop_block: 0.3
min_new_file_score: 7.0
block_on_introduced: true
block_at: high
checks_comment: on_signal # off | on_signal | always
check_runs: [review, coverage] # review | coverage | security | doc_drift
coverage_fail_under: 80 # percent of changed lines; omit to report only
not_evaluated: neutral # neutral | failureThe comment's parts each have a switch: show_health, show_checklist,
show_coupling, show_ownership, show_evidence and show_declining_alert.
Pre-v2 key names (show_introduced with introduced_posts_at,
inline_threads, show_findings_on_lines, coverage_check_run,
checks_comment_mode and the rest) still read into the key they became.
PR labels (opt-in)
With apply_labels: true the bot also applies repowise:* labels, created on
demand and reconciled on every run: a label is removed once its signal clears,
and labels outside the repowise: namespace are never touched.
| Label | Applied when |
|---|---|
repowise:gate-failed | A blocking gate you configured actually tripped |
repowise:risk-high | Top tercile of this repository's own commit-risk distribution |
repowise:missing-tests | A file with recent fix history changed, and no test that imports it was touched |
repowise:size-xl | Too large for granular analysis |
They are off by default, and the list is short on purpose. A label is permanent, binary, and public in the pull-request list, so it reads as a verdict on the author in a way an editable comment does not, which means it has to be reserved for things that are actually rare. Signals that fire on ordinary work (a repo score that dipped, a hotspot touched, a moderately-sized diff) stay in the comment, where they carry their context with them.
Pricing
Signals is free forever for public / OSS repos: no model, no tokens, no PR cap. AI review is part of Pro and billed from credits, about 9 cents a pull request on average (see review modes). Private repos require the Pro plan as well. Private installs still index on connect, so the snapshot is ready when you upgrade. See the pricing page.
How it relates to the rest of Repowise
Same engine, different surface. The bot reads the code-health,
git-intelligence, and
dependency-graph layers, and every
comment links to the pull request's page on the dashboard, where the same data is queryable
by humans (the web UI) and by AI agents (the MCP tools,
including get_health for a pre-PR self-check).