Metadata-Version: 2.5
Name: pull-request-view
Version: 0.2.1
Summary: Review a GitHub pull request file-by-file in your browser, with AI from your local claude CLI
Project-URL: Homepage, https://gwicho38.github.io/prview/
Project-URL: Repository, https://github.com/gwicho38/prview
Project-URL: Issues, https://github.com/gwicho38/prview/issues
Project-URL: Changelog, https://github.com/gwicho38/prview/releases
License-Expression: MIT
License-File: LICENSE
Keywords: ai,claude,code-review,developer-tools,diff,github,pull-request
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Topic :: Software Development :: Version Control :: Git
Requires-Python: >=3.10
Requires-Dist: fastapi>=0.110
Requires-Dist: uvicorn[standard]>=0.27
Description-Content-Type: text/markdown

# prview

[![CI](https://github.com/gwicho38/prview/actions/workflows/ci.yml/badge.svg)](https://github.com/gwicho38/prview/actions/workflows/ci.yml)

**Review a pull request in your browser. Free, no install, no API key.**

→ **[Open prview](https://gwicho38.github.io/prview/)** and paste a PR URL.

The AI review is answered by a code model running on your own GPU through WebGPU, so the
diff never leaves the tab and there is no key to buy. Private repositories work with a
GitHub token that is sent only to `api.github.com`. The page is static: there is no
prview server to trust.

There is also a local app, for reviewing with the `claude` CLI and for the Repowise
codebase-intelligence tab — the two things a web page cannot start. It reuses your
existing `gh` and `claude` CLIs, so there are still no API keys to manage.

See the full [user guide](docs/user-guide.md).

![prview file-by-file review with AI summary](docs/assets/review-screenshot.png)

## What it does

- Load a PR by `owner/repo#123` or a GitHub URL.
- Walk the changed files (sorted by change size) with a side-by-side diff.
- Per-file **AI summary** (auto), **Explain**, and **Ask** — powered by your `claude` CLI. Responses are cached per file and the panel scrolls.
- **Mark viewed**, **flag** with notes, **comment** (file-level or anchored to selected diff lines, GitHub-style), and **submit a review** (approve / request changes / comment).
- Optional **Repowise** tab: codebase intelligence (architecture, code health, commits, coverage, AI docs) scoped to the whole repo *or* just the PR's changed files.
- Light & dark themes (toggle in the app bar); resumable per-PR state in `~/.prview/state`.

## Setup

prview drives your existing CLIs instead of managing API keys, so setup is mostly making sure `gh` and `claude` work, then installing prview.

### 1. GitHub CLI (`gh`) — required

prview reads PRs/diffs and posts reviews through `gh`.

```sh
# install (pick your platform)
brew install gh                 # macOS / Linuxbrew
# or: see https://github.com/cli/cli#installation

gh auth login                   # authenticate (choose GitHub.com → HTTPS → browser)
gh auth status                  # verify: should show "Logged in to github.com"
```

### 2. Claude CLI (`claude`) — required for AI features

The AI summary / Explain / Ask features shell out to the `claude` CLI (Claude Code). prview sends it the **full file diff**, so it benefits from a large context window.

```sh
# install Claude Code: https://docs.claude.com/claude-code
claude --version                # verify it's on your PATH
```

> Without `claude`, PR review still works — only the AI panel is disabled.

### 3. prview itself

```sh
# Python >= 3.10. The package is pull-request-view; the command it installs is prview.
uv tool install pull-request-view    # or: pipx install pull-request-view
prview start                         # runs it in the background
prview open                          # opens it in your browser
prview stop                          # stops it
```

The PyPI name is **`pull-request-view`**. An unrelated project already owns `prview`
there, so `pip install prview` gets someone else's tool. The command stays `prview`.

From a checkout instead:

```sh
git clone https://github.com/gwicho38/prview && cd prview
make install                    # uv tool install from source
```

`prview` picks a free `127.0.0.1` port, mints a per-session token, and starts the server.
`start` runs it detached in the background (survives the shell exiting); `open` launches your
browser at the running instance; `stop` shuts it down. Running `prview` with no subcommand keeps
the original foreground behavior — auto-opens the browser, `Ctrl-C` to quit.

Working from a checkout without a global install? `make dev` (`uv sync`) then `uv run prview`, or
`make start` / `make open` / `make stop`, which wrap the same subcommands via `uv run`. `make
update` pulls the latest `main` and reinstalls the CLI.

> There is no `./prview` script — the package directory occupies that name. Use `prview` (once
> installed), `uv run prview`, or `python -m prview`.

### 4. Repowise (optional) — for the codebase-intelligence tab

The **Repowise** tab embeds a [repowise](https://github.com/repowise/repowise) dashboard for the PR. It's optional; install it only if you want architecture/health/coverage/docs analysis.

```sh
uv tool install repowise        # provides the `repowise` CLI
node --version                  # Node ≥ 20 required (repowise serves a web UI)
```

For local, no-cost AI docs generation, also install [ollama](https://ollama.com) and pull a model:

```sh
ollama pull qwen2.5:3b          # fast; or a larger model for better prose
```

See **[Repowise tab](#repowise-tab-optional)** below for first-run steps.

## Try it without installing anything

prview is also published as a static site: **https://gwicho38.github.io/prview/**

Reviews there are answered by a code model running on your own GPU through WebGPU — nothing is
sent anywhere, and there is no key to paste. `claude` is not reachable from a web page, so that
engine is offered only in the local app.

The hosted build has no backend. It fetches the PR from the GitHub API, runs prview's real
`core.py` / `order.py` / `behaviors.py` in your browser through Pyodide — the same modules and
the same tests as the local app, staged by `scripts/build_pages.py` — and keeps review state in
`localStorage`. Public PRs work with no sign-in.

### Reviewing a private PR on the hosted site

Paste a GitHub token in the bar at the top. The site checks it against `/user` and shows which
account it belongs to, so a wrong or revoked token is caught there rather than as a 404 halfway
through a review. The token is sent only to `api.github.com`.

- **Classic token:** the `repo` scope.
- **Fine-grained token:** *Contents: read* and *Pull requests: read* on the repositories you review.
  Add *Pull requests: write* only if you want to post comments and reviews from the page.
- **Organisation with SAML SSO:** authorize the token for that organisation, or every request
  comes back 403. The page says so and links GitHub's authorize page when GitHub supplies it.

The token lives in `sessionStorage` and dies with the tab. **Remember on this browser** moves it
to `localStorage` instead — convenient for daily review, but the token then sits at rest on a
public origin that loads Pyodide and the model runtime from CDNs, so anything that can run
script there can read it. **Forget** clears both stores.

Two features stay local-only, because they need processes a web page cannot start: the `claude`
engine and everything under Repowise. Set the AI engine to `in-browser` and a small code model
runs on your own GPU instead.

## Reviewing a PR

1. Enter `owner/repo#123` (or a full GitHub PR URL) and press **Load PR**.
2. Click files in the sidebar (or `j`/`k`) to read each diff.
   The sidebar dropdown sets the **review order**: **Story** (the default — schema and
   type definitions first, then core logic, then the call sites that use it, then UI,
   config, tests, generated files), **Complexity** (most added branching first),
   **Largest**, or **A–Z**. `o` cycles; the choice sticks across PRs.
3. Press `G` (or the **Flat**/**Grouped** button) to group files under **behaviors** —
   one per commit in the PR, titled from the commit subject. `▶ Name` rewrites the titles
   with AI; 💬 on a behavior header posts a comment addressed to that behavior, anchored to
   its highest-tier file. Squashed (single-commit) PRs have nothing to group.
4. Use the AI panel: a summary auto-loads; **Explain** for a deep walk-through; **Ask** to query the file.
   The **engine** dropdown picks who answers. `claude (local)` runs the CLI. `in-browser`
   runs a small code model on your own GPU via WebGPU — no CLI, no API key, and nothing
   leaves the machine. The in-browser engine downloads weights (4.3 GB for the default
   Qwen2.5-Coder 7B, 1.1 GB for the smaller 1.5B) from the MLC CDN on first use and caches
   them in the browser; it is the only part of prview that contacts a third party, and it
   only runs when you select it. Expect ~45s for the first answer and ~5s after that, and
   a smaller model than claude — good for per-file summaries, weaker on whole-PR reasoning.
5. **Flag** files with notes, **Comment**, mark **Viewed**, then **Submit** your review.

**Keyboard shortcuts:** `v` viewed · `e` explain · `a` ask · `c` comment · `f` flag · `o` order · `G` group · `s` submit · `j`/`k` navigate · `q` back/close.

Reopen `prview` later and pick the PR from the resume list — your viewed/flagged state is restored.

### Comments

**Comment** posts to the PR. With no diff text selected it's a file-level comment; **select lines in the diff first** and it's posted as a GitHub *review comment* anchored to that line range — and rendered inline at the line, like GitHub's review UI. Your comments are cached per PR and shown back on the file.

### Ask, anchored

When you **Ask** a question that references something specific — a symbol, function, file, or line — the AI treats that reference as the anchor: it starts there and expands outward through the surrounding code as needed, unless you scope it otherwise.

## Repowise tab (optional)

If the [`repowise` CLI is installed](#4-repowise-optional--for-the-codebase-intelligence-tab), a **Repowise** tab appears next to **Review**. It embeds a repowise dashboard for the PR — architecture/knowledge graph, code health, commits, and more.

**First run:** open the tab; prview checks out the PR head into an isolated git worktree (under `~/.prview/worktrees`, so your clone is never touched — a dirty tree won't block it), indexes it, and starts the dashboard. You'll be asked once for the local path to your clone of the repo.

Two scopes, toggled in the tab's bar:

- **Complete** — the full repowise dashboard over the whole codebase.
- **Diff associations** — scoped to the PR's changed files: which files the diff touches, transitively-affected (1-hop+) files *not* in the diff, historical co-change partners missing from the PR, suggested reviewers, and an overall risk score.

Two more actions in the bar:

- **Ingest coverage** — the coverage / risk×coverage panels need a report. Generate one in your clone (e.g. `pytest --cov --cov-report=lcov`), then click **Ingest coverage** (blank path auto-detects `coverage.lcov`, `lcov.info`, `coverage.xml`, …; LCOV/Cobertura/Clover supported).
- **Generate docs** — the docs/wiki panel is AI-generated. Click **Generate docs**, pick a local **ollama** model (e.g. `qwen2.5:3b`), and prview runs the generation locally — free, no cloud key. Larger models give better prose but take longer; progress shows per page.

> The embedded dashboard's own chat defaults to ollama `llama3.2`; if you don't have that model pulled, either `ollama pull llama3.2` or pick a catalog model from its in-dashboard model menu.

## Security

`prview` binds to `127.0.0.1` only, requires a per-session token on every API call (validated via the `X-Prview-Token` header / `?token=` on first load), and checks the `Origin`/`Host` headers. It runs `claude --dangerously-skip-permissions` locally to drive non-interactive AI calls. Because the server can run privileged `gh`/`claude` commands on your behalf, **do not expose its port** beyond localhost.

## Development

Common tasks are wrapped in the `Makefile` (`make help` to list them):

```sh
make dev            # uv sync (deps + dev group)
make test           # uv run pytest — full suite
make run            # launch prview in the foreground
make docker-build   # build the container image

make install        # install the prview CLI globally (uv tool install)
make uninstall      # remove the globally installed CLI
make update         # git pull main + reinstall the CLI
make start          # start prview in the background
make stop           # stop the background prview
make open           # open the running prview in your browser
```

The codebase keeps a pure functional core (`prview/core.py`) with all subprocess / filesystem / network I/O pushed to the edges (`gh.py`, `jobs.py`, `state_store.py`, `server.py`). The diff renderer (diff2html) is vendored under `prview/static/vendor/` — the app makes zero external network requests at runtime.

## Container

```sh
make docker-build   # docker build -t prview:dev .
```

The image builds and runs the server, and CI verifies it on every push. Note: live PR
review shells out to the host's `gh` and `claude` CLIs, which are **not** baked into the
image — so the container is for build/CI verification and reproducible packaging; for
actual reviewing, run prview on your host (`uv run prview`).

## License

[MIT](LICENSE).
