groundmail-cli 0.18.1 → 0.20.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.
Files changed (2) hide show
  1. package/dist/cli.js +182 -113
  2. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -69,6 +69,9 @@ async function runSendCommand(args, deps) {
69
69
  unsubscribe: options.unsubscribe
70
70
  });
71
71
  stdout(JSON.stringify(result));
72
+ if (result.test) {
73
+ stderr("Test send: simulated, nothing was delivered. Its status and webhooks are marked test.");
74
+ }
72
75
  return 0;
73
76
  } catch (error) {
74
77
  stderr(error instanceof Error ? error.message : String(error));
@@ -109,8 +112,8 @@ function createDefaultSendDeps(apiKey, baseUrl) {
109
112
  return {
110
113
  sendEmail: async (params) => {
111
114
  const { Groundmail } = await import("groundmail");
112
- const client = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
113
- return client.emails.send(params);
115
+ const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
116
+ return client2.emails.send(params);
114
117
  }
115
118
  };
116
119
  }
@@ -179,10 +182,10 @@ async function runBatchCommandWithClient(args, env = process.env) {
179
182
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
180
183
  }
181
184
  const { Groundmail } = await import("groundmail");
182
- const client = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
185
+ const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
183
186
  return runBatchCommand(args, {
184
187
  env,
185
- sendBatch: (emails) => client.emails.batch(emails)
188
+ sendBatch: (emails) => client2.emails.batch(emails)
186
189
  });
187
190
  }
188
191
  function parseBatchPayload(source) {
@@ -235,10 +238,10 @@ async function runCancelCommandWithClient(args, env = process.env) {
235
238
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
236
239
  }
237
240
  const { Groundmail } = await import("groundmail");
238
- const client = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
241
+ const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
239
242
  return runCancelCommand(args, {
240
243
  env,
241
- cancelEmail: (id) => client.emails.cancel(id)
244
+ cancelEmail: (id) => client2.emails.cancel(id)
242
245
  });
243
246
  }
244
247
 
@@ -278,10 +281,10 @@ async function runResendCommandWithClient(args, env = process.env) {
278
281
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
279
282
  }
280
283
  const { Groundmail } = await import("groundmail");
281
- const client = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
284
+ const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
282
285
  return runResendCommand(args, {
283
286
  env,
284
- resendEmail: (id) => client.emails.resend(id)
287
+ resendEmail: (id) => client2.emails.resend(id)
285
288
  });
286
289
  }
287
290
 
@@ -321,10 +324,10 @@ async function runGetCommandWithClient(args, env = process.env) {
321
324
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
322
325
  }
323
326
  const { Groundmail } = await import("groundmail");
324
- const client = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
327
+ const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
325
328
  return runGetCommand(args, {
326
329
  env,
327
- getEmail: (id) => client.emails.get(id)
330
+ getEmail: (id) => client2.emails.get(id)
328
331
  });
329
332
  }
330
333
 
@@ -364,10 +367,10 @@ async function runInsightsCommandWithClient(args, env = process.env) {
364
367
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
365
368
  }
366
369
  const { Groundmail } = await import("groundmail");
367
- const client = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
370
+ const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
368
371
  return runInsightsCommand(args, {
369
372
  env,
370
- getInsights: (window) => client.emails.insights(window)
373
+ getInsights: (window) => client2.emails.insights(window)
371
374
  });
372
375
  }
373
376
 
@@ -389,10 +392,16 @@ async function runListCommand(args, deps) {
389
392
  const limitRaw = readFlag7(args, "--limit");
390
393
  const cursor = readFlag7(args, "--cursor");
391
394
  const limit = limitRaw ? Number(limitRaw) : void 0;
395
+ if (args.includes("--test") && args.includes("--live")) {
396
+ stderr("Pass --test or --live, not both.");
397
+ return { exitCode: 1, error: "conflicting flags" };
398
+ }
399
+ const test = args.includes("--test") ? true : args.includes("--live") ? false : void 0;
392
400
  try {
393
401
  const result = await deps.listEmails({
394
402
  ...limit != null && Number.isFinite(limit) ? { limit } : {},
395
- ...cursor ? { cursor } : {}
403
+ ...cursor ? { cursor } : {},
404
+ ...test !== void 0 ? { test } : {}
396
405
  });
397
406
  stdout(JSON.stringify(result));
398
407
  return { exitCode: 0 };
@@ -408,10 +417,10 @@ async function runListCommandWithClient(args, env = process.env) {
408
417
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
409
418
  }
410
419
  const { Groundmail } = await import("groundmail");
411
- const client = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
420
+ const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
412
421
  return runListCommand(args, {
413
422
  env,
414
- listEmails: (params) => client.emails.list(params)
423
+ listEmails: (params) => client2.emails.list(params)
415
424
  });
416
425
  }
417
426
 
@@ -458,8 +467,8 @@ async function runSendEventCommand(args, env = process.env) {
458
467
  }
459
468
  }
460
469
  try {
461
- const client = await createClient(apiKey, baseUrl);
462
- const result = await client.events.trigger({
470
+ const client2 = await createClient(apiKey, baseUrl);
471
+ const result = await client2.events.trigger({
463
472
  name,
464
473
  email,
465
474
  user_id: userId,
@@ -542,8 +551,8 @@ async function runListCommand2(args, env = process.env) {
542
551
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
543
552
  }
544
553
  try {
545
- const client = await createAutomationsClient(apiKey, options.baseUrl);
546
- const result = await client.automations.list();
554
+ const client2 = await createAutomationsClient(apiKey, options.baseUrl);
555
+ const result = await client2.automations.list();
547
556
  console.log(JSON.stringify(result));
548
557
  return { exitCode: 0 };
549
558
  } catch (error) {
@@ -561,8 +570,8 @@ async function runGetCommand2(args, env = process.env) {
561
570
  const id = readFlag9(args, "--id");
562
571
  if (!id) return { exitCode: 1, error: "Required flag: --id" };
563
572
  try {
564
- const client = await createAutomationsClient(apiKey, options.baseUrl);
565
- const result = await client.automations.get(id);
573
+ const client2 = await createAutomationsClient(apiKey, options.baseUrl);
574
+ const result = await client2.automations.get(id);
566
575
  console.log(JSON.stringify(result));
567
576
  return { exitCode: 0 };
568
577
  } catch (error) {
@@ -590,8 +599,8 @@ async function runCreateCommand(args, env = process.env) {
590
599
  return { exitCode: 1, error: "Required: --steps or steps in --file" };
591
600
  }
592
601
  try {
593
- const client = await createAutomationsClient(apiKey, options.baseUrl);
594
- const result = await client.automations.create({
602
+ const client2 = await createAutomationsClient(apiKey, options.baseUrl);
603
+ const result = await client2.automations.create({
595
604
  name,
596
605
  trigger,
597
606
  steps
@@ -622,8 +631,8 @@ async function runUpdateCommand(args, env = process.env) {
622
631
  };
623
632
  }
624
633
  try {
625
- const client = await createAutomationsClient(apiKey, options.baseUrl);
626
- const result = await client.automations.update(id, {
634
+ const client2 = await createAutomationsClient(apiKey, options.baseUrl);
635
+ const result = await client2.automations.update(id, {
627
636
  ...name ? { name } : {},
628
637
  ...trigger ? { trigger } : {},
629
638
  ...steps ? { steps } : {}
@@ -645,8 +654,8 @@ async function runActivateCommand(args, env = process.env) {
645
654
  const id = readFlag9(args, "--id");
646
655
  if (!id) return { exitCode: 1, error: "Required flag: --id" };
647
656
  try {
648
- const client = await createAutomationsClient(apiKey, options.baseUrl);
649
- const result = await client.automations.activate(id);
657
+ const client2 = await createAutomationsClient(apiKey, options.baseUrl);
658
+ const result = await client2.automations.activate(id);
650
659
  console.log(JSON.stringify(result));
651
660
  return { exitCode: 0 };
652
661
  } catch (error) {
@@ -662,8 +671,8 @@ async function runPauseCommand(args, env = process.env) {
662
671
  const id = readFlag9(args, "--id");
663
672
  if (!id) return { exitCode: 1, error: "Required flag: --id" };
664
673
  try {
665
- const client = await createAutomationsClient(apiKey, options.baseUrl);
666
- const result = await client.automations.pause(id);
674
+ const client2 = await createAutomationsClient(apiKey, options.baseUrl);
675
+ const result = await client2.automations.pause(id);
667
676
  console.log(JSON.stringify(result));
668
677
  return { exitCode: 0 };
669
678
  } catch (error) {
@@ -679,8 +688,8 @@ async function runDeleteCommand(args, env = process.env) {
679
688
  const id = readFlag9(args, "--id");
680
689
  if (!id) return { exitCode: 1, error: "Required flag: --id" };
681
690
  try {
682
- const client = await createAutomationsClient(apiKey, options.baseUrl);
683
- const result = await client.automations.remove(id);
691
+ const client2 = await createAutomationsClient(apiKey, options.baseUrl);
692
+ const result = await client2.automations.remove(id);
684
693
  console.log(JSON.stringify(result));
685
694
  return { exitCode: 0 };
686
695
  } catch (error) {
@@ -740,9 +749,9 @@ async function runAddCommand(args, env = process.env) {
740
749
  };
741
750
  }
742
751
  try {
743
- const client = await createDomainsClient(apiKey, options.baseUrl);
752
+ const client2 = await createDomainsClient(apiKey, options.baseUrl);
744
753
  const inbound = readFlag10(args, "--inbound");
745
- const result = await client.domains.create({
754
+ const result = await client2.domains.create({
746
755
  name,
747
756
  ...inbound === "true" || inbound === "1" ? { inbound_enabled: true } : {}
748
757
  });
@@ -788,12 +797,12 @@ async function runApplyCommand(args, env = process.env) {
788
797
  };
789
798
  }
790
799
  try {
791
- const client = await createDomainsClient(apiKey, options.baseUrl);
800
+ const client2 = await createDomainsClient(apiKey, options.baseUrl);
792
801
  const localCloudflare = env.CLOUDFLARE_API_TOKEN || env.CLOUDFLARE_API_KEY;
793
802
  const localVercel = env.VERCEL_API_TOKEN;
794
803
  const useStoredCloudflare = provider === "cloudflare" && !localCloudflare;
795
804
  const useStoredVercel = provider === "vercel" && !localVercel;
796
- const result = useStoredCloudflare || useStoredVercel ? await client.domains.apply(idOrName, { provider }) : await client.domains.applyDns({
805
+ const result = useStoredCloudflare || useStoredVercel ? await client2.domains.apply(idOrName, { provider }) : await client2.domains.applyDns({
797
806
  idOrName,
798
807
  provider,
799
808
  cloudflareApiToken: localCloudflare,
@@ -827,8 +836,8 @@ async function runDeleteCommand2(args, env = process.env) {
827
836
  const idOrName = options.id || options.name || readFirstPositional2(args);
828
837
  if (!idOrName) return { exitCode: 1, error: "Missing domain. Usage: groundmail domains delete example.com" };
829
838
  try {
830
- const client = await createDomainsClient(apiKey, options.baseUrl);
831
- console.log(JSON.stringify(await client.domains.delete(idOrName)));
839
+ const client2 = await createDomainsClient(apiKey, options.baseUrl);
840
+ console.log(JSON.stringify(await client2.domains.delete(idOrName)));
832
841
  return { exitCode: 0 };
833
842
  } catch (error) {
834
843
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -855,8 +864,8 @@ async function runGetCommand3(args, env = process.env) {
855
864
  const idOrName = options.id || options.name || readFirstPositional3(args);
856
865
  if (!idOrName) return { exitCode: 1, error: "Missing domain. Usage: groundmail domains get example.com" };
857
866
  try {
858
- const client = await createDomainsClient(apiKey, options.baseUrl);
859
- console.log(JSON.stringify(await client.domains.get(idOrName)));
867
+ const client2 = await createDomainsClient(apiKey, options.baseUrl);
868
+ console.log(JSON.stringify(await client2.domains.get(idOrName)));
860
869
  return { exitCode: 0 };
861
870
  } catch (error) {
862
871
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -882,8 +891,8 @@ async function runListCommand3(args, env = process.env) {
882
891
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
883
892
  }
884
893
  try {
885
- const client = await createDomainsClient(apiKey, options.baseUrl);
886
- const result = await client.domains.list();
894
+ const client2 = await createDomainsClient(apiKey, options.baseUrl);
895
+ const result = await client2.domains.list();
887
896
  console.log(JSON.stringify(result));
888
897
  return { exitCode: 0 };
889
898
  } catch (error) {
@@ -954,8 +963,8 @@ async function runUpdateCommand2(args, env = process.env) {
954
963
  error: "No updates provided. Pass --inbound true|false, --tls-mode opportunistic|enforced, --open-tracking true|false, or --click-tracking true|false."
955
964
  };
956
965
  }
957
- const client = await createDomainsClient(apiKey, options.baseUrl);
958
- console.log(JSON.stringify(await client.domains.update(idOrName, payload)));
966
+ const client2 = await createDomainsClient(apiKey, options.baseUrl);
967
+ console.log(JSON.stringify(await client2.domains.update(idOrName, payload)));
959
968
  return { exitCode: 0 };
960
969
  } catch (error) {
961
970
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -977,8 +986,8 @@ async function runVerifyCommand(args, env = process.env) {
977
986
  };
978
987
  }
979
988
  try {
980
- const client = await createDomainsClient(apiKey, options.baseUrl);
981
- const result = await client.domains.verify(idOrName);
989
+ const client2 = await createDomainsClient(apiKey, options.baseUrl);
990
+ const result = await client2.domains.verify(idOrName);
982
991
  console.log(JSON.stringify(result));
983
992
  if (result.verified) {
984
993
  console.error(`Domain ${result.domain.name} verified.`);
@@ -1034,8 +1043,8 @@ async function runGetCommand4(args, env = process.env) {
1034
1043
  return { exitCode: 1, error: "Missing id. Usage: groundmail received-emails get inb_..." };
1035
1044
  }
1036
1045
  try {
1037
- const client = await createReceivedEmailsClient(apiKey, options.baseUrl);
1038
- console.log(JSON.stringify(await client.receivedEmails.get(id)));
1046
+ const client2 = await createReceivedEmailsClient(apiKey, options.baseUrl);
1047
+ console.log(JSON.stringify(await client2.receivedEmails.get(id)));
1039
1048
  return { exitCode: 0 };
1040
1049
  } catch (error) {
1041
1050
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -1050,10 +1059,10 @@ async function runListCommand4(args, env = process.env) {
1050
1059
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
1051
1060
  }
1052
1061
  try {
1053
- const client = await createReceivedEmailsClient(apiKey, options.baseUrl);
1062
+ const client2 = await createReceivedEmailsClient(apiKey, options.baseUrl);
1054
1063
  console.log(
1055
1064
  JSON.stringify(
1056
- await client.receivedEmails.list({
1065
+ await client2.receivedEmails.list({
1057
1066
  limit: readFlag11(args, "--limit") ? Number(readFlag11(args, "--limit")) : void 0,
1058
1067
  cursor: readFlag11(args, "--cursor"),
1059
1068
  domain: readFlag11(args, "--domain")
@@ -1098,8 +1107,8 @@ async function runCreateCommand2(args, env = process.env) {
1098
1107
  return { exitCode: 1, error: "Required flag: --url" };
1099
1108
  }
1100
1109
  try {
1101
- const client = await createWebhooksClient(apiKey, options.baseUrl);
1102
- const result = await client.webhooks.create({ url });
1110
+ const client2 = await createWebhooksClient(apiKey, options.baseUrl);
1111
+ const result = await client2.webhooks.create({ url });
1103
1112
  console.log(JSON.stringify(result));
1104
1113
  return { exitCode: 0 };
1105
1114
  } catch (error) {
@@ -1116,8 +1125,8 @@ async function runGetCommand5(args, env = process.env) {
1116
1125
  const id = readFlag13(args, "--id") || readFirstPositional6(args);
1117
1126
  if (!id) return { exitCode: 1, error: "Missing webhook id. Pass --id wh_\u2026" };
1118
1127
  try {
1119
- const client = await createWebhooksClient(apiKey, options.baseUrl);
1120
- console.log(JSON.stringify(await client.webhooks.get(id)));
1128
+ const client2 = await createWebhooksClient(apiKey, options.baseUrl);
1129
+ console.log(JSON.stringify(await client2.webhooks.get(id)));
1121
1130
  return { exitCode: 0 };
1122
1131
  } catch (error) {
1123
1132
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -1151,8 +1160,8 @@ async function runDeleteCommand3(args, env = process.env) {
1151
1160
  return { exitCode: 1, error: "Required flag: --id" };
1152
1161
  }
1153
1162
  try {
1154
- const client = await createWebhooksClient(apiKey, options.baseUrl);
1155
- const result = await client.webhooks.delete(id);
1163
+ const client2 = await createWebhooksClient(apiKey, options.baseUrl);
1164
+ const result = await client2.webhooks.delete(id);
1156
1165
  console.log(JSON.stringify(result));
1157
1166
  return { exitCode: 0 };
1158
1167
  } catch (error) {
@@ -1168,8 +1177,8 @@ async function runListCommand5(args, env = process.env) {
1168
1177
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
1169
1178
  }
1170
1179
  try {
1171
- const client = await createWebhooksClient(apiKey, options.baseUrl);
1172
- const result = await client.webhooks.list();
1180
+ const client2 = await createWebhooksClient(apiKey, options.baseUrl);
1181
+ const result = await client2.webhooks.list();
1173
1182
  console.log(JSON.stringify(result));
1174
1183
  return { exitCode: 0 };
1175
1184
  } catch (error) {
@@ -1198,8 +1207,8 @@ async function runUpdateCommand3(args, env = process.env) {
1198
1207
  ...enabled.value !== void 0 ? { enabled: enabled.value } : {}
1199
1208
  };
1200
1209
  try {
1201
- const client = await createWebhooksClient(apiKey, options.baseUrl);
1202
- console.log(JSON.stringify(await client.webhooks.update(id, payload)));
1210
+ const client2 = await createWebhooksClient(apiKey, options.baseUrl);
1211
+ console.log(JSON.stringify(await client2.webhooks.update(id, payload)));
1203
1212
  return { exitCode: 0 };
1204
1213
  } catch (error) {
1205
1214
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -1247,11 +1256,11 @@ async function runListKeysCommandWithClient(args, env = process.env) {
1247
1256
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
1248
1257
  }
1249
1258
  const { Groundmail } = await import("groundmail");
1250
- const client = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
1259
+ const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
1251
1260
  try {
1252
1261
  const limitRaw = readFlag15(args, "--limit");
1253
1262
  const cursor = readFlag15(args, "--cursor");
1254
- const result = await client.apiKeys.list({
1263
+ const result = await client2.apiKeys.list({
1255
1264
  ...limitRaw ? { limit: Number(limitRaw) } : {},
1256
1265
  ...cursor ? { cursor } : {}
1257
1266
  });
@@ -1288,7 +1297,7 @@ function trimUrl(value) {
1288
1297
  }
1289
1298
 
1290
1299
  // package.json
1291
- var version = "0.18.1";
1300
+ var version = "0.20.0";
1292
1301
 
1293
1302
  // src/user-agent.ts
1294
1303
  function buildUserAgent(own) {
@@ -2146,6 +2155,7 @@ async function runCreateKeyCommandWithClient(args, env = process.env) {
2146
2155
  if (scopes && !scopes.ok) return { exitCode: 1, error: scopes.error };
2147
2156
  const domainsFlag = readFlag16(args, "--allowed-domains");
2148
2157
  const allowedDomains = domainsFlag?.split(/[\s,]+/).map((domain) => domain.trim()).filter(Boolean);
2158
+ const test = args.includes("--test");
2149
2159
  try {
2150
2160
  const response = await apiRequest(baseUrl, "/api-keys", {
2151
2161
  apiKey,
@@ -2154,13 +2164,17 @@ async function runCreateKeyCommandWithClient(args, env = process.env) {
2154
2164
  ...name ? { name } : {},
2155
2165
  ...scope && !scopes ? { scope } : {},
2156
2166
  ...scopes?.ok ? { scopes: scopes.scope.split(" ") } : {},
2157
- ...allowedDomains?.length ? { allowed_domains: allowedDomains } : {}
2167
+ ...allowedDomains?.length ? { allowed_domains: allowedDomains } : {},
2168
+ ...test ? { test: true } : {}
2158
2169
  }
2159
2170
  });
2160
2171
  if (!response.ok) {
2161
2172
  return { exitCode: 1, error: errorMessage(response, "Could not create the key") };
2162
2173
  }
2163
2174
  console.log(JSON.stringify(response.body));
2175
+ if (test) {
2176
+ console.error("Test key: sends with it run every check and fire webhooks, but nothing is delivered. https://docs.groundmail.dev/testing");
2177
+ }
2164
2178
  return { exitCode: 0 };
2165
2179
  } catch (error) {
2166
2180
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -2184,9 +2198,9 @@ async function runDeleteKeyCommandWithClient(args, env = process.env) {
2184
2198
  return { exitCode: 1, error: "Required: --id <api-key-id>" };
2185
2199
  }
2186
2200
  const { Groundmail } = await import("groundmail");
2187
- const client = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
2201
+ const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
2188
2202
  try {
2189
- const result = await client.apiKeys.remove(id);
2203
+ const result = await client2.apiKeys.remove(id);
2190
2204
  console.log(JSON.stringify(result));
2191
2205
  return { exitCode: 0 };
2192
2206
  } catch (error) {
@@ -2224,11 +2238,11 @@ async function runListCommand6(args, env = process.env) {
2224
2238
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
2225
2239
  }
2226
2240
  try {
2227
- const client = await createSuppressionsClient(apiKey, options.baseUrl);
2241
+ const client2 = await createSuppressionsClient(apiKey, options.baseUrl);
2228
2242
  const limitRaw = readFlag18(args, "--limit");
2229
2243
  const cursor = readFlag18(args, "--cursor");
2230
2244
  const email = readFlag18(args, "--email");
2231
- const result = await client.suppressions.list({
2245
+ const result = await client2.suppressions.list({
2232
2246
  ...limitRaw ? { limit: Number(limitRaw) } : {},
2233
2247
  ...cursor ? { cursor } : {},
2234
2248
  ...email ? { email } : {}
@@ -2252,9 +2266,9 @@ async function runAddCommand2(args, env = process.env) {
2252
2266
  return { exitCode: 1, error: "Missing email. Pass --email user@example.com" };
2253
2267
  }
2254
2268
  try {
2255
- const client = await createSuppressionsClient(apiKey, options.baseUrl);
2269
+ const client2 = await createSuppressionsClient(apiKey, options.baseUrl);
2256
2270
  const reason = readFlag18(args, "--reason");
2257
- const result = await client.suppressions.create({
2271
+ const result = await client2.suppressions.create({
2258
2272
  email,
2259
2273
  ...reason ? { reason } : {}
2260
2274
  });
@@ -2277,8 +2291,8 @@ async function runRemoveCommand(args, env = process.env) {
2277
2291
  return { exitCode: 1, error: "Missing id or email. Pass --id <uuid> or --email user@example.com" };
2278
2292
  }
2279
2293
  try {
2280
- const client = await createSuppressionsClient(apiKey, options.baseUrl);
2281
- const result = await client.suppressions.remove(idOrEmail);
2294
+ const client2 = await createSuppressionsClient(apiKey, options.baseUrl);
2295
+ const result = await client2.suppressions.remove(idOrEmail);
2282
2296
  console.log(JSON.stringify(result));
2283
2297
  return { exitCode: 0 };
2284
2298
  } catch (error) {
@@ -2315,8 +2329,8 @@ async function runDeleteCommand4(args, env = process.env) {
2315
2329
  const idOrAlias = readFlag19(args, "--id") || readFlag19(args, "--alias") || readFirstPositional8(args);
2316
2330
  if (!idOrAlias) return { exitCode: 1, error: "Missing template id or alias. Pass --id tpl_\u2026 or --alias welcome" };
2317
2331
  try {
2318
- const client = await createTemplatesClient(apiKey, options.baseUrl);
2319
- console.log(JSON.stringify(await client.templates.remove(idOrAlias)));
2332
+ const client2 = await createTemplatesClient(apiKey, options.baseUrl);
2333
+ console.log(JSON.stringify(await client2.templates.remove(idOrAlias)));
2320
2334
  return { exitCode: 0 };
2321
2335
  } catch (error) {
2322
2336
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -2344,8 +2358,8 @@ async function runDuplicateCommand(args, env = process.env) {
2344
2358
  if (!idOrAlias) return { exitCode: 1, error: "Missing template id or alias. Pass --id tpl_\u2026 or --alias welcome" };
2345
2359
  const name = readFlag19(args, "--name");
2346
2360
  try {
2347
- const client = await createTemplatesClient(apiKey, options.baseUrl);
2348
- console.log(JSON.stringify(await client.templates.duplicate(idOrAlias, name ? { name } : {})));
2361
+ const client2 = await createTemplatesClient(apiKey, options.baseUrl);
2362
+ console.log(JSON.stringify(await client2.templates.duplicate(idOrAlias, name ? { name } : {})));
2349
2363
  return { exitCode: 0 };
2350
2364
  } catch (error) {
2351
2365
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -2372,8 +2386,8 @@ async function runGetCommand6(args, env = process.env) {
2372
2386
  const idOrAlias = readFlag19(args, "--id") || readFlag19(args, "--alias") || readFirstPositional10(args);
2373
2387
  if (!idOrAlias) return { exitCode: 1, error: "Missing template id or alias. Pass --id tpl_\u2026 or --alias welcome" };
2374
2388
  try {
2375
- const client = await createTemplatesClient(apiKey, options.baseUrl);
2376
- console.log(JSON.stringify(await client.templates.get(idOrAlias)));
2389
+ const client2 = await createTemplatesClient(apiKey, options.baseUrl);
2390
+ console.log(JSON.stringify(await client2.templates.get(idOrAlias)));
2377
2391
  return { exitCode: 0 };
2378
2392
  } catch (error) {
2379
2393
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -2399,11 +2413,11 @@ async function runListCommand7(args, env = process.env) {
2399
2413
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
2400
2414
  }
2401
2415
  try {
2402
- const client = await createTemplatesClient(apiKey, options.baseUrl);
2416
+ const client2 = await createTemplatesClient(apiKey, options.baseUrl);
2403
2417
  const limitRaw = readFlag19(args, "--limit");
2404
2418
  const cursor = readFlag19(args, "--cursor");
2405
2419
  const status = readFlag19(args, "--status");
2406
- const result = await client.templates.list({
2420
+ const result = await client2.templates.list({
2407
2421
  ...limitRaw ? { limit: Number(limitRaw) } : {},
2408
2422
  ...cursor ? { cursor } : {},
2409
2423
  ...status ? { status } : {}
@@ -2424,8 +2438,8 @@ async function runPublishCommand(args, env = process.env) {
2424
2438
  const idOrAlias = readFlag19(args, "--id") || readFlag19(args, "--alias") || readFirstPositional11(args);
2425
2439
  if (!idOrAlias) return { exitCode: 1, error: "Missing template id or alias. Pass --id tpl_\u2026 or --alias welcome" };
2426
2440
  try {
2427
- const client = await createTemplatesClient(apiKey, options.baseUrl);
2428
- console.log(JSON.stringify(await client.templates.publish(idOrAlias)));
2441
+ const client2 = await createTemplatesClient(apiKey, options.baseUrl);
2442
+ console.log(JSON.stringify(await client2.templates.publish(idOrAlias)));
2429
2443
  return { exitCode: 0 };
2430
2444
  } catch (error) {
2431
2445
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -2600,10 +2614,10 @@ async function runPushCommand(args, env = process.env, deps = {}) {
2600
2614
  return { exitCode: 1, error: `${file} produced no content to push.` };
2601
2615
  }
2602
2616
  const createClient2 = deps.createClient ?? createTemplatesClient;
2603
- const client = await createClient2(apiKey, options.baseUrl);
2617
+ const client2 = await createClient2(apiKey, options.baseUrl);
2604
2618
  let existed = true;
2605
2619
  try {
2606
- await client.templates.get(alias);
2620
+ await client2.templates.get(alias);
2607
2621
  } catch (error) {
2608
2622
  if (statusOf(error) !== 404) throw error;
2609
2623
  existed = false;
@@ -2618,7 +2632,7 @@ async function runPushCommand(args, env = process.env, deps = {}) {
2618
2632
  };
2619
2633
  let result;
2620
2634
  if (existed) {
2621
- result = await client.templates.update(alias, body);
2635
+ result = await client2.templates.update(alias, body);
2622
2636
  } else {
2623
2637
  if (!subject) {
2624
2638
  return {
@@ -2626,7 +2640,7 @@ async function runPushCommand(args, env = process.env, deps = {}) {
2626
2640
  error: `Template "${alias}" does not exist yet. Pass --subject to create it.`
2627
2641
  };
2628
2642
  }
2629
- result = await client.templates.create({
2643
+ result = await client2.templates.create({
2630
2644
  name: name || alias,
2631
2645
  subject,
2632
2646
  alias,
@@ -2634,7 +2648,7 @@ async function runPushCommand(args, env = process.env, deps = {}) {
2634
2648
  });
2635
2649
  }
2636
2650
  if (shouldPublish) {
2637
- result = await client.templates.publish(alias);
2651
+ result = await client2.templates.publish(alias);
2638
2652
  }
2639
2653
  console.log(JSON.stringify({ ...result, pushed: { file, alias, created: !existed } }));
2640
2654
  return { exitCode: 0 };
@@ -2667,8 +2681,8 @@ async function runCreateCommand3(args, env = process.env) {
2667
2681
  return { exitCode: 1, error: 'Missing body. Pass --html "<p>Hi</p>" or --text "Hi"' };
2668
2682
  }
2669
2683
  try {
2670
- const client = await createTemplatesClient(apiKey, options.baseUrl);
2671
- const result = await client.templates.create({
2684
+ const client2 = await createTemplatesClient(apiKey, options.baseUrl);
2685
+ const result = await client2.templates.create({
2672
2686
  name,
2673
2687
  subject,
2674
2688
  ...html ? { html } : {},
@@ -2723,8 +2737,8 @@ async function runUpdateCommand4(args, env = process.env) {
2723
2737
  };
2724
2738
  }
2725
2739
  try {
2726
- const client = await createTemplatesClient(apiKey, options.baseUrl);
2727
- const result = await client.templates.update(idOrAlias, {
2740
+ const client2 = await createTemplatesClient(apiKey, options.baseUrl);
2741
+ const result = await client2.templates.update(idOrAlias, {
2728
2742
  ...name ? { name } : {},
2729
2743
  ...subject ? { subject } : {},
2730
2744
  ...html ? { html } : {},
@@ -2787,8 +2801,8 @@ async function runFromStarterCommand(args, env = process.env) {
2787
2801
  };
2788
2802
  }
2789
2803
  try {
2790
- const client = await createTemplatesClient(apiKey, options.baseUrl);
2791
- console.log(JSON.stringify(await client.templates.fromStarter(alias)));
2804
+ const client2 = await createTemplatesClient(apiKey, options.baseUrl);
2805
+ console.log(JSON.stringify(await client2.templates.fromStarter(alias)));
2792
2806
  return { exitCode: 0 };
2793
2807
  } catch (error) {
2794
2808
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -2801,8 +2815,8 @@ async function runListStartersCommand(args, env = process.env) {
2801
2815
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
2802
2816
  }
2803
2817
  try {
2804
- const client = await createTemplatesClient(apiKey, options.baseUrl);
2805
- console.log(JSON.stringify(await client.templates.listStarters()));
2818
+ const client2 = await createTemplatesClient(apiKey, options.baseUrl);
2819
+ console.log(JSON.stringify(await client2.templates.listStarters()));
2806
2820
  return { exitCode: 0 };
2807
2821
  } catch (error) {
2808
2822
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -2833,8 +2847,8 @@ async function runVersionsCommand(args, env = process.env) {
2833
2847
  return { exitCode: 1, error: "Missing template id or alias. Pass --id tpl_\u2026 or --alias welcome" };
2834
2848
  }
2835
2849
  try {
2836
- const client = await createTemplatesClient(apiKey, options.baseUrl);
2837
- console.log(JSON.stringify(await client.templates.listVersions(idOrAlias)));
2850
+ const client2 = await createTemplatesClient(apiKey, options.baseUrl);
2851
+ console.log(JSON.stringify(await client2.templates.listVersions(idOrAlias)));
2838
2852
  return { exitCode: 0 };
2839
2853
  } catch (error) {
2840
2854
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -2856,8 +2870,8 @@ async function runRestoreCommand(args, env = process.env) {
2856
2870
  };
2857
2871
  }
2858
2872
  try {
2859
- const client = await createTemplatesClient(apiKey, options.baseUrl);
2860
- console.log(JSON.stringify(await client.templates.restoreVersion(idOrAlias, version2)));
2873
+ const client2 = await createTemplatesClient(apiKey, options.baseUrl);
2874
+ console.log(JSON.stringify(await client2.templates.restoreVersion(idOrAlias, version2)));
2861
2875
  return { exitCode: 0 };
2862
2876
  } catch (error) {
2863
2877
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -2879,8 +2893,8 @@ async function runTestSendCommand(args, env = process.env) {
2879
2893
  };
2880
2894
  }
2881
2895
  try {
2882
- const client = await createTemplatesClient(apiKey, options.baseUrl);
2883
- console.log(JSON.stringify(await client.templates.testSend(idOrAlias, { from, to })));
2896
+ const client2 = await createTemplatesClient(apiKey, options.baseUrl);
2897
+ console.log(JSON.stringify(await client2.templates.testSend(idOrAlias, { from, to })));
2884
2898
  return { exitCode: 0 };
2885
2899
  } catch (error) {
2886
2900
  return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
@@ -2915,8 +2929,8 @@ async function runTwilioStatusCommand(args, env = process.env) {
2915
2929
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
2916
2930
  }
2917
2931
  try {
2918
- const client = await createIntegrationsClient(apiKey, options.baseUrl);
2919
- const result = await client.integrations.getTwilio();
2932
+ const client2 = await createIntegrationsClient(apiKey, options.baseUrl);
2933
+ const result = await client2.integrations.getTwilio();
2920
2934
  console.log(JSON.stringify(result));
2921
2935
  return { exitCode: 0 };
2922
2936
  } catch (error) {
@@ -2946,8 +2960,8 @@ async function runTwilioConnectCommand(args, env = process.env) {
2946
2960
  };
2947
2961
  }
2948
2962
  try {
2949
- const client = await createIntegrationsClient(apiKey, options.baseUrl);
2950
- const result = await client.integrations.connectTwilio({
2963
+ const client2 = await createIntegrationsClient(apiKey, options.baseUrl);
2964
+ const result = await client2.integrations.connectTwilio({
2951
2965
  accountSid: accountSid.trim(),
2952
2966
  authToken: authToken.trim(),
2953
2967
  ...defaultFrom.trim() ? { defaultFrom: defaultFrom.trim() } : {},
@@ -2966,8 +2980,8 @@ async function runTwilioDisconnectCommand(args, env = process.env) {
2966
2980
  return { exitCode: 1, error: "Missing API key. Set GROUNDMAIL_API_KEY or pass --api-key." };
2967
2981
  }
2968
2982
  try {
2969
- const client = await createIntegrationsClient(apiKey, options.baseUrl);
2970
- const result = await client.integrations.disconnectTwilio();
2983
+ const client2 = await createIntegrationsClient(apiKey, options.baseUrl);
2984
+ const result = await client2.integrations.disconnectTwilio();
2971
2985
  console.log(JSON.stringify(result));
2972
2986
  return { exitCode: 0 };
2973
2987
  } catch (error) {
@@ -3120,6 +3134,7 @@ var KEY_ENV = {
3120
3134
  mailgun: "MAILGUN_API_KEY"
3121
3135
  };
3122
3136
  var LABELS = { sendgrid: "SendGrid", postmark: "Postmark", mailgun: "Mailgun" };
3137
+ var VALUE_FLAGS2 = /* @__PURE__ */ new Set(["--api-key", "--base-url"]);
3123
3138
  function readFlag21(args, flag) {
3124
3139
  const index = args.indexOf(flag);
3125
3140
  if (index === -1) return void 0;
@@ -3148,6 +3163,10 @@ function formatMigrationSummary(m) {
3148
3163
  lines.push(
3149
3164
  m.dry_run ? ` Suppressions ${n(s.found)}${m.suppressions.estimated ? "+ (first page of each list)" : ""}` : ` Suppressions ${n(s.imported)} added, ${n(s.already_suppressed)} already suppressed`
3150
3165
  );
3166
+ if (s.product_opt_out) lines.push(` ${n(s.product_opt_out)} of them product email opt-outs (transactional mail still reaches them)`);
3167
+ for (const [reason, count] of Object.entries(m.suppressions.skipped_reasons)) {
3168
+ lines.push(` ${n(count)} skipped: ${reason}`);
3169
+ }
3151
3170
  }
3152
3171
  if (m.errors.length) {
3153
3172
  lines.push("", "Could not read:");
@@ -3163,6 +3182,17 @@ function formatMigrationSummary(m) {
3163
3182
  for (const line of failed.slice(0, 20)) lines.push(` ${line}`);
3164
3183
  if (failed.length > 20) lines.push(` \u2026and ${failed.length - 20} more (see the JSON report)`);
3165
3184
  }
3185
+ const plans = (m.domains?.items ?? []).filter((d) => d.dns_plan);
3186
+ for (const d of plans) {
3187
+ const changes = d.dns_plan.changes.filter((c) => c.action === "add" || c.action === "update");
3188
+ lines.push("", `DNS changes for ${d.name}${changes.length ? "" : ": all published"}`);
3189
+ for (const c of changes) {
3190
+ lines.push(` ${c.action === "update" ? "edit" : "add "} ${c.type.padEnd(5)} ${c.host} ${c.value}`);
3191
+ if (c.action === "update" && c.current) lines.push(` now: ${c.current}`);
3192
+ }
3193
+ for (const c of d.dns_plan.changes.filter((c2) => c2.action === "keep")) lines.push(` keep ${c.type.padEnd(5)} ${c.host} (yours)`);
3194
+ lines.push(` ${d.dns_plan.keep_old_records}`);
3195
+ }
3166
3196
  if (m.attention.length) {
3167
3197
  lines.push("", "Next:");
3168
3198
  for (const line of m.attention) lines.push(` - ${line}`);
@@ -3170,11 +3200,48 @@ function formatMigrationSummary(m) {
3170
3200
  const node = m.code_changes?.find((c) => c.stack === "node");
3171
3201
  if (node) lines.push("", "Code change (Node.js):", node.diff);
3172
3202
  if (m.agent_prompt) lines.push("", "Prompt for your coding agent is in the JSON report (`agent_prompt`).");
3203
+ if (!m.dry_run && !m.has_more) lines.push("", `Report: groundmail migrate report ${m.id} --csv > import-report.csv`);
3173
3204
  return lines.join("\n");
3174
3205
  }
3206
+ async function client(args, env) {
3207
+ const apiKey = readFlag21(args, "--api-key") || env.GROUNDMAIL_API_KEY;
3208
+ if (!apiKey) return null;
3209
+ const { Groundmail } = await import("groundmail");
3210
+ const baseUrl = readFlag21(args, "--base-url");
3211
+ return new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
3212
+ }
3213
+ async function runStoredCommand(sub, args, env) {
3214
+ const gm = await client(args, env);
3215
+ if (!gm) return { exitCode: 1, error: "Not signed in. Run `groundmail login`, or set GROUNDMAIL_API_KEY." };
3216
+ try {
3217
+ if (sub === "list") {
3218
+ const { data } = await gm.migrations.list();
3219
+ console.log(JSON.stringify({ data }));
3220
+ for (const m of data) console.error(`${m.id} ${LABELS[m.provider]} ${m.status} ${m.started_at.slice(0, 10)}`);
3221
+ if (!data.length) console.error("No imports yet. Previews are not stored.");
3222
+ return { exitCode: 0 };
3223
+ }
3224
+ const id = args.find((arg, i) => !arg.startsWith("--") && !VALUE_FLAGS2.has(args[i - 1] ?? ""));
3225
+ if (!id) return { exitCode: 1, error: "Usage: groundmail migrate report <import id> [--csv]" };
3226
+ if (args.includes("--csv")) {
3227
+ process.stdout.write(await gm.migrations.reportCsv(id));
3228
+ return { exitCode: 0 };
3229
+ }
3230
+ const { migration } = await gm.migrations.get(id);
3231
+ console.log(JSON.stringify(migration));
3232
+ console.error(formatMigrationSummary(migration));
3233
+ return { exitCode: 0 };
3234
+ } catch (error) {
3235
+ return { exitCode: 1, error: error instanceof Error ? error.message : String(error) };
3236
+ }
3237
+ }
3175
3238
  async function runMigrateCommand(provider, args, env = process.env) {
3239
+ if (provider === "list" || provider === "report") return runStoredCommand(provider, args, env);
3176
3240
  if (!provider || !PROVIDERS.includes(provider)) {
3177
- return { exitCode: 1, error: "Usage: groundmail migrate <sendgrid|postmark|mailgun> [--dry-run] [--only templates,suppressions]" };
3241
+ return {
3242
+ exitCode: 1,
3243
+ error: "Usage: groundmail migrate <sendgrid|postmark|mailgun> [--dry-run] [--only templates,suppressions], groundmail migrate list, or groundmail migrate report <id> [--csv]"
3244
+ };
3178
3245
  }
3179
3246
  const id = provider;
3180
3247
  const apiKey = readFlag21(args, "--api-key") || env.GROUNDMAIL_API_KEY;
@@ -3210,9 +3277,9 @@ async function runMigrateCommand(provider, args, env = process.env) {
3210
3277
  try {
3211
3278
  const { Groundmail } = await import("groundmail");
3212
3279
  const baseUrl = readFlag21(args, "--base-url");
3213
- const client = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
3280
+ const client2 = new Groundmail(apiKey, baseUrl ? { baseUrl } : void 0);
3214
3281
  console.error(`${params.dry_run ? "Previewing" : "Importing"} from ${LABELS[id]} (Beta)\u2026`);
3215
- const report = await client.migrations.run(params, {
3282
+ const report = await client2.migrations.run(params, {
3216
3283
  onProgress: (m) => {
3217
3284
  if (m.has_more) {
3218
3285
  const s = m.suppressions?.totals;
@@ -3242,8 +3309,8 @@ async function runValidateCommand(args, env = process.env) {
3242
3309
  return { exitCode: 1, error: "Missing email. Usage: groundmail validate user@example.com" };
3243
3310
  }
3244
3311
  try {
3245
- const client = await createSuppressionsClient(apiKey, options.baseUrl);
3246
- const result = await client.validate(email);
3312
+ const client2 = await createSuppressionsClient(apiKey, options.baseUrl);
3313
+ const result = await client2.validate(email);
3247
3314
  console.log(JSON.stringify(result));
3248
3315
  return { exitCode: result.verdict === "invalid" ? 2 : 0 };
3249
3316
  } catch (error) {
@@ -3272,7 +3339,7 @@ var USAGE_LINES = [
3272
3339
  " groundmail received-emails get inb_...",
3273
3340
  ' groundmail emails send --from you@domain.com --to user@example.com --subject "Hello" --html "<p>Hi</p>" [--category transactional|product] [--unsubscribe]',
3274
3341
  " groundmail emails batch --file ./emails.json",
3275
- " groundmail emails list [--limit 25] [--cursor \u2026]",
3342
+ " groundmail emails list [--limit 25] [--cursor \u2026] [--test | --live]",
3276
3343
  " groundmail emails insights [--window 7d|30d]",
3277
3344
  " groundmail emails get --id msg_\u2026",
3278
3345
  " groundmail emails cancel --id msg_\u2026",
@@ -3310,11 +3377,13 @@ var USAGE_LINES = [
3310
3377
  ' groundmail templates duplicate --id tpl_\u2026 [--name "Copy"]',
3311
3378
  " groundmail templates delete --id tpl_\u2026",
3312
3379
  " groundmail keys list",
3313
- " groundmail keys create [--name Default] [--scopes emails:send,domains:read] [--allowed-domains example.com]",
3380
+ " groundmail keys create [--name Default] [--scopes emails:send,domains:read] [--allowed-domains example.com] [--test] --test: a gm_test_ key, sends are simulated",
3314
3381
  " groundmail keys delete --id <api-key-id>",
3315
3382
  " groundmail migrate sendgrid [--dry-run] [--only templates,suppressions,domains,webhooks] [--region eu] import from SendGrid (Beta)",
3316
3383
  " groundmail migrate postmark [--dry-run] [--only \u2026] import from Postmark (Beta)",
3317
3384
  " groundmail migrate mailgun [--dry-run] [--only \u2026] [--region eu] import from Mailgun (Beta)",
3385
+ " groundmail migrate list your recent imports",
3386
+ " groundmail migrate report <id> [--csv] an import report (JSON, or CSV to stdout)",
3318
3387
  " groundmail integrations twilio status",
3319
3388
  " groundmail integrations twilio connect --account-sid AC\u2026 --auth-token \u2026 --from +15551234567",
3320
3389
  " groundmail integrations twilio disconnect"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "groundmail-cli",
3
- "version": "0.18.1",
3
+ "version": "0.20.0",
4
4
  "description": "Groundmail CLI — send transactional email from the terminal",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -38,7 +38,7 @@
38
38
  "prepublishOnly": "npm run build"
39
39
  },
40
40
  "dependencies": {
41
- "groundmail": "0.15.1"
41
+ "groundmail": "0.17.0"
42
42
  },
43
43
  "devDependencies": {
44
44
  "tsup": "^8.5.0",