page-harness 0.1.2 → 0.1.4
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/LICENSE +421 -21
- package/README.md +231 -54
- package/README.zh-CN.md +231 -54
- package/dist/cli.js +2008 -654
- package/dist/cli.js.map +1 -1
- package/dist/client/app/assets/{history-Clt0CHe-.js → history-BpjPiEWL.js} +1 -1
- package/dist/client/app/assets/{index.es-BK9-mTsa.js → index.es-5I8QYCO4.js} +1 -1
- package/dist/client/app/assets/{jspdf.es.min-Qzb6sJ_Q.js → jspdf.es.min-BF5gKf3S.js} +4 -4
- package/dist/client/app/assets/{panel-B47-AaSQ.js → panel-DWp67jXP.js} +2 -2
- package/dist/client/app/assets/{ws-DAWfQL6l.js → ws-Kt3Cg5KH.js} +1 -1
- package/dist/client/app/history.html +2 -2
- package/dist/client/app/panel.html +2 -2
- package/dist/client/page/live-overlay.js +2 -2
- package/dist/client/page/overlay.js +29 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,72 +1,110 @@
|
|
|
1
|
-
|
|
1
|
+
<!-- TODO(Tencent OSS): swap in the Tencent open-source hero banner (en / zh) once brand guidelines are confirmed. No marketing copy in the image. -->
|
|
2
|
+
<p align="center">
|
|
3
|
+
<img src="./docs/logo.svg" width="72" alt="page-harness logo">
|
|
4
|
+
</p>
|
|
2
5
|
|
|
3
|
-
|
|
6
|
+
<h1 align="center">page-harness</h1>
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
<p align="center">
|
|
9
|
+
<a href="https://www.npmjs.com/package/page-harness"><img alt="npm page-harness" src="https://img.shields.io/npm/v/page-harness?label=npm&labelColor=16161A&color=7C5CFF&style=flat-square"></a>
|
|
10
|
+
<a href="./LICENSE"><img alt="License" src="https://img.shields.io/badge/license-MIT-7C5CFF?labelColor=16161A&color=7C5CFF&style=flat-square"></a>
|
|
11
|
+
<img alt="Node" src="https://img.shields.io/badge/node-%E2%89%A520.11-7C5CFF?labelColor=16161A&color=7C5CFF&style=flat-square">
|
|
12
|
+
<!-- TODO(Tencent OSS): enable the line below (Release / Stars / CI) once the repo URL is final; replace TODO/page-harness. -->
|
|
13
|
+
<!-- <a href="https://github.com/TODO/page-harness/releases"><img alt="Release" src="https://img.shields.io/github/v/release/TODO/page-harness?labelColor=16161A&color=7C5CFF&style=flat-square"></a>
|
|
14
|
+
<a href="https://github.com/TODO/page-harness/stargazers"><img alt="Stars" src="https://img.shields.io/github/stars/TODO/page-harness?labelColor=16161A&color=7C5CFF&style=flat-square"></a>
|
|
15
|
+
<br/>
|
|
16
|
+
<a href="https://github.com/TODO/page-harness/actions/workflows/ci.yml"><img alt="ci" src="https://img.shields.io/github/actions/workflow/status/TODO/page-harness/ci.yml?branch=main&label=ci&labelColor=16161A&style=flat-square"></a> -->
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
<p align="center">
|
|
20
|
+
<b>English</b> · <a href="./README.zh-CN.md">简体中文</a>
|
|
21
|
+
</p>
|
|
22
|
+
|
|
23
|
+
<p align="center">
|
|
24
|
+
<a href="#overview">Overview</a> ·
|
|
25
|
+
<a href="#quick-start">Quick start</a> ·
|
|
26
|
+
<a href="#product-tour">Product tour</a> ·
|
|
27
|
+
<a href="#features">Features</a> ·
|
|
28
|
+
<a href="#usage">Usage</a> ·
|
|
29
|
+
<a href="#documentation">Docs</a> ·
|
|
30
|
+
<a href="#development">Development</a>
|
|
31
|
+
</p>
|
|
32
|
+
|
|
33
|
+
<p align="center">
|
|
34
|
+
<a href="docs/hero.mp4?raw=true">
|
|
35
|
+
<img src="./docs/hero.webp" width="720" alt="page-harness promo video (0:30)">
|
|
36
|
+
</a>
|
|
37
|
+
</p>
|
|
38
|
+
|
|
39
|
+
<p align="center"><sub>0:30 · 1080p · click to open the mp4 (with sound)</sub></p>
|
|
40
|
+
|
|
41
|
+
## Overview
|
|
42
|
+
|
|
43
|
+
> **TODO (Tencent OSS):** Tencent logo, attribution line and compliance notes are pending confirmation. Repo URL is a placeholder: `https://github.com/TODO/page-harness`.
|
|
44
|
+
|
|
45
|
+
**Turn any running web page into a workspace for your coding agent.**
|
|
46
|
+
|
|
47
|
+
Click the thing you want changed and tell your agent what to do, right on the page: Pick, Chat and Artifacts, driven by the agent CLI already on your machine (Claude Code, Codex, Cursor Agent, CodeBuddy Code, OpenCode). For feedback only, `--no-agent` keeps just Pick and Notes; run it with no URL and you get a home page with a **✦ Page-Harness** bookmarklet that works on any site.
|
|
48
|
+
|
|
49
|
+
Describing UI in a terminal is painful: "the second button in the card on the left, make it a bit softer". With page-harness you just click the thing on the page and talk to your agent right there. It writes the code, your dev server reloads, you see the result on the same page.
|
|
50
|
+
|
|
51
|
+
## Quick start
|
|
52
|
+
|
|
53
|
+
One line. Point it at your dev server:
|
|
6
54
|
|
|
7
55
|
```bash
|
|
8
|
-
npx page-harness http://localhost:5173 --project ./my-app
|
|
9
|
-
|
|
56
|
+
npx page-harness http://localhost:5173 --project ./my-app
|
|
57
|
+
npx page-harness --no-agent http://localhost:5173 # review only: Pick and Notes, no agent CLI
|
|
58
|
+
npx page-harness # no URL: home page with a bookmarklet
|
|
10
59
|
```
|
|
11
60
|
|
|
12
|
-
|
|
61
|
+
Open **http://127.0.0.1:17990**. That is your app as usual, plus a dock in the bottom-right corner.
|
|
13
62
|
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
- **Artifacts** — the agent writes reports, mockups, JSON, images and other files through MCP. Preview them in tabs with version history: Markdown, sandboxed HTML (desktop / mobile widths), structured JSON, code, images; copy, download, export to PNG or PDF.
|
|
18
|
-
- **Notes** — comment on or edit elements in place, threaded replies, resolve and per-page approval; teammates on your network can join as reviewers with `--share`. Works on sites you have no source for.
|
|
19
|
-
- **Questions** — the agent can ask you multiple-choice questions or a short form and wait for the answer.
|
|
20
|
-
- **History** — every chat is an append-only event log on disk. Browse, search and export it at `http://127.0.0.1:17991/__ph/history`, or from the chat switcher.
|
|
63
|
+
- Needs **Node.js 20.11+** and at least one signed-in agent CLI on `PATH` (see below).
|
|
64
|
+
- The target can be a bare port (`3000`), `host:port` or a full URL. HMR (Vite, webpack, Next.js…) keeps working through the proxy.
|
|
65
|
+
- No sandbox, no accounts, no changes to your app. Everything stays in `<project>/.page-harness/`.
|
|
21
66
|
|
|
22
|
-
|
|
67
|
+
| Service | URL |
|
|
68
|
+
|---|---|
|
|
69
|
+
| Your app + dock | `http://127.0.0.1:17990` |
|
|
70
|
+
| Panel / API (control port) | `http://127.0.0.1:17991` |
|
|
71
|
+
| Chat history | `http://127.0.0.1:17991/__ph/history` |
|
|
72
|
+
| Bookmarklet home (no URL) | `http://127.0.0.1:17991` |
|
|
23
73
|
|
|
24
|
-
|
|
25
|
-
- At least one agent CLI on `PATH`, signed in:
|
|
26
|
-
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code) (`claude`)
|
|
27
|
-
- [Codex](https://github.com/openai/codex) (`codex`)
|
|
28
|
-
- [Cursor Agent](https://docs.cursor.com/en/cli/overview) (`cursor-agent`)
|
|
29
|
-
- [CodeBuddy Code](https://www.codebuddy.ai/cli) (`codebuddy`, `npm i -g @tencent-ai/codebuddy-code`)
|
|
30
|
-
- [OpenCode](https://opencode.ai) (`opencode`, `npm i -g opencode-ai`)
|
|
74
|
+
### Other ways to run
|
|
31
75
|
|
|
32
|
-
|
|
76
|
+
| Option | When to use it |
|
|
77
|
+
|---|---|
|
|
78
|
+
| `npx page-harness <url>` | The standard setup above: your app behind the proxy, with Pick, Chat and Artifacts driven by an agent CLI |
|
|
79
|
+
| `--no-agent <url>` | Feedback only: Pick and Notes, no agent CLI needed ([details](#review-only---no-agent)) |
|
|
80
|
+
| no URL | A home page with the **✦ Page-Harness** bookmarklet, to leave notes on any site without a proxy ([details](#bookmarklet-no-url)) |
|
|
81
|
+
| `--share` | Teammates on your network join as reviewers with a link ([details](#team-review---share)) |
|
|
33
82
|
|
|
34
|
-
|
|
83
|
+
## Product tour
|
|
35
84
|
|
|
36
|
-
|
|
37
|
-
|---|---|---|---|---|---|
|
|
38
|
-
| Streaming text / thinking | ✓ | ✓ | ✓ | ✓ | per block¹ |
|
|
39
|
-
| Tool cards, changed files | ✓ | ✓ | ✓ | ✓ | ✓¹ |
|
|
40
|
-
| Resume a chat | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
41
|
-
| Model list | ✓ | ✓ | ✓ | ✓ (from `--help`) | ✓ (`opencode models`) |
|
|
42
|
-
| Reasoning effort | – | ✓ | – | ✓ (`--effort`) | ✓ (`--variant`) |
|
|
43
|
-
| Image attachments | ✓ | ✓ | file path in prompt | ✓ | ✓ (`--file`) |
|
|
85
|
+
### Review only
|
|
44
86
|
|
|
45
|
-
|
|
87
|
+
**Pick and Notes, nothing else.** With `--no-agent` no agent CLI is started. Pick an element, leave a comment or an edit, reply, resolve and approve per page. [Details →](#review-only---no-agent)
|
|
46
88
|
|
|
47
|
-
|
|
89
|
+
<p align="center"><img src="./docs/review-only.png" width="720" alt="Page notes panel in review-only mode"></p>
|
|
48
90
|
|
|
49
|
-
|
|
50
|
-
page-harness <frontend-url> [options]
|
|
91
|
+
### Bookmarklet home
|
|
51
92
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
--live-guard-hook Install a git pre-commit hook that rejects Live candidate markers
|
|
64
|
-
--review / --source Force review mode (no source) or source mode; default is by host
|
|
65
|
-
--share Let teammates on your network join as reviewers (listens on 0.0.0.0)
|
|
66
|
-
--verbose / --quiet
|
|
67
|
-
```
|
|
93
|
+
**One button to drag.** Run `npx page-harness` with no URL and the home page has a single **✦ Page-Harness** button. Drag it to the bookmarks bar. [Details →](#bookmarklet-no-url)
|
|
94
|
+
|
|
95
|
+
<p align="center"><img src="./docs/home.png" width="520" alt="Home page with the ✦ Page-Harness button"></p>
|
|
96
|
+
|
|
97
|
+
### Notes on any site
|
|
98
|
+
|
|
99
|
+
**Click the bookmark on any page.** The dock is injected into that page in a Shadow DOM, with no proxy, and notes are saved to your local server, grouped by site.
|
|
100
|
+
|
|
101
|
+
<p align="center"><img src="./docs/bookmarklet.png" width="720" alt="Bookmarklet dock on a plain page"></p>
|
|
102
|
+
|
|
103
|
+
### My notes
|
|
68
104
|
|
|
69
|
-
|
|
105
|
+
**Every site's notes in one place.** Sites on the left, that site's notes on the right, with Export Markdown, Export JSON and Copy prompt for your agent.
|
|
106
|
+
|
|
107
|
+
<p align="center"><img src="./docs/home-notes.png" width="720" alt="My notes view"></p>
|
|
70
108
|
|
|
71
109
|
## How it works
|
|
72
110
|
|
|
@@ -124,7 +162,7 @@ When the target is a public site (anything that is not localhost, a private IP o
|
|
|
124
162
|
|
|
125
163
|
Notes work in both modes; hand edits and `page_patch` only without source.
|
|
126
164
|
|
|
127
|
-
- Notes belong to the page they were made on (path without hash, trailing slash or tracking parameters). **This page** shows the current page; **All** groups every page, and clicking a note on another page goes there and opens it. The dock badge counts open notes on the current page and shows a dot when other pages have some.
|
|
165
|
+
- Notes belong to the page they were made on (path without hash, trailing slash or tracking parameters) and to the **site** (`host`, hostname plus a non-default port). Proxy mode stores the target host; the bookmarklet stores `location.host`. The overlay only pins notes for the site you are on. **This page** shows the current page; **All** groups every page of that site, and clicking a note on another page goes there and opens it. The dock badge counts open notes on the current page and shows a dot when other pages have some.
|
|
128
166
|
- Each pin opens a thread: author, replies, Resolve / Reopen, compare a change with the original, quote the element into the chat (owner) and delete (author or owner).
|
|
129
167
|
- **Approve** / **Request changes** records a verdict per page and person.
|
|
130
168
|
- Pins are re-attached with a fingerprint (tag, id, stable classes, key attributes, text and its context) when the selector breaks after a re-render or a redesign. If nothing fits well enough the note is shown as *not found on the page* instead of being pinned to the wrong element. Changes are re-applied after reloads and re-renders; nothing is sent to the site.
|
|
@@ -140,6 +178,101 @@ npx page-harness https://example.com --share
|
|
|
140
178
|
|
|
141
179
|
Send the Share link (also in Settings → Team) to teammates on the same network. Opening it gives them a reviewer session for that browser; they enter a display name once and then see the page with everyone's notes and changes in real time. Reviewers can comment, edit (review mode), reply, resolve and approve. They cannot run or see the agent, chats, history, uploads or page control. Other machines without the link get `403`.
|
|
142
180
|
|
|
181
|
+
## Features
|
|
182
|
+
|
|
183
|
+
| Area | Highlights |
|
|
184
|
+
|---|---|
|
|
185
|
+
| **Pick** | Click any element and **Quote in chat** (selector, text and HTML go along; Shift+click quotes directly), **Comment**, **Edit** (sites without source) or start **Live candidates**. |
|
|
186
|
+
| **Live candidates** | Describe a change and the agent writes 2–4 variants straight into your source. Flip between them on the page, compare side by side, tune parameters, refine one, then accept or discard. |
|
|
187
|
+
| **Chat** | Draggable, resizable window with streaming Markdown, collapsible thinking, tool cards, changed-file lists, image/file attachments, a reorderable per-chat queue, Stop / Retry, multiple chats with per-chat agent and model. |
|
|
188
|
+
| **Artifacts** | The agent writes reports, mockups, JSON and images through MCP. Preview them in tabs with version history; export to PNG or PDF. |
|
|
189
|
+
| **Page control (off by default)** | Let the agent read, click, type, select and scroll on the page. A banner shows while it is on; Stop takes it back any time. |
|
|
190
|
+
| **Notes & review** | Pin threaded comments to elements, resolve them and approve per page. Works on sites you have no source for (review mode). |
|
|
191
|
+
| **Team review** | `--share` lets teammates on your network join as reviewers with a link. |
|
|
192
|
+
| **Questions** | The agent can ask you multiple-choice questions or a short form and wait for the answer. |
|
|
193
|
+
| **History** | Every chat is an append-only event log on disk; browse, search and export it. |
|
|
194
|
+
|
|
195
|
+
### Supported agents
|
|
196
|
+
|
|
197
|
+
page-harness drives the CLI you already use and detects which ones are installed:
|
|
198
|
+
|
|
199
|
+
| Agent | Command | Install |
|
|
200
|
+
|---|---|---|
|
|
201
|
+
| [Claude Code](https://docs.anthropic.com/en/docs/claude-code) | `claude` | see docs |
|
|
202
|
+
| [Codex](https://github.com/openai/codex) | `codex` | see docs |
|
|
203
|
+
| [Cursor Agent](https://docs.cursor.com/en/cli/overview) | `cursor-agent` | see docs |
|
|
204
|
+
| [CodeBuddy Code](https://www.codebuddy.ai/cli) | `codebuddy` | `npm i -g @tencent-ai/codebuddy-code` |
|
|
205
|
+
| [OpenCode](https://opencode.ai) | `opencode` | `npm i -g opencode-ai` |
|
|
206
|
+
|
|
207
|
+
Pick one with `--agent claude|codex|cursor|codebuddy|opencode` (default: the first one installed). Non-standard locations: `--claude-path`, `--codex-path`, `--cursor-path`, `--codebuddy-path`, `--opencode-path`.
|
|
208
|
+
|
|
209
|
+
| | Claude Code | Codex | Cursor Agent | CodeBuddy Code | OpenCode |
|
|
210
|
+
|---|---|---|---|---|---|
|
|
211
|
+
| Streaming text / thinking | ✓ | ✓ | ✓ | ✓ | per block¹ |
|
|
212
|
+
| Tool cards, changed files | ✓ | ✓ | ✓ | ✓ | ✓¹ |
|
|
213
|
+
| Resume a chat | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
214
|
+
| Model list | ✓ | ✓ | ✓ | ✓ (from `--help`) | ✓ (`opencode models`) |
|
|
215
|
+
| Reasoning effort | – | ✓ | – | ✓ (`--effort`) | ✓ (`--variant`) |
|
|
216
|
+
| Image attachments | ✓ | ✓ | file path in prompt | ✓ | ✓ (`--file`) |
|
|
217
|
+
|
|
218
|
+
¹ `opencode run --format json` reports text, reasoning and tool calls once each part has finished, so replies arrive a block at a time and a tool card opens and closes together.
|
|
219
|
+
|
|
220
|
+
## Usage
|
|
221
|
+
|
|
222
|
+
```text
|
|
223
|
+
page-harness [frontend-url] [options]
|
|
224
|
+
|
|
225
|
+
--project <dir> Project the agent works in (default: current directory)
|
|
226
|
+
--agent <id> claude | codex | cursor | codebuddy | opencode (default: first one installed)
|
|
227
|
+
--model <name> Default model for new chats
|
|
228
|
+
--port <n> App port: the proxied frontend (default 17990)
|
|
229
|
+
--control-port <n> Panel / API port (default: app port + 1, or 17991 with no URL)
|
|
230
|
+
--host <addr> Listen address (default 127.0.0.1)
|
|
231
|
+
--allow-host <name> Extra Host header to accept (repeatable), e.g. a LAN name
|
|
232
|
+
--keep-host Forward the browser's Host header to the target
|
|
233
|
+
--public-scheme <s> http | https: scheme browsers use to reach both ports (default http);
|
|
234
|
+
https behind a load balancer that terminates TLS on the same ports
|
|
235
|
+
--open Open the browser
|
|
236
|
+
--live-guard-hook Install a git pre-commit hook that rejects Live candidate markers
|
|
237
|
+
--review / --source Force review mode (no source) or source mode; default is by host
|
|
238
|
+
--no-agent Review only. Do not detect or start an agent CLI.
|
|
239
|
+
The dock is Pick and Notes. Implied when no URL is given.
|
|
240
|
+
--lang <zh|en> Home page and dock language. Omit it and each browser keeps its own.
|
|
241
|
+
--share Let teammates on your network join as reviewers (listens on 0.0.0.0)
|
|
242
|
+
--verbose / --quiet
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
`<frontend-url>` can be a bare port (`3000`), `host:port` or a full URL. Omit it to start the bookmarklet home page. Dev-server HMR (Vite, webpack, Next.js…) keeps working through the proxy, including WebSockets.
|
|
246
|
+
|
|
247
|
+
### Review only (`--no-agent`)
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
npx page-harness --no-agent http://localhost:5173
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
No agent CLI is detected or started, and MCP is refused. The dock is **Pick** and **Notes** only: comment, edit, reply, resolve and approve. Chat, Artifacts, Live, page control and questions are not shown. Notes are still saved in the project's `review.json`, under the **target** site's host (not the proxy's `127.0.0.1:17990`).
|
|
254
|
+
|
|
255
|
+
### Bookmarklet (no URL)
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
npx page-harness
|
|
259
|
+
# Home http://127.0.0.1:17991
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
This starts only the control server, always in review-only mode. The home page is one button, **✦ Page-Harness**: drag it to the bookmarks bar, open any site and click it. **Having trouble?** on the home page lists the usual reasons it does nothing. The bookmark only works for this run; drag it again after a restart. The overlay is injected into that page (no reverse proxy) inside a Shadow DOM, so the host page's CSS does not restyle the dock. The script always loads from this server: `http://127.0.0.1:<control-port>/__ph/overlay.js`.
|
|
263
|
+
|
|
264
|
+
`--lang zh` or `--lang en` sets the home page and the dock (including exported Markdown and the copied prompt). Omit it and each browser uses its saved choice, or the browser language.
|
|
265
|
+
|
|
266
|
+
Notes are written to this local server and grouped by site (`location.host`, including a non-default port). **My notes (n)** at the top right opens the notes view: sites on the left, that site's notes on the right, with Export Markdown, Export JSON and Copy prompt. The copied prompt calls this control server and includes `host=` so an agent only pulls that site:
|
|
267
|
+
|
|
268
|
+
```text
|
|
269
|
+
GET http://127.0.0.1:17991/__ph/api/review?scope=all&path=%2F&page=1&pageSize=20&host=shop.example.com
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
The same `host` query works on the paging API when you want one site. Omit it and the API still returns every site, as before.
|
|
273
|
+
|
|
274
|
+
**Limits.** An https page usually blocks a script loaded from `http://127.0.0.1` (mixed content), and saving a note still calls that http control port. Chrome generally allows `127.0.0.1` and may ask for local-network access; the server answers `Access-Control-Allow-Private-Network` on the bookmarklet routes. Firefox and Safari often block that request as mixed content. A host page CSP that forbids connections to `127.0.0.1` blocks saving too. When the bookmarklet cannot reach the control port, use `page-harness <url> --no-agent` and review through the proxy instead. The bookmarklet carries a per-run token (`X-PH-Token`). It is visible in the bookmark and on pages where you click it; other sites cannot read or write notes without it. The unauthenticated paging API (`GET /__ph/api/review`) does not send CORS headers, so a random page cannot read notes through it.
|
|
275
|
+
|
|
143
276
|
## Security model
|
|
144
277
|
|
|
145
278
|
There is no login: it is a local developer tool and binds to `127.0.0.1` by default. Internally every surface is locked down:
|
|
@@ -147,7 +280,7 @@ There is no login: it is a local developer tool and binds to `127.0.0.1` by defa
|
|
|
147
280
|
- **Two origins.** Your app (and any script on it) runs on the app port; the panel, API and agent endpoints are on the control port, so page scripts cannot read them.
|
|
148
281
|
- **Owner and reviewers.** Without `--share` only this machine can connect and everything behaves as one user. With `--share`, the owner session is only issued to loopback requests; other machines need the invite link, which sets signed (HMAC) reviewer cookies for the panel and the app port; without them both ports answer `403`. Reviewers are limited to the review actions on the WebSocket and to reading artifacts; everything else returns `403`. Name the owner in Settings → Team.
|
|
149
282
|
- **Session cookie.** The panel gets an `HttpOnly`, `SameSite=Strict` cookie scoped to `/__ph`; the cookie is stripped before requests are forwarded to your dev server.
|
|
150
|
-
- **API.** Reads require a same-origin `Sec-Fetch-Site`; writes require a matching `Origin` plus a custom `X-PH` header. The WebSocket checks the cookie and `Origin`.
|
|
283
|
+
- **API.** Reads require a same-origin `Sec-Fetch-Site`; writes require a matching `Origin` plus a custom `X-PH` header. The WebSocket checks the cookie and `Origin`. The bookmarklet is the exception: cross-origin review reads and writes need the per-run `X-PH-Token`, and the response reflects that page's `Origin` (never `*`). `GET /__ph/api/review` stays callable from curl without CORS headers.
|
|
151
284
|
- **MCP.** Every agent turn gets its own bearer token (passed through an environment variable or a private temp file, never on the command line) that is revoked when the turn ends. Browser requests to the MCP endpoint are rejected.
|
|
152
285
|
- **Host allow-list.** Requests with unexpected `Host` headers get `421` (DNS rebinding). Add names with `--allow-host` if you expose it on a LAN.
|
|
153
286
|
- **Framing.** The panel may only be framed by the app origin; the history page cannot be framed at all.
|
|
@@ -172,6 +305,38 @@ team.json invite token, signing key and reviewer names (mode 6
|
|
|
172
305
|
|
|
173
306
|
Delete the folder to start over.
|
|
174
307
|
|
|
308
|
+
## FAQ
|
|
309
|
+
|
|
310
|
+
**Do I need to change my app?**
|
|
311
|
+
No. page-harness is a reverse proxy that injects one script into HTML responses. Your code is untouched unless the agent edits it.
|
|
312
|
+
|
|
313
|
+
**Does it work on sites I don't have the source for?**
|
|
314
|
+
Yes. Public URLs start in review mode: the agent leaves notes and temporary page changes instead of editing files. Force it with `--review` / `--source`.
|
|
315
|
+
|
|
316
|
+
**Which model does it use? Do I need an API key?**
|
|
317
|
+
Whatever your agent CLI is signed in with. page-harness has no accounts or keys of its own; pick the model per chat.
|
|
318
|
+
|
|
319
|
+
**Is it safe to expose?**
|
|
320
|
+
It binds to `127.0.0.1` with no login by default. `--share` opens it to your network with signed reviewer links. Agents run with non-interactive permissions inside `--project`, so only use it on projects you'd let the agent edit.
|
|
321
|
+
|
|
322
|
+
**What if Live markers end up in my code?**
|
|
323
|
+
page-harness scans the working tree after every Live or file-editing turn and warns you; `--live-guard-hook` installs a pre-commit hook that rejects them.
|
|
324
|
+
|
|
325
|
+
**How do I reset?**
|
|
326
|
+
Delete `<project>/.page-harness/`.
|
|
327
|
+
|
|
328
|
+
## Documentation
|
|
329
|
+
|
|
330
|
+
| Start here | |
|
|
331
|
+
|---|---|
|
|
332
|
+
| [Quick start](#quick-start) | Install and the first run |
|
|
333
|
+
| [Usage](#usage) | All CLI options, review only and the bookmarklet |
|
|
334
|
+
| [How it works](#how-it-works) | Proxy, overlay, MCP tools, Live candidates, review mode |
|
|
335
|
+
| [Security model](#security-model) | What is locked down and how |
|
|
336
|
+
| [Data](#data) | What is stored in `.page-harness/` |
|
|
337
|
+
| [FAQ](#faq) | Common questions |
|
|
338
|
+
| [npm package](https://www.npmjs.com/package/page-harness) | Released versions |
|
|
339
|
+
|
|
175
340
|
## Development
|
|
176
341
|
|
|
177
342
|
```bash
|
|
@@ -188,6 +353,18 @@ npm run build && npm run test:e2e # browser tests against a fixture app
|
|
|
188
353
|
|
|
189
354
|
`PH_FAKE_AGENT=1` adds a scripted `fake` agent used by the tests; it drives the real MCP endpoint, so the whole pipeline is exercised without an LLM.
|
|
190
355
|
|
|
356
|
+
## Contributing
|
|
357
|
+
|
|
358
|
+
Issues and pull requests are welcome at `https://github.com/TODO/page-harness` (placeholder until the public repo URL is final).
|
|
359
|
+
|
|
360
|
+
- **Process:** Fork → create a branch → commit → open a PR
|
|
361
|
+
- **Before you push:** `npm run lint`, `npm run typecheck` and `npm test`; for UI changes also `npm run build && npm run test:e2e`
|
|
362
|
+
|
|
363
|
+
<!-- TODO(Tencent OSS): contributors image once the repo URL is final:
|
|
364
|
+
[](https://github.com/TODO/page-harness/graphs/contributors) -->
|
|
365
|
+
|
|
191
366
|
## License
|
|
192
367
|
|
|
193
368
|
[MIT](./LICENSE). Bundled third-party code is listed in [THIRD_PARTY_LICENSES.md](./THIRD_PARTY_LICENSES.md).
|
|
369
|
+
|
|
370
|
+
<!-- TODO(Tencent OSS): copyright holder / Tencent attribution and any required compliance or security-contact section go here. -->
|