aem-eds-kit 0.4.48 → 0.4.54

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.
Files changed (4) hide show
  1. package/CHANGELOG.md +110 -58
  2. package/README.md +130 -28
  3. package/dist/bin/eds.js +157 -121
  4. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -6,6 +6,47 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ### Changed
10
+ - **Docs and site match the CLI again** (EDS-063). README screenshots of real
11
+ runs (the menu, `eds new`, `block from-design`, `migrate component`,
12
+ `block test` / `check`, the preview harness) and design-vs-block images;
13
+ `docs.html` gains `block test` / `block check`, local models and configuration
14
+ sections plus the missing flags; the site covers `eds new`, local models,
15
+ AEMaaCS proxy / Classic UI migration and the real Figma REST limits.
16
+ - **CHANGELOG split into the versions published on npm** (0.4.22, 0.4.25,
17
+ 0.4.26, 0.4.48), worked out from the CHANGELOG inside each npm package.
18
+ Version links point at npm; the GitHub release links never existed.
19
+
20
+ ### Fixed
21
+ - **`eds init --yes` no longer prompts for the authoring model** (EDS-061). It
22
+ detects it from the `fstab.yaml` mountpoint (AEM author → Universal Editor,
23
+ `content.da.live` → DA, Google Drive, SharePoint) or a crosswalk `paths.json`,
24
+ and stops with exit 1 and a `--authoring` hint when it can't tell. Interactively
25
+ the detected model is preselected.
26
+ - **`eds init --yes` no longer prompts for the project name** (EDS-058). Without
27
+ `--name` it now takes the folder name (or `package.json`'s, unless that is still
28
+ the boilerplate's own), so it runs in CI and without a terminal.
29
+ - **`eds sandbox new --ue` used a crosswalk boilerplate that doesn't exist**
30
+ (EDS-056): `adobe/aem-boilerplate-xwalk` is now `adobe-rnd/aem-boilerplate-xwalk`,
31
+ where the Universal Editor boilerplate actually lives.
32
+
33
+ ### Added
34
+ - **`eds new [dir]`: clone the latest EDS boilerplate locally** (EDS-055). DA,
35
+ Universal Editor (crosswalk) or Commerce, or any repo / git URL; no GitHub auth.
36
+ Fresh git history by default, or `--keep-history` with an `upstream` remote;
37
+ `--ref`, `--remote`, `--install`; then `eds init`, with UE preselected for
38
+ crosswalk. Also first in the interactive menu.
39
+ - **Local models: Ollama and oMLX** (EDS-051). `--agent ollama | omlx | local`
40
+ runs `from-design` on a local model (Ollama's native API with `num_ctx`;
41
+ oMLX or any OpenAI-compatible server). The CLI embeds the design (scraped /
42
+ REST spec, SVG text) or attaches a PNG/JPG for a vision model, asks for every
43
+ file in a `=== FILE: … ===` format and writes them itself, only inside
44
+ `blocks/<name>/`. Model from `--model`, `local.model` or a coder model on the
45
+ server; context from `local.contextTokens` (default 32768, raised to fit).
46
+ Used automatically when no CLI agent is installed. New `--model` flag.
47
+
48
+ ## [0.4.48] - 2026-10-20
49
+
9
50
  ### Changed
10
51
  - **README rewritten for the npm page** (EDS-047): absolute links (relative
11
52
  ones break on npmjs.com), a docs / changelog / e2e links row, a "What it does"
@@ -17,29 +58,6 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
17
58
  hundreds of pixels of white and a height change inside them went unnoticed.
18
59
  Existing baselines need one `eds block test --update`; a run against an old
19
60
  baseline says so instead of reporting a size change.
20
- - **`block from-design` now fetches the design once into a cached snapshot,
21
- then generates from it** (fetch → cache → generate). The CLI resolves the
22
- design via the cheapest adapter - local SVG/PNG export, a cached snapshot
23
- (`tmp/eds-cli/design-cache/`), the **Figma REST** API (with a token), or a
24
- **single** Figma MCP call the agent caches - so retries and refine passes
25
- never re-fetch. Replaces the old flow where the agent made several MCP calls
26
- mid-generation. New `src/lib/figma/rest.ts` and `design-source.ts`.
27
- - **MCP usage cut to one call per block.** The prompt now uses only
28
- `get_design_context` (dropped `get_variable_defs`; `get_screenshot` is opt-in
29
- via `--screenshot`) - the Figma Dev Mode MCP server meters tool calls per plan
30
- (20/month on Starter or with a View/Collab seat; 200-600/day with Dev/Full on
31
- paid plans). Set a Figma token to fetch via REST instead, on its own budget.
32
- - **Block generation defaults to the fastest model (Haiku)**, overridable with
33
- `model` in config - block codegen is structured, bounded work.
34
- - **`eds block preview` no longer auto-launches.** After `from-design` you get a
35
- menu to refine the block or open the preview on demand; `--no-serve` became
36
- `--serve` (opt-in, non-interactive runs only).
37
- - **Shorter interactive-menu labels** (details moved to each choice's
38
- description).
39
- - **Smaller published package (~206 kB → ~73 kB packed; 808 kB → ~220 kB
40
- unpacked).** The build no longer ships a source map (it was ~60% of the
41
- package; re-enable ad hoc with `tsup --sourcemap`) and now minifies the single
42
- bundled binary (`dist/bin/eds.js` 265 kB → ~170 kB).
43
61
 
44
62
  ### Fixed
45
63
  - **Figma limits described correctly** (EDS-040). Code comments, README, docs
@@ -64,19 +82,6 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
64
82
  take the prompt as one command-line argument; past 96 KB (a scraped page of
65
83
  ~30 sections) it's replaced by a short instruction to read the saved prompt
66
84
  file, so the spawn can't hit Linux's 128 KB per-argument limit (E2BIG).
67
- - **Block preview blank-screen cases.** The harness now (a) reduces a full-HTML
68
- `_<name>.preview.html` mock to its `<body>` contents, (b) reveals the body past
69
- the EDS `body.appear` visibility gate (which `scripts.js` would normally flip),
70
- and (c) loads the block script via a defensive dynamic `import()` so a bad
71
- import (e.g. a missing `scripts/*.js`) shows the authored markup instead of a
72
- blank frame. The prompt now requires a bare preview fragment and self-contained
73
- block JS.
74
- - **`eds block preview header|footer`** now warns that these are page chrome and
75
- can't render standalone (they fetch the nav/footer fragment and need the full
76
- page runtime).
77
- - Removed the dangling `main`/`types` fields that pointed at a never-built
78
- `dist/index.js` (a bare `import "aem-eds-kit"` would have failed) - the package
79
- is a CLI, exposed via its `bin`.
80
85
 
81
86
  ### Added
82
87
  - **Changelog page on the site** (EDS-048): `site/changelog.html` is generated
@@ -102,6 +107,43 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
102
107
  datasource → text), smartimage, multifield (plain multi-value, or ACS
103
108
  `multifieldpanel` → container), tabpanel and `cqinclude`. Tested on the 22
104
109
  Classic UI dialogs of ACS Commons 3.14: 21 migrate, 63 valid fields.
110
+
111
+ ## [0.4.26] - 2026-10-12
112
+
113
+ ### Changed
114
+ - **`block from-design` now fetches the design once into a cached snapshot,
115
+ then generates from it** (fetch → cache → generate). The CLI resolves the
116
+ design via the cheapest adapter - local SVG/PNG export, a cached snapshot
117
+ (`tmp/eds-cli/design-cache/`), the **Figma REST** API (with a token), or a
118
+ **single** Figma MCP call the agent caches - so retries and refine passes
119
+ never re-fetch. Replaces the old flow where the agent made several MCP calls
120
+ mid-generation. New `src/lib/figma/rest.ts` and `design-source.ts`.
121
+ - **MCP usage cut to one call per block.** The prompt now uses only
122
+ `get_design_context` (dropped `get_variable_defs`; `get_screenshot` is opt-in
123
+ via `--screenshot`) - the Figma Dev Mode MCP server meters tool calls per plan
124
+ (20/month on Starter or with a View/Collab seat; 200-600/day with Dev/Full on
125
+ paid plans). Set a Figma token to fetch via REST instead, on its own budget.
126
+ - **Block generation defaults to the fastest model (Haiku)**, overridable with
127
+ `model` in config - block codegen is structured, bounded work.
128
+ - **`eds block preview` no longer auto-launches.** After `from-design` you get a
129
+ menu to refine the block or open the preview on demand; `--no-serve` became
130
+ `--serve` (opt-in, non-interactive runs only).
131
+ - **Shorter interactive-menu labels** (details moved to each choice's
132
+ description).
133
+
134
+ ### Fixed
135
+ - **Block preview blank-screen cases.** The harness now (a) reduces a full-HTML
136
+ `_<name>.preview.html` mock to its `<body>` contents, (b) reveals the body past
137
+ the EDS `body.appear` visibility gate (which `scripts.js` would normally flip),
138
+ and (c) loads the block script via a defensive dynamic `import()` so a bad
139
+ import (e.g. a missing `scripts/*.js`) shows the authored markup instead of a
140
+ blank frame. The prompt now requires a bare preview fragment and self-contained
141
+ block JS.
142
+ - **`eds block preview header|footer`** now warns that these are page chrome and
143
+ can't render standalone (they fetch the nav/footer fragment and need the full
144
+ page runtime).
145
+
146
+ ### Added
105
147
  - **`eds block preview` with no name → a live gallery of every content block**,
106
148
  each in its own width-honest iframe. Routes are computed per request, so a
107
149
  block generated while the gallery is open appears on the next reload
@@ -113,12 +155,31 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
113
155
  `figma.token` config, scope `file_content:read`) - a quota separate from the
114
156
  MCP tool-call limit. New flags `--mcp` (force MCP) and `--refresh` (ignore the
115
157
  cache).
158
+
159
+ ## [0.4.25] - 2026-10-09
160
+
161
+ ### Changed
162
+ - **Smaller published package (~206 kB → ~73 kB packed; 808 kB → ~220 kB
163
+ unpacked).** The build no longer ships a source map (it was ~60% of the
164
+ package; re-enable ad hoc with `tsup --sourcemap`) and now minifies the single
165
+ bundled binary (`dist/bin/eds.js` 265 kB → ~170 kB).
166
+
167
+ ### Fixed
168
+ - Removed the dangling `main`/`types` fields that pointed at a never-built
169
+ `dist/index.js` (a bare `import "aem-eds-kit"` would have failed) - the package
170
+ is a CLI, exposed via its `bin`.
171
+
172
+ ### Added
116
173
  - **`block from-design` records the design's frame widths** in the block's
117
174
  `.eds-meta.json` (`breakpoints`), so `eds block preview` is width-honest at the
118
175
  **real design widths**, not a fixed device set. The agent writes the widths it
119
176
  reads from the design (prompt instruction), `--widths 390,768,1440` overrides,
120
177
  and 375/768/1280 remains the fallback. New `src/lib/figma/breakpoints.ts`
121
178
  (`parseWidths` / `normalizeBreakpoints`), extended `edsMetaSchema`.
179
+
180
+ ## [0.4.22] - 2026-10-08
181
+
182
+ ### Added
122
183
  - **`eds init` writes a local-dev `.env` + `xwalk.json` by default.** `.env`
123
184
  carries the `aem up` config (`AEM_OPEN=/`, `AEM_PORT=3007`, `AEM_PAGES_URL`
124
185
  prefilled from the git remote); it's never overwritten and always gitignored.
@@ -419,25 +480,16 @@ harness, gradient ANSI logo. Not published (superseded by 0.3.0).
419
480
  Initial CLI scaffold: `block create`, `block from-figma`, `block list`,
420
481
  `figma setup`, `doctor`, `preview`, `publish`. Not published.
421
482
 
422
- [Unreleased]: https://github.com/piotrgodycki/aem-eds-kit/compare/v0.4.19...HEAD
423
- [0.4.19]: https://github.com/piotrgodycki/aem-eds-kit/releases/tag/v0.4.19
424
- [0.4.18]: https://github.com/piotrgodycki/aem-eds-kit/releases/tag/v0.4.18
425
- [0.4.17]: https://github.com/piotrgodycki/aem-eds-kit/releases/tag/v0.4.17
426
- [0.4.16]: https://github.com/piotrgodycki/aem-eds-kit/releases/tag/v0.4.16
427
- [0.4.15]: https://github.com/piotrgodycki/aem-eds-kit/releases/tag/v0.4.15
428
- [0.4.14]: https://github.com/piotrgodycki/aem-eds-kit/releases/tag/v0.4.14
429
- [0.4.13]: https://github.com/piotrgodycki/aem-eds-kit/releases/tag/v0.4.13
430
- [0.4.12]: https://github.com/piotrgodycki/aem-eds-kit/releases/tag/v0.4.12
431
- [0.4.11]: https://github.com/piotrgodycki/aem-eds-kit/releases/tag/v0.4.11
432
- [0.4.10]: https://github.com/piotrgodycki/aem-eds-kit/releases/tag/v0.4.10
433
- [0.4.9]: https://github.com/piotrgodycki/aem-eds-kit/releases/tag/v0.4.9
434
- [0.4.8]: https://github.com/piotrgodycki/aem-eds-kit/releases/tag/v0.4.8
435
- [0.4.7]: https://github.com/piotrgodycki/aem-eds-kit/releases/tag/v0.4.7
436
- [0.4.6]: https://github.com/piotrgodycki/aem-eds-kit/releases/tag/v0.4.6
437
- [0.4.5]: https://github.com/piotrgodycki/aem-eds-kit/releases/tag/v0.4.5
438
- [0.4.4]: https://github.com/piotrgodycki/aem-eds-kit/releases/tag/v0.4.4
439
- [0.4.3]: https://github.com/piotrgodycki/aem-eds-kit/releases/tag/v0.4.3
440
- [0.4.2]: https://github.com/piotrgodycki/aem-eds-kit/releases/tag/v0.4.2
441
- [0.4.1]: https://github.com/piotrgodycki/aem-eds-kit/releases/tag/v0.4.1
442
- [0.4.0]: https://github.com/piotrgodycki/aem-eds-kit/releases/tag/v0.4.0
443
- [0.3.0]: https://github.com/piotrgodycki/aem-eds-kit/releases/tag/v0.3.0
483
+ [Unreleased]: https://github.com/piotrgodycki/aem-eds-kit/commits/main
484
+ [0.4.48]: https://www.npmjs.com/package/aem-eds-kit/v/0.4.48
485
+ [0.4.26]: https://www.npmjs.com/package/aem-eds-kit/v/0.4.26
486
+ [0.4.25]: https://www.npmjs.com/package/aem-eds-kit/v/0.4.25
487
+ [0.4.22]: https://www.npmjs.com/package/aem-eds-kit/v/0.4.22
488
+ [0.4.16]: https://www.npmjs.com/package/aem-eds-kit/v/0.4.16
489
+ [0.4.12]: https://www.npmjs.com/package/aem-eds-kit/v/0.4.12
490
+ [0.4.9]: https://www.npmjs.com/package/aem-eds-kit/v/0.4.9
491
+ [0.4.7]: https://www.npmjs.com/package/aem-eds-kit/v/0.4.7
492
+ [0.4.4]: https://www.npmjs.com/package/aem-eds-kit/v/0.4.4
493
+ [0.4.2]: https://www.npmjs.com/package/aem-eds-kit/v/0.4.2
494
+ [0.4.1]: https://www.npmjs.com/package/aem-eds-kit/v/0.4.1
495
+ [0.4.0]: https://www.npmjs.com/package/aem-eds-kit/v/0.4.0
package/README.md CHANGED
@@ -12,13 +12,13 @@
12
12
 
13
13
  **Turn a design into an EDS block** - JS, CSS and a Universal Editor model - without leaving your terminal.
14
14
 
15
- `aem-eds-kit` gives you the `eds` command. Paste a design link - a Figma URL, or a Framer / Google Stitch page - and it hands the design to the AI agent you already use (Claude Code, Cursor or Codex), which writes production-ready code straight into your repo. Figma is read through MCP or the REST API; Framer and Stitch render real HTML, so they're **scraped with headless Chromium** (no token needed). It also scaffolds blocks, previews them in your browser, and keeps your project healthy with a few quick audits.
15
+ `aem-eds-kit` gives you the `eds` command. Paste a design link - a Figma URL, or a Framer / Google Stitch page - and it hands the design to the AI agent you already use (Claude Code, Cursor or Codex, or a local model through Ollama / oMLX), which writes production-ready code straight into your repo. Figma is read through MCP or the REST API; Framer and Stitch render real HTML, so they're **scraped with headless Chromium** (no token needed). It also scaffolds blocks, previews them in your browser, and keeps your project healthy with a few quick audits.
16
16
 
17
17
  It lives next to `@adobe/aem-cli` (your local dev server) and handles everything around it.
18
18
 
19
19
  ## What it does
20
20
 
21
- - **Blocks from a design.** A Figma frame (REST or MCP), a Framer / Google Stitch page (scraped with headless Chromium) or a local PNG / SVG export becomes `blocks/<name>/`: JS, CSS, a Universal Editor model and a preview mock. Works with Claude Code, Cursor and Codex. Content Fragment blocks (`--source cf` / `mixed`) get an async, fetching `decorate()`.
21
+ - **Blocks from a design.** A Figma frame (REST or MCP), a Framer / Google Stitch page (scraped with headless Chromium) or a local PNG / SVG export becomes `blocks/<name>/`: JS, CSS, a Universal Editor model and a preview mock. Works with Claude Code, Cursor and Codex, or a [local model](#local-models-ollama-omlx) through Ollama or oMLX. Content Fragment blocks (`--source cf` / `mixed`) get an async, fetching `decorate()`.
22
22
  - **Migration from AEM.** `eds migrate component` turns a classic component's dialog into a block and a UE model, with no agent involved. It handles AEM as a Cloud Service proxy components (via `sling:resourceSuperType`, e.g. onto Core Components) and AEM 6.5 Classic UI `dialog.xml` files.
23
23
  - **Within Figma's limits.** One REST or MCP call per block, then a cache. REST calls are paced per minute across parallel runs. A rate limit stops with the reset time; it never spends your MCP budget behind your back. [The limits](#how-figma-integration-works).
24
24
  - **QA before review.** `eds block test` does visual regression on the block itself, plus a design↔render diff. `eds block check` covers content and a11y, including preview mocks nested deeper than real EDS markup. There are also `doctor`, loading and security audits.
@@ -26,6 +26,17 @@ It lives next to `@adobe/aem-cli` (your local dev server) and handles everything
26
26
 
27
27
  Proof: the whole example screen (11 blocks) was generated from a scraped page and from Figma exports, screenshotted next to the design, and 163 + 22 real AEM components were migrated. See the [end-to-end test](https://piotrgodycki.github.io/aem-eds-kit/e2e-example.html).
28
28
 
29
+ <p align="center"><img src="https://raw.githubusercontent.com/piotrgodycki/aem-eds-kit/main/.github/assets/readme/design-vs-block.webp" alt="A Google Stitch hero design next to the EDS block eds generated from it: same layout, type scale, colours and buttons, with placeholder copy" width="100%"></p>
30
+
31
+ <details>
32
+ <summary><strong>The whole screen</strong>: design vs. the 11 generated blocks</summary>
33
+
34
+ <p align="center"><img src="https://raw.githubusercontent.com/piotrgodycki/aem-eds-kit/main/.github/assets/readme/design-vs-page.webp" alt="The full example page design next to the page built from 11 generated EDS blocks" width="100%"></p>
35
+
36
+ Generated blocks ship with placeholder copy (and empty image slots) until authors fill them in; the layout, spacing, type and colours come from the design.
37
+
38
+ </details>
39
+
29
40
  ## Install
30
41
 
31
42
  ```bash
@@ -70,7 +81,7 @@ eds block from-design "<figma-url>" --name hero
70
81
 
71
82
  ## Try it in 30 seconds (no Figma account, no token)
72
83
 
73
- From inside an EDS project (or spin a throwaway one up with `eds sandbox new demo`):
84
+ From inside an EDS project (or clone a fresh one with `eds new demo && cd demo`):
74
85
 
75
86
  ```bash
76
87
  eds block from-design --sample --name hero --dry-run # see the prompt - zero setup
@@ -80,6 +91,14 @@ eds block preview hero # see it live in the bro
80
91
 
81
92
  `--sample` uses a **bundled "Kiri Bloom" hero design**, read straight from disk - **no Figma token, no MCP call, no network**. (`--dry-run` needs no AI agent either - it just prints the prompt.)
82
93
 
94
+ A real run (Claude Code): the agent's live log, a verification pass over the files it wrote, then a menu to refine, preview or finish.
95
+
96
+ <p align="center"><img src="https://raw.githubusercontent.com/piotrgodycki/aem-eds-kit/main/.github/assets/readme/cli-fd.png" alt="Terminal: eds block from-design --sample --name promo, showing the design source, the agent's live log, the files it wrote, a verification table and the refine / preview / finish menu" width="760"></p>
97
+
98
+ `eds block preview` serves the block at the design's own widths, with live reload:
99
+
100
+ <p align="center"><img src="https://raw.githubusercontent.com/piotrgodycki/aem-eds-kit/main/.github/assets/readme/block-preview.webp" alt="Browser: the eds block preview harness showing the hero block at 1440 px with a breakpoint dropdown" width="100%"></p>
101
+
83
102
  Ready for the real thing? Point it at the official **Kiri Bloom AEM EDS Kit** training file in Figma:
84
103
 
85
104
  ```bash
@@ -90,7 +109,11 @@ eds block from-design \
90
109
 
91
110
  ## Interactive mode
92
111
 
93
- Run `eds` with no command and it opens an **interactive menu** that stays open between actions (arrows to move, Enter to run, **Esc** to go back - or to quit from the menu itself; Ctrl+C quits anywhere). It walks you through every feature (set up the project, generate a block from a design, migrate a classic AEM component, scaffold, create a block, add an integration, preview, Admin API, audits, Figma setup). Most commands are also interactive on their own when you omit arguments - e.g. `eds init`, `eds block from-design` (wizard), `eds migrate component`, `eds scaffold`, `eds integrate`, `eds preview`. Flags and subcommands still work for CI / power users.
112
+ Run `eds` with no command and it opens an **interactive menu** that stays open between actions (arrows to move, Enter to run, **Esc** to go back - or to quit from the menu itself; Ctrl+C quits anywhere). It walks you through every feature: new project (clone the boilerplate), set up project, page template, sandbox repo, block from design, migrate component, scaffold UE, empty block, integration, model fields, analytics, structured data, Universal Editor, preview block, pages (preview / publish), audits and Figma MCP.
113
+
114
+ <p align="center"><img src="https://raw.githubusercontent.com/piotrgodycki/aem-eds-kit/main/.github/assets/readme/cli-menu.png" alt="Terminal: the eds interactive menu with Block from design selected" width="560"></p>
115
+
116
+ Most commands are also interactive on their own when you omit arguments - e.g. `eds init`, `eds block from-design` (wizard), `eds migrate component`, `eds scaffold`, `eds integrate`, `eds preview`. Flags and subcommands still work for CI / power users.
94
117
 
95
118
  A full A-Z reference of every command lives on the docs page: **https://piotrgodycki.github.io/aem-eds-kit/docs.html**
96
119
 
@@ -99,6 +122,9 @@ A full A-Z reference of every command lives on the docs page: **https://piotrgod
99
122
  ```bash
100
123
  eds # interactive menu
101
124
 
125
+ # Start from the latest boilerplate (DA, Universal Editor or Commerce)
126
+ eds new my-site
127
+
102
128
  # Just cloned an EDS boilerplate? Set it up for your authoring model
103
129
  eds init
104
130
 
@@ -131,7 +157,8 @@ The full path, command by command. This example targets **DA (da.live)** authori
131
157
  # 1. Install the CLI
132
158
  npm i -g aem-eds-kit
133
159
 
134
- # 2. Set up the project (pick DA, enter org + site). Writes fstab + CI + naming.
160
+ # 2. Clone the latest boilerplate, then set it up (pick DA, enter org + site)
161
+ eds new my-site && cd my-site
135
162
  eds init --authoring da --org my-org --site my-site
136
163
 
137
164
  # 3. Scaffold the Universal Editor config + helper functions
@@ -160,6 +187,32 @@ Every step is also interactive when you omit the flags - run `eds` for the menu.
160
187
 
161
188
  ## Commands
162
189
 
190
+ ### `eds new [dir]`
191
+
192
+ Clone the **current EDS boilerplate** into a local folder. No GitHub auth needed, and nothing is created on GitHub (for a repo on GitHub, see [`eds sandbox`](#eds-sandbox)). Choose Document Authoring / DA (`adobe/aem-boilerplate`), Universal Editor / crosswalk (`adobe-rnd/aem-boilerplate-xwalk`), the Adobe Commerce storefront (`hlxsites/aem-boilerplate-commerce`), or any repo or git URL.
193
+
194
+ By default the copy starts a **fresh git history**, with one initial commit naming the boilerplate commit it came from. `--keep-history` keeps the boilerplate's history with its remote named `upstream`, so `git pull upstream main` brings in later boilerplate changes. It refuses a folder that isn't empty, then offers `npm install` and `eds init`, with Universal Editor preselected for the crosswalk boilerplate.
195
+
196
+ ```bash
197
+ eds new # guided
198
+ eds new my-site --yes # DA boilerplate, fresh history
199
+ eds new my-site --ue --keep-history # crosswalk, with an upstream remote
200
+ eds new shop --boilerplate commerce --install
201
+ eds new my-site --remote git@github.com:me/my-site.git
202
+ ```
203
+
204
+ | Flag | Description |
205
+ |---|---|
206
+ | `--boilerplate <repo>` | `da` \| `ue` \| `commerce`, `owner/repo` on GitHub, or any git URL / path |
207
+ | `--ue` | The crosswalk / Universal Editor boilerplate |
208
+ | `--ref <ref>` | Branch or tag to clone |
209
+ | `--keep-history` | Keep the boilerplate's history (remote renamed to `upstream`) |
210
+ | `--remote <url>` | Set `origin` to your own repo |
211
+ | `--install` | Run `npm install` after cloning |
212
+ | `--yes` | Skip the guided prompts |
213
+
214
+ <p align="center"><img src="https://raw.githubusercontent.com/piotrgodycki/aem-eds-kit/main/.github/assets/readme/cli-new-picker.png" alt="Terminal: eds new asking for a folder and offering the DA, Universal Editor and Commerce boilerplates" width="660"></p>
215
+
163
216
  ### `eds init`
164
217
 
165
218
  Adapt a freshly cloned EDS boilerplate to your setup in one interactive wizard. Pick the authoring model - **Universal Editor (crosswalk), DA (da.live), Google Drive or SharePoint** - and `eds` sets the project name (`package.json` + boilerplate placeholders), writes `fstab.yaml` **only when the model needs it** (UE/crosswalk doesn't), scaffolds the crosswalk config + `paths.json` for UE, optionally adds the CI workflow, then walks the **external steps** (AEM Code Sync app, content-source share, Sidekick) as a clickable checklist.
@@ -171,15 +224,18 @@ By default it also writes, out of the box:
171
224
 
172
225
  Opt out with `--no-env` / `--no-xwalk`, or (re)generate either later with `eds scaffold env` / `eds scaffold xwalk`.
173
226
 
227
+ **Non-interactive (`--yes`).** The project name defaults to the folder name (or `package.json`'s, unless that's still the boilerplate's own). The authoring model is detected from the `fstab.yaml` mountpoint (an AEM author → Universal Editor, `content.da.live` → DA, Google Drive, SharePoint) or a crosswalk `paths.json`, and preselected in the interactive picker. When it can't be told (the DA boilerplate ships no `fstab.yaml`), `--yes` stops with exit 1 and asks for `--authoring`.
228
+
174
229
  ```bash
175
230
  eds init # interactive
231
+ eds init --yes # detect everything (e.g. right after `eds new --ue`)
176
232
  eds init --name my-site --authoring da --org my-org --site my-site --yes
177
233
  ```
178
234
 
179
235
  | Flag | Description |
180
236
  |---|---|
181
237
  | `--name <name>` | Project name (kebab-case) |
182
- | `--authoring <model>` | `ue` \| `da` \| `gdrive` \| `sharepoint` |
238
+ | `--authoring <model>` | `ue` \| `da` \| `gdrive` \| `sharepoint` (else detected from `fstab.yaml` / `paths.json`) |
183
239
  | `--mountpoint <url>` | Content source URL (document models) |
184
240
  | `--org <org>` / `--site <site>` | DA org / site (`--authoring da`) |
185
241
  | `--no-ci` | Skip the GitHub Actions workflow |
@@ -216,18 +272,21 @@ Spin up and tear down **disposable EDS sandbox repos** on GitHub - a rapid, thro
216
272
  eds sandbox login # authorize GitHub (device flow or token)
217
273
  eds sandbox new my-test # guided: boilerplate, visibility, Code Sync, eds init
218
274
  eds sandbox new my-test --ue --private --yes
275
+ eds sandbox new shop --boilerplate hlxsites/aem-boilerplate-commerce # any template repo
219
276
  eds sandbox list # your sandboxes (tagged eds-sandbox) + preview URLs
220
277
  eds sandbox rm my-test # delete it (with confirmation)
221
278
  ```
222
279
 
223
- `sandbox new` creates the repo from a boilerplate (Document Authoring `adobe/aem-boilerplate` or Universal Editor `adobe/aem-boilerplate-xwalk`) via the GitHub API, clones it, tags it `eds-sandbox`, then walks you through opening the AEM Code Sync install page and running `eds init`. The preview URL is `https://main--<repo>--<owner>.aem.page/`.
280
+ `sandbox new` creates the repo from a boilerplate (Document Authoring `adobe/aem-boilerplate`, Universal Editor `adobe-rnd/aem-boilerplate-xwalk`, or any template repo with `--boilerplate <owner/repo>`) via the GitHub API, clones it, tags it `eds-sandbox`, then walks you through opening the AEM Code Sync install page and running `eds init`. The preview URL is `https://main--<repo>--<owner>.aem.page/`.
224
281
 
225
282
  Sandboxes are **throwaway test repos** - stand one up to debug or try an integration, then delete it; they work fine on a personal account. Two safety guarantees:
226
283
 
227
284
  - **Never overwrites an existing repo.** `sandbox new` checks first and refuses if `<owner>/<name>` already exists (and the GitHub template API never clobbers either way).
228
285
  - **Least privilege.** Scope the token to just your sandboxes - a fine-grained token limited to one repo, or a dedicated sandbox org used via `--org`. `eds sandbox login` links you straight to the token page with the minimal permissions. See the [Secure GitHub sandboxes guide](https://piotrgodycki.github.io/aem-eds-kit/secure-github-sandboxes.html).
229
286
 
230
- The token is stored owner-only (mode `0600`) in `~/.eds/github.json`; `eds sandbox logout` removes it. `list` only ever shows `eds-sandbox` repos and `rm` deletes only the named repo, with confirmation.
287
+ The token is stored owner-only (mode `0600`) in `~/.eds/github.json`; `eds sandbox logout` removes it. `list` only ever shows `eds-sandbox` repos and `rm` deletes only the named repo (under `--org <org>` when it lives in an org), with confirmation.
288
+
289
+ Just want the code on your machine, no GitHub repo? Use [`eds new`](#eds-new-dir).
231
290
 
232
291
  ### `eds migrate component [dir]`
233
292
 
@@ -244,6 +303,8 @@ eds migrate component ./ui.apps/.../apps/wknd/components/teaser \
244
303
  --super-root ../aem-core-wcm-components/content/src/content/jcr_root # proxy → Core Component dialog
245
304
  ```
246
305
 
306
+ <p align="center"><img src="https://raw.githubusercontent.com/piotrgodycki/aem-eds-kit/main/.github/assets/readme/cli-mig.png" alt="Terminal: eds migrate component on the WKND teaser proxy component; the dialog is inherited from the Core Components teaser and its 13 fields are mapped to Universal Editor field types" width="760"></p>
307
+
247
308
  Dialogs map cleanly because Granite's `sling:resourceType` set is finite. The most faithful CSS actually comes from the **rendered page** (resolves LESS vars + cascade) - that capture lands in a later phase; for now the clientlib source gets you most of the way.
248
309
 
249
310
  ### `eds track block <name>`
@@ -306,7 +367,7 @@ The generated `_<name>.json` uses the EDS block-plugin (xwalk) format (`definiti
306
367
 
307
368
  ### `eds block from-design [design-url]`
308
369
 
309
- Translates a design - **a Figma URL, a Framer / Google Stitch page, or a local SVG/PNG export** - into an EDS block. Run with **no URL** for a step-by-step wizard (design source, name, link, content source, UE model, screenshot, run mode). It builds a prompt with EDS conventions + your project's design tokens and hands it to your AI agent (Claude Code, Cursor, or Codex). *(This was `from-figma` before it went design-agnostic; Figma is the most battle-tested source and stays pixel-perfect.)*
370
+ Translates a design - **a Figma URL, a Framer / Google Stitch page, or a local SVG/PNG export** - into an EDS block. Run with **no URL** for a step-by-step wizard (design source, name, link, content source, UE model, screenshot, run mode). It builds a prompt with EDS conventions + your project's design tokens and hands it to your AI agent (Claude Code, Cursor or Codex, or a [local model](#local-models-ollama-omlx)). *(This was `from-figma` before it went design-agnostic; Figma is the most battle-tested source and stays pixel-perfect.)*
310
371
 
311
372
  **Figma vs. web sources.** Figma paints to a WebGL canvas, so it's read through the **REST API** (with a token) or **MCP**. Framer and Google Stitch render **real HTML**, so `eds` **scrapes** them with headless Chromium — reading computed layout, typography, colours and geometry straight off the page (no token, no MCP). Canva and Sketch are canvas/image-based and aren't scrapeable — export a frame and pass it as a local SVG/PNG. The provider is detected from the URL host, or set with `--provider`.
312
373
 
@@ -351,7 +412,8 @@ eds block from-design "<figma-url>" --dry-run # just build the prompt
351
412
  | `--provider <type>` | Design source: `figma` \| `framer` \| `stitch` (else detected from the URL) |
352
413
  | `--source <type>` | Content source: `document` \| `ue` \| `cf` \| `mixed` (`cf` / `mixed` default to the `sonnet` model) |
353
414
  | `--widths <list>` | Design frame widths for preview breakpoints (e.g. `390,768,1440`) |
354
- | `--agent <type>` | Force `claude` \| `cursor` \| `codex` \| `none` (a prompt too large for one argument reaches Cursor / Codex as its file) |
415
+ | `--agent <type>` | Force `claude` \| `cursor` \| `codex` \| `ollama` \| `omlx` \| `local` \| `none` (a prompt too large for one argument reaches Cursor / Codex as its file; see [Local models](#local-models-ollama-omlx)) |
416
+ | `--model <name>` | Model to run: a Claude alias / id, or a local model such as `qwen2.5-coder:14b` |
355
417
  | `--dry-run` | Build the prompt only |
356
418
  | `--no-ue-model` | Skip the Universal Editor model |
357
419
  | `--screenshot` | Add a screenshot MCP call for a pixel check (opt-in — costs a call) |
@@ -376,7 +438,7 @@ The generated block records the **design's frame widths** in its `.eds-meta.json
376
438
  ### `eds figma setup`
377
439
 
378
440
  Interactive wizard that:
379
- 1. Detects installed AI agents (Claude Code, Cursor, Codex)
441
+ 1. Detects installed AI agents (Claude Code, Cursor, Codex) and running local model servers (Ollama, oMLX)
380
442
  2. Checks if Figma MCP is configured for your agent
381
443
  3. Shows install commands if not
382
444
  4. Saves preferences to `~/.eds/config.json`
@@ -403,6 +465,13 @@ eds block preview hero --widths 375,768,1280 # custom breakpoints
403
465
  eds block preview hero --port 9000 --no-open
404
466
  ```
405
467
 
468
+ - A dropdown switches the block between breakpoints inside an `<iframe>`, so the block's media queries fire against the chosen width - a **width-honest** comparison that isn't distorted by your monitor size.
469
+ - Breakpoints come from the block's `.eds-meta.json` (`breakpoints`, marking which widths have a real Figma frame → pixel-perfect) and fall back to `375 / 768 / 1280` or `--widths`.
470
+ - If the block has a `.eds-meta.json` with a Figma source, an **Open in Figma** link is shown.
471
+ - Authored sample content is read from `blocks/<name>/_<name>.preview.html` if present; otherwise a placeholder is used (and the chrome tells you to add one).
472
+
473
+ > Not to be confused with `eds preview [paths...]` (lower down), which previews **pages** via the AEM Admin API.
474
+
406
475
  ### `eds block test [name]` · `eds block check [name]`
407
476
 
408
477
  Two deterministic QA passes over a block's **rendered** DOM (no agent) - one block, or **all** of them when you omit the name. Both render the block in headless Chromium (Playwright), so install the browser once: `npx playwright install chromium`. Wire them into CI next to the audits - both exit non-zero on failure.
@@ -417,6 +486,11 @@ eds block test hero --design # rendered block vs its Figma design imag
417
486
  eds block test --threshold 0.02 # allow 2% changed pixels
418
487
  ```
419
488
 
489
+ A CSS change that moved the hero's buttons and text, caught at 1440 px, with the diff image it wrote:
490
+
491
+ <p align="center"><img src="https://raw.githubusercontent.com/piotrgodycki/aem-eds-kit/main/.github/assets/readme/cli-test.png" alt="Terminal: eds block test hero reporting 2.48% changed pixels at 1440px and the diff PNG path" width="760"></p>
492
+ <p align="center"><img src="https://raw.githubusercontent.com/piotrgodycki/aem-eds-kit/main/.github/assets/readme/visual-diff.webp" alt="Diff image: the changed pixels of the hero block highlighted in red and yellow" width="760"></p>
493
+
420
494
  | Flag | Description |
421
495
  |---|---|
422
496
  | `--update` | (Re)write baseline screenshots instead of comparing |
@@ -433,6 +507,8 @@ eds block check hero # one block
433
507
  eds block check --strict # fail on warnings too
434
508
  ```
435
509
 
510
+ <p align="center"><img src="https://raw.githubusercontent.com/piotrgodycki/aem-eds-kit/main/.github/assets/readme/cli-check.png" alt="Terminal: eds block check hero warning that the preview mock nests cell content one div deeper than EDS markup" width="760"></p>
511
+
436
512
  | Flag | Description |
437
513
  |---|---|
438
514
  | `--strict` | Fail on warnings too, not just errors |
@@ -473,28 +549,23 @@ eds integrate # interactive
473
549
  eds integrate gtm # gtm · ga4 · chat · cookiebot · custom
474
550
  ```
475
551
 
476
- - A dropdown switches the block between breakpoints inside an `<iframe>`, so the block's media queries fire against the chosen width - a **width-honest** comparison that isn't distorted by your monitor size.
477
- - Breakpoints come from the block's `.eds-meta.json` (`breakpoints`, marking which widths have a real Figma frame → pixel-perfect) and fall back to `375 / 768 / 1280` or `--widths`.
478
- - If the block has a `.eds-meta.json` with a Figma source, an **Open in Figma** link is shown.
479
- - Authored sample content is read from `blocks/<name>/_<name>.preview.html` if present; otherwise a placeholder is used (and the chrome tells you to add one).
480
-
481
- > Not to be confused with `eds preview <paths...>` (lower down), which previews **pages** via the AEM Admin API.
482
-
483
- ### `eds preview <path...>`
552
+ ### `eds preview [paths...]`
484
553
 
485
- Preview pages via the AEM Admin API (`admin.hlx.page`).
554
+ Preview pages via the AEM Admin API (`admin.hlx.page`). Run it with no paths for a wizard (pick the action, the paths and the org / site / ref).
486
555
 
487
556
  ```bash
557
+ eds preview # wizard
488
558
  eds preview /index
489
559
  eds preview /blog/my-post /about
490
560
  eds preview /index --org my-org --site my-repo --ref main
491
561
  ```
492
562
 
493
- ### `eds publish <path...>`
563
+ ### `eds publish [paths...]`
494
564
 
495
- Publish pages to live via the AEM Admin API.
565
+ Publish pages to live via the AEM Admin API (a wizard when run with no paths).
496
566
 
497
567
  ```bash
568
+ eds publish # wizard
498
569
  eds publish /index
499
570
  eds publish /blog/my-post /about
500
571
  ```
@@ -571,7 +642,8 @@ The design is fetched **once** into a cached snapshot, then the agent generates
571
642
  ┌─ local SVG/PNG ─┐
572
643
  ├─ cache hit ──────┤ design.json ┌─────────────┐ block files
573
644
  design reference ──┼─ Figma REST ─────┼───→ (cached) ───────→│ Claude Code │ ───────────────→ repo
574
- (url / file) └─ Figma MCP ──────┘ snapshot │ /Cursor/Codex│
645
+ (url / file) ├─ web scrape ─────┤ snapshot │ Cursor/Codex│
646
+ └─ Figma MCP ──────┘ │ Ollama/oMLX │
575
647
  (1 call, agent dumps to cache) └─────────────┘
576
648
  ```
577
649
 
@@ -587,6 +659,35 @@ The prompt includes:
587
659
  - Lighthouse performance requirements + a single structural self-verification pass
588
660
  - Output file structure
589
661
 
662
+ ## Local models (Ollama, oMLX)
663
+
664
+ Keep designs and code on your machine: `eds block from-design` can run a local model instead of Claude Code / Cursor / Codex.
665
+
666
+ ```bash
667
+ ollama pull qwen2.5-coder:14b && ollama serve # or: omlx start (Apple Silicon)
668
+ eds block from-design "<framer-url>" --name hero --agent ollama
669
+ eds block from-design ./hero.png --name hero --agent ollama --model qwen2.5vl:7b # PNG → vision model
670
+ eds block from-design ./hero.svg --name hero --agent omlx
671
+ ```
672
+
673
+ | Agent | Server (default) | API |
674
+ |---|---|---|
675
+ | `ollama` | `http://127.0.0.1:11434` | native `/api/chat` (so `num_ctx` can be raised) |
676
+ | `omlx` | `http://127.0.0.1:8000/v1` | OpenAI-compatible `/v1/chat/completions` |
677
+ | `local` | `local.baseUrl` | any OpenAI-compatible server (LM Studio, llama.cpp, vLLM…) |
678
+
679
+ - **No tools, so the CLI does the I/O.** A local model can't read files or call MCP. `eds` sends the whole prompt - a scraped page or Figma REST spec embedded, an SVG export inlined, a PNG / JPG attached as an image - and asks for every file in a `=== FILE: … ===` format. It then writes those files itself, **only inside `blocks/<name>/`**. The raw reply is kept in `tmp/eds-cli/local-reply-*.md`.
680
+ - **Figma needs REST or an export.** A Figma link without a token would need MCP, which a local model can't call: set `FIGMA_TOKEN`, or export the frame as PNG/SVG.
681
+ - **Model.** `--model`, else `local.model`, else a coder model the server has (`*coder*`, Codestral/Devstral, Qwen, DeepSeek…). A PNG/JPG design needs a vision model.
682
+ - **Context.** A design prompt is ~20-40k tokens. Ollama is asked for `local.contextTokens` (default **32768**, raised automatically when the prompt needs more); for other servers set the context length on the server. `eds` warns when the prompt won't fit.
683
+ - **Auto-detect.** With no CLI agent installed, `eds` uses a running Ollama or oMLX server. Refine passes work too: the model gets the block's current files and returns the changed ones.
684
+
685
+ ```json
686
+ { "agent": "ollama", "local": { "model": "qwen2.5-coder:14b", "contextTokens": 49152 } }
687
+ ```
688
+
689
+ `local.baseUrl` points at a different host or port, and `local.apiKey` is sent as a bearer token for servers that want one.
690
+
590
691
  ## Configuration
591
692
 
592
693
  Priority: CLI flags → env vars → `.edsrc.json` (project) → `~/.eds/config.json` (global)
@@ -596,10 +697,11 @@ Priority: CLI flags → env vars → `.edsrc.json` (project) → `~/.eds/config.
596
697
  {
597
698
  "agent": "claude",
598
699
  "model": "haiku",
599
- "figma": { "token": "figd_…", "restPerMinute": 10 }
700
+ "figma": { "token": "figd_…", "restPerMinute": 10 },
701
+ "local": { "model": "qwen2.5-coder:14b", "contextTokens": 49152 }
600
702
  }
601
703
  ```
602
- `model` sets the block-generation model (default: fastest / Haiku). `figma.token` (or the `FIGMA_TOKEN` env var) enables the REST fetch path — a Personal Access Token with scope `file_content:read`. Tokens are secrets; keep them out of the repo.
704
+ `agent` picks the agent (`claude`, `cursor`, `codex`, `ollama`, `omlx`, `local`); `model` sets the block-generation model (default: fastest / Haiku). `local.*` configures a [local model](#local-models-ollama-omlx). `figma.token` (or the `FIGMA_TOKEN` env var) enables the REST fetch path — a Personal Access Token with scope `file_content:read`. Tokens are secrets; keep them out of the repo.
603
705
 
604
706
  `figma.restPerMinute` paces Figma REST calls across every `eds` run in the project (they share `tmp/eds-cli/figma-rest-calls.json`), so a batch of blocks waits for a free slot instead of hitting a 429. Default **10** (Tier 1, Dev / Full seat on Professional); use 15 on Organization, 20 on Enterprise. On Starter or with a View / Collab seat the cap is monthly (20), so pacing can't help there.
605
707
 
@@ -620,13 +722,13 @@ Priority: CLI flags → env vars → `.edsrc.json` (project) → `~/.eds/config.
620
722
  |---|---|
621
723
  | `--verbose` | Debug-level output |
622
724
  | `--quiet` | Errors only |
623
- | `--json` | Machine-readable JSON output |
725
+ | `--json` | Machine-readable JSON output (`doctor`, `audit loading`, `audit security`, `block list`) |
624
726
  | `--no-color` | Disable colors (also respects `NO_COLOR` env) |
625
727
 
626
728
  ## Development
627
729
 
628
730
  ```bash
629
- git clone <repo-url> && cd eds-cli
731
+ git clone https://github.com/piotrgodycki/aem-eds-kit.git && cd aem-eds-kit
630
732
  npm install
631
733
  ```
632
734
 
@@ -700,7 +802,7 @@ Tests use fixtures in `tests/fixtures/` - a sample EDS project and recorded Figm
700
802
 
701
803
  - **Design sources** - Figma (REST/MCP), Framer and Google Stitch (headless-Chromium scrape) are wired; next is deepening the scrape extractor (multi-breakpoint capture, component/variant detection), a generic `eds setup` in place of `eds figma setup`, and an end-to-end run against a real Figma file ([EDS-020](https://github.com/piotrgodycki/aem-eds-kit/issues/20)). Canva/Sketch stay on the local-export path (canvas/image — not scrapeable).
702
804
  - **Migration** - dialogs (Touch UI and Classic UI) map deterministically today; next is HTL → `decorate()` and capturing CSS from the rendered page.
703
- - **Screenshot-to-block** - build a block from a plain image (harder: no structured layout/measurements, so pixel-perfect is tougher).
805
+ - **Image-only designs** - a plain PNG/JPG already works (`from-design ./hero.png`, or a vision model with `--agent ollama --model qwen2.5vl:7b`); next is measuring it (no structured layout in a bitmap, so pixel-perfect is harder than from Figma or a scraped page).
704
806
  - **Tokens & sync** - design variables → CSS custom properties, and incremental re-sync of an existing block (`--update`).
705
807
  - **Headless & CI** - a direct MCP client (no agent needed) for CI/CD, plus `eds lighthouse`, `eds rum` and `eds migrate page`.
706
808