<h1 align="center">prtour</h1>
<p align="center">Guided PR reviews and recaps, written by your coding agent.</p>
<p align="center">
<a href="#run-it">Get started</a> ·
<a href="#with-an-agent">With an agent</a> ·
<a href="#recaps">Recaps</a> ·
<a href="#commands">Commands</a>
</p>
prtour turns a diff into a guided review. Your agent reorders the diff into
chapters by idea and puts numbered notes on the lines that matter. Tests,
generated files and helper noise are hidden but still listed, so a 2,000-line
PR becomes the 400 lines a maintainer needs to read. Pointed at weeks of
merged PRs instead, it writes a recap of what got fixed, what is new and what
got better.

Live examples, both from the public [ptyd](https://github.com/2018kguo/ptyd) repo:
a [guided review of PR #11](https://2018kguo.github.io/prtour/examples/ptyd-tour/) and a [recap of its first week](https://2018kguo.github.io/prtour/examples/ptyd-recap/)
([PDF](https://2018kguo.github.io/prtour/examples/ptyd-recap/recap.pdf)).
One `tour.json` renders four ways:
- **HTML**: one self-contained file. Diffs are pre-rendered with
[@pierre/diffs](https://diffs.com), so the file needs no server and works as
an artifact, an attachment, a static page or a `file://` URL.
- **Markdown**: for a PR comment, Slack or chat.
- **Terminal**: `prtour show`, colored and paged. Diagrams draw as text, and
screenshots show inline in kitty, Ghostty, WezTerm and iTerm2.
- **PDF**: `prtour render --format pdf`, through headless Chrome.
## Run it
Needs Node 20 or newer. Run it with `npx`, or `npm i -g prtour` to keep a
`prtour` command around.
```sh
npx prtour 123 # PR in this repo → scaffold → opens in the browser
npx prtour # this branch (incl. uncommitted) vs. the default branch
npx prtour 101 102 103 # several PRs as one tour, one part per PR
npx prtour 103 --stack # the whole stack 103 sits in, found via base/head branches
```
## With an agent
**Claude Code**, as a plugin:
```
/plugin marketplace add 2018kguo/prtour
/plugin install prtour@prtour
```
**Any agent with skills** (Claude Code, Codex, Cursor and others), through
[skills](https://github.com/vercel-labs/skills):
```sh
npx skills add 2018kguo/prtour
```
**Without installing anything**, the instructions ship with the tool:
```sh
npx -y prtour skill # print them (pipe into any agent)
npx -y prtour skill --install # write .claude/skills/prtour/SKILL.md
```
Or add one line to `AGENTS.md` / `CLAUDE.md`. This works for cloud agents too,
since all they need is `npx`:
```md
For a guided review of a diff, run `npx -y prtour skill` and follow it.
```
Then paste one of these to your agent:
```text
Make a guided review of PR #123 with npx -y prtour (run `npx -y prtour skill` first), open it for me, and post the notes on the PR.
```
```text
Recap what <login> merged in <owner/repo> since <YYYY-MM-DD> with npx -y prtour (run `npx -y prtour skill` first). Render HTML and PDF.
```
Shorter asks work too: *"open this PR in prtour"*, *"walk me through this
branch"*.
The agent:
1. Runs `prtour init <pr|range>`. This fetches the diff with `gh` or `git` and
scaffolds `.prtour/<slug>/tour.json`, with lockfiles, generated files and
tests already hidden.
2. Writes the tour: chapters in reading order, `1/N` notes anchored to lines,
and hides whatever doesn't need review, down to single hunks in a mixed file.
`prtour hunks <file> --lines` prints the hunk indices and line numbers it
needs.
3. Runs `prtour check` until it is clean. Every file must be placed, and every
note must point at a line that is shown.
4. Delivers the result:
- **Locally**: `prtour open` serves the page with live reload. You comment
on any line, note or chapter, the comments go to `feedback.json`, and the
agent reads them with `prtour feedback`.
- **On the PR**: `prtour post` posts one GitHub review with each note as
an inline comment on its line, and the summary on top. `--link <url>`
links the full page, and `--dry-run` prints the review without posting.
A stack gets one review per PR.
- **Cloud agents**: `prtour render -o review.html` (attach it) and
`prtour render --format md` (post it).
## What the page does

- Overview: the summary, the flow of the change, the reading order of notes,
and what was left out and why.
- Chapters, each with a "Reviewed" checkbox (remembered per browser) and
progress shown in the sidebar.
- `j` / `k` move between notes.
- Click any line number to comment on it. The comments are sent to the agent
under `prtour open`; otherwise **Copy feedback** puts them on the clipboard
as Markdown.
- "Not in review" holds every hidden file and hunk, collapsed, so nothing
skips review by accident.
- Stacks get a Stack list in the overview, with per-PR stats, and `#101`
badges on every file and note. Each PR's diff is against its own base, so
the same file changed in two PRs appears once per PR.
- Light and dark mode follow the system.
## Recaps

```sh
prtour recap --author you,teammate --since 2026-10-27 --until 2026-11-03
```
This gathers every PR the authors merged in that window into `recap.json`,
with one context file per PR. A context file holds the description, the
largest files, and what the person asked the agent that opened the PR. That
last part is read from local Claude Code and Codex transcripts and never
leaves your machine; pass `--no-lanes` to skip it.
The agent writes it as a product release post, for readers who have never
heard of the product:
- **Top stories.** A one-line `about` says what the product is. Then a lead
story and a grid of the next biggest, each with a headline, a line on why it
matters, and a real screenshot or clip, followed by a short TL;DR.
- **Headlines that say what happened.** Every section has a headline with the
outcome and a 2 to 4 word nav label such as "PDFs 5× faster". `prtour check`
flags titles that only name an area, like "Page renders".
- **Meet the new pieces.** A glossary explains each new engine, package or
internal name in one plain sentence. The first use of each term links to
it. `check` warns when a headline uses a code-looking name the glossary
doesn't cover.
- **Fixes, New and Better** below that, each leading with what people lived
through, why it happened, and the result: a Before/After timeline, a chart
of real measurements, the screenshots, and a few lines of the diff that
carry the idea. The biggest story's group goes first. Engineering detail is
folded away.
`check` still fails only on the 0.1 rules; this advice prints as
suggestions. Screenshots and clips are embedded in the page. `prtour media` compresses
them first: stills to webp or jpg at most 1600 px wide, clips to muted H.264
mp4 at most 1280 px wide with a poster frame, using ffmpeg, cwebp or sips.
Clips play muted and looped while on screen. The page carries Open Graph and
X card tags, and `--format thread` drafts an X thread with one post per top
story and the file to attach to each (`--media-dir` gathers them in one
folder). `"private": true` or `--no-links` leaves out the repo name and PR
links for a public post about a private repo. The recap also renders as a compact
PDF (clips as their poster frames), Markdown that links the media files, or
in the terminal.

## Design
Components come from [Basecoat](https://basecoatui.com), which is shadcn/ui
in plain HTML and CSS, so pages need no build step and stay one file. Type is
Geist for reviews and IBM Plex for recaps. Icons are [Lucide](https://lucide.dev)
and [SVGL](https://svgl.app). Diffs are [@pierre/diffs](https://diffs.com).
## Commands
```
prtour [target…] init + open in the browser
prtour init [target…] fetch the diff, scaffold .prtour/<slug>/tour.json (--stack, --dir)
prtour hunks [file…] list hunk indices; --lines adds old/new line numbers
prtour check [dir] validate tour.json against the diff (exit 1 on warnings)
prtour render [dir] self-contained HTML (-o file; --format md|term|pdf|thread; --split; --wrap; --media-dir; --no-links)
prtour show [dir] terminal view
prtour open [dir] live-reload server + reviewer feedback
prtour feedback [dir] reviewer comments as Markdown (--clear)
prtour post [dir] notes as an inline GitHub review (--link, --dry-run)
prtour recap what shipped across many PRs (--author, --since, --until, --repo, --no-lanes)
prtour media <file…> compress screenshots and clips for a recap (--dir <recap>, -o <dir>, --force)
prtour skill [--install] agent instructions
target: 123 | https://github.com/o/r/pull/123 | o/r#123 | main...HEAD | file.patch | -
```
PRs need [`gh`](https://cli.github.com) to be signed in. Ranges and the current
branch only need `git`. Node 20 or newer.
The `tour.json` and `recap.json` schemas are in
[skills/prtour/SKILL.md](./skills/prtour/SKILL.md).
## Credits
The idea comes from [@d0xxed's "hide the non-core edits" hunk
reviews](https://x.com/d0xxed/status/2117672152724083113) and [Capy's Guided
Reviews](https://x.com/0xluffy/status/2107593041519501477). Diff rendering is
[@pierre/diffs](https://diffs.com).
## License
MIT