@mailmodo/cli 0.0.49-beta.pr51.79 → 0.0.50-beta.pr52.80

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.
@@ -3,12 +3,30 @@ export default class Deploy extends BaseCommand {
3
3
  static description: string;
4
4
  static examples: string[];
5
5
  static flags: {
6
+ pause: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
+ resume: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
6
8
  json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
9
  yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
10
  };
9
11
  private fetchDomainVerifyForDeploy;
10
12
  run(): Promise<void>;
11
13
  private validateSequence;
14
+ /**
15
+ * Calls `POST /sequences/{id}/status` with `{ status: "paused" }` and prints
16
+ * a confirmation-aware success/no-op message. Skips the prompt entirely when
17
+ * `--yes` is set so the command stays scriptable. `--json` always emits the
18
+ * raw server payload (sequenceId, status, alreadyInStatus).
19
+ */
20
+ private pauseSequence;
21
+ /**
22
+ * Calls `POST /sequences/{id}/status` with `{ status: "active" }`. No prompt
23
+ * — resuming is the safe direction (it does not start sends that weren't
24
+ * already queued). `--json` always emits the raw server payload (sequenceId,
25
+ * status, alreadyInStatus).
26
+ */
27
+ private resumeSequence;
28
+ private updateSequenceStatus;
29
+ private sequenceStatusPath;
12
30
  private buildDeployPayload;
13
31
  private resolveMonthlyCapForDeploy;
14
32
  private mapEmailToPayload;
@@ -1,17 +1,28 @@
1
+ import { Flags } from '@oclif/core';
1
2
  import { confirm, input } from '@inquirer/prompts';
2
3
  import chalk from 'chalk';
3
4
  import { BaseCommand } from '../../lib/base-command.js';
4
5
  import { API_ENDPOINTS, DEFAULT_BRAND_COLOR } from '../../lib/constants.js';
5
- import { ERRORS, INFO, PROMPTS, SEPARATOR } from '../../lib/messages.js';
6
+ import { ERRORS, INFO, pauseAlready, pauseSuccess, PROMPTS, resumeAlready, resumeSuccess, SEPARATOR, } from '../../lib/messages.js';
6
7
  import { loadTemplate, } from '../../lib/yaml-config.js';
7
8
  export default class Deploy extends BaseCommand {
8
- static description = 'Deploy email sequences and verify sending domain';
9
+ static description = 'Deploy, pause, or resume an email sequence';
9
10
  static examples = [
10
11
  '<%= config.bin %> deploy',
11
12
  '<%= config.bin %> deploy --yes',
13
+ '<%= config.bin %> deploy --pause seq_abc123',
14
+ '<%= config.bin %> deploy --resume seq_abc123 --json',
12
15
  ];
13
16
  static flags = {
14
17
  ...BaseCommand.baseFlags,
18
+ pause: Flags.string({
19
+ description: 'Pause a deployed sequence by ID (stops scheduled + triggered sends)',
20
+ exclusive: ['resume'],
21
+ }),
22
+ resume: Flags.string({
23
+ description: 'Resume a paused sequence by ID',
24
+ exclusive: ['pause'],
25
+ }),
15
26
  };
16
27
  fetchDomainVerifyForDeploy(jsonOutput, domain) {
17
28
  return this.withApiSpinner({ json: jsonOutput, text: ' Checking domain verification...' }, () => this.apiClient.get(API_ENDPOINTS.DOMAIN_VERIFY, {
@@ -21,6 +32,15 @@ export default class Deploy extends BaseCommand {
21
32
  async run() {
22
33
  const { flags } = await this.parse(Deploy);
23
34
  await this.ensureAuth();
35
+ const baseFlags = { json: flags.json, yes: flags.yes };
36
+ if (flags.pause) {
37
+ await this.pauseSequence(flags.pause, baseFlags);
38
+ return;
39
+ }
40
+ if (flags.resume) {
41
+ await this.resumeSequence(flags.resume, baseFlags);
42
+ return;
43
+ }
24
44
  const yamlConfig = await this.ensureYaml();
25
45
  const domainReady = await this.ensureDomainReady(yamlConfig, flags);
26
46
  if (!domainReady)
@@ -60,6 +80,60 @@ export default class Deploy extends BaseCommand {
60
80
  }
61
81
  return response.data;
62
82
  }
83
+ /**
84
+ * Calls `POST /sequences/{id}/status` with `{ status: "paused" }` and prints
85
+ * a confirmation-aware success/no-op message. Skips the prompt entirely when
86
+ * `--yes` is set so the command stays scriptable. `--json` always emits the
87
+ * raw server payload (sequenceId, status, alreadyInStatus).
88
+ */
89
+ async pauseSequence(sequenceId, flags) {
90
+ if (!flags.yes) {
91
+ const confirmed = await confirm({
92
+ default: false,
93
+ message: PROMPTS.PAUSE_CONFIRM,
94
+ });
95
+ if (!confirmed) {
96
+ this.log(`\n ${INFO.PAUSE_CANCELLED}\n`);
97
+ return;
98
+ }
99
+ }
100
+ const data = await this.updateSequenceStatus(sequenceId, 'paused', flags, ' Pausing sequence...');
101
+ if (flags.json) {
102
+ this.log(JSON.stringify(data, null, 2));
103
+ return;
104
+ }
105
+ const message = data.alreadyInStatus
106
+ ? pauseAlready(data.sequenceId || sequenceId)
107
+ : pauseSuccess(data.sequenceId || sequenceId);
108
+ this.log(`\n ${message}\n`);
109
+ }
110
+ /**
111
+ * Calls `POST /sequences/{id}/status` with `{ status: "active" }`. No prompt
112
+ * — resuming is the safe direction (it does not start sends that weren't
113
+ * already queued). `--json` always emits the raw server payload (sequenceId,
114
+ * status, alreadyInStatus).
115
+ */
116
+ async resumeSequence(sequenceId, flags) {
117
+ const data = await this.updateSequenceStatus(sequenceId, 'active', flags, ' Resuming sequence...');
118
+ if (flags.json) {
119
+ this.log(JSON.stringify(data, null, 2));
120
+ return;
121
+ }
122
+ const message = data.alreadyInStatus
123
+ ? resumeAlready(data.sequenceId || sequenceId)
124
+ : resumeSuccess(data.sequenceId || sequenceId);
125
+ this.log(`\n ${message}\n`);
126
+ }
127
+ async updateSequenceStatus(sequenceId, status, flags, spinnerText) {
128
+ const response = await this.withApiSpinner({ json: flags.json, text: spinnerText }, () => this.apiClient.post(this.sequenceStatusPath(sequenceId), { status }));
129
+ if (!response.ok) {
130
+ this.handleApiError(response);
131
+ }
132
+ return response.data;
133
+ }
134
+ sequenceStatusPath(sequenceId) {
135
+ return `${API_ENDPOINTS.SEQUENCES}/${encodeURIComponent(sequenceId)}/status`;
136
+ }
63
137
  async buildDeployPayload(yamlConfig) {
64
138
  const [emailsWithHtml, monthlyCap] = await Promise.all([
65
139
  Promise.all(yamlConfig.emails.map(async (email) => {
@@ -0,0 +1,14 @@
1
+ import { BaseCommand } from '../../lib/base-command.js';
2
+ export default class Deployments extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
+ yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
+ };
9
+ run(): Promise<void>;
10
+ private renderTable;
11
+ private statusColor;
12
+ private colWidth;
13
+ private formatDate;
14
+ }
@@ -0,0 +1,76 @@
1
+ import chalk from 'chalk';
2
+ import { BaseCommand } from '../../lib/base-command.js';
3
+ import { API_ENDPOINTS } from '../../lib/constants.js';
4
+ export default class Deployments extends BaseCommand {
5
+ static description = 'List every deployed sequence on this account, with the IDs needed for deploy --pause / --resume';
6
+ static examples = [
7
+ '<%= config.bin %> deployments',
8
+ '<%= config.bin %> deployments --json',
9
+ ];
10
+ static flags = {
11
+ ...BaseCommand.baseFlags,
12
+ };
13
+ async run() {
14
+ const { flags } = await this.parse(Deployments);
15
+ await this.ensureAuth();
16
+ const response = await this.withApiSpinner({ json: flags.json, text: ' Loading deployments...' }, () => this.apiClient.get(API_ENDPOINTS.SEQUENCES));
17
+ if (!response.ok) {
18
+ this.handleApiError(response);
19
+ }
20
+ if (flags.json) {
21
+ this.log(JSON.stringify(response.data, null, 2));
22
+ return;
23
+ }
24
+ this.renderTable(response.data);
25
+ }
26
+ renderTable(data) {
27
+ const sequences = data.sequences ?? [];
28
+ if (sequences.length === 0) {
29
+ this.log(`\n ${chalk.dim('No deployed sequences yet.')}`);
30
+ this.log(` Run ${chalk.cyan('mailmodo deploy')} to deploy one.\n`);
31
+ return;
32
+ }
33
+ const rows = sequences.map((seq) => ({
34
+ emails: String(seq.emailCount ?? 0),
35
+ product: seq.productName ?? '',
36
+ sequenceId: seq.sequenceId ?? '',
37
+ status: seq.status ?? '',
38
+ updated: this.formatDate(seq.updatedAt),
39
+ }));
40
+ const widths = {
41
+ emails: this.colWidth(rows, 'emails', 'Emails'),
42
+ product: this.colWidth(rows, 'product', 'Product'),
43
+ sequenceId: this.colWidth(rows, 'sequenceId', 'Sequence ID'),
44
+ status: this.colWidth(rows, 'status', 'Status'),
45
+ updated: this.colWidth(rows, 'updated', 'Updated'),
46
+ };
47
+ this.log(`\n ${chalk.bold(String(sequences.length))} deployed ${sequences.length === 1 ? 'sequence' : 'sequences'}:\n`);
48
+ this.log(` ${chalk.bold('Product'.padEnd(widths.product))}${chalk.bold('Status'.padEnd(widths.status))}${chalk.bold('Emails'.padEnd(widths.emails))}${chalk.bold('Sequence ID'.padEnd(widths.sequenceId))}${chalk.bold('Updated')}`);
49
+ this.log(` ${'─'.repeat(widths.product + widths.status + widths.emails + widths.sequenceId + widths.updated)}`);
50
+ for (const row of rows) {
51
+ const status = this.statusColor(row.status)(row.status.padEnd(widths.status));
52
+ this.log(` ${row.product.padEnd(widths.product)}${status}${row.emails.padEnd(widths.emails)}${chalk.cyan(row.sequenceId.padEnd(widths.sequenceId))}${chalk.dim(row.updated)}`);
53
+ }
54
+ this.log('');
55
+ this.log(` Pause: ${chalk.cyan('mailmodo deploy --pause <sequence-id>')}`);
56
+ this.log(` Resume: ${chalk.cyan('mailmodo deploy --resume <sequence-id>')}\n`);
57
+ }
58
+ statusColor(status) {
59
+ if (status === 'active')
60
+ return chalk.green;
61
+ if (status === 'paused')
62
+ return chalk.yellow;
63
+ return chalk.white;
64
+ }
65
+ colWidth(rows, key, header) {
66
+ return Math.max(...rows.map((r) => r[key].length), header.length) + 2;
67
+ }
68
+ formatDate(iso) {
69
+ if (!iso)
70
+ return '';
71
+ const parsed = new Date(iso);
72
+ if (Number.isNaN(parsed.getTime()))
73
+ return iso;
74
+ return parsed.toISOString().slice(0, 10);
75
+ }
76
+ }
@@ -9,6 +9,7 @@ export declare const PROMPTS: {
9
9
  readonly DOMAIN: "What domain will you send from?";
10
10
  readonly ENTER_AFTER_RECORDS: "Press Enter once you've added the records, or 'skip'.";
11
11
  readonly FROM_NAME: "Display name (optional, shown as sender name):";
12
+ readonly PAUSE_CONFIRM: "Pause this sequence? All scheduled and triggered sends will stop until you resume.";
12
13
  readonly REPLY_TO: "Reply-to address (optional, press Enter to use sender email):";
13
14
  readonly SENDER_EMAIL: "Sender email address:";
14
15
  };
@@ -37,8 +38,13 @@ export declare const INFO: {
37
38
  Then: ${string}`;
38
39
  readonly DOMAIN_PENDING_VERIFICATION: `Your domain is not verified yet. Please verify it first. Run ${string} to check the status.`;
39
40
  readonly FREE_TIER_CAP_BLOCKED: `Monthly cap is a paid-tier setting and is not available on the free tier. Run ${string} to add a payment method, then set a cap.`;
41
+ readonly PAUSE_CANCELLED: "Pause cancelled. Sequence is still live.";
40
42
  readonly SEQUENCES_NOT_DEPLOYED: `Sequences saved but ${string}.`;
41
43
  };
44
+ export declare function pauseSuccess(sequenceId: string): string;
45
+ export declare function pauseAlready(sequenceId: string): string;
46
+ export declare function resumeSuccess(sequenceId: string): string;
47
+ export declare function resumeAlready(sequenceId: string): string;
42
48
  export declare function yamlParseError(detail: string): string;
43
49
  export declare function recordLabel(index: number): string;
44
50
  /**
@@ -10,6 +10,7 @@ export const PROMPTS = {
10
10
  DOMAIN: 'What domain will you send from?',
11
11
  ENTER_AFTER_RECORDS: "Press Enter once you've added the records, or 'skip'.",
12
12
  FROM_NAME: 'Display name (optional, shown as sender name):',
13
+ PAUSE_CONFIRM: 'Pause this sequence? All scheduled and triggered sends will stop until you resume.',
13
14
  REPLY_TO: 'Reply-to address (optional, press Enter to use sender email):',
14
15
  SENDER_EMAIL: 'Sender email address:',
15
16
  };
@@ -37,8 +38,21 @@ export const INFO = {
37
38
  DOMAIN_NOT_DEPLOYED_HINT: `When ready, run: ${chalk.cyan('mailmodo domain')}\n Then: ${chalk.cyan('mailmodo deploy')}`,
38
39
  DOMAIN_PENDING_VERIFICATION: `Your domain is not verified yet. Please verify it first. Run ${chalk.cyan('mailmodo domain --verify')} to check the status.`,
39
40
  FREE_TIER_CAP_BLOCKED: `Monthly cap is a paid-tier setting and is not available on the free tier. Run ${chalk.cyan("'mailmodo billing --checkout'")} to add a payment method, then set a cap.`,
41
+ PAUSE_CANCELLED: 'Pause cancelled. Sequence is still live.',
40
42
  SEQUENCES_NOT_DEPLOYED: `Sequences saved but ${chalk.yellow('NOT deployed')}.`,
41
43
  };
44
+ export function pauseSuccess(sequenceId) {
45
+ return `Sequence ${chalk.cyan(sequenceId)} paused. Run ${chalk.cyan(`mailmodo deploy --resume ${sequenceId}`)} to resume.`;
46
+ }
47
+ export function pauseAlready(sequenceId) {
48
+ return `Sequence ${chalk.cyan(sequenceId)} is already paused. No change made.`;
49
+ }
50
+ export function resumeSuccess(sequenceId) {
51
+ return `Sequence ${chalk.cyan(sequenceId)} resumed. Scheduled and triggered sends are live again.`;
52
+ }
53
+ export function resumeAlready(sequenceId) {
54
+ return `Sequence ${chalk.cyan(sequenceId)} is already active. No change made.`;
55
+ }
42
56
  export function yamlParseError(detail) {
43
57
  return `mailmodo.yaml has invalid YAML syntax:\n${detail}`;
44
58
  }
@@ -76,14 +76,15 @@
76
76
  "index.js"
77
77
  ]
78
78
  },
79
- "domain": {
79
+ "contacts": {
80
80
  "aliases": [],
81
81
  "args": {},
82
- "description": "Set up and verify your sending domain",
82
+ "description": "Manage contacts search, export, or delete",
83
83
  "examples": [
84
- "<%= config.bin %> domain",
85
- "<%= config.bin %> domain --verify",
86
- "<%= config.bin %> domain --status"
84
+ "<%= config.bin %> contacts",
85
+ "<%= config.bin %> contacts --search sarah@example.com",
86
+ "<%= config.bin %> contacts --export # GDPR CSV → contacts.csv",
87
+ "<%= config.bin %> contacts --delete sarah@example.com"
87
88
  ],
88
89
  "flags": {
89
90
  "json": {
@@ -99,22 +100,30 @@
99
100
  "allowNo": false,
100
101
  "type": "boolean"
101
102
  },
102
- "status": {
103
- "description": "Show domain health status",
104
- "name": "status",
105
- "allowNo": false,
106
- "type": "boolean"
103
+ "delete": {
104
+ "description": "GDPR hard delete a contact by email",
105
+ "name": "delete",
106
+ "hasDynamicHelp": false,
107
+ "multiple": false,
108
+ "type": "option"
107
109
  },
108
- "verify": {
109
- "description": "Verify DNS records",
110
- "name": "verify",
110
+ "export": {
111
+ "description": "Export all contacts as GDPR-compliant CSV (writes contacts.csv in the current directory)",
112
+ "name": "export",
111
113
  "allowNo": false,
112
114
  "type": "boolean"
115
+ },
116
+ "search": {
117
+ "description": "Search for a contact by email",
118
+ "name": "search",
119
+ "hasDynamicHelp": false,
120
+ "multiple": false,
121
+ "type": "option"
113
122
  }
114
123
  },
115
124
  "hasDynamicHelp": false,
116
125
  "hiddenAliases": [],
117
- "id": "domain",
126
+ "id": "contacts",
118
127
  "pluginAlias": "@mailmodo/cli",
119
128
  "pluginName": "@mailmodo/cli",
120
129
  "pluginType": "core",
@@ -124,17 +133,19 @@
124
133
  "relativePath": [
125
134
  "dist",
126
135
  "commands",
127
- "domain",
136
+ "contacts",
128
137
  "index.js"
129
138
  ]
130
139
  },
131
140
  "deploy": {
132
141
  "aliases": [],
133
142
  "args": {},
134
- "description": "Deploy email sequences and verify sending domain",
143
+ "description": "Deploy, pause, or resume an email sequence",
135
144
  "examples": [
136
145
  "<%= config.bin %> deploy",
137
- "<%= config.bin %> deploy --yes"
146
+ "<%= config.bin %> deploy --yes",
147
+ "<%= config.bin %> deploy --pause seq_abc123",
148
+ "<%= config.bin %> deploy --resume seq_abc123 --json"
138
149
  ],
139
150
  "flags": {
140
151
  "json": {
@@ -149,6 +160,26 @@
149
160
  "name": "yes",
150
161
  "allowNo": false,
151
162
  "type": "boolean"
163
+ },
164
+ "pause": {
165
+ "description": "Pause a deployed sequence by ID (stops scheduled + triggered sends)",
166
+ "exclusive": [
167
+ "resume"
168
+ ],
169
+ "name": "pause",
170
+ "hasDynamicHelp": false,
171
+ "multiple": false,
172
+ "type": "option"
173
+ },
174
+ "resume": {
175
+ "description": "Resume a paused sequence by ID",
176
+ "exclusive": [
177
+ "pause"
178
+ ],
179
+ "name": "resume",
180
+ "hasDynamicHelp": false,
181
+ "multiple": false,
182
+ "type": "option"
152
183
  }
153
184
  },
154
185
  "hasDynamicHelp": false,
@@ -167,15 +198,13 @@
167
198
  "index.js"
168
199
  ]
169
200
  },
170
- "contacts": {
201
+ "deployments": {
171
202
  "aliases": [],
172
203
  "args": {},
173
- "description": "Manage contacts search, export, or delete",
204
+ "description": "List every deployed sequence on this account, with the IDs needed for deploy --pause / --resume",
174
205
  "examples": [
175
- "<%= config.bin %> contacts",
176
- "<%= config.bin %> contacts --search sarah@example.com",
177
- "<%= config.bin %> contacts --export # GDPR CSV → contacts.csv",
178
- "<%= config.bin %> contacts --delete sarah@example.com"
206
+ "<%= config.bin %> deployments",
207
+ "<%= config.bin %> deployments --json"
179
208
  ],
180
209
  "flags": {
181
210
  "json": {
@@ -190,31 +219,63 @@
190
219
  "name": "yes",
191
220
  "allowNo": false,
192
221
  "type": "boolean"
222
+ }
223
+ },
224
+ "hasDynamicHelp": false,
225
+ "hiddenAliases": [],
226
+ "id": "deployments",
227
+ "pluginAlias": "@mailmodo/cli",
228
+ "pluginName": "@mailmodo/cli",
229
+ "pluginType": "core",
230
+ "strict": true,
231
+ "enableJsonFlag": false,
232
+ "isESM": true,
233
+ "relativePath": [
234
+ "dist",
235
+ "commands",
236
+ "deployments",
237
+ "index.js"
238
+ ]
239
+ },
240
+ "domain": {
241
+ "aliases": [],
242
+ "args": {},
243
+ "description": "Set up and verify your sending domain",
244
+ "examples": [
245
+ "<%= config.bin %> domain",
246
+ "<%= config.bin %> domain --verify",
247
+ "<%= config.bin %> domain --status"
248
+ ],
249
+ "flags": {
250
+ "json": {
251
+ "description": "Output as JSON",
252
+ "name": "json",
253
+ "allowNo": false,
254
+ "type": "boolean"
193
255
  },
194
- "delete": {
195
- "description": "GDPR hard delete a contact by email",
196
- "name": "delete",
197
- "hasDynamicHelp": false,
198
- "multiple": false,
199
- "type": "option"
256
+ "yes": {
257
+ "char": "y",
258
+ "description": "Skip confirmation prompts",
259
+ "name": "yes",
260
+ "allowNo": false,
261
+ "type": "boolean"
200
262
  },
201
- "export": {
202
- "description": "Export all contacts as GDPR-compliant CSV (writes contacts.csv in the current directory)",
203
- "name": "export",
263
+ "status": {
264
+ "description": "Show domain health status",
265
+ "name": "status",
204
266
  "allowNo": false,
205
267
  "type": "boolean"
206
268
  },
207
- "search": {
208
- "description": "Search for a contact by email",
209
- "name": "search",
210
- "hasDynamicHelp": false,
211
- "multiple": false,
212
- "type": "option"
269
+ "verify": {
270
+ "description": "Verify DNS records",
271
+ "name": "verify",
272
+ "allowNo": false,
273
+ "type": "boolean"
213
274
  }
214
275
  },
215
276
  "hasDynamicHelp": false,
216
277
  "hiddenAliases": [],
217
- "id": "contacts",
278
+ "id": "domain",
218
279
  "pluginAlias": "@mailmodo/cli",
219
280
  "pluginName": "@mailmodo/cli",
220
281
  "pluginType": "core",
@@ -224,7 +285,7 @@
224
285
  "relativePath": [
225
286
  "dist",
226
287
  "commands",
227
- "contacts",
288
+ "domain",
228
289
  "index.js"
229
290
  ]
230
291
  },
@@ -512,14 +573,19 @@
512
573
  "index.js"
513
574
  ]
514
575
  },
515
- "settings": {
576
+ "preview": {
516
577
  "aliases": [],
517
- "args": {},
518
- "description": "View and update project settings",
578
+ "args": {
579
+ "id": {
580
+ "description": "Email template ID to preview",
581
+ "name": "id"
582
+ }
583
+ },
584
+ "description": "Preview an email in browser, as text, or send a test",
519
585
  "examples": [
520
- "<%= config.bin %> settings",
521
- "<%= config.bin %> settings --set brand_color=#0F3460",
522
- "<%= config.bin %> settings --json"
586
+ "<%= config.bin %> preview welcome",
587
+ "<%= config.bin %> preview welcome --text",
588
+ "<%= config.bin %> preview welcome --send me@example.com"
523
589
  ],
524
590
  "flags": {
525
591
  "json": {
@@ -535,17 +601,23 @@
535
601
  "allowNo": false,
536
602
  "type": "boolean"
537
603
  },
538
- "set": {
539
- "description": "Set a setting (format: key=value)",
540
- "name": "set",
604
+ "send": {
605
+ "description": "Send test email to this address",
606
+ "name": "send",
541
607
  "hasDynamicHelp": false,
542
608
  "multiple": false,
543
609
  "type": "option"
610
+ },
611
+ "text": {
612
+ "description": "Output plain text version (for AI agents)",
613
+ "name": "text",
614
+ "allowNo": false,
615
+ "type": "boolean"
544
616
  }
545
617
  },
546
618
  "hasDynamicHelp": false,
547
619
  "hiddenAliases": [],
548
- "id": "settings",
620
+ "id": "preview",
549
621
  "pluginAlias": "@mailmodo/cli",
550
622
  "pluginName": "@mailmodo/cli",
551
623
  "pluginType": "core",
@@ -555,17 +627,18 @@
555
627
  "relativePath": [
556
628
  "dist",
557
629
  "commands",
558
- "settings",
630
+ "preview",
559
631
  "index.js"
560
632
  ]
561
633
  },
562
- "status": {
634
+ "settings": {
563
635
  "aliases": [],
564
636
  "args": {},
565
- "description": "View email performance metrics and quota usage",
637
+ "description": "View and update project settings",
566
638
  "examples": [
567
- "<%= config.bin %> status",
568
- "<%= config.bin %> status --json"
639
+ "<%= config.bin %> settings",
640
+ "<%= config.bin %> settings --set brand_color=#0F3460",
641
+ "<%= config.bin %> settings --json"
569
642
  ],
570
643
  "flags": {
571
644
  "json": {
@@ -580,11 +653,18 @@
580
653
  "name": "yes",
581
654
  "allowNo": false,
582
655
  "type": "boolean"
656
+ },
657
+ "set": {
658
+ "description": "Set a setting (format: key=value)",
659
+ "name": "set",
660
+ "hasDynamicHelp": false,
661
+ "multiple": false,
662
+ "type": "option"
583
663
  }
584
664
  },
585
665
  "hasDynamicHelp": false,
586
666
  "hiddenAliases": [],
587
- "id": "status",
667
+ "id": "settings",
588
668
  "pluginAlias": "@mailmodo/cli",
589
669
  "pluginName": "@mailmodo/cli",
590
670
  "pluginType": "core",
@@ -594,23 +674,17 @@
594
674
  "relativePath": [
595
675
  "dist",
596
676
  "commands",
597
- "status",
677
+ "settings",
598
678
  "index.js"
599
679
  ]
600
680
  },
601
- "preview": {
681
+ "status": {
602
682
  "aliases": [],
603
- "args": {
604
- "id": {
605
- "description": "Email template ID to preview",
606
- "name": "id"
607
- }
608
- },
609
- "description": "Preview an email in browser, as text, or send a test",
683
+ "args": {},
684
+ "description": "View email performance metrics and quota usage",
610
685
  "examples": [
611
- "<%= config.bin %> preview welcome",
612
- "<%= config.bin %> preview welcome --text",
613
- "<%= config.bin %> preview welcome --send me@example.com"
686
+ "<%= config.bin %> status",
687
+ "<%= config.bin %> status --json"
614
688
  ],
615
689
  "flags": {
616
690
  "json": {
@@ -625,24 +699,11 @@
625
699
  "name": "yes",
626
700
  "allowNo": false,
627
701
  "type": "boolean"
628
- },
629
- "send": {
630
- "description": "Send test email to this address",
631
- "name": "send",
632
- "hasDynamicHelp": false,
633
- "multiple": false,
634
- "type": "option"
635
- },
636
- "text": {
637
- "description": "Output plain text version (for AI agents)",
638
- "name": "text",
639
- "allowNo": false,
640
- "type": "boolean"
641
702
  }
642
703
  },
643
704
  "hasDynamicHelp": false,
644
705
  "hiddenAliases": [],
645
- "id": "preview",
706
+ "id": "status",
646
707
  "pluginAlias": "@mailmodo/cli",
647
708
  "pluginName": "@mailmodo/cli",
648
709
  "pluginType": "core",
@@ -652,10 +713,10 @@
652
713
  "relativePath": [
653
714
  "dist",
654
715
  "commands",
655
- "preview",
716
+ "status",
656
717
  "index.js"
657
718
  ]
658
719
  }
659
720
  },
660
- "version": "0.0.49-beta.pr51.79"
721
+ "version": "0.0.50-beta.pr52.80"
661
722
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mailmodo/cli",
3
3
  "description": "Email lifecycle automation for the AI-native builder generation.",
4
- "version": "0.0.49-beta.pr51.79",
4
+ "version": "0.0.50-beta.pr52.80",
5
5
  "author": "provishalk",
6
6
  "bin": {
7
7
  "mailmodo": "bin/run.js"