Better PRs

Privacy Policy

Last updated: 11 October 2026

Who operates Better PRs

Better PRs is a free public beta for reviewing GitHub pull requests. It is operated under the name Better PRs. No separate legal entity is named in this policy.

Accounts and GitHub

Sign-in and sign-up use Clerk. You connect a GitHub account through Clerk. Clerk stores that account and the GitHub OAuth access token. When Better PRs calls the GitHub API, the server asks Clerk for the token. The token is not written to the app database.

The design for this app specifies a GitHub connection with at least the read:user and repo OAuth scopes, so the app can read your GitHub profile and repositories you can access, including private ones, and can carry out review actions you start (comments, reviews, merges, and similar). read:org is described as optional. The scopes that are actually granted are whatever is configured on the Clerk GitHub connection. This repository does not store that configuration.

GitHub data the app reads

While you are signed in, the server calls the GitHub API with your token to load pull requests you can access: titles, descriptions, diffs, comments, reviews, checks, and related metadata. Actions you take, such as commenting, reviewing, merging, closing, or updating a branch, are sent to GitHub as you.

Better PRs does not keep a full copy of your repositories. It does store the GitHub-related fields described below.

What is stored in Postgres

App data is stored in Postgres (Neon for the hosted database). That includes:

  • A user row: Clerk user id, GitHub user id and login when they have been synced, an inbox repository allowlist, and device preferences. Those preferences can include starred pull requests, snoozed pull requests (title, repository, number, and reminder time), recently opened pull requests (title, repository, number, and time), saved views, theme, and notification settings.
  • A personal account shell and membership for that user.
  • Audit events for actions such as syncing a GitHub profile, changing inbox settings, submitting a review, merging, and editing task boards. Metadata can include a GitHub login or a pull request reference such as owner/repo#number. It does not include the GitHub token.
  • Custom inbox sections you define (label and search definition).
  • Task boards: names, column and sprint names, task titles and descriptions, priorities, assignees, and optional pull request links. Personal boards are tied to your user. Organization boards are stored against a Clerk organization id.
  • Guided review plans, stored for a repository, pull request number, and head commit. A plan stores the model's steps, findings, and testing gaps, plus short diff snippets the tour focused on. When a plan is saved, it records the Clerk user id of the account that saved that version. Plans saved before that field existed have no creator id. Another signed-in user who can read that pull request on GitHub can be shown the stored plan. The route loads the pull request with the viewer's GitHub token before it returns a plan. A regeneration does not replace the stored plan.
  • Guided review regenerate records: Clerk user id, repository, pull request number, and time. These count regenerations (5 per pull request per hour). The hint you type is sent to the model and is not written on this row.
  • Guided review generation records: Clerk user id, repository, pull request number, and time. These count new guided reviews (20 per account each UTC day). The server reads GUIDED_TOUR_DAILY_NEW_LIMIT for that number. Opening a saved review does not add a row. Regenerating a review uses the regenerate records above.

Guided review and the AI provider

Guided review is optional. It runs only when a provider key is set: OpenAI when OPENAI_API_KEY is set, otherwise Vercel AI Gateway when AI_GATEWAY_API_KEY is set. The default model is gpt-4o-mini (sent as openai/gpt-4o-mini through the gateway). GUIDED_TOUR_MODEL can select a different model id. If neither key is set, guided review does not run and nothing is sent to a model provider.

When it runs, the prompt sent to that provider includes:

  • the pull request title
  • the description, truncated to 4,000 characters
  • each changed file's path, status, and change counts
  • a patch excerpt of up to 8,000 characters per file, or a note that the excerpt was left out because the prompt was too large
  • an optional hint you type when you regenerate

The whole prompt is capped at 80,000 characters. It does not include repository history or a separate team-conventions document. The model's reply is stored in the shared guided-review plan above. A new guided review counts toward 20 per account each UTC day. Opening a review that is already saved does not count again. Regenerating a review is counted separately, up to 5 times per pull request per hour.

Error tracking

If SENTRY_DSN or NEXT_PUBLIC_SENTRY_DSNis set, error, tracing, and log events are sent to Sentry. Tracing is sampled at 10% outside development. Sentry's default personal-data option is off (sendDefaultPii) in the browser, server, and edge configs, so those events are sent without the IP address, cookies, and email that option would add. Before an error, a transaction, or a log is sent, the app redacts email addresses, IP addresses, and GitHub token strings, and it redacts authorization, cookie, and forwarding headers. When the browser DSN is set, session replay masks all text and inputs, blocks media, and does not capture request bodies. 10% of sessions are recorded, and a replay is recorded when an error is captured. If no DSN is set, this reporting is off.

Page analytics

Production builds load Cloudflare Web Analytics when NEXT_PUBLIC_CF_BEACON_TOKEN is set. Development does not load the script. A build with the token unset does not load it either, so preview and CI do not send page views unless the token is set there.

Cloudflare Web Analytics is cookieless, privacy-first page-view analytics. It does not do cross-site tracking. It collects the page URL, the referrer, browser and device information, performance metrics, and the visitor's country. The beacon request reaches Cloudflare with the source IP address as part of normal HTTP handling. Cloudflare discards that IP at the nearest Cloudflare data center and does not store it in its core databases or logs. Cloudflare is a sub-processor for that data.

Cookies and data on your device

Clerk sets the cookies it uses to keep you signed in. This codebase does not add advertising cookies. Cloudflare Web Analytics, described above, does not set a cookie.

The browser also stores preferences and drafts in localStorage and sessionStorage. Those keys use a meridian: prefix and can hold theme, snooze, review drafts, pending comments, recently opened pull requests, and similar UI state. Some of the same preferences are copied onto the user row in Postgres so they can sync across devices. Pending comments and unsaved review text stay in the browser until you submit or clear them.

Account deletion and the 90-day purge

Account deletion happens in Clerk, from the account menu. Clerk then sends a user.deleted webhook. The app sets a deletion time on your user row. It does not delete that row immediately.

A scheduled job runs daily at 05:00 UTC (GET /api/cron/purge-deleted). It permanently deletes user rows whose deletion time is older than 90 days. That number is the default of USER_SOFT_DELETE_RETENTION_DAYS and can be set to another positive number in the server environment.

For each account past that window, the job deletes:

  • the user row, including device preferences stored on it
  • custom inbox sections
  • personal task boards, including their columns, sprints, and tasks
  • the account membership, and a personal account shell with no members left
  • guided review plans whose current version was saved by that Clerk user. That plan is deleted, including the diff snippets. Other people who could open that cached plan lose it and can generate a new one. Clearing only the creator id would leave the snippets in the database, so the row is removed.
  • every regenerate row for that Clerk user id
  • every generation row for that Clerk user id
  • audit log rows for that account, including rows whose metadata still contains that Clerk user id

On every run, the job also deletes audit rows that no longer point at a user. Earlier purges cleared the user id and left those rows, which can still contain a GitHub login or a Clerk user id.

Organization task boards stay. The purge clears that account as the board creator, as the task creator, and as the task assignee. An organization admin can still manage the board. A copy of the personal user id stored on a task for workspace checks is cleared.

Plans saved before this creator id existed have no Clerk user id. Those plans stay, because they cannot be tied to an account. Regenerating a plan does not save it, so a regeneration does not cause someone else's plan to be deleted.

Browser storage under meridian: keys stays on the device.

Selling data

Better PRs does not sell personal information. The app has no advertising and no analytics product of its own. Page views use Cloudflare Web Analytics, described above.

Changes

This policy can change. The Last updated date above changes with the text.