sitedrift 0.1.0 → 0.2.0
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/AGENTS.md +101 -0
- package/README.md +151 -27
- package/assets/viewer.css +766 -0
- package/assets/viewer.html +159 -0
- package/assets/viewer.js +859 -0
- package/docs/images/sitedrift-collaboration.jpg +0 -0
- package/docs/images/sitedrift-diff.jpg +0 -0
- package/docs/images/sitedrift-mobile.jpg +0 -0
- package/docs/images/sitedrift-split.jpg +0 -0
- package/package.json +19 -4
- package/sitedrift-mcp.mjs +4 -0
- package/sitedrift.mjs +71 -1789
- package/src/agent.mjs +73 -0
- package/src/browser.mjs +9 -0
- package/src/cli.mjs +215 -0
- package/src/http.mjs +21 -0
- package/src/mcp.mjs +324 -0
- package/src/notes.mjs +78 -0
- package/src/proxy.mjs +146 -0
- package/src/server.mjs +171 -0
- package/src/session.mjs +53 -0
- package/src/tls.mjs +115 -0
- package/src/viewer.mjs +38 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# sitedrift for agents
|
|
2
|
+
|
|
3
|
+
sitedrift compares a local site with production and keeps a shared review-note
|
|
4
|
+
channel for humans and AI tools. Prefer the packaged MCP server. Use the JSON CLI
|
|
5
|
+
only when the host cannot run MCP.
|
|
6
|
+
|
|
7
|
+
## Fast path
|
|
8
|
+
|
|
9
|
+
1. Install once: `npm install --global sitedrift`
|
|
10
|
+
2. In the project, create `sitedrift.config.json`:
|
|
11
|
+
|
|
12
|
+
```json
|
|
13
|
+
{
|
|
14
|
+
"dev": "http://localhost:4321",
|
|
15
|
+
"live": "https://example.com",
|
|
16
|
+
"open": true
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
3. Start the app: `sitedrift`
|
|
21
|
+
4. Configure the AI host to run:
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"command": "sitedrift-mcp",
|
|
26
|
+
"args": []
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
No global install: use `"command": "npx"` and
|
|
31
|
+
`"args": ["-y", "sitedrift", "mcp"]`.
|
|
32
|
+
|
|
33
|
+
Common one-command setup:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
codex mcp add sitedrift -- sitedrift-mcp
|
|
37
|
+
claude mcp add sitedrift -- sitedrift-mcp
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
For Cursor and other JSON-configured hosts, put this in the host's MCP
|
|
41
|
+
configuration under `mcpServers`:
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
{
|
|
45
|
+
"sitedrift": {
|
|
46
|
+
"command": "sitedrift-mcp",
|
|
47
|
+
"args": []
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Agent workflow
|
|
53
|
+
|
|
54
|
+
1. Call `sitedrift_context` first. Do not guess the URLs or active session.
|
|
55
|
+
2. Inspect the requested route in the viewer or with the host's browser tools.
|
|
56
|
+
3. Call `sitedrift_notes_list` before adding notes to avoid duplicates.
|
|
57
|
+
4. Add one concrete finding per `sitedrift_note_add` call. Always provide
|
|
58
|
+
`route`; provide `side` when the issue belongs specifically to DEV or LIVE.
|
|
59
|
+
5. Re-list notes after code changes. Resolve only findings you verified.
|
|
60
|
+
6. Remove or clear notes only when the user explicitly requests it.
|
|
61
|
+
|
|
62
|
+
## MCP tools
|
|
63
|
+
|
|
64
|
+
- `sitedrift_context`: active targets, viewer URL, and capabilities.
|
|
65
|
+
- `sitedrift_notes_list`: shared findings.
|
|
66
|
+
- `sitedrift_note_add`: add one actionable finding.
|
|
67
|
+
- `sitedrift_note_resolve`: mark a verified finding complete.
|
|
68
|
+
- `sitedrift_note_reopen`: reopen a regressed or incomplete finding.
|
|
69
|
+
- `sitedrift_note_remove`: permanently remove one finding.
|
|
70
|
+
- `sitedrift_notes_clear`: permanently remove all findings.
|
|
71
|
+
- `sitedrift_setup`: return install, config, HTTPS, and MCP setup instructions.
|
|
72
|
+
|
|
73
|
+
Default port is `4178`. Pass `port` to every tool when the user runs another
|
|
74
|
+
session port.
|
|
75
|
+
|
|
76
|
+
## CLI fallback
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
sitedrift context
|
|
80
|
+
sitedrift notes list
|
|
81
|
+
sitedrift notes add "CTA differs" --route /pricing --side live --author agent
|
|
82
|
+
sitedrift notes resolve <id>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
All CLI output is JSON. The MCP server communicates over stdio and writes no
|
|
86
|
+
logs to stdout.
|
|
87
|
+
|
|
88
|
+
## HTTPS
|
|
89
|
+
|
|
90
|
+
Loopback HTTP is normally sufficient. When the compared site requires HTTPS:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
sitedrift --setup-https
|
|
94
|
+
sitedrift --https
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Security
|
|
98
|
+
|
|
99
|
+
sitedrift accepts loopback hosts only. The control API uses a random bearer
|
|
100
|
+
token stored in `~/.sitedrift/sessions/<port>.json` with mode `0600`. DEV and
|
|
101
|
+
LIVE render on separate origins. Never expose sitedrift through a public proxy.
|
package/README.md
CHANGED
|
@@ -5,15 +5,11 @@ that frames your local site and production **side-by-side on the same route**,
|
|
|
5
5
|
locked to the same scroll — then overlays them in `difference` mode so the only
|
|
6
6
|
things that light up are the pixels that actually changed.
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
│ │ [Start…] │ │ │ [Get…] │ ✓ author notes │
|
|
14
|
-
│ └───────────┘ │ └───────────┘ │
|
|
15
|
-
└──────────────────────────────────────────┘
|
|
16
|
-
```
|
|
8
|
+
<p align="center">
|
|
9
|
+
<img src="docs/images/sitedrift-split.jpg" alt="sitedrift comparing a redesigned local product page with production" width="100%">
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
<p align="center"><strong>Same route. Same scroll. Every change visible.</strong></p>
|
|
17
13
|
|
|
18
14
|
---
|
|
19
15
|
|
|
@@ -39,6 +35,72 @@ npm i -g sitedrift
|
|
|
39
35
|
sitedrift /pricing -d http://localhost:4321 -l https://example.com -o
|
|
40
36
|
```
|
|
41
37
|
|
|
38
|
+
For a project you use repeatedly, add `sitedrift.config.json`:
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"dev": "http://localhost:4321",
|
|
43
|
+
"live": "https://example.com",
|
|
44
|
+
"author": "joe",
|
|
45
|
+
"open": true
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Configuration precedence is **flag > environment > project file > default**.
|
|
50
|
+
The file is discovered from the current directory upward; `--config <file>`
|
|
51
|
+
selects one explicitly.
|
|
52
|
+
|
|
53
|
+
### HTTPS
|
|
54
|
+
|
|
55
|
+
The default (`http://127.0.0.1`) just works — loopback is a browser "secure
|
|
56
|
+
context", so you usually need nothing. When you do want HTTPS:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
sitedrift --setup-https # one-time: generate + trust a local cert
|
|
60
|
+
sitedrift --https # serve over HTTPS from then on
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`--setup-https` uses [mkcert](https://github.com/FiloSottile/mkcert) if it's
|
|
64
|
+
installed — that gives a **locally-trusted cert with zero browser warnings**. If
|
|
65
|
+
mkcert isn't found it falls back to an `openssl` self-signed cert and prints the
|
|
66
|
+
one command to trust it on your OS. Already have a cert? Skip all of this and
|
|
67
|
+
pass `--cert <file> --key <file>`.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## See the whole review loop
|
|
72
|
+
|
|
73
|
+
The included example compares a fictional Northstar release candidate against
|
|
74
|
+
production. It uses realistic release drift: primary CTA, metric values, and a
|
|
75
|
+
release badge change while the underlying layout stays aligned.
|
|
76
|
+
|
|
77
|
+
<table>
|
|
78
|
+
<tr>
|
|
79
|
+
<td width="50%">
|
|
80
|
+
<img src="docs/images/sitedrift-diff.jpg" alt="Difference overlay showing only changed pixels">
|
|
81
|
+
<br><strong>Pixel difference</strong><br>
|
|
82
|
+
Overlay both pages and light up only what changed.
|
|
83
|
+
</td>
|
|
84
|
+
<td width="50%">
|
|
85
|
+
<img src="docs/images/sitedrift-collaboration.jpg" alt="Review drawer with notes from a human and an AI agent">
|
|
86
|
+
<br><strong>Human + AI review channel</strong><br>
|
|
87
|
+
Share route-specific findings through the viewer, CLI, or MCP.
|
|
88
|
+
</td>
|
|
89
|
+
</tr>
|
|
90
|
+
</table>
|
|
91
|
+
|
|
92
|
+
<p align="center">
|
|
93
|
+
<img src="docs/images/sitedrift-mobile.jpg" alt="sitedrift Solo mode on a narrow mobile viewport" width="360">
|
|
94
|
+
<br><strong>Focused mobile review</strong><br>
|
|
95
|
+
Narrow screens default to Solo; Swap flips between DEV and LIVE.
|
|
96
|
+
</p>
|
|
97
|
+
|
|
98
|
+
Rebuild these screenshots from the deterministic local showcase:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
npm run docs:screenshots
|
|
102
|
+
```
|
|
103
|
+
|
|
42
104
|
---
|
|
43
105
|
|
|
44
106
|
## What it does
|
|
@@ -59,7 +121,7 @@ sitedrift /pricing -d http://localhost:4321 -l https://example.com -o
|
|
|
59
121
|
file the viewer polls every 4s, so a teammate or an AI coding session can leave
|
|
60
122
|
notes that appear live. Click a note to jump to its route, copy a per-note
|
|
61
123
|
deep link, dock or float the drawer, and **Send to vault** or export Markdown.
|
|
62
|
-
- **No dependencies.** Node standard library only.
|
|
124
|
+
- **No runtime dependencies.** Node standard library only.
|
|
63
125
|
|
|
64
126
|
### Keyboard
|
|
65
127
|
|
|
@@ -82,7 +144,6 @@ Shortcuts work whether focus is in the viewer chrome or inside either pane.
|
|
|
82
144
|
## Options
|
|
83
145
|
|
|
84
146
|
Every option is a CLI flag, and also reads a `SITEDRIFT_<NAME>` env var.
|
|
85
|
-
Precedence is **flag > env > default**.
|
|
86
147
|
|
|
87
148
|
| Flag | Env | Default | Purpose |
|
|
88
149
|
|---|---|---|---|
|
|
@@ -91,36 +152,85 @@ Precedence is **flag > env > default**.
|
|
|
91
152
|
| `-p, --port <n>` | `SITEDRIFT_PORT` | `4178` | Listen port. |
|
|
92
153
|
| `--host <addr>` | `SITEDRIFT_HOST` | `127.0.0.1` | Bind address. |
|
|
93
154
|
| `-o, --open` | — | off | Open the viewer in your browser. |
|
|
94
|
-
| `--
|
|
95
|
-
| `--
|
|
155
|
+
| `--https` | — | off | Serve HTTPS with an auto cert (mkcert if present, else openssl). |
|
|
156
|
+
| `--setup-https` | — | — | One-time: generate + trust a local cert, then exit. |
|
|
157
|
+
| `--http` | — | — | Force plain HTTP (the default; overrides `--https`). |
|
|
158
|
+
| `--cert <file>` / `--key <file>` | `SITEDRIFT_CERT` / `_KEY` | — | Bring your own cert; if both set, serve over HTTPS. |
|
|
96
159
|
| `--notes <file>` | `SITEDRIFT_NOTES` | `$TMPDIR/sitedrift-notes.json` | Shared review-notes file. |
|
|
97
160
|
| `--brand <text>` | `SITEDRIFT_BRAND` | — | Strip `\| <text>` from titles in pane headers. |
|
|
98
161
|
| `--author <name>` | `SITEDRIFT_AUTHOR` | `you` | Byline for notes added in the viewer. |
|
|
99
162
|
| `--vault <dir>` | `SITEDRIFT_VAULT` | — | Enable **Send to vault** (writes the review markdown here). |
|
|
163
|
+
| `--config <file>` | — | discovered | Read project configuration from JSON. |
|
|
100
164
|
|
|
101
165
|
A positional `[path]` (e.g. `sitedrift /pricing`) sets the initial route.
|
|
102
166
|
`-h, --help` and `-v, --version` do what you'd expect.
|
|
103
167
|
|
|
168
|
+
### AI and automation
|
|
169
|
+
|
|
170
|
+
The running process writes a private mode-`0600` descriptor under
|
|
171
|
+
`~/.sitedrift/sessions/`. The npm package includes a zero-dependency stdio MCP
|
|
172
|
+
server and an `AGENTS.md` operating guide.
|
|
173
|
+
|
|
174
|
+
Configure an MCP host with:
|
|
175
|
+
|
|
176
|
+
```json
|
|
177
|
+
{
|
|
178
|
+
"command": "sitedrift-mcp",
|
|
179
|
+
"args": []
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Codex and Claude Code can register it directly:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
codex mcp add sitedrift -- sitedrift-mcp
|
|
187
|
+
claude mcp add sitedrift -- sitedrift-mcp
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Without a global install:
|
|
191
|
+
|
|
192
|
+
```json
|
|
193
|
+
{
|
|
194
|
+
"command": "npx",
|
|
195
|
+
"args": ["-y", "sitedrift", "mcp"]
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Agents call `sitedrift_context` first, then use the note tools to share findings
|
|
200
|
+
with the user. The server also exposes `sitedrift://guide`, a `review_route`
|
|
201
|
+
prompt, and `sitedrift_setup` for install/config/HTTPS guidance.
|
|
202
|
+
|
|
203
|
+
For hosts without MCP, use the JSON CLI instead of scraping the viewer or
|
|
204
|
+
constructing authenticated requests:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
sitedrift context
|
|
208
|
+
sitedrift notes list
|
|
209
|
+
sitedrift notes add "CTA differs" --route /pricing --side live --author codex
|
|
210
|
+
sitedrift notes resolve <id>
|
|
211
|
+
sitedrift notes reopen <id>
|
|
212
|
+
sitedrift notes remove <id>
|
|
213
|
+
sitedrift notes clear
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Commands print JSON and return non-zero on failure. They work over HTTP or local
|
|
217
|
+
HTTPS without an agent-specific SDK.
|
|
218
|
+
|
|
104
219
|
### HTTP endpoints
|
|
105
220
|
|
|
106
221
|
| Route | Purpose |
|
|
107
222
|
|---|---|
|
|
108
223
|
| `GET /` | The viewer. |
|
|
109
224
|
| `GET /health` | `{ dev, live, version }`. |
|
|
110
|
-
| `GET /
|
|
225
|
+
| `GET /api/v1/session` | Authenticated session context and capabilities. |
|
|
226
|
+
| `GET /api/v1/notes` · `POST /api/v1/notes` | Authenticated note list / operations. |
|
|
111
227
|
| `GET /notes.md` | Notes as a Markdown checklist. |
|
|
112
|
-
| `POST /notes/save` | Write
|
|
228
|
+
| `POST /api/v1/notes/save` | Write notes markdown into `--vault`. |
|
|
113
229
|
| `GET /icon.svg` | The app mark / favicon. |
|
|
114
|
-
| `GET /__dev/*` · `GET /__live/*` |
|
|
230
|
+
| frame ports: `GET /__dev/*` · `GET /__live/*` | Isolated proxied origins. |
|
|
115
231
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
```bash
|
|
120
|
-
curl -X POST localhost:4178/notes -H 'content-type: application/json' \
|
|
121
|
-
-d '{"op":"add","text":"H1 on /about is larger on LIVE",
|
|
122
|
-
"author":"claude","route":"/about","side":"live"}'
|
|
123
|
-
```
|
|
232
|
+
The control API requires the per-session bearer token. The CLI commands above
|
|
233
|
+
are the supported machine interface.
|
|
124
234
|
|
|
125
235
|
Most viewer state (route, layout, scroll mode, focus) is mirrored into the URL
|
|
126
236
|
query string, so a link reproduces the exact view.
|
|
@@ -131,12 +241,26 @@ query string, so a link reproduces the exact view.
|
|
|
131
241
|
|
|
132
242
|
The proxy strips `Content-Security-Policy`, `X-Frame-Options`, and the
|
|
133
243
|
Cross-Origin-{Embedder,Opener,Resource}-Policy headers so production can be
|
|
134
|
-
framed next to dev.
|
|
244
|
+
framed next to dev.
|
|
135
245
|
|
|
136
|
-
-
|
|
137
|
-
|
|
246
|
+
- Only loopback hosts are accepted, and Host headers are validated.
|
|
247
|
+
- The viewer/control API uses `--port`; DEV and LIVE frames use `--port + 1`
|
|
248
|
+
and `--port + 2`, so neither page can inspect the other.
|
|
249
|
+
- Framed pages communicate through a narrow `postMessage` bridge and cannot
|
|
250
|
+
access the viewer DOM, bearer token, notes API, or vault endpoint.
|
|
138
251
|
- Treat the notes file as plaintext shared scratch space.
|
|
139
252
|
|
|
253
|
+
## Development
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
npm test
|
|
257
|
+
npm run test:e2e:visual
|
|
258
|
+
npm run test:e2e:visual:update # intentionally accept visual changes
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
The visual suite uses deterministic origins and checked-in Chromium baselines
|
|
262
|
+
for desktop split, narrow Solo, difference overlay, and the notes drawer.
|
|
263
|
+
|
|
140
264
|
## Limitations
|
|
141
265
|
|
|
142
266
|
- **URL rewriting is regex-based**, tuned for static sites (e.g. Astro builds).
|