@emailens/cli 0.6.0 → 0.7.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 +113 -188
- package/dist/index.js +142 -81
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<img src="./docs/wordmark-light.svg" alt="emailens / cli" width="444">
|
|
6
6
|
</picture>
|
|
7
7
|
|
|
8
|
-
**The rendering linter for
|
|
8
|
+
**The email rendering linter for terminal and CI**
|
|
9
9
|
|
|
10
10
|
[](https://github.com/emailens/cli/actions/workflows/ci.yml)
|
|
11
11
|
[](https://www.npmjs.com/package/@emailens/cli)
|
|
@@ -14,15 +14,40 @@
|
|
|
14
14
|
|
|
15
15
|
</div>
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
Your email looks perfect in Apple Mail. Gmail strips half the CSS. Outlook renders it in Word.
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
`@emailens/cli` checks HTML, React Email, MJML, and Maizzle against real client behavior across 21 email clients. It flags compatibility issues before they ship, in your terminal, in CI, or in your AI workflow.
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
The quickest way to try it:
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
```bash
|
|
24
|
+
npx @emailens/cli lint email.html
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
If you want a hosted preview, screenshots, and team workflows, see [emailens.dev](https://emailens.dev).
|
|
28
|
+
|
|
29
|
+
## Why Emailens
|
|
30
|
+
|
|
31
|
+
Email clients are the hardest frontend target in existence. Every client has different CSS support, different rendering engines, and different failure modes.
|
|
32
|
+
|
|
33
|
+
Emailens gives you:
|
|
34
|
+
|
|
35
|
+
- per-client compatibility scoring across 21 clients
|
|
36
|
+
- file:line reporting for HTML inputs
|
|
37
|
+
- CI-safe exit codes for build pipelines
|
|
38
|
+
- support for React Email, MJML, Maizzle, and raw HTML
|
|
39
|
+
- local/offline usage with no account required
|
|
40
|
+
|
|
41
|
+
## The ecosystem
|
|
24
42
|
|
|
25
|
-
|
|
43
|
+
| Project | Purpose | Start here |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| [@emailens/engine](https://github.com/emailens/engine) | Core analysis engine and library API | If you want to build on top of it |
|
|
46
|
+
| [@emailens/cli](https://github.com/emailens/cli) | Terminal linting and CI checks | Best first stop |
|
|
47
|
+
| [@emailens/mcp](https://github.com/emailens/mcp) | Claude/Cursor/AI agent integration | If you want AI-assisted email QA |
|
|
48
|
+
| [emailens/action](https://github.com/emailens/action) | GitHub Action quality gate | If you want PR blocking |
|
|
49
|
+
| [emailens/vscode](https://github.com/emailens/vscode) | VS Code linting and preview | If you want editor feedback |
|
|
50
|
+
| [emailens.dev](https://emailens.dev) | Hosted previews, screenshots, team workflows | If you want team-grade QA and shareable reports |
|
|
26
51
|
|
|
27
52
|
## Install
|
|
28
53
|
|
|
@@ -30,35 +55,80 @@ Across the 255 CSS and HTML features we track, only 6 are fully supported in eve
|
|
|
30
55
|
npm install -g @emailens/cli
|
|
31
56
|
```
|
|
32
57
|
|
|
33
|
-
Or use
|
|
58
|
+
Or use it without installing:
|
|
34
59
|
|
|
35
60
|
```bash
|
|
36
|
-
npx @emailens/cli
|
|
61
|
+
npx @emailens/cli lint email.html
|
|
37
62
|
```
|
|
38
63
|
|
|
39
|
-
|
|
64
|
+
Maizzle HTML needs `@maizzle/framework@5` installed beside the CLI. A `.vue` file needs `@maizzle/framework@6`. One install is one major.
|
|
40
65
|
|
|
41
|
-
|
|
66
|
+
## Quick start
|
|
42
67
|
|
|
43
|
-
|
|
68
|
+
### Check a single file
|
|
44
69
|
|
|
45
70
|
```bash
|
|
46
71
|
emailens analyze email.html
|
|
47
72
|
emailens analyze email.html --clients gmail-web,outlook-windows
|
|
48
73
|
emailens analyze email.html --json
|
|
49
|
-
cat email.html | emailens analyze -
|
|
50
74
|
```
|
|
51
75
|
|
|
52
|
-
|
|
53
|
-
problem:
|
|
76
|
+
### Lint in CI
|
|
54
77
|
|
|
78
|
+
```bash
|
|
79
|
+
npx @emailens/cli lint 'emails/**/*.{html,tsx,mjml}' --fail-on-warning
|
|
55
80
|
```
|
|
56
|
-
|
|
57
|
-
|
|
81
|
+
|
|
82
|
+
### Preview a render
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
emailens preview email.html
|
|
86
|
+
emailens preview email.html --dark-mode
|
|
87
|
+
emailens preview email.html --screenshots --out ./screenshots
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Fix common issues
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
emailens fix email.html
|
|
94
|
+
emailens fix email.html -o fixed.html
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## What the output looks like
|
|
98
|
+
|
|
99
|
+
```text
|
|
100
|
+
src/emails/welcome.html
|
|
101
|
+
error 12:8 outlook-windows border-radius Not supported in Outlook Windows
|
|
102
|
+
warn spam caps-ratio 20%+ of words are ALL CAPS
|
|
103
|
+
|
|
104
|
+
2 files | 1 error | 1 warning
|
|
58
105
|
```
|
|
59
106
|
|
|
60
|
-
|
|
61
|
-
|
|
107
|
+
This is intentionally readable in a terminal and structured enough for CI, editors, and agents.
|
|
108
|
+
|
|
109
|
+
## Supported formats
|
|
110
|
+
|
|
111
|
+
Point it at:
|
|
112
|
+
|
|
113
|
+
- HTML
|
|
114
|
+
- JSX / React Email
|
|
115
|
+
- MJML
|
|
116
|
+
- Maizzle
|
|
117
|
+
|
|
118
|
+
Format is detected from the file extension, and the CLI compiles your template before it analyzes the actual HTML that would be sent.
|
|
119
|
+
|
|
120
|
+
## Commands
|
|
121
|
+
|
|
122
|
+
### `emailens analyze <file>`
|
|
123
|
+
|
|
124
|
+
Analyze CSS compatibility and get per-client scores.
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
emailens analyze email.html
|
|
128
|
+
emailens analyze email.html --clients gmail-web,outlook-windows
|
|
129
|
+
emailens analyze email.html --json
|
|
130
|
+
cat email.html | emailens analyze -
|
|
131
|
+
```
|
|
62
132
|
|
|
63
133
|
### `emailens preview <file>`
|
|
64
134
|
|
|
@@ -78,93 +148,47 @@ Export a self-contained HTML or JSON report.
|
|
|
78
148
|
```bash
|
|
79
149
|
emailens export email.html -o ./report
|
|
80
150
|
emailens export email.html --json -o ./report
|
|
81
|
-
emailens export email.html --dark-mode --screenshots -o ./report
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
### `emailens fix <file>`
|
|
85
|
-
|
|
86
|
-
Generate AI-powered fixes for email compatibility issues. Uses `@emailens/engine` analysis to build a structured prompt, then calls Claude to fix structural issues (table layouts, VML, MSO conditionals) that static snippets can't handle.
|
|
87
|
-
|
|
88
|
-
Requires `ANTHROPIC_API_KEY` environment variable and the optional `@anthropic-ai/sdk` dependency.
|
|
89
|
-
|
|
90
|
-
```bash
|
|
91
|
-
emailens fix email.html # Fix and print to stdout
|
|
92
|
-
emailens fix email.html -o fixed.html # Write to file
|
|
93
|
-
emailens fix email.html --estimate # Show token estimate only (no AI call)
|
|
94
|
-
emailens fix email.html --clients outlook-windows # Scope to one client
|
|
95
|
-
emailens fix email.html --json # Full JSON output with metadata
|
|
96
|
-
emailens fix email.html --max-tokens 8000 # Limit prompt size
|
|
97
|
-
cat email.html | emailens fix - --format jsx # Pipe from stdin
|
|
98
151
|
```
|
|
99
152
|
|
|
100
|
-
| Flag | Alias | Description |
|
|
101
|
-
|------|-------|-------------|
|
|
102
|
-
| `--format` | `-f` | Input format: `html`, `jsx`, `mjml`, `maizzle` |
|
|
103
|
-
| `--clients` | `-c` | Comma-separated client IDs to scope the fix |
|
|
104
|
-
| `--output` | `-o` | Write fixed code to file instead of stdout |
|
|
105
|
-
| `--json` | | Output as JSON (includes token estimates and metadata) |
|
|
106
|
-
| `--quiet` | `-q` | Suppress spinners and decorations |
|
|
107
|
-
| `--estimate` | | Only show token estimate without calling the AI |
|
|
108
|
-
| `--max-tokens` | | Maximum input tokens for the prompt (default: 16000) |
|
|
109
|
-
|
|
110
153
|
### `emailens lint <file|glob>`
|
|
111
154
|
|
|
112
|
-
CI
|
|
155
|
+
CI-friendly linting with structured exit codes.
|
|
113
156
|
|
|
114
157
|
```bash
|
|
115
158
|
emailens lint email.html
|
|
116
159
|
emailens lint src/*.html
|
|
117
160
|
emailens lint email.html --json
|
|
118
161
|
emailens lint email.html --fail-on-warning
|
|
119
|
-
emailens lint email.html --skip spam,links
|
|
120
162
|
emailens lint email.html --max-warnings 5
|
|
121
163
|
```
|
|
122
164
|
|
|
123
165
|
| Flag | Alias | Description |
|
|
124
166
|
|------|-------|-------------|
|
|
125
|
-
| `--format` | `-f` | Input format: `html`, `jsx`, `mjml`, `maizzle` |
|
|
167
|
+
| `--format` | `-f` | Input format: `html`, `jsx`, `mjml`, `maizzle`. `.vue` is `maizzle`. A pasted Vue file with no flag is detected. |
|
|
126
168
|
| `--json` | | Output as JSON |
|
|
127
169
|
| `--fail-on-warning` | | Exit 2 if warnings found |
|
|
128
|
-
| `--skip` | | Comma-separated checks to skip: `spam,links,accessibility,images,compatibility,inboxPreview,size,templateVariables,overflow,visual,darkContrast,mobileContrast,design` |
|
|
170
|
+
| `--skip` | | Comma-separated checks to skip: `spam,links,accessibility,images,compatibility,inboxPreview,size,templateVariables,overflow,visual,darkContrast,mobileContrast,design,vml,styleSurvival,targeting` |
|
|
171
|
+
| `--targeting-policy` | | `progressive` (default), `strict`, or `lenient` |
|
|
129
172
|
| `--max-warnings` | | Fail if more than n warnings |
|
|
130
173
|
|
|
131
|
-
|
|
174
|
+
Exit codes:
|
|
175
|
+
|
|
132
176
|
- `0`: clean
|
|
133
177
|
- `1`: errors found
|
|
134
178
|
- `2`: warnings only (with `--fail-on-warning` or `--max-warnings` exceeded)
|
|
135
179
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
```
|
|
139
|
-
src/emails/welcome.html
|
|
140
|
-
error 12:8 outlook-windows border-radius Not supported in Outlook Windows
|
|
141
|
-
warn spam caps-ratio 20%+ of words are ALL CAPS
|
|
180
|
+
### `emailens clients`
|
|
142
181
|
|
|
143
|
-
|
|
144
|
-
pass No issues found
|
|
182
|
+
List all 21 supported clients.
|
|
145
183
|
|
|
146
|
-
|
|
184
|
+
```bash
|
|
185
|
+
emailens clients
|
|
186
|
+
emailens clients --json
|
|
147
187
|
```
|
|
148
188
|
|
|
149
|
-
|
|
150
|
-
about the document as a whole (spam signals, Gmail clipping, inbox preview) have
|
|
151
|
-
no position and leave the column blank. With `--json`, each issue carries a
|
|
152
|
-
`loc` object instead (`line`, `column`, `endLine`, `endColumn`, `offset`,
|
|
153
|
-
`length`) for editors, annotations, and agents that need to point at or edit
|
|
154
|
-
the exact source.
|
|
155
|
-
|
|
156
|
-
One property can break in many places, so CSS issues also carry `locs`: every
|
|
157
|
-
occurrence in document order, with `loc` as the first, and `locsTruncated: true`
|
|
158
|
-
when there were more than 100.
|
|
159
|
-
|
|
160
|
-
Positions are reported for **HTML sources only**. JSX, MJML and Maizzle are
|
|
161
|
-
compiled before analysis, so a line number would refer to generated output
|
|
162
|
-
rather than the file you wrote; the CLI omits it rather than print one that
|
|
163
|
-
looks authoritative and isn't.
|
|
189
|
+
## GitHub Actions
|
|
164
190
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
Drop this into `.github/workflows/email-lint.yml` to fail PRs that introduce broken email CSS, spam triggers, or accessibility regressions:
|
|
191
|
+
Add a PR gate to fail builds when email regressions appear:
|
|
168
192
|
|
|
169
193
|
```yaml
|
|
170
194
|
name: Email lint
|
|
@@ -187,125 +211,25 @@ jobs:
|
|
|
187
211
|
run: npx -y @emailens/cli lint 'emails/**/*.{html,tsx,mjml}' --fail-on-warning
|
|
188
212
|
```
|
|
189
213
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
### `.emailensrc`
|
|
193
|
-
|
|
194
|
-
The project file the [VS Code extension](https://github.com/emailens/vscode)
|
|
195
|
-
already reads, so the editor and CI agree about what matters. Put it at the
|
|
196
|
-
repo root, or use an `emailens` key in `package.json`:
|
|
197
|
-
|
|
198
|
-
```json
|
|
199
|
-
{
|
|
200
|
-
"skip": ["spam"],
|
|
201
|
-
"rules": {
|
|
202
|
-
"border-radius": "error",
|
|
203
|
-
"font-size": "off"
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
**`rules`** sets the severity of one rule, keyed by the code `lint` prints: a
|
|
209
|
-
CSS property (`border-radius`) or a rule id (`insecure-link`). `off` drops it
|
|
210
|
-
entirely. Promoting a rule to `error` makes it exit 1, which is the point:
|
|
211
|
-
without this the only control is `--skip`, and a team that cares about one
|
|
212
|
-
Outlook property has to keep the whole compatibility check at warning level.
|
|
213
|
-
|
|
214
|
-
A rule demoted in the editor that still fails the build is the worst of both
|
|
215
|
-
worlds, and this is the file that stops that happening.
|
|
214
|
+
## AI and MCP
|
|
216
215
|
|
|
217
|
-
|
|
218
|
-
choice for one invocation. In the editor it is the other way round: the repo's
|
|
219
|
-
file wins over personal settings, because those are ambient and the file is
|
|
220
|
-
the team's.
|
|
221
|
-
|
|
222
|
-
A malformed file is linted without rather than fatal. A severity that is not
|
|
223
|
-
one of `error`, `warning`, `info`, `off` is named on stderr and ignored, so a
|
|
224
|
-
typo cannot quietly leave a rule on that you believe is off. Warnings go to
|
|
225
|
-
stderr, so `lint --json | jq` stays parseable.
|
|
226
|
-
|
|
227
|
-
### `emailens clients`
|
|
228
|
-
|
|
229
|
-
List all 21 supported email clients.
|
|
216
|
+
Prefer AI? Use the [MCP server](https://github.com/emailens/mcp). It gives your coding agent access to the same analysis engine and lets it preview, audit, fix, and diff email templates.
|
|
230
217
|
|
|
231
218
|
```bash
|
|
232
|
-
emailens
|
|
233
|
-
emailens clients --json
|
|
219
|
+
claude mcp add emailens -- npx -y @emailens/mcp
|
|
234
220
|
```
|
|
235
221
|
|
|
236
|
-
##
|
|
237
|
-
|
|
238
|
-
All file-processing commands share:
|
|
222
|
+
## Why not just use the hosted app?
|
|
239
223
|
|
|
240
|
-
|
|
241
|
-
|------|-------|-------------|
|
|
242
|
-
| `--format` | `-f` | Input format: `html`, `jsx`, `mjml`, `maizzle` |
|
|
243
|
-
| `--clients` | `-c` | Comma-separated client IDs to filter |
|
|
244
|
-
| `--json` | | Output JSON instead of terminal table |
|
|
245
|
-
| `--quiet` | `-q` | Suppress spinners and decorations |
|
|
224
|
+
You can. But the open-source tools are what let developers:
|
|
246
225
|
|
|
247
|
-
|
|
226
|
+
- validate before a push
|
|
227
|
+
- fail CI before a broken email ships
|
|
228
|
+
- run audits offline
|
|
229
|
+
- keep email QA in their editor and terminal
|
|
230
|
+
- build local automation without signing up for a platform
|
|
248
231
|
|
|
249
|
-
|
|
250
|
-
|------|-------|-------------|
|
|
251
|
-
| `--dark-mode` | `-d` | Include dark mode simulation |
|
|
252
|
-
| `--screenshots` | | Capture screenshots (requires `BROWSERLESS_URL`) |
|
|
253
|
-
| `--out` | `-o` | Output directory |
|
|
254
|
-
|
|
255
|
-
## AI Fixes
|
|
256
|
-
|
|
257
|
-
The `fix` command requires an `ANTHROPIC_API_KEY` environment variable and the `@anthropic-ai/sdk` package:
|
|
258
|
-
|
|
259
|
-
```bash
|
|
260
|
-
npm install @anthropic-ai/sdk
|
|
261
|
-
export ANTHROPIC_API_KEY=sk-ant-...
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
Use `--estimate` to check token usage before making an API call:
|
|
265
|
-
|
|
266
|
-
```bash
|
|
267
|
-
emailens fix email.html --estimate
|
|
268
|
-
# Input tokens: ~4,200
|
|
269
|
-
# Output tokens: ~5,400
|
|
270
|
-
# Warnings: 23 (5 structural)
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
## Framework Support
|
|
274
|
-
|
|
275
|
-
The CLI can compile React Email (JSX/TSX), MJML, and Maizzle templates to HTML before analysis. Format is auto-detected from file extension, or specify with `--format`.
|
|
276
|
-
|
|
277
|
-
```bash
|
|
278
|
-
emailens analyze newsletter.tsx # Auto-detected as JSX
|
|
279
|
-
emailens analyze template.mjml # Auto-detected as MJML
|
|
280
|
-
emailens preview email.html --format maizzle # Explicit format
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
Framework compilers are optional peer dependencies; install only what you need:
|
|
284
|
-
|
|
285
|
-
```bash
|
|
286
|
-
npm install sucrase react @react-email/components @react-email/render # For JSX
|
|
287
|
-
npm install mjml # For MJML
|
|
288
|
-
npm install @maizzle/framework # For Maizzle
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
## Screenshots
|
|
292
|
-
|
|
293
|
-
Screenshots require a [Browserless](https://www.browserless.io/) instance and `playwright-core`:
|
|
294
|
-
|
|
295
|
-
```bash
|
|
296
|
-
npm install playwright-core
|
|
297
|
-
export BROWSERLESS_URL=ws://localhost:3000
|
|
298
|
-
emailens preview email.html --screenshots --out ./screenshots
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
## Piping
|
|
302
|
-
|
|
303
|
-
Read from stdin with `-`:
|
|
304
|
-
|
|
305
|
-
```bash
|
|
306
|
-
cat email.html | emailens analyze -
|
|
307
|
-
echo '<html><body>Hello</body></html>' | emailens preview - --json
|
|
308
|
-
```
|
|
232
|
+
The hosted SaaS adds screenshot previews, shared reports, and team workflows. The OSS tools give you the developer-first layer.
|
|
309
233
|
|
|
310
234
|
## License
|
|
311
235
|
|
|
@@ -314,3 +238,4 @@ MIT
|
|
|
314
238
|
---
|
|
315
239
|
|
|
316
240
|
If this saved you from an Outlook surprise, [a star](https://github.com/emailens/cli) helps other email developers find it.
|
|
241
|
+
|