leglas 0.9.0 → 1.1.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/README.md +297 -379
- package/dist/bin.js +4337 -2094
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1788 -222
- package/dist/restart.d.ts +13 -0
- package/dist/run.d.ts +5 -0
- package/dist/shell/assets/index-BzaBzGEv.css +1 -0
- package/dist/shell/assets/index-CKmxj5gW.js +14 -0
- package/dist/shell/index.html +2 -2
- package/package.json +1 -1
- package/dist/shell/assets/index-BMpAHiSA.js +0 -14
- package/dist/shell/assets/index-pfmBGQQ0.css +0 -1
package/README.md
CHANGED
|
@@ -44,7 +44,7 @@ Your app doesn't change to make any of this work. Leglas proxies the same
|
|
|
44
44
|
dev server in your project: one config file to delete when you're done
|
|
45
45
|
and sessions that clean up after themselves.
|
|
46
46
|
|
|
47
|
-
## What
|
|
47
|
+
## What it does
|
|
48
48
|
|
|
49
49
|
<p align="center">
|
|
50
50
|
<img src="https://raw.githubusercontent.com/FredAmartey/leglas/main/.github/assets/screenshots/compare-artboards.jpg" width="900" alt="The Leglas interface: the rail on the left, and two directions running side by side as the real app, each labelled with its name and the width it is drawn at." />
|
|
@@ -52,66 +52,30 @@ and sessions that clean up after themselves.
|
|
|
52
52
|
|
|
53
53
|
<p align="center"><i>Two directions for the same page, running side by side as the actual app.</i></p>
|
|
54
54
|
|
|
55
|
-
-
|
|
56
|
-
- Name each direction, drag to reorder
|
|
57
|
-
|
|
58
|
-
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
reports in a card above the field: who is working, what file they
|
|
80
|
-
are touching, how long it has been, a stop button while it runs and
|
|
81
|
-
retry when it fails. Your agent, your subscription, no keys. Claude
|
|
82
|
-
Code, Codex and Cursor pick the conversation back up between
|
|
83
|
-
requests, so a run after the first goes straight to the change
|
|
84
|
-
instead of reading the project again. Claude Code and Codex warm up
|
|
85
|
-
while you type and let their process go once you have left Leglas
|
|
86
|
-
alone for a few minutes, so an open window is not holding one.
|
|
87
|
-
Prefer a terminal? `npx leglas watch` is the same loop with the
|
|
88
|
-
agent's own output scrolling by. In Claude Code, the Leglas MCP
|
|
89
|
-
server can also push each request straight into your open session as
|
|
90
|
-
a channel event (channels are a research preview: start Claude Code
|
|
91
|
-
with `--dangerously-load-development-channels
|
|
92
|
-
server:<your leglas server name>`).
|
|
93
|
-
- A change makes a variant, not a rewrite. Ask for something on the
|
|
94
|
-
direction you are looking at and the result registers under it in the
|
|
95
|
-
rail, with the original still there to compare against. A chip beside
|
|
96
|
-
the send button switches to changing the direction itself, for when a
|
|
97
|
-
change really is a fix. Hover any direction to see what it was built
|
|
98
|
-
from and the change that was asked for, in the words that were typed.
|
|
99
|
-
- Your agent sees what you see. Every change you send carries a screenshot
|
|
100
|
-
of the direction at the width you are looking at, a crop of whatever you
|
|
101
|
-
pointed at with a note, the other pane when you are comparing, and any
|
|
102
|
-
image you pasted into the composer as a reference. Leglas renders them
|
|
103
|
-
with a Chrome, Chromium, Brave or Edge already on your machine, nothing
|
|
104
|
-
to install; with none found, the request says so and goes anyway. Agents
|
|
105
|
-
can look for themselves too: `npx leglas show "Aurora" --screenshot`
|
|
106
|
-
writes a PNG of a direction (`--width 390` for the phone layout) and the
|
|
107
|
-
MCP `show` tool returns the image. The instructions Leglas writes for
|
|
108
|
-
agents ask for one look after each change, so a broken layout gets fixed
|
|
109
|
-
before you see it.
|
|
110
|
-
- Keep the winner with one command. Leglas moves it into your source
|
|
111
|
-
tree and clears the exploration away.
|
|
112
|
-
- No app yet or want plain HTML comparisons? Some people want exactly that, and it works fine. Same comparison, no dev server.
|
|
113
|
-
|
|
114
|
-
## Quick start
|
|
55
|
+
- Put any two directions side by side when it gets hard to choose.
|
|
56
|
+
- Name each direction, drag to reorder, set aside the ones that don't feel
|
|
57
|
+
right. Your opinion of every idea survives a long exploration.
|
|
58
|
+
- Share the rail with someone who has no repo: a client, a cofounder, a
|
|
59
|
+
teammate on another machine. They get the real app, in your order, and
|
|
60
|
+
cannot change anything. See [Sharing](#sharing).
|
|
61
|
+
- Compare things no design tool can hold: three git branches, a local build
|
|
62
|
+
against production, yesterday's direction against today's.
|
|
63
|
+
- Hand the workflow to your coding agent. `leglas init` teaches it, and
|
|
64
|
+
`leglas explore` briefs an exploration: five separate ideas, or five
|
|
65
|
+
variants of the one you already like. You choose the spread; your agent
|
|
66
|
+
supplies the taste.
|
|
67
|
+
- Ask for changes without leaving the comparison. Describe what you want on
|
|
68
|
+
the direction you are looking at, or point at it, and Leglas turns that
|
|
69
|
+
into a precise request for your agent, file path and screenshots
|
|
70
|
+
included. The agents on your machine are one click away next to the send
|
|
71
|
+
button. Your agent, your subscription, no keys.
|
|
72
|
+
- A change makes a variant, not a rewrite. The result registers under the
|
|
73
|
+
direction it came from, with the original still there to compare against.
|
|
74
|
+
- Keep the winner with one command. Leglas moves it into your source tree,
|
|
75
|
+
writes down what the exploration decided and clears the rest away.
|
|
76
|
+
- No app yet? Plain HTML files compare the same way, no dev server needed.
|
|
77
|
+
|
|
78
|
+
## Get started
|
|
115
79
|
|
|
116
80
|
Start your dev server, then run Leglas from the project directory:
|
|
117
81
|
|
|
@@ -119,194 +83,168 @@ Start your dev server, then run Leglas from the project directory:
|
|
|
119
83
|
npx leglas
|
|
120
84
|
```
|
|
121
85
|
|
|
122
|
-
Leglas starts on port 4100, proxies your app
|
|
86
|
+
Leglas starts on port 4100, proxies your app and opens
|
|
123
87
|
`http://localhost:4100/leglas`. With no configuration you get a single
|
|
124
|
-
preview of your app root
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
88
|
+
preview of your app root; a config file, described under
|
|
89
|
+
[Configuration](#configuration), is how you get more than one thing to
|
|
90
|
+
compare.
|
|
91
|
+
If that port turns out to be served from outside your project, Leglas says
|
|
92
|
+
so and points at `devServer` and `--user-port` rather than quietly proxying
|
|
93
|
+
the wrong app.
|
|
94
|
+
|
|
95
|
+
It works with whatever you are building in. Leglas never imports or
|
|
96
|
+
executes your framework, so the target can be Next, Vite, Remix, SvelteKit,
|
|
97
|
+
Astro or a folder of static files. It needs Node 24 or newer, and nothing
|
|
98
|
+
else: `npx` fetches the CLI on first use and starts from the cache after
|
|
99
|
+
that. To pin a version for a project, `npm install -D leglas`; to type
|
|
100
|
+
`leglas` without the prefix, `npm install -g leglas`.
|
|
101
|
+
|
|
102
|
+
Leglas asks npm once a day whether a newer version exists and says so in
|
|
103
|
+
the terminal and beside its name in the interface, where one click installs
|
|
104
|
+
it and starts Leglas again. The check reads the registry your npm is
|
|
105
|
+
configured for. Set `LEGLAS_NO_UPDATE_CHECK=1` to turn it off; the version
|
|
106
|
+
stays in the interface and you can still check by hand from there.
|
|
107
|
+
|
|
108
|
+
## Using Leglas
|
|
109
|
+
|
|
110
|
+
### The rail and the stage
|
|
111
|
+
|
|
112
|
+
Directions live in a rail on the left. The stage shows the active one in a
|
|
113
|
+
framed viewport at Full, 1440, 834 or 390 wide. Rename, reorder, hide and
|
|
114
|
+
tag directions from the rail; open the removed list to restore one, delete
|
|
115
|
+
it for good or clear the list. Your layout is saved per project and
|
|
116
|
+
survives restarts.
|
|
128
117
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
118
|
+
A small tools widget floats over the stage and can be dragged to any
|
|
119
|
+
corner. Its popover holds the viewport presets and a few preferences,
|
|
120
|
+
including hiding the dev badge your framework paints over the corner of
|
|
121
|
+
the app when it lands on the part you are judging.
|
|
132
122
|
|
|
133
|
-
|
|
123
|
+
### Comparing
|
|
134
124
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
125
|
+
Flipping shows a difference over time. A split shows it at once, which is
|
|
126
|
+
what you want for the last two in contention: press `C`, or hover a
|
|
127
|
+
direction and press its compare button, and it becomes the right pane
|
|
128
|
+
while the active direction holds the left.
|
|
129
|
+
|
|
130
|
+
Each side is drawn at the width it had on its own and scaled to fit, so
|
|
131
|
+
nothing reflows and flipping and splitting agree about what the design is.
|
|
132
|
+
An app given half the room would cross its own breakpoints and draw a
|
|
133
|
+
different design. If the narrow rendering is what you want, the tools
|
|
134
|
+
popover's "Scale each side to fit" switch is for that.
|
|
135
|
+
|
|
136
|
+
### Asking for a change
|
|
137
|
+
|
|
138
|
+
Type what you want into the field under the rail, or press `R`, and Leglas
|
|
139
|
+
composes a request naming the direction and the file behind it, copies it
|
|
140
|
+
to your clipboard and queues it. The direction it means is the one
|
|
141
|
+
highlighted directly above the field. By default the request asks for a
|
|
142
|
+
new variant beside that direction; the chip next to the send button
|
|
143
|
+
switches it to a change in place, for when a change really is a fix.
|
|
144
|
+
|
|
145
|
+
Pick an agent once from the picker beside the send button and the card
|
|
146
|
+
above the field shows it working: which file it is editing, how long it
|
|
147
|
+
has been, a stop if you change your mind, a retry when a run goes wrong.
|
|
148
|
+
Every request carries a screenshot of the direction at the width you are
|
|
149
|
+
looking at, a crop of anything you pointed at, the other pane when you are
|
|
150
|
+
comparing and any image you pasted in as a reference. Leglas runs no model
|
|
151
|
+
of its own; your agent already knows your conventions and your taste.
|
|
139
152
|
|
|
140
|
-
|
|
153
|
+
<p align="center">
|
|
154
|
+
<img src="https://raw.githubusercontent.com/FredAmartey/leglas/main/.github/assets/screenshots/field-idle.png" width="290" alt="The change field, empty, with its agent picker reading Choose an agent" />
|
|
155
|
+
<img src="https://raw.githubusercontent.com/FredAmartey/leglas/main/.github/assets/screenshots/field-queued.png" width="290" alt="A card above the change field reading: Change queued, pick who runs your changes" />
|
|
156
|
+
<img src="https://raw.githubusercontent.com/FredAmartey/leglas/main/.github/assets/screenshots/field-pickedup.png" width="290" alt="A card above the change field reading: Codex is on it, editing .leglas/variants/hero/poster.tsx, 56s, with a stop button" />
|
|
157
|
+
</p>
|
|
141
158
|
|
|
142
|
-
|
|
143
|
-
CI get the same Leglas from their normal install, and `npx` resolves
|
|
144
|
-
the local copy from then on.
|
|
145
|
-
- `npm install -g leglas` is for typing `leglas` without the prefix.
|
|
159
|
+
<p align="center"><i>Nothing waiting, then a request queued, then an agent that has taken it.</i></p>
|
|
146
160
|
|
|
147
|
-
|
|
161
|
+
Hover any direction to see what it was built from and the change that was
|
|
162
|
+
asked for, in the words that were typed.
|
|
148
163
|
|
|
149
|
-
|
|
164
|
+
### Pointing at the problem
|
|
150
165
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
166
|
+
Most of what you would type is the part describing where the problem is,
|
|
167
|
+
so point at it instead. Press `A` and the preview becomes a picker:
|
|
168
|
+
hovering outlines the element under the pointer, clicking drops a numbered
|
|
169
|
+
pin that takes a note, and dragging marks an area and names every element
|
|
170
|
+
inside it. Click a pin again to reread it, reword it or drop it. The page
|
|
171
|
+
still scrolls, so the thing three screens down is as easy to mark as the
|
|
172
|
+
headline.
|
|
154
173
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
project's `AGENTS.md`, creates a starter config, and gitignores Leglas's
|
|
162
|
-
working directory. That section travels with the repo, so Claude Code,
|
|
163
|
-
Cursor, Codex, or whatever you switch to next opens the project already
|
|
164
|
-
knowing how to add design directions to it. Every command accepts
|
|
165
|
-
`--json` and prints a single machine-readable envelope, so agents drive
|
|
166
|
-
the same CLI you do.
|
|
174
|
+
Annotations are a request on their own, so the field can stay empty: leave
|
|
175
|
+
three and send once. Each carries the element's own words, its tag and
|
|
176
|
+
classes, a path and the box it filled, and tells your agent which of those
|
|
177
|
+
to trust first, because the design moves under them by design. A pin whose
|
|
178
|
+
element has since gone turns amber rather than pointing confidently at the
|
|
179
|
+
wrong thing.
|
|
167
180
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
direction registers. Unbriefed, six requests come back as six variants
|
|
176
|
-
of one idea. With `--based-on "Aurora"` the goal flips: six deliberate
|
|
177
|
-
variants of a direction you already like, and drifting into a new
|
|
178
|
-
direction is the failure. The designs themselves are the agent's;
|
|
179
|
-
Leglas prescribes none.
|
|
180
|
-
- `npx leglas new hero --from src/Hero.tsx` scaffolds a switcher under
|
|
181
|
-
`.leglas/variants/hero/`. With `--from`, the baseline re-exports your
|
|
182
|
-
real component, so you never compare against a stale copy. Leglas
|
|
183
|
-
prints the one line to add in your component and does not edit it,
|
|
184
|
-
because rewriting a file it does not understand is how a tool breaks a
|
|
185
|
-
codebase. Scaffolded branch points return the fallback in production
|
|
186
|
-
builds, so a committed one cannot expose an unreleased direction.
|
|
187
|
-
- `npx leglas classify --change package.json --rewrite src/theme.css` answers
|
|
188
|
-
where a direction should live before it is written. Changing
|
|
189
|
-
dependencies, build configuration, or an existing file's behaviour
|
|
190
|
-
cannot be additive, so those directions build on their own git branch
|
|
191
|
-
and register with `leglas add --branch`. Everything else stays in-app,
|
|
192
|
-
where switching is instant.
|
|
193
|
-
- `npx leglas show "Aurora" --json` answers for one direction: its entry, the
|
|
194
|
-
source file behind it, the variants based on it, what it is being compared
|
|
195
|
-
against, and anything still pending on it. Add `--screenshot` and it
|
|
196
|
-
renders the direction too, so an agent can look at what it built. Copying
|
|
197
|
-
a direction from the rail hands over a block that ends in this command, so
|
|
198
|
-
an agent given the block can go and get the rest.
|
|
199
|
-
- `npx leglas keep "Aurora" --to src/components/hero.tsx` moves the winner
|
|
200
|
-
into real source and ends the exploration. It also writes down what the
|
|
201
|
-
exploration was, into `design-log/`: every direction with its note, the words
|
|
202
|
-
you typed at each of them, the captures the agent was sent, and which one
|
|
203
|
-
won. Plain markdown and PNGs, committed, so a pull request can link it and
|
|
204
|
-
somebody can read it in three months without this tool. Exploring is
|
|
205
|
-
episodic, and the archive is what makes coming back to a surface cheaper than
|
|
206
|
-
starting over. `npx leglas log` lists what is there. Set `logDir` if you want
|
|
207
|
-
it somewhere else.
|
|
208
|
-
|
|
209
|
-
Asking for a change works from the interface too. Type what you want
|
|
210
|
-
changed into the field under the rail (or press `R`) and Leglas composes a
|
|
211
|
-
prompt naming the direction and the file behind it, copies it to your
|
|
212
|
-
clipboard, and queues it. The direction it means is the one highlighted
|
|
213
|
-
directly above the field. By default the request asks for a new variant
|
|
214
|
-
beside that direction; the chip next to the send button switches it to a
|
|
215
|
-
change in place. Your agent drains the queue with `npx leglas requests --json` and clears
|
|
216
|
-
it with `--clear`. Leglas runs no model of its own; your agent already
|
|
217
|
-
knows your conventions and your taste.
|
|
218
|
-
|
|
219
|
-
Most of what you would type into that field is the part describing where
|
|
220
|
-
the problem is, so you can point at it instead. Press `A` and the preview
|
|
221
|
-
becomes a picker: hovering outlines the element under the pointer,
|
|
222
|
-
clicking drops a numbered pin that takes a note, and dragging marks an
|
|
223
|
-
area and names every element inside it. Click a pin again to reread what
|
|
224
|
-
it says, reword it or drop it. The page still scrolls, so the thing three
|
|
225
|
-
screens down is as easy to mark as the headline. Annotations
|
|
226
|
-
are a request on their own, so the field can stay empty; leave three and
|
|
227
|
-
send once. Each one carries the element's own words, its tag and classes,
|
|
228
|
-
a path and the box it filled, and the request tells your agent which of
|
|
229
|
-
those to trust first, because the design moves under them by design. One
|
|
230
|
-
whose element has since gone turns amber rather than pointing confidently
|
|
231
|
-
at the wrong thing, and one already sent with a change takes a ring until
|
|
232
|
-
that change settles.
|
|
233
|
-
|
|
234
|
-
The card above the field is the whole status: what you have queued, who
|
|
235
|
-
has taken it and for how long, and what went wrong when a run fails.
|
|
181
|
+
### Sharing
|
|
182
|
+
|
|
183
|
+
The rail is local, and the person who most needs to see it often has no
|
|
184
|
+
repo. The share control in the rail's header fixes that: pick the whole rail
|
|
185
|
+
as you see it, or what is on stage (one direction, or the pair being
|
|
186
|
+
compared), and start sharing. Leglas opens a second listener on your
|
|
187
|
+
machine, points a tunnel at it and copies the link once it answers.
|
|
236
188
|
|
|
237
189
|
<p align="center">
|
|
238
|
-
<img src="https://raw.githubusercontent.com/FredAmartey/leglas/main/.github/assets/screenshots/
|
|
239
|
-
<img src="https://raw.githubusercontent.com/FredAmartey/leglas/main/.github/assets/screenshots/
|
|
240
|
-
<img src="https://raw.githubusercontent.com/FredAmartey/leglas/main/.github/assets/screenshots/field-pickedup.png" width="290" alt="A card above the change field reading: Codex is on it, editing .leglas/variants/hero/poster.tsx, 56s, with a stop button" />
|
|
190
|
+
<img src="https://raw.githubusercontent.com/FredAmartey/leglas/main/.github/assets/screenshots/share-links.png" width="426" alt="The share panel under the rail's header while sharing: the tunnel address, two links named Link 1 and Client review each with 24h left, the hovered row showing copy, extend and turn off, Another link, the scope line reading The whole rail, 6 directions, only what you shared, then Replace all and Stop" />
|
|
191
|
+
<img src="https://raw.githubusercontent.com/FredAmartey/leglas/main/.github/assets/screenshots/share-viewer.png" width="426" alt="The same rail as a viewer sees it: a strip reading Shared with you, the whole rail, then the directions in the sharer's order with no composer" />
|
|
241
192
|
</p>
|
|
242
193
|
|
|
243
|
-
<p align="center"><i>
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
194
|
+
<p align="center"><i>Sharing, and what the person on the other end gets.</i></p>
|
|
195
|
+
|
|
196
|
+
Whoever opens the link gets the real app, running, with your order, your
|
|
197
|
+
names, your folded families and your viewport. They can flip, compare,
|
|
198
|
+
search and change the width. They cannot change anything: the share
|
|
199
|
+
listener refuses every write, whoever the caller is, and answers every path
|
|
200
|
+
with 403 without the cookie the link sets, so your dev server never faces
|
|
201
|
+
the internet bare. Viewers do not get hot reload either, since an app's
|
|
202
|
+
live-reload socket is a way in; they refresh to see a change.
|
|
203
|
+
|
|
204
|
+
What a viewer can do is read what your dev server serves, and you choose
|
|
205
|
+
how much of it. **Anywhere in the app** is the whole dev server over GET,
|
|
206
|
+
source included, because Leglas proxies it faithfully and that is the
|
|
207
|
+
point; it suits a demo. **Only what you shared** serves the pages you shared
|
|
208
|
+
and the files they load, refuses the rest before the dev server hears of it
|
|
209
|
+
and holds against a console or curl as well as a browser. The list is read
|
|
210
|
+
off what your own directions loaded while you looked at them, not written
|
|
211
|
+
by hand, and anything it did not predict shows up in the panel with one
|
|
212
|
+
click to let that path or its folder through. Bounded still means a viewer
|
|
213
|
+
sees everything your shared pages themselves load. Either way Leglas
|
|
214
|
+
refuses the routes a dev server mounts to act on your machine, Vite's
|
|
215
|
+
editor launcher among them, hidden files like `.env` however the path is
|
|
216
|
+
spelled and a service worker that would outlive the share.
|
|
253
217
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
218
|
+
<p align="center">
|
|
219
|
+
<img src="https://raw.githubusercontent.com/FredAmartey/leglas/main/.github/assets/screenshots/share-reach.png" width="426" alt="The share panel before starting: The whole rail, 6 directions, 2 on branches left out; The direction on stage, Table; How far they can go: Anywhere in the app, Your whole dev server over GET; Only what you shared, These pages and the 22 files they loaded; a Start sharing button" />
|
|
220
|
+
</p>
|
|
257
221
|
|
|
258
|
-
|
|
222
|
+
<p align="center"><i>Choosing what to share, and how far a viewer goes.</i></p>
|
|
259
223
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
already pushes each request into the session as it arrives.
|
|
224
|
+
A share hands out links rather than a link. Name one for each person, up
|
|
225
|
+
to sixteen; each lasts a day, extends by another with one click and turns
|
|
226
|
+
off on its own without touching the others. The panel shows which links
|
|
227
|
+
are answering and how many sessions are on each. When your rail has moved
|
|
228
|
+
since you shared, it offers to push what you see now; stop the share from
|
|
229
|
+
the same place, and it stops with Leglas either way.
|
|
267
230
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
231
|
+
The tunnel is borrowed, not shipped. Leglas looks for `cloudflared` or
|
|
232
|
+
`ngrok` on your machine and runs whichever it finds; with neither, the link
|
|
233
|
+
only works on this machine and the panel says so. Branch directions run on
|
|
234
|
+
their own port and are not part of a share.
|
|
271
235
|
|
|
272
|
-
|
|
236
|
+
### Keys
|
|
273
237
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
238
|
+
Arrows move between directions and `1` to `9` jump straight to one. `R`
|
|
239
|
+
asks for a change, `A` annotates, `C` compares, `Cmd K` (`Ctrl K`
|
|
240
|
+
elsewhere) searches, `T` opens the tools popover and `B` collapses the
|
|
241
|
+
rail. Press `?` for the whole keymap.
|
|
277
242
|
|
|
278
|
-
|
|
279
|
-
CLI. A host that starts the server somewhere else is asked where the
|
|
280
|
-
project is, over MCP roots. The `start` tool boots the viewer and returns
|
|
281
|
-
its URL, and anything it started stops when the session ends.
|
|
243
|
+
## Setting up a project
|
|
282
244
|
|
|
283
|
-
###
|
|
245
|
+
### Configuration
|
|
284
246
|
|
|
285
|
-
|
|
286
|
-
open standard for shipping Agent Skills and MCP server configuration in
|
|
287
|
-
one format. Clients that implement it install the skill and the server
|
|
288
|
-
together, instead of the two steps above. It is a layout rather than a
|
|
289
|
-
build: `plugin.json` and `mcp.json` at the root, the skill in
|
|
290
|
-
`skills/leglas/`, nothing generated.
|
|
291
|
-
|
|
292
|
-
An Agent Plugins client starts a plugin's server in the plugin's own
|
|
293
|
-
install directory rather than the project, so on that path the working
|
|
294
|
-
directory names a copy of Leglas and nothing else. The server therefore
|
|
295
|
-
takes the project from the workspace the host declares over MCP roots,
|
|
296
|
-
and the working directory only when it sits inside one. If a host offers
|
|
297
|
-
neither, `LEGLAS_PROJECT_DIR` names the project outright; without it the
|
|
298
|
-
tools report that there is no project rather than writing into a plugin
|
|
299
|
-
cache. `mcp.json` passes `${PLUGIN_ROOT}` for exactly that check, and
|
|
300
|
-
nothing else.
|
|
301
|
-
|
|
302
|
-
The plugin's version covers the skill and the configuration, not the
|
|
303
|
-
server it launches: `npx` fetches the current `leglas-mcp` the same way
|
|
304
|
-
every `npx leglas` in these instructions fetches the current CLI, which
|
|
305
|
-
keeps both faces of Leglas on one version in a project they share.
|
|
306
|
-
|
|
307
|
-
## Configuration
|
|
308
|
-
|
|
309
|
-
Create `leglas.config.ts` at the project root. `.js`, `.mjs`, and `.json`
|
|
247
|
+
Create `leglas.config.ts` at the project root. `.js`, `.mjs` and `.json`
|
|
310
248
|
work too. Resolution walks upward from the working directory, so in a
|
|
311
249
|
monorepo the nearest file wins. Node reads the TypeScript config natively;
|
|
312
250
|
there is no compiler or extra dependency involved.
|
|
@@ -346,129 +284,18 @@ A broken config never stops the server. Leglas starts anyway and the
|
|
|
346
284
|
interface reports what to fix, so you are not hunting through a stack
|
|
347
285
|
trace.
|
|
348
286
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
Directions live in a rail on the left. The stage shows the active one in
|
|
352
|
-
a framed viewport at Full, 1440, 834 or 390 wide. Rename, reorder, hide
|
|
353
|
-
and tag directions from the rail. Open the removed list to restore a
|
|
354
|
-
direction, delete one permanently or clear the full list. Machine-local
|
|
355
|
-
directions are removed from `.leglas/previews.json`; shared project config
|
|
356
|
-
and preview source files stay untouched. Layout is saved per project and
|
|
357
|
-
survives restarts and port changes.
|
|
358
|
-
|
|
359
|
-
Flipping shows a difference over time. A split shows it at once, which is
|
|
360
|
-
what you want for the last two directions in contention: press `C`, or
|
|
361
|
-
hover a direction and press its compare button, and it becomes the right
|
|
362
|
-
pane while the active direction holds the left.
|
|
363
|
-
|
|
364
|
-
A split does not hand each side half the room. An app given half the room
|
|
365
|
-
crosses its own breakpoints and draws a different design, so you would be
|
|
366
|
-
choosing between two narrow renderings of directions meant for the wide
|
|
367
|
-
one. Instead each side is drawn at the width it had on its own and scaled
|
|
368
|
-
to fit, keeping the same proportions, so nothing reflows and flipping and
|
|
369
|
-
splitting agree about what the design is. Each pane says the width it is
|
|
370
|
-
drawn at and the scale it is shown at. If you want the narrow rendering,
|
|
371
|
-
that is what the tools popover's "Scale each side to fit" switch is for.
|
|
372
|
-
|
|
373
|
-
Arrows move between directions, `1` to `9` jump straight to one, `R` asks
|
|
374
|
-
for a change to the one you are on, `A` annotates the design itself,
|
|
375
|
-
`Cmd K` (`Ctrl K` elsewhere) searches, `T` opens the tools popover and `B`
|
|
376
|
-
collapses the rail. Press `?` for the whole keymap.
|
|
377
|
-
|
|
378
|
-
A small tools widget floats over the stage and can be dragged to any
|
|
379
|
-
corner, because a floating control has a habit of sitting exactly where
|
|
380
|
-
you need to look. Its popover holds the viewport presets and a few
|
|
381
|
-
preferences.
|
|
382
|
-
|
|
383
|
-
Frameworks paint a dev badge over the corner of the running app. It
|
|
384
|
-
belongs to your app, so Leglas leaves it alone; when it lands on the part
|
|
385
|
-
you are judging, the popover hides it, and does that by styling inside
|
|
386
|
-
the preview frame, never by altering what the proxy forwards.
|
|
387
|
-
|
|
388
|
-
## Command line
|
|
389
|
-
|
|
390
|
-
```text
|
|
391
|
-
Usage
|
|
392
|
-
leglas init Prepare a project and teach its agents
|
|
393
|
-
leglas [options] Start the server and open the interface
|
|
394
|
-
leglas new <surface> Scaffold a branch point for a surface
|
|
395
|
-
leglas explore <surface> Brief an agent's exploration of a surface
|
|
396
|
-
leglas classify Decide where a direction should live
|
|
397
|
-
leglas add --title T --url U Register a preview on this machine
|
|
398
|
-
leglas list Show every preview, shared and local
|
|
399
|
-
leglas log [entry] What past explorations decided
|
|
400
|
-
leglas show <title> Everything Leglas knows about one direction
|
|
401
|
-
leglas requests Show change requests made from the interface
|
|
402
|
-
leglas watch --run "<cmd>" Hand each request to your agent as it arrives
|
|
403
|
-
leglas keep <title> --to <path> Keep a winner and end the exploration
|
|
404
|
-
|
|
405
|
-
Options
|
|
406
|
-
--user-port <port> Port your dev server is on (default: from config, or 3000)
|
|
407
|
-
--port <port> Port for Leglas itself (default: 4100, next free if taken)
|
|
408
|
-
--config <path> Config file to use instead of searching upward
|
|
409
|
-
--no-open Do not open the browser
|
|
410
|
-
--json Print a single machine-readable envelope
|
|
411
|
-
-h, --help Show this
|
|
412
|
-
-v, --version Show the version
|
|
413
|
-
|
|
414
|
-
Options for new
|
|
415
|
-
--print Print the scaffold instead of writing it
|
|
416
|
-
--from <path> Use an existing component as the baseline
|
|
417
|
-
|
|
418
|
-
Options for explore
|
|
419
|
-
--count <n> How many directions (default 3)
|
|
420
|
-
--based-on <title> Variants of an existing direction instead of new ones
|
|
421
|
-
|
|
422
|
-
Options for watch
|
|
423
|
-
--run <command> Your agent, with {prompt} where the request goes, for
|
|
424
|
-
example "claude -p {prompt}". Remembered after first use
|
|
425
|
-
--port <port> Port Leglas itself is on (default: 4100)
|
|
426
|
-
|
|
427
|
-
Options for classify
|
|
428
|
-
--change <path> A file the direction creates or wires up (repeatable)
|
|
429
|
-
--rewrite <path> An existing file whose behaviour it must change (repeatable)
|
|
430
|
-
|
|
431
|
-
Options for add
|
|
432
|
-
--note <text> Second line under the title
|
|
433
|
-
--tag <text> Repeatable
|
|
434
|
-
--branch <name> Back the preview with a checkout of this git branch
|
|
435
|
-
--file <path> Preview a plain HTML file served by Leglas itself
|
|
436
|
-
--based-on <title> The direction this is a variant of; groups the family
|
|
437
|
-
--asked-for <text> The change that was asked for, in the words that were typed
|
|
438
|
-
|
|
439
|
-
Options for show
|
|
440
|
-
--screenshot Render the direction and write a PNG
|
|
441
|
-
--width <n> Capture width from 320 to 3840 (needs --screenshot)
|
|
442
|
-
--port <port> Running Leglas port (needs --screenshot)
|
|
443
|
-
```
|
|
444
|
-
|
|
445
|
-
`leglas.config.ts` is the shared description of a project: commit it and a
|
|
287
|
+
The config is the shared description of a project: commit it and a
|
|
446
288
|
teammate gets the same directions on clone. `leglas add` registers a
|
|
447
289
|
preview on your machine only, in `.leglas/previews.json`, because
|
|
448
|
-
exploration is short-lived and its code lives in a gitignored directory
|
|
449
|
-
`leglas list` shows both and marks which are local.
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
`.leglas/renames.json`. Leglas will not edit your config to rename
|
|
453
|
-
something you only renamed for yourself, so the config title stays the
|
|
454
|
-
one a teammate sees, and `leglas show` and `leglas keep` take either
|
|
455
|
-
name.
|
|
456
|
-
|
|
457
|
-
## Comparing branches
|
|
458
|
-
|
|
459
|
-
A preview with a `branch` field is served from its own checkout: Leglas
|
|
460
|
-
creates a worktree, installs, starts the app with your `devCommand` on a
|
|
461
|
-
free port, and tears it all down when you quit. In the interface it looks
|
|
462
|
-
like any other direction, so a branch against your working tree, or three
|
|
463
|
-
branches against each other, compares the same way two query parameters
|
|
464
|
-
do.
|
|
465
|
-
|
|
466
|
-
## Without a dev server
|
|
290
|
+
exploration is short-lived and its code lives in a gitignored directory;
|
|
291
|
+
`leglas list` shows both and marks which are local. Renaming a direction
|
|
292
|
+
in the rail is local in the same way, so the config title stays the one a
|
|
293
|
+
teammate sees, and `leglas show` and `leglas keep` take either name.
|
|
467
294
|
|
|
468
|
-
|
|
295
|
+
### Without a dev server
|
|
469
296
|
|
|
470
297
|
If the project exists but nothing is listening, set `devCommand` and
|
|
471
|
-
Leglas starts your app itself, proxies it
|
|
298
|
+
Leglas starts your app itself, proxies it and stops it on exit. When
|
|
472
299
|
`--user-port` names a server explicitly, Leglas never starts a different
|
|
473
300
|
one behind that flag.
|
|
474
301
|
|
|
@@ -489,7 +316,16 @@ the lone file, so stylesheets and images beside it resolve. When the real
|
|
|
489
316
|
app arrives, directions graduate to app code and nothing about the
|
|
490
317
|
interface changes.
|
|
491
318
|
|
|
492
|
-
|
|
319
|
+
### Comparing branches
|
|
320
|
+
|
|
321
|
+
A preview with a `branch` field is served from its own checkout: Leglas
|
|
322
|
+
creates a worktree, installs, starts the app with your `devCommand` on a
|
|
323
|
+
free port and tears it all down when you quit. In the interface it looks
|
|
324
|
+
like any other direction, so a branch against your working tree, or three
|
|
325
|
+
branches against each other, compares the same way two query parameters
|
|
326
|
+
do.
|
|
327
|
+
|
|
328
|
+
### How it works
|
|
493
329
|
|
|
494
330
|
Leglas runs one local server that serves the interface at `/leglas` and
|
|
495
331
|
forwards every other request to your dev server. Previews load through
|
|
@@ -503,7 +339,7 @@ app behaves differently through Leglas than on its own port, that is a
|
|
|
503
339
|
bug.
|
|
504
340
|
|
|
505
341
|
Because a preview is a URL, the same interface compares two routes, two
|
|
506
|
-
implementations behind a query parameter
|
|
342
|
+
implementations behind a query parameter or a local server against a
|
|
507
343
|
deployed one. Absolute URLs load directly rather than through the proxy,
|
|
508
344
|
so a site that refuses to be framed will not preview; the interface says
|
|
509
345
|
so instead of showing an empty pane.
|
|
@@ -511,10 +347,10 @@ so instead of showing an empty pane.
|
|
|
511
347
|
Leglas also compares what each preview actually draws and warns when two
|
|
512
348
|
are identical. This catches a typo like `?v-hero=wavee` that your app
|
|
513
349
|
silently ignores while the rail implies a comparison. The check reads the
|
|
514
|
-
rendered page, runs only on previews you have opened
|
|
350
|
+
rendered page, runs only on previews you have opened and skips
|
|
515
351
|
cross-origin previews, which the browser will not let it read.
|
|
516
352
|
|
|
517
|
-
|
|
353
|
+
### Limitations
|
|
518
354
|
|
|
519
355
|
- Leglas runs no model of its own. Comparing existing routes costs
|
|
520
356
|
nothing, but a new direction is still code your agent writes; Leglas
|
|
@@ -526,43 +362,125 @@ cross-origin previews, which the browser will not let it read.
|
|
|
526
362
|
- The interface is built for desktop widths.
|
|
527
363
|
- Leglas is a development tool. Nothing in it ships to production.
|
|
528
364
|
|
|
529
|
-
##
|
|
365
|
+
## Working with agents
|
|
366
|
+
|
|
367
|
+
The fastest way in is the agent skill:
|
|
368
|
+
|
|
369
|
+
```sh
|
|
370
|
+
npx skills add FredAmartey/leglas
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
One install, and your agent recognises "give me a few directions for the
|
|
374
|
+
pricing page" as a Leglas exploration in any project, including ones that
|
|
375
|
+
have never seen Leglas. It sets the project up itself and gets to work.
|
|
376
|
+
|
|
377
|
+
In a project, `npx leglas init` writes a section into `AGENTS.md`, creates
|
|
378
|
+
a starter config and gitignores Leglas's working directory. That section
|
|
379
|
+
is the agent's whole workflow, and it travels with the repo, so Claude
|
|
380
|
+
Code, Cursor, Codex or whatever you switch to next opens the project
|
|
381
|
+
already knowing how to add design directions to it. Every command accepts
|
|
382
|
+
`--json` and prints a single machine-readable envelope, so agents drive
|
|
383
|
+
the same CLI you do.
|
|
384
|
+
|
|
385
|
+
### Add beside, never rewrite
|
|
386
|
+
|
|
387
|
+
The instructions center on one rule. Two directions that rewrite the same
|
|
388
|
+
file cannot render from one server, and asking an agent to "make the hero
|
|
389
|
+
calmer" tempts it to edit the hero. So a direction is added next to what
|
|
390
|
+
exists: a switcher scaffolded beside your component, a query parameter
|
|
391
|
+
that selects it, and your real component untouched as the baseline.
|
|
392
|
+
Anything that cannot be additive, a dependency, a build change, an
|
|
393
|
+
existing file's behaviour, builds on its own git branch instead.
|
|
394
|
+
|
|
395
|
+
### What an agent runs
|
|
396
|
+
|
|
397
|
+
| Command | What it does |
|
|
398
|
+
| --- | --- |
|
|
399
|
+
| `leglas explore <surface> --count 6` | Briefs the exploration: what the set is for, and why it only works if the six genuinely disagree. `--based-on "Aurora"` flips it to six deliberate variants of one you like. The designs are the agent's; Leglas prescribes none. |
|
|
400
|
+
| `leglas new <surface> --from src/Hero.tsx` | Scaffolds a switcher under `.leglas/variants/`, with the baseline re-exporting your real component. Prints the one line to add and does not edit your file. Scaffolded branch points return the fallback in production builds. |
|
|
401
|
+
| `leglas classify --change … --rewrite …` | Says where a direction should live before it is written: in-app, where switching is instant, or on its own branch. |
|
|
402
|
+
| `leglas add --title … --url …` | Registers a direction on this machine. |
|
|
403
|
+
| `leglas show "Aurora" --json` | Everything about one direction: its entry, the file behind it, its variants, what it is compared against, what is pending. `--screenshot` renders it too, so an agent can look at what it built. |
|
|
404
|
+
| `leglas requests --json` | The change requests queued from the interface; `--clear` acknowledges them. |
|
|
405
|
+
| `leglas keep "Aurora" --to src/components/hero.tsx` | Moves the winner into real source and ends the exploration, writing what it decided into `design-log/` as markdown and PNGs. `leglas log` lists what is there. |
|
|
406
|
+
|
|
407
|
+
### Running requests
|
|
408
|
+
|
|
409
|
+
Requests made from the interface wait in a queue. An agent picked in the
|
|
410
|
+
interface drains it on its own. In a terminal, `npx leglas watch` is the
|
|
411
|
+
same loop with the agent's own output in view, and needs no flag once an
|
|
412
|
+
agent has been picked; for a CLI that is not in the picker, keep the
|
|
413
|
+
command explicit:
|
|
414
|
+
|
|
415
|
+
```sh
|
|
416
|
+
npx leglas watch --run "my-agent {prompt}"
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
### MCP server
|
|
530
420
|
|
|
531
|
-
|
|
421
|
+
For agent hosts that cannot run shell commands, `leglas-mcp` exposes the
|
|
422
|
+
same operations as MCP tools over stdio: `start`, `add`, `list`, `show`,
|
|
423
|
+
`classify`, `explore`, `scaffold`, `keep`, `requests` and `init`. Each
|
|
424
|
+
tool calls exactly what the CLI calls and returns the same envelope. The
|
|
425
|
+
`start` tool boots the viewer and returns its URL, and anything it started
|
|
426
|
+
stops when the session ends.
|
|
532
427
|
|
|
533
428
|
```sh
|
|
534
|
-
|
|
535
|
-
pnpm build # build every package
|
|
536
|
-
pnpm test # run the test suite
|
|
537
|
-
pnpm typecheck # type check every package
|
|
538
|
-
pnpm site # build the site, homepage and changelog, into dist/site
|
|
429
|
+
claude mcp add leglas -- npx -y leglas-mcp
|
|
539
430
|
```
|
|
540
431
|
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
432
|
+
Or in `.mcp.json`:
|
|
433
|
+
|
|
434
|
+
```json
|
|
435
|
+
{ "mcpServers": { "leglas": { "command": "npx", "args": ["-y", "leglas-mcp"] } } }
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
The host's working directory names the project, the same contract as the
|
|
439
|
+
CLI. A host that starts the server somewhere else is asked where the
|
|
440
|
+
project is, over MCP roots. On a host that speaks channels, the server
|
|
441
|
+
pushes each request into the session as it arrives.
|
|
442
|
+
|
|
443
|
+
### Agent Plugin
|
|
444
|
+
|
|
445
|
+
The repository is also an [Agent Plugin](https://agent-plugins.org), the
|
|
446
|
+
open standard for shipping a skill and MCP configuration together, so a
|
|
447
|
+
client that implements it installs both in one step. It is a layout, not a
|
|
448
|
+
build: `plugin.json` and `mcp.json` at the root, the skill in
|
|
449
|
+
`skills/leglas/`. Such a client starts the server in the plugin's own
|
|
450
|
+
directory, so the project is taken from the workspace the host declares
|
|
451
|
+
over MCP roots, or from `LEGLAS_PROJECT_DIR` when it declares none. The
|
|
452
|
+
plugin's version covers the skill and the configuration; the server it
|
|
453
|
+
launches is whatever `npx` fetches, the same as every command above.
|
|
454
|
+
|
|
455
|
+
## Command line
|
|
456
|
+
|
|
457
|
+
```text
|
|
458
|
+
leglas init Prepare a project and teach its agents
|
|
459
|
+
leglas [options] Start the server and open the interface
|
|
460
|
+
leglas new <surface> Scaffold a branch point for a surface
|
|
461
|
+
leglas explore <surface> Brief an agent's exploration of a surface
|
|
462
|
+
leglas classify Decide where a direction should live
|
|
463
|
+
leglas add --title T --url U Register a preview on this machine
|
|
464
|
+
leglas list Show every preview, shared and local
|
|
465
|
+
leglas log [entry] What past explorations decided
|
|
466
|
+
leglas show <title> Everything Leglas knows about one direction
|
|
467
|
+
leglas requests Show change requests made from the interface
|
|
468
|
+
leglas watch --run "<cmd>" Hand each request to your agent as it arrives
|
|
469
|
+
leglas keep <title> --to <path> Keep a winner and end the exploration
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
`--json` on any command prints a single machine-readable envelope.
|
|
473
|
+
`--port` chooses Leglas's own port and `--user-port` your dev server's;
|
|
474
|
+
`--config` names a config file instead of searching upward. Every
|
|
475
|
+
command's options are under `leglas <command> --help`.
|
|
476
|
+
|
|
477
|
+
## Development
|
|
478
|
+
|
|
479
|
+
This repository is a pnpm workspace: `pnpm install`, then `pnpm build`,
|
|
480
|
+
`pnpm test` and `pnpm typecheck`. Two packages are published, `leglas` and
|
|
481
|
+
`leglas-mcp`, and the repository is also the Agent Plugin. How to work on
|
|
482
|
+
it, what a pull request needs and how a release is cut are in
|
|
483
|
+
[CONTRIBUTING.md](CONTRIBUTING.md).
|
|
566
484
|
|
|
567
485
|
## License
|
|
568
486
|
|