@cychien/ezdesign 0.8.1 → 0.9.1
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/README.md +166 -37
- package/dist/announcements/template-ERNKAKI5.svg +33 -0
- package/dist/cli.mjs +7603 -3157
- package/dist/constants.d.ts +36 -8
- package/dist/events-worker.js +77 -0
- package/dist/extension/g/0.9.1-16d05e759b/dialog.css +1 -0
- package/dist/extension/g/0.9.1-16d05e759b/dialog.html +13 -0
- package/dist/extension/g/0.9.1-16d05e759b/dialog.js +1 -0
- package/dist/extension/g/0.9.1-16d05e759b/icon-128.png +0 -0
- package/dist/extension/g/0.9.1-16d05e759b/icon-16.png +0 -0
- package/dist/extension/g/0.9.1-16d05e759b/icon-32.png +0 -0
- package/dist/extension/g/0.9.1-16d05e759b/icon-48.png +0 -0
- package/dist/extension/g/0.9.1-16d05e759b/media.html +9 -0
- package/dist/extension/g/0.9.1-16d05e759b/media.js +1 -0
- package/dist/extension/g/0.9.1-16d05e759b/page.js +39 -0
- package/dist/extension/g/0.9.1-16d05e759b/setup.css +1 -0
- package/dist/extension/g/0.9.1-16d05e759b/setup.html +17 -0
- package/dist/extension/g/0.9.1-16d05e759b/setup.js +1 -0
- package/dist/extension/g/0.9.1-16d05e759b/worker.js +57 -0
- package/dist/extension/manifest.json +57 -0
- package/dist/native-host.mjs +20594 -0
- package/dist/overlay.css +0 -43
- package/dist/overlay.js +284 -89
- package/dist/shell.css +1599 -21
- package/dist/shell.js +4374 -734
- package/dist/vite.mjs +5 -0
- package/package.json +8 -5
- package/skills/ezdesign/SKILL.md +24 -67
- package/skills/ezdesign/reference/start.md +3 -1
package/README.md
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
<h1>
|
|
2
|
+
<picture>
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/brand/ezdesign-dark.svg">
|
|
4
|
+
<img alt="ezdesign" src="docs/brand/ezdesign-light.svg" height="32">
|
|
5
|
+
</picture>
|
|
6
|
+
</h1>
|
|
2
7
|
|
|
3
8
|
> Point at your live app. Your agent fixes it.
|
|
4
9
|
|
|
@@ -6,12 +11,15 @@ ezdesign turns any locally running dev server into an annotatable review surface
|
|
|
6
11
|
agent iteration. The user marks up the **real page** - click an element, frame a region, select
|
|
7
12
|
some text, leave a comment - and the feedback flows to a local coding agent (Claude Code, Codex,
|
|
8
13
|
anything that can run a CLI) as structured items that resolve to **exact source locations**. The
|
|
9
|
-
agent edits the code, HMR updates the page in place, the user reviews the next round.
|
|
14
|
+
agent edits the code, HMR updates the page in place, the user reviews the next round. Beside the
|
|
15
|
+
app, **canvases** hold HTML designs the agent draws, for exploring ideas before (or instead of)
|
|
16
|
+
changing the real thing.
|
|
10
17
|
|
|
11
18
|
```
|
|
12
19
|
$ npx -y @cychien/ezdesign@latest http://localhost:5173/pricing --agent claude # managed ACP agent
|
|
13
20
|
$ npx -y @cychien/ezdesign@latest http://localhost:5173/pricing # portable poll mode
|
|
14
|
-
$ npx -y @cychien/ezdesign@latest poll
|
|
21
|
+
$ npx -y @cychien/ezdesign@latest poll # agent waits for feedback
|
|
22
|
+
$ npx -y @cychien/ezdesign@latest --agent claude # no dev server: canvases only
|
|
15
23
|
```
|
|
16
24
|
|
|
17
25
|
- **Zero config.** A local daemon reverse-proxies your dev server and injects the annotation
|
|
@@ -21,9 +29,12 @@ $ npx -y @cychien/ezdesign@latest poll http://localhost:5173/
|
|
|
21
29
|
guessing which part of the page you meant. Paste or drop a screenshot into any comment and the
|
|
22
30
|
agent gets a path to it; `/element` points a comment at a second element, so "make this match
|
|
23
31
|
that one" arrives as a `file:line` too.
|
|
24
|
-
- **Every screen at once.** Review on one device or lay all three out on a
|
|
32
|
+
- **Every screen at once.** Review on one device or lay all three out on a grid - desktop,
|
|
25
33
|
iPad and iPhone side by side at their real viewports, scrolling together. An annotation stays on
|
|
26
34
|
the screen it was made on, and reaches the agent tagged with the width it was made at.
|
|
35
|
+
- **Canvases beside the app.** Tabs next to the App hold boards of frames - complete HTML pages
|
|
36
|
+
at real viewport widths that the agent adds, you arrange, and both of you annotate. `/element`
|
|
37
|
+
crosses tabs, so "build [ref 1] into the app" points at a frame from an App comment.
|
|
27
38
|
- **Built for the loop.** In ACP mode, ezdesign owns the agent and keeps its live work, questions,
|
|
28
39
|
and permission prompts in the review shell. Poll mode keeps the blocking structured-JSON contract
|
|
29
40
|
for any external agent or automation. HMR keeps iterations in place; the review chrome lives
|
|
@@ -103,7 +114,7 @@ Two modes, and the toolbar shows which one is armed. Both leave the page live un
|
|
|
103
114
|
which is what tells two instances of the same component apart. This is the mode for "this whole
|
|
104
115
|
block", "these four cards", "the spacing through here".
|
|
105
116
|
|
|
106
|
-
One comment is composed at a time - across every preview on the
|
|
117
|
+
One comment is composed at a time - across every preview on the grid, not just the one you are
|
|
107
118
|
in - so a box drawn in one screen cannot open a second comment box behind the one you are writing.
|
|
108
119
|
|
|
109
120
|
## The comment box
|
|
@@ -220,36 +231,36 @@ half of what a responsive review is looking at:
|
|
|
220
231
|
| `3` | 電腦 | 1440×788 - a 1440×900 laptop screen, less the menu bar and the browser's own |
|
|
221
232
|
|
|
222
233
|
The sizes are the **page area** a browser leaves on that device, not the screen it leaves it on -
|
|
223
|
-
so a card on the
|
|
234
|
+
so a card on the grid stops showing the page exactly where the real thing stops showing it. On
|
|
224
235
|
its own a size takes only its width from the table and the height from your screen: one preview
|
|
225
|
-
gets the whole stage to show the page in, and the
|
|
236
|
+
gets the whole stage to show the page in, and the grid is where the fold is what you are
|
|
226
237
|
checking.
|
|
227
238
|
|
|
228
239
|
The names are shelves, not machines - a 手機 row naming a handset would claim a precision the
|
|
229
240
|
row does not have, when phone widths run from 360 up past 430. The sizes are still taken from
|
|
230
241
|
real machines; the comments in `devices.ts` say which.
|
|
231
242
|
|
|
232
|
-
**`4` lays them out on one
|
|
243
|
+
**`4` lays them out on one grid** - phone and tablet side by side, the desktop on the row below.
|
|
233
244
|
The control in the stage's top corner picks which sizes are on it: the three above, plus a portrait
|
|
234
245
|
tablet (834×1018) that is off by default.
|
|
235
246
|
|
|
236
|
-
The
|
|
247
|
+
The grid is drawn at **true size**, always. A 375 card is 375 pixels whether it is standing alone
|
|
237
248
|
or with three others beside it - a scaled 375 is not 375 to a media query, and a page measured at a
|
|
238
249
|
size nobody browses at is not a measurement. Turning a size off does not resize or rearrange the
|
|
239
250
|
ones that are left. What does not fit is what the dragging is for.
|
|
240
251
|
|
|
241
|
-
Every card is the device it names, at its own height. What keeps the
|
|
252
|
+
Every card is the device it names, at its own height. What keeps the grid short enough to work
|
|
242
253
|
on is the two-row layout, not a cap on the cards - a card cut to a shared height would be lying
|
|
243
254
|
about where the fold falls, which is half of what the preview is for.
|
|
244
255
|
|
|
245
|
-
**Drag a card by its label to rearrange the
|
|
256
|
+
**Drag a card by its label to rearrange the grid.** A card cannot stop just anywhere: it lands
|
|
246
257
|
top-aligned in an existing row, or on a row of its own, and a line marks where it would go -
|
|
247
258
|
upright between two cards, flat between two rows. The arrangement is remembered, and a size turned
|
|
248
259
|
on later joins as its own row at the bottom rather than reshuffling what you laid out.
|
|
249
260
|
|
|
250
|
-
**Drag the background to move the
|
|
251
|
-
the page, so the backdrop and the gaps are what the
|
|
252
|
-
|
|
261
|
+
**Drag the background to move the grid.** The frames are the app: a press inside one belongs to
|
|
262
|
+
the page, so the backdrop and the gaps are what the grid is panned by. That is also why the
|
|
263
|
+
grid does not have to fit - what is off the edge is a drag away.
|
|
253
264
|
|
|
254
265
|
Scrolling inside any one preview scrolls the others to the same point in the page, and navigating
|
|
255
266
|
one - a link, back, forward - takes all of them: annotations are filtered by path, and three
|
|
@@ -258,7 +269,60 @@ previews on three pages is three separate reviews.
|
|
|
258
269
|
An annotation belongs to the screen it was made on: mark up the iPhone card and the pin lives
|
|
259
270
|
there, not on all three. The agent gets `@mobile 390x844` in the anchor either way. Everything the
|
|
260
271
|
overlay draws - the comment box, the element label, the pins - is drawn back up to full size, so a
|
|
261
|
-
|
|
272
|
+
grid scaled to 60% is still one you can read and type into.
|
|
273
|
+
|
|
274
|
+
## Canvases
|
|
275
|
+
|
|
276
|
+
A canvas is an infinite board of frames. Each frame is one complete, self-contained HTML document -
|
|
277
|
+
its own `<head>`, its own styles, scripts and CDN assets allowed - rendered in its own iframe at a
|
|
278
|
+
real viewport width, so a 390 frame is a phone to its media queries however far the board is zoomed
|
|
279
|
+
out. No CSS is shared between frames: exploration directions diverge, and that is the point.
|
|
280
|
+
|
|
281
|
+
**Tabs.** The strip above the stage has an **App** tab while a dev server is attached, then one tab
|
|
282
|
+
per open canvas. `+` makes a new one, a double-click on a tab renames it, and closing a tab
|
|
283
|
+
archives the canvas: the tab goes, the files stay. **Canvas** lists every canvas, open and
|
|
284
|
+
archived, and reopens one; hover a row for **刪除**, which removes the canvas and all its frames
|
|
285
|
+
(after asking). A session has one active tab:
|
|
286
|
+
two shell windows follow each other, and every batch tells the agent which tab you sent it from.
|
|
287
|
+
|
|
288
|
+
Run `ezdesign` with no url in a project without a dev server and the shell opens on that
|
|
289
|
+
project's canvases - one empty `未命名 canvas` the first time. Run `ezdesign <url>` later and the
|
|
290
|
+
App tab joins the same shell; the conversation carries on.
|
|
291
|
+
|
|
292
|
+
**The board.** Drag the background or hold Space to pan, scroll to pan, pinch or Cmd/Ctrl+scroll to
|
|
293
|
+
zoom around the pointer, `-`/`+` in the corner to step, `⇧1` to fit everything, `⇧0` to go back to
|
|
294
|
+
100%. Click a frame to select it, Shift+click to add, `⌘A` for all; drag to move, with guides that
|
|
295
|
+
snap to other frames' edges and centres; `⌘D` duplicates, `⌫` deletes, arrows nudge (`⇧` for 10). A
|
|
296
|
+
frame keeps the size it was added at: it is a viewport, so it is never resized. Every step undoes
|
|
297
|
+
and redoes (`⌘Z`, `⌘⇧Z`). Double-click a frame to scroll it or click through its controls; Escape
|
|
298
|
+
hands the pointer back. Positions, the open tabs, the active tab and each canvas's camera survive a
|
|
299
|
+
reload and a daemon restart.
|
|
300
|
+
|
|
301
|
+
**Annotating.** `元素` and `範圍` work inside frames as they do on the app, and an annotation in a
|
|
302
|
+
frame reaches the agent as a line of that frame's file -
|
|
303
|
+
`.ezdesign/canvases/<canvas>/frames/<frame>.html:14 · [canvas frame "Hero A" on canvas "首頁探索"]`.
|
|
304
|
+
`/element` crosses tabs both ways: start it in an App comment, switch to a canvas, Cmd+click the
|
|
305
|
+
frame you mean, and the comment comes back with the ref in it - or the reverse.
|
|
306
|
+
|
|
307
|
+
**The agent.** An ACP agent gets the `ezdesign-canvas` tools - `list_canvases`, `create_canvas`,
|
|
308
|
+
`read_canvas`, `reopen_canvas`, `add_frame`, `update_frame`, `remove_frame` - from its first turn,
|
|
309
|
+
granted without asking. New frames go on the canvas you sent from, or else the newest open one; the
|
|
310
|
+
agent starts a new canvas only when none is open or you ask for one. A canvas it creates becomes the
|
|
311
|
+
active tab and its frames appear as each call returns. A frame's HTML is the agent's: it changes it
|
|
312
|
+
through the tools or by editing the file, and the open shell reloads that frame either way. The agent
|
|
313
|
+
picks a frame's size when it adds it; after that, where the frame sits is yours, and the tools
|
|
314
|
+
refuse geometry on a frame that exists. Poll mode has no canvas tools.
|
|
315
|
+
|
|
316
|
+
**On disk.** Canvases live in the project, in `.ezdesign/canvases/<canvas>/`: `canvas.json` (name,
|
|
317
|
+
frames), `layout.json` (where each frame is) and `frames/<frame>.html`. ezdesign writes the two
|
|
318
|
+
JSON files and never reads back an edit made to them by hand; frame files are yours to edit. It
|
|
319
|
+
does not touch your `.gitignore`: committing canvases is your call.
|
|
320
|
+
|
|
321
|
+
**Isolation.** Frame documents are agent-written pages running third-party scripts, so they are
|
|
322
|
+
served from `http://localhost:<port>` while the shell stays on `http://127.0.0.1:<port>` - another
|
|
323
|
+
site. A frame cannot read the shell's storage, script it, or call the session's api, and the
|
|
324
|
+
overlay inside it reaches the review through the shell. Two shortcuts do not fire while focus is
|
|
325
|
+
inside a frame: send (`⌘↵`) and stop (`⌘.`).
|
|
262
326
|
|
|
263
327
|
## Configuration
|
|
264
328
|
|
|
@@ -267,26 +331,43 @@ canvas scaled to 60% is still one you can read and type into.
|
|
|
267
331
|
| `EZDESIGN_DATA_DIR` | `~/.ezdesign` | Session state, the daemon registry and log, versions installed by the in-shell update, and the update-check cache |
|
|
268
332
|
| `EZDESIGN_CONTROL_PORT` | `4400` | First port of the ten-port range the daemon searches for its control server |
|
|
269
333
|
| `EZDESIGN_NO_UPDATE_CHECK` | unset | Set to `1` and the daemon never asks the npm registry for the latest version, so the shell never offers an update |
|
|
334
|
+
| `EZDESIGN_NO_IDLE_STOP` | unset | Set to `1` and the daemon never stops itself for being idle; something else, like `npm run dev`, owns its lifetime |
|
|
335
|
+
| `EZDESIGN_DESIGN_HARNESS` | unset (off) | Set to `1` in the environment the daemon starts from and the experimental 增強設計 design harness is available; unset, the shell has no switch and no agent is asked to use it |
|
|
270
336
|
| `EZDESIGN_INSPIRE_URL` | `https://inspire.ezdesign.dev` | The inspiration database the `inspire` commands query |
|
|
337
|
+
| `EZDESIGN_API_URL` | `https://api.ezdesign.dev` | The ezdesign backend the review shell signs in through |
|
|
271
338
|
|
|
272
|
-
Set
|
|
273
|
-
daemon
|
|
274
|
-
|
|
339
|
+
Set `EZDESIGN_DATA_DIR` to run a second, fully isolated instance: a starting daemon only adopts a
|
|
340
|
+
live daemon that serves its own data dir, so instances sharing a control range each take their own
|
|
341
|
+
port in it. `npm run dev` sets both.
|
|
275
342
|
|
|
276
343
|
Sessions outlive the daemon that served them. On start, the daemon picks each session back up
|
|
277
344
|
from disk and re-binds it to the port it last held, so a review shell tab you already have open
|
|
278
|
-
|
|
279
|
-
since been taken, the session moves to a free one and the CLI re-resolves it. A
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
A session
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
345
|
+
reconnects by itself, and feedback you queued before the restart is still waiting. If that port
|
|
346
|
+
has since been taken, the session moves to a free one and the CLI re-resolves it. A daemon brings
|
|
347
|
+
back the sessions that were live when it went down; one that stopped itself after half an hour
|
|
348
|
+
with no shell open brings back none, and the next `ezdesign` or `poll` in a project wakes that
|
|
349
|
+
project's session. Only time awake counts toward that half hour, so a laptop that sleeps with a
|
|
350
|
+
shell open wakes to a review that is still there. A shell left open while its daemon is gone says
|
|
351
|
+
so, and the `ezdesign` that brings the session back finds it reconnecting instead of opening a
|
|
352
|
+
second window. A session that was driving an ACP agent starts that agent again **and asks it to
|
|
353
|
+
resume the conversation they were having**, so the review carries on where it stopped. Whether
|
|
354
|
+
that works is the agent's answer to give - a transcript it no longer has, or an agent that cannot
|
|
355
|
+
resume at all, leaves the review in a fresh context, and only then does the thread say so.
|
|
356
|
+
|
|
357
|
+
A session belongs to a project, not to a dev-server origin. The project is the nearest `.git` or
|
|
358
|
+
`package.json` ancestor of the directory you run `ezdesign` from. A dev server that comes back on
|
|
359
|
+
another port keeps the review: `ezdesign http://localhost:5174/` in the same project points the
|
|
360
|
+
open shell at the new port, with the conversation and the queue intact. Dev servers all default to
|
|
361
|
+
the same port, so one origin is attached to one project at a time: opening a second project on
|
|
362
|
+
`localhost:5173` moves the origin to it, and the first project keeps its conversation and queue and
|
|
363
|
+
only loses its app until you attach one again. `poll`, `progress` and `end` find the session by the
|
|
364
|
+
project they run from; a url passed to them is only checked against the attached app, with a note
|
|
365
|
+
when it differs.
|
|
366
|
+
|
|
367
|
+
Sessions from versions before this one were per origin. The first daemon of this version folds them
|
|
368
|
+
into project sessions, keeping every queued annotation, batch and conversation, and moves the old
|
|
369
|
+
directories to `sessions-legacy/` in the data dir, never deleting them. A daemon older than this
|
|
370
|
+
version does not read the new format, so going back to one starts with no sessions.
|
|
290
371
|
|
|
291
372
|
## Agent modes
|
|
292
373
|
|
|
@@ -358,8 +439,11 @@ other's - so there is no way to hand a conversation over. Nothing ezdesign owns
|
|
|
358
439
|
conversation stays in the thread's own picker with the agent that had it, and switching back finds it
|
|
359
440
|
again, resumable by the agent that remembers it.
|
|
360
441
|
|
|
361
|
-
The agent can design the way a designer works, through a five-step harness
|
|
362
|
-
product, stack, design, components, make. It is
|
|
442
|
+
The agent can design the way a designer works, through a five-step harness shipped with the daemon:
|
|
443
|
+
product, stack, design, components, make. It is off by default: set `EZDESIGN_DESIGN_HARNESS=1` in the
|
|
444
|
+
environment the daemon starts from to enable it, and until then the shell has no switch, no agent is asked
|
|
445
|
+
to use it, and the remembered choice for each project is kept untouched for when it is on. With
|
|
446
|
+
the flag on it is opt-in, experimental - the switch says 實驗 - and a
|
|
363
447
|
premium feature: the **增強設計** switch on its own line above the agent and the model, marked with a
|
|
364
448
|
gold sparkle, turns it on, and the choice is remembered for the project - across sessions, a dev
|
|
365
449
|
server that moved ports, `/new` and daemon restarts - except that it starts off when the project's
|
|
@@ -377,8 +461,8 @@ agent may go past it. An ordinary change edits code only. The two files change
|
|
|
377
461
|
when you ask for it, when a correction has come twice, or when you state a rule - only on what you
|
|
378
462
|
actually said, never on what the agent reads into a send-back; a change that only leaves a line stale is mentioned in the reply, not edited. Between them,
|
|
379
463
|
`.ezdesign/config.json` records the stack and the browser tool the agent looks at the page with. The
|
|
380
|
-
skill
|
|
381
|
-
|
|
464
|
+
installed skill does not carry the harness: it opens reviews, and the harness is reached only
|
|
465
|
+
through the daemon with the flag on.
|
|
382
466
|
|
|
383
467
|
Turning the switch on in a project that lacks either file asks first, in the card above the
|
|
384
468
|
composer: 啟用增強設計 - 增強設計會建立 PRODUCT.md 與 DESIGN.md,是否繼續? 取消 leaves the switch off,
|
|
@@ -423,10 +507,11 @@ Without `--agent`, the review uses the existing CLI contract:
|
|
|
423
507
|
|
|
424
508
|
```
|
|
425
509
|
npx -y @cychien/ezdesign@latest http://localhost:5173/
|
|
426
|
-
npx -y @cychien/ezdesign@latest poll
|
|
510
|
+
npx -y @cychien/ezdesign@latest poll
|
|
427
511
|
```
|
|
428
512
|
|
|
429
|
-
`poll` blocks until the user sends feedback, prints the structured batch as JSON, and exits.
|
|
513
|
+
`poll` blocks until the user sends feedback, prints the structured batch as JSON, and exits. Run it
|
|
514
|
+
from the project, like the command that opened the session. This
|
|
430
515
|
mode remains available for scripts and integrations that consume the CLI contract directly.
|
|
431
516
|
|
|
432
517
|
## Inspiration
|
|
@@ -456,6 +541,46 @@ results belong in the agent's reply, not in your repository. A search that finds
|
|
|
456
541
|
with one line, and one that cannot run - no token, a refused token, a service that cannot be
|
|
457
542
|
reached - exits 2 with one line, so the agent says so and carries on.
|
|
458
543
|
|
|
544
|
+
## Saving references from Chrome
|
|
545
|
+
|
|
546
|
+
The capture extension saves an image, a video or a region of any page into one design library
|
|
547
|
+
under `~/.ezdesign/library/`, shared by every project, with your tags and a note. Saving needs no
|
|
548
|
+
dev server, no session and no daemon: Chrome talks to a small native host that ezdesign installs.
|
|
549
|
+
|
|
550
|
+
```
|
|
551
|
+
npx -y @cychien/ezdesign@latest extension install
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
`install` copies the host into `~/.ezdesign/native-host/`, registers it with every Chromium browser
|
|
555
|
+
it finds (Chrome and its channels, Chromium, Arc, Brave, Edge, Vivaldi; macOS and Linux), and
|
|
556
|
+
prints the folder to load once: open `chrome://extensions`, turn on **Developer mode**, choose
|
|
557
|
+
**Load unpacked** and pick `~/.ezdesign/extension`. The folder stays put across ezdesign updates,
|
|
558
|
+
and the daemon brings the host and the extension up to its own version when it starts. The host
|
|
559
|
+
needs Node 22.13 or newer. `--user-data-dir <dir>` installs into one browser profile only.
|
|
560
|
+
|
|
561
|
+
- **Right-click an image or a video** and choose **儲存至 ezdesign**. A dialog opens over the page
|
|
562
|
+
with a preview, tags (suggested by how often you use them) and a note; **儲存** or Cmd+Enter saves,
|
|
563
|
+
Esc or a click outside leaves nothing behind. Saving the same bytes again shows **已收藏過** and
|
|
564
|
+
adds to the item you already have.
|
|
565
|
+
- **The toolbar icon or Alt+Shift+S** starts a region capture: drag a rectangle, or click once for
|
|
566
|
+
the whole visible page. On pages an extension cannot draw on, such as `chrome://` pages, the
|
|
567
|
+
visible page is captured at once and the dialog opens in its own window.
|
|
568
|
+
- Images and plain video files keep their original bytes. A streaming video (YouTube, Instagram,
|
|
569
|
+
anything playing through MediaSource) and a video over 200 MB are saved as a link with the time
|
|
570
|
+
you were at and the frame on screen. An image the host is refused for (a signed-in CDN) offers
|
|
571
|
+
**允許讀取** for that site, then is read with your cookies.
|
|
572
|
+
|
|
573
|
+
`ezdesign extension status` lists each browser and any problem, and exits 1 when there is one.
|
|
574
|
+
`ezdesign extension uninstall` removes the host and the extension folder; the library stays.
|
|
575
|
+
|
|
576
|
+
## Signing in
|
|
577
|
+
|
|
578
|
+
Some features will run on the ezdesign backend, and those need you signed in. The icon at the foot of the review shell's right-hand bar then signs you in, with Google or an
|
|
579
|
+
email and a password. It opens the sign-in page in a new tab. When you are through, the tab closes
|
|
580
|
+
itself and the icon shows your initial. Its menu shows the account and signs you out. One sign-in
|
|
581
|
+
covers every review the daemon is serving. The token is kept in `~/.ezdesign/credentials.json`,
|
|
582
|
+
mode 600, beside the inspiration token, and signing out revokes it.
|
|
583
|
+
|
|
459
584
|
## Development
|
|
460
585
|
|
|
461
586
|
Working on ezdesign itself takes one command:
|
|
@@ -466,6 +591,7 @@ npm run dev # watch src/, serve the playground fixture, start an
|
|
|
466
591
|
npm run dev -- --no-plugin # the same page without ezdesignSource(), to see fallback-only anchors
|
|
467
592
|
npm run dev:agent # a stand-in poll-mode agent, for working on the poll contract itself
|
|
468
593
|
npm run dev:cli status # the ezdesign CLI, pointed at the dev daemon instead of the real one
|
|
594
|
+
npm run brand # regenerate the logo's PNG and SVG copies after editing src/brand.ts
|
|
469
595
|
```
|
|
470
596
|
|
|
471
597
|
`npm run dev` opens the review in ACP mode, scoped to the fixture - the agent's working directory
|
|
@@ -474,7 +600,10 @@ is only for the poll contract.
|
|
|
474
600
|
|
|
475
601
|
A client rebuild (`src/client/**`) only needs a browser reload; a rebuild the daemon loads
|
|
476
602
|
restarts it, and in-flight polls reconnect on their own. Dev mode keeps its daemon registry and
|
|
477
|
-
sessions in `.dev/`, so your own `~/.ezdesign` is never touched.
|
|
603
|
+
sessions in `.dev/`, so your own `~/.ezdesign` is never touched. Each checkout runs its own stack:
|
|
604
|
+
its daemon takes a control range in 4100-4199 and the fixture a port from 5173, both picked from
|
|
605
|
+
the checkout's path and recorded in `.dev/dev.json`, so worktrees run `npm run dev` side by side
|
|
606
|
+
and `npm run dev:cli` reaches its own checkout's daemon. The review target is
|
|
478
607
|
[`fixtures/playground`](fixtures/playground/README.md).
|
|
479
608
|
|
|
480
609
|
## Status
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="640" height="400" viewBox="0 0 640 400">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="ground" x1="0" y1="0" x2="1" y2="1">
|
|
4
|
+
<stop offset="0" stop-color="#3a3632"/>
|
|
5
|
+
<stop offset="0.55" stop-color="#5c4a3d"/>
|
|
6
|
+
<stop offset="1" stop-color="#c9825a"/>
|
|
7
|
+
</linearGradient>
|
|
8
|
+
<radialGradient id="glow" cx="0.85" cy="0.9" r="0.7">
|
|
9
|
+
<stop offset="0" stop-color="#f2b48c" stop-opacity="0.55"/>
|
|
10
|
+
<stop offset="1" stop-color="#f2b48c" stop-opacity="0"/>
|
|
11
|
+
</radialGradient>
|
|
12
|
+
<filter id="lift" x="-20%" y="-20%" width="140%" height="160%">
|
|
13
|
+
<feDropShadow dx="0" dy="12" stdDeviation="18" flood-color="#000" flood-opacity="0.28"/>
|
|
14
|
+
</filter>
|
|
15
|
+
</defs>
|
|
16
|
+
<rect width="640" height="400" fill="url(#ground)"/>
|
|
17
|
+
<rect width="640" height="400" fill="url(#glow)"/>
|
|
18
|
+
<g filter="url(#lift)">
|
|
19
|
+
<rect x="96" y="72" width="448" height="296" rx="16" fill="#faf9f6"/>
|
|
20
|
+
</g>
|
|
21
|
+
<rect x="96" y="72" width="448" height="40" rx="16" fill="#f2f0e9"/>
|
|
22
|
+
<rect x="96" y="96" width="448" height="16" fill="#f2f0e9"/>
|
|
23
|
+
<circle cx="122" cy="92" r="5" fill="#d9d5ca"/>
|
|
24
|
+
<circle cx="140" cy="92" r="5" fill="#d9d5ca"/>
|
|
25
|
+
<circle cx="158" cy="92" r="5" fill="#d9d5ca"/>
|
|
26
|
+
<rect x="128" y="144" width="200" height="18" rx="9" fill="#171717"/>
|
|
27
|
+
<rect x="128" y="176" width="292" height="10" rx="5" fill="#e9e6dd"/>
|
|
28
|
+
<rect x="128" y="196" width="248" height="10" rx="5" fill="#e9e6dd"/>
|
|
29
|
+
<rect x="128" y="236" width="112" height="32" rx="8" fill="#171717"/>
|
|
30
|
+
<rect x="320" y="228" width="192" height="108" rx="10" fill="#f2f0e9" stroke="#e56d41" stroke-width="2" stroke-dasharray="6 5"/>
|
|
31
|
+
<circle cx="320" cy="228" r="13" fill="#e56d41"/>
|
|
32
|
+
<text x="320" y="233" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="14" font-weight="700" fill="#fff" text-anchor="middle">1</text>
|
|
33
|
+
</svg>
|