@qwertybit/pr-preview 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +81 -0
- package/README.md +89 -28
- package/assets/demo.gif +0 -0
- package/assets/demo.mp4 +0 -0
- package/dist/cli/index.js +1029 -131
- package/dist/cli/index.js.map +1 -1
- package/dist/inpage/recorder.global.js +79 -14
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,84 @@ All notable changes to this project are documented here. The format follows
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project
|
|
5
5
|
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [0.1.5] — 2026-07-07
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- **New demo animation** — refreshed the README/npm demo with a designed
|
|
14
|
+
walkthrough of the full flow: a Claude Code prompt kicks off the run, the app is
|
|
15
|
+
driven automatically in a real Chrome window (add to cart → checkout, recording a
|
|
16
|
+
before/after), and out come `before.mp4` + `after.mp4`. Also available as an MP4.
|
|
17
|
+
|
|
18
|
+
## [0.1.4] — 2026-07-07
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- **The cursor is visible again** — the synthetic pointer is now anchored to the
|
|
23
|
+
viewport origin, so it no longer drifts off-frame (and out of the cropped clip)
|
|
24
|
+
when the app centers its layout with flexbox/grid. It's also larger, with an
|
|
25
|
+
always-on highlight halo, so it reads clearly once the clip is downscaled — and a
|
|
26
|
+
regression test now asserts it renders and moves across captured frames.
|
|
27
|
+
- **Motion smoothing actually applies now** — corrected the ffmpeg `minterpolate`
|
|
28
|
+
scene-change-detection argument. The previous value was an invalid token, so the
|
|
29
|
+
interpolation command failed on every clip and silently fell back to a
|
|
30
|
+
non-interpolated, choppy encode. MP4s now interpolate as intended, and the
|
|
31
|
+
fallback logs a warning instead of failing quietly.
|
|
32
|
+
|
|
33
|
+
### Changed
|
|
34
|
+
|
|
35
|
+
- **Snappier motion** — cursor glides, scrolling, and settle pauses are quicker now
|
|
36
|
+
that the capture runs at ~60fps during motion; the slow pacing was only needed for
|
|
37
|
+
the old low, variable capture rate.
|
|
38
|
+
|
|
39
|
+
### Added
|
|
40
|
+
|
|
41
|
+
- **Smoother recordings** — agent-driven clips now read as fluid video instead of
|
|
42
|
+
a slideshow. Three changes: (1) the CDP screencast is capped to ~the CSS window
|
|
43
|
+
size so Chrome stops JPEG-encoding full Retina-resolution frames, raising the
|
|
44
|
+
delivered frame rate; (2) the agent animates motion in-page — the synthetic
|
|
45
|
+
cursor glides (distance-scaled), scroll eases, and text types character-by-
|
|
46
|
+
character; (3) a new `gif.interpolate` option (`"blend"` default / `"mci"` /
|
|
47
|
+
`"off"`) synthesises intermediate MP4 frames from the real captured frames up to
|
|
48
|
+
`gif.smoothFps` (default 60), so a low, variable capture rate still plays smooth.
|
|
49
|
+
`"blend"` never warps text/geometry; `"mci"` is sharper with a slight warp risk
|
|
50
|
+
on fast-scrolling dense pages.
|
|
51
|
+
|
|
52
|
+
- **Claude Code integration via MCP** — a new `pr-preview mcp` command starts a
|
|
53
|
+
Model Context Protocol server (stdio) so an agent can record a journey from a
|
|
54
|
+
plain-English prompt. Claude reads the app's accessibility tree and drives it
|
|
55
|
+
with real clicks/typing, so the existing engine captures a real live clip — it
|
|
56
|
+
is agent-driven, not synthesized. Tools: `start_recording`, `snapshot`, `act`,
|
|
57
|
+
`next_pass`, `finish_recording`, `open_pr`, `cancel_recording`.
|
|
58
|
+
- **Agent before/after** — `start_recording({ mode: "before-after" })` records the
|
|
59
|
+
same journey on the PR base branch (in a git worktree) and on your branch,
|
|
60
|
+
producing `before.*` and `after.*`, all driven by the agent.
|
|
61
|
+
- **`open_pr` tool** — commits the clip into `pr-preview/`, pushes the branch, and
|
|
62
|
+
opens a pull request with the preview embedded (an inline GIF plus a link to the
|
|
63
|
+
full MP4). Requires the GitHub CLI (`gh`) authenticated.
|
|
64
|
+
- **`detect_localhost` tool + "never guess the URL"** — probes common dev-server
|
|
65
|
+
ports and reports which local apps are running (with page titles). When no URL
|
|
66
|
+
is given, the agent uses it to ask which running app to record, or to ask for a
|
|
67
|
+
local/staging/production URL — it never guesses.
|
|
68
|
+
- **`/record` slash command** — `init` installs a Claude Code skill at
|
|
69
|
+
`.claude/skills/record/SKILL.md`, so you can record any flow in one line:
|
|
70
|
+
`/record localhost:3000 add a book, then checkout`. It drives the recording
|
|
71
|
+
through the MCP tools (agent mode). Non-destructive: skipped if it already exists.
|
|
72
|
+
- **`init` now writes `.mcp.json`** (merging into an existing file) so Claude Code
|
|
73
|
+
discovers the server automatically, plus the `/record` skill above.
|
|
74
|
+
- **`init` prompts before overwriting** — when a `pr-preview` config, MCP server
|
|
75
|
+
entry, or `/record` skill already exists, it asks `Overwrite it? (y/N)` instead
|
|
76
|
+
of silently skipping. In a non-interactive shell (CI) it defaults to keeping the
|
|
77
|
+
existing file.
|
|
78
|
+
|
|
79
|
+
### Notes
|
|
80
|
+
|
|
81
|
+
- Agent before/after needs a managed dev server (omit `url`); already-running
|
|
82
|
+
apps (`--url`) remain single-clip in agent mode. Manual `pr-preview run` is
|
|
83
|
+
unchanged and still supports the full `--url` before/after flow.
|
|
84
|
+
|
|
7
85
|
## [0.1.0] — 2026-06-08
|
|
8
86
|
|
|
9
87
|
Initial release.
|
|
@@ -30,4 +108,7 @@ Initial release.
|
|
|
30
108
|
CSP `frame-ancestors`) are stripped.
|
|
31
109
|
- CLI: `pr-preview init`, `pr-preview record`, `pr-preview run`.
|
|
32
110
|
|
|
111
|
+
[Unreleased]: https://github.com/QwertyBit-Ventures/pr-preview/compare/v0.1.5...HEAD
|
|
112
|
+
[0.1.5]: https://github.com/QwertyBit-Ventures/pr-preview/compare/v0.1.4...v0.1.5
|
|
113
|
+
[0.1.4]: https://github.com/QwertyBit-Ventures/pr-preview/compare/v0.1.0...v0.1.4
|
|
33
114
|
[0.1.0]: https://github.com/QwertyBit-Ventures/pr-preview/releases/tag/v0.1.0
|
package/README.md
CHANGED
|
@@ -16,7 +16,11 @@
|
|
|
16
16
|
</p>
|
|
17
17
|
|
|
18
18
|
<p align="center">
|
|
19
|
-
<img src="https://cdn.jsdelivr.net/npm/@qwertybit/pr-preview/assets/demo.gif" alt="PR Preview demo —
|
|
19
|
+
<img src="https://cdn.jsdelivr.net/npm/@qwertybit/pr-preview/assets/demo.gif" alt="PR Preview demo — a Claude Code prompt drives the app in Chrome and produces before/after videos" width="720" />
|
|
20
|
+
</p>
|
|
21
|
+
|
|
22
|
+
<p align="center">
|
|
23
|
+
<a href="https://cdn.jsdelivr.net/npm/@qwertybit/pr-preview/assets/demo.mp4">▶ Watch in higher quality (MP4)</a>
|
|
20
24
|
</p>
|
|
21
25
|
|
|
22
26
|
**PR Preview** opens your app in a controlled Chrome window and records the journey you perform —
|
|
@@ -38,33 +42,35 @@ about a minute.
|
|
|
38
42
|
|
|
39
43
|
---
|
|
40
44
|
|
|
41
|
-
##
|
|
45
|
+
## Features
|
|
42
46
|
|
|
43
|
-
-
|
|
47
|
+
- **Record by demonstration** — just use your app. Clicks, typing, scrolling and navigation are
|
|
44
48
|
captured as an editable outline; no selectors or scripts to hand-write.
|
|
45
|
-
-
|
|
49
|
+
- **Live capture, zero drift** — the clip is your real recording, not a replay, so it never
|
|
46
50
|
desyncs on stateful apps. A synthetic cursor makes every move easy to follow.
|
|
47
|
-
-
|
|
51
|
+
- **True before/after** — the base branch runs in an isolated git **worktree**; your working
|
|
48
52
|
tree is never touched. Or point it at an app you already run with `--url`.
|
|
49
|
-
-
|
|
53
|
+
- **Tiny, sharp MP4s** — H.264, near-Full-HD, a few hundred KB. GitHub renders them inline in a
|
|
50
54
|
PR. High-quality GIF fallback when ffmpeg isn't installed.
|
|
51
|
-
-
|
|
55
|
+
- **Runs entirely on your machine** — nothing is uploaded. Your source and app data never leave
|
|
52
56
|
your computer.
|
|
53
|
-
-
|
|
54
|
-
-
|
|
57
|
+
- **Self-describing clips** — each is captioned with its branch and a timestamp.
|
|
58
|
+
- **Drive it from Claude Code** — a built-in MCP server lets Claude record a journey for you from
|
|
59
|
+
a plain-English prompt: it opens Chrome, performs the flow step by step, and can even open the PR.
|
|
60
|
+
Agent-driven, but still a real capture of your real app — never synthesized. Manual mode still works.
|
|
55
61
|
|
|
56
|
-
##
|
|
62
|
+
## Install
|
|
57
63
|
|
|
58
64
|
```bash
|
|
59
65
|
npm i -D @qwertybit/pr-preview
|
|
60
66
|
npx playwright install chromium # one-time browser download
|
|
61
|
-
npx pr-preview init # scaffolds pr-preview.config.js
|
|
67
|
+
npx pr-preview init # scaffolds pr-preview.config.js + .mcp.json (Claude Code)
|
|
62
68
|
```
|
|
63
69
|
|
|
64
70
|
> **ffmpeg** (optional, recommended) gives you MP4 output. macOS: `brew install ffmpeg` ·
|
|
65
71
|
> Debian/Ubuntu: `apt install ffmpeg`. Without it, PR Preview produces a high-quality GIF instead.
|
|
66
72
|
|
|
67
|
-
##
|
|
73
|
+
## Quick start
|
|
68
74
|
|
|
69
75
|
On your PR branch:
|
|
70
76
|
|
|
@@ -85,7 +91,7 @@ Both clips land in `.pr-preview/output/`. Drag them into your PR description —
|
|
|
85
91
|
Just need one clip (a demo, a bug repro)? `npx pr-preview run --single` records a single standalone
|
|
86
92
|
video, no comparison.
|
|
87
93
|
|
|
88
|
-
##
|
|
94
|
+
## How it works
|
|
89
95
|
|
|
90
96
|
A run is a short wizard shown in the harness sidebar:
|
|
91
97
|
|
|
@@ -103,7 +109,7 @@ Record Capture Record Capture Generate
|
|
|
103
109
|
keep a session you set up by hand (e.g. a manual login) — only shown when there's state to reset.
|
|
104
110
|
- **Refresh button** in the frame corner reloads the app whenever you need a clean slate.
|
|
105
111
|
|
|
106
|
-
##
|
|
112
|
+
## Output
|
|
107
113
|
|
|
108
114
|
| `format` | Result | Needs ffmpeg |
|
|
109
115
|
| --- | --- | --- |
|
|
@@ -113,7 +119,7 @@ Record Capture Record Capture Generate
|
|
|
113
119
|
|
|
114
120
|
MP4 is recommended: full color, far smaller than GIF, and GitHub embeds it inline.
|
|
115
121
|
|
|
116
|
-
##
|
|
122
|
+
## Configuration
|
|
117
123
|
|
|
118
124
|
Everything lives in `pr-preview.config.js` (or `.ts` / `.json`), so a project is set up once and
|
|
119
125
|
runs with **no flags**:
|
|
@@ -161,13 +167,14 @@ export default {
|
|
|
161
167
|
| `permissions` | allow-all | Browser permissions to grant (Playwright names). Unlisted ones stay denied — no native prompt blocks the run. |
|
|
162
168
|
| `geolocation` | — | Fixed `{ latitude, longitude }` so location apps render identical results in both clips. |
|
|
163
169
|
|
|
164
|
-
##
|
|
170
|
+
## CLI
|
|
165
171
|
|
|
166
172
|
| Command | What it does |
|
|
167
173
|
| --- | --- |
|
|
168
|
-
| `pr-preview init` | Scaffold `pr-preview.config.js
|
|
174
|
+
| `pr-preview init` | Scaffold `pr-preview.config.js`, a `.gitignore` entry, `.mcp.json`, and the `/record` Claude Code skill. |
|
|
169
175
|
| `pr-preview record` | Record a journey on the current branch only (`-o <file>`). |
|
|
170
176
|
| `pr-preview run` | The full before/after flow. |
|
|
177
|
+
| `pr-preview mcp` | Run the MCP server (stdio) so Claude Code can drive a recording. |
|
|
171
178
|
|
|
172
179
|
`run` flags: `-b, --base <ref>` (override base) · `--keep-worktree` (reuse the base worktree) ·
|
|
173
180
|
`-u, --url <url>` (use your own running app) · `-s, --single` (one standalone clip, no comparison).
|
|
@@ -185,14 +192,68 @@ npx pr-preview run --url http://localhost:3000
|
|
|
185
192
|
It records BEFORE on your running app, then **pauses** — you switch branches, restart on the same
|
|
186
193
|
URL, and click **Continue** — then it records AFTER. No worktree, no managed dev server.
|
|
187
194
|
|
|
188
|
-
##
|
|
195
|
+
## Use it from Claude Code
|
|
196
|
+
|
|
197
|
+
PR Preview ships an **MCP server** so Claude Code can record a journey for you — you describe the
|
|
198
|
+
flow in plain English and Claude drives your real app in Chrome, records it, and (optionally) opens
|
|
199
|
+
the PR. It's agent-driven, but still a real capture of your real app; nothing is synthesized.
|
|
200
|
+
|
|
201
|
+
**Setup** — `npx pr-preview init` writes a `.mcp.json` that registers the server:
|
|
202
|
+
|
|
203
|
+
```json
|
|
204
|
+
{ "mcpServers": { "pr-preview": { "command": "npx", "args": ["pr-preview", "mcp"] } } }
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Open the project in Claude Code (it auto-discovers `.mcp.json`) and just ask:
|
|
208
|
+
|
|
209
|
+
> **You:** Record my add-to-cart flow — add 3 books to the cart, then go to checkout. Then open the PR.
|
|
210
|
+
>
|
|
211
|
+
> **Claude:** *opens Chrome, performs each step live, renders `before.mp4` + `after.mp4`, and opens
|
|
212
|
+
> the pull request with the clip embedded.*
|
|
213
|
+
|
|
214
|
+
**The tools Claude uses:**
|
|
215
|
+
|
|
216
|
+
| Tool | What it does |
|
|
217
|
+
| --- | --- |
|
|
218
|
+
| `start_recording` | Open the app + start recording. `mode: "single"` (one clip) or `"before-after"`. Omit `url` to start your dev server; pass one to record an app you already run. |
|
|
219
|
+
| `snapshot` | Read the page as an accessibility tree with `[ref=eN]` handles. |
|
|
220
|
+
| `act` | Perform one action: `click` / `fill` / `press` / `hover` / `navigate` / `scroll` / `wait`. |
|
|
221
|
+
| `next_pass` | *(before-after)* finish the BEFORE clip, switch to your branch, start AFTER. |
|
|
222
|
+
| `finish_recording` | Stop, encode, and return the clip path(s). |
|
|
223
|
+
| `open_pr` | Commit the clip, push the branch, and open a PR with the preview embedded. |
|
|
224
|
+
| `detect_localhost` | Probe common dev-server ports and report which local apps are running (with their page titles). |
|
|
225
|
+
| `cancel_recording` | Abort and close the browser without producing a clip. |
|
|
226
|
+
|
|
227
|
+
Claude targets elements by their accessible name (no selectors or scripts), so it works on any app.
|
|
228
|
+
|
|
229
|
+
**No URL? Claude asks — it never guesses.** If you don't name a URL, Claude runs `detect_localhost`
|
|
230
|
+
first: if apps are running it asks which one to record; if none are, it asks for a local, staging, or
|
|
231
|
+
production URL. That way it always records the app you meant.
|
|
232
|
+
|
|
233
|
+
**The `/record` slash command.** `init` also installs a Claude Code skill at
|
|
234
|
+
`.claude/skills/record/SKILL.md`, so you can record any flow in one line:
|
|
235
|
+
|
|
236
|
+
```
|
|
237
|
+
/record localhost:3000 add a book to the cart, then checkout
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
The skill drives the recording through the MCP tools above (agent mode), resolving the URL the same
|
|
241
|
+
way. It's non-destructive — `init` skips it if the file already exists.
|
|
242
|
+
|
|
243
|
+
**Before/after in agent mode** needs a managed dev server (omit `url`) and for you to be on a PR
|
|
244
|
+
branch: Claude records the journey on the base branch (in a git worktree), then redoes the *same*
|
|
245
|
+
journey on your branch. `--url` / already-running apps stay single-clip in agent mode, since an
|
|
246
|
+
external app can't be branch-swapped without you.
|
|
247
|
+
|
|
248
|
+
**About `open_pr`:** GitHub only plays inline video from its own attachment CDN (no public API), so
|
|
249
|
+
the open-source path embeds an animated **GIF** (rendered inline) and links the full MP4. It creates
|
|
250
|
+
a commit on your branch and pushes it, and needs the [GitHub CLI](https://cli.github.com) (`gh`)
|
|
251
|
+
authenticated. One-click *hosted video in the PR body* is part of PR Preview for Teams.
|
|
189
252
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
through the ~30-second journey**, and the agent picks up the finished `before.mp4` / `after.mp4` to
|
|
193
|
-
drop into your PR. The agent triggers and finalizes; you demonstrate the journey.
|
|
253
|
+
**Prefer to record by hand?** Manual mode is unchanged: `npx pr-preview run` opens Chrome for you to
|
|
254
|
+
click through yourself. Both modes produce the same clips — the only difference is whose hands drive.
|
|
194
255
|
|
|
195
|
-
##
|
|
256
|
+
## Privacy
|
|
196
257
|
|
|
197
258
|
PR Preview runs locally — it opens your app in a Chrome window, records, and writes video files to
|
|
198
259
|
your project. Nothing is uploaded. The clip is a real screen recording, so avoid typing real
|
|
@@ -216,25 +277,25 @@ PR Preview drives a real app inside a controlled browser, so a few things are ou
|
|
|
216
277
|
|
|
217
278
|
## Contributing
|
|
218
279
|
|
|
219
|
-
See [CONTRIBUTING.md](./CONTRIBUTING.md). Issues and PRs welcome — and a
|
|
280
|
+
See [CONTRIBUTING.md](./CONTRIBUTING.md). Issues and PRs welcome — and a star helps a lot.
|
|
220
281
|
|
|
221
282
|
## License & what's free
|
|
222
283
|
|
|
223
284
|
The **CLI is open source under the [MIT license](./LICENSE)** — free to use, including commercially.
|
|
224
285
|
This is an open-core project:
|
|
225
286
|
|
|
226
|
-
-
|
|
287
|
+
- **This CLI** — recording and before/after clip generation. MIT, free forever. Clips carry a
|
|
227
288
|
small `pr-preview.com` watermark.
|
|
228
|
-
-
|
|
289
|
+
- **PR Preview for Teams** ([pr-preview.com](https://pr-preview.com)) — the hosted service:
|
|
229
290
|
clip hosting, a synced review player, team reviewers & comments, sharing, and watermark-free
|
|
230
291
|
clips. A separate, proprietary commercial offering — *coming soon*.
|
|
231
|
-
-
|
|
292
|
+
- The **"PR Preview" name and logo** are trademarks of SC QWERTYBIT SRL; the MIT license covers
|
|
232
293
|
the code, not the brand.
|
|
233
294
|
|
|
234
295
|
---
|
|
235
296
|
|
|
236
297
|
<p align="center">
|
|
237
|
-
<a href="https://pr-preview.com"><strong
|
|
298
|
+
<a href="https://pr-preview.com"><strong>pr-preview.com</strong></a><br/>
|
|
238
299
|
<sub>See it in action, and <a href="https://pr-preview.com/#teams">join the early-access list for PR Preview for Teams</a> —<br/>
|
|
239
300
|
hosted clips, team reviews & sharing, coming soon.</sub>
|
|
240
301
|
</p>
|
package/assets/demo.gif
CHANGED
|
Binary file
|
package/assets/demo.mp4
ADDED
|
Binary file
|