emailr-cli 1.4.2 → 1.5.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/index.js +144 -10
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { Command as Command10 } from "commander";
4
+ import { Command as Command11 } from "commander";
5
5
 
6
6
  // src/commands/send.ts
7
7
  import { Command } from "commander";
@@ -854,14 +854,14 @@ It creates a local file with hot-reload preview, then use this command to save.`
854
854
  subject: options.subject
855
855
  };
856
856
  if (options.htmlFile) {
857
- const fs5 = await import("fs");
858
- request.html_content = fs5.readFileSync(options.htmlFile, "utf-8");
857
+ const fs6 = await import("fs");
858
+ request.html_content = fs6.readFileSync(options.htmlFile, "utf-8");
859
859
  } else if (options.html) {
860
860
  request.html_content = options.html;
861
861
  }
862
862
  if (options.textFile) {
863
- const fs5 = await import("fs");
864
- request.text_content = fs5.readFileSync(options.textFile, "utf-8");
863
+ const fs6 = await import("fs");
864
+ request.text_content = fs6.readFileSync(options.textFile, "utf-8");
865
865
  } else if (options.text) {
866
866
  request.text_content = options.text;
867
867
  }
@@ -914,14 +914,14 @@ It downloads the template with hot-reload preview, then use this command to save
914
914
  if (options.name) request.name = options.name;
915
915
  if (options.subject) request.subject = options.subject;
916
916
  if (options.htmlFile) {
917
- const fs5 = await import("fs");
918
- request.html_content = fs5.readFileSync(options.htmlFile, "utf-8");
917
+ const fs6 = await import("fs");
918
+ request.html_content = fs6.readFileSync(options.htmlFile, "utf-8");
919
919
  } else if (options.html) {
920
920
  request.html_content = options.html;
921
921
  }
922
922
  if (options.textFile) {
923
- const fs5 = await import("fs");
924
- request.text_content = fs5.readFileSync(options.textFile, "utf-8");
923
+ const fs6 = await import("fs");
924
+ request.text_content = fs6.readFileSync(options.textFile, "utf-8");
925
925
  } else if (options.text) {
926
926
  request.text_content = options.text;
927
927
  }
@@ -2322,8 +2322,141 @@ async function executeLogin(options) {
2322
2322
  }
2323
2323
  }
2324
2324
 
2325
+ // src/commands/agent.ts
2326
+ import { Command as Command10 } from "commander";
2327
+ import { spawn, execSync } from "child_process";
2328
+ import fs5 from "fs";
2329
+ import path5 from "path";
2330
+ import os3 from "os";
2331
+ var OPENCODE_SKILL_DIR = path5.join(os3.homedir(), ".config", "opencode", "skills", "emailr-cli");
2332
+ var SKILL_MD = `---
2333
+ name: emailr-cli
2334
+ description: Operate the Emailr CLI to send emails, manage contacts, templates, domains, broadcasts, webhooks, and segments. Includes LIVE PREVIEW editing for templates with hot-reload.
2335
+ ---
2336
+ # Emailr CLI
2337
+
2338
+ ## Quick start
2339
+ - Ensure auth: \`emailr login\` (browser-based) or \`emailr config set api-key <token>\`.
2340
+ - Prefer machine-readable output with \`--format json\` on listing/get commands.
2341
+
2342
+ ## LIVE TEMPLATE EDITING (Agentic Workflow)
2343
+
2344
+ ### Edit existing template with live preview
2345
+ 1. Start live editing: \`emailr templates edit <template_id> --file ./template.html\`
2346
+ 2. Edit the file - browser auto-refreshes on every save
2347
+ 3. When satisfied: \`emailr templates update <template_id> --html-file ./template.html\`
2348
+
2349
+ ### Create new template with live preview
2350
+ 1. Start drafting: \`emailr templates draft --file ./new-template.html\`
2351
+ 2. Edit the file - browser auto-refreshes on every save
2352
+ 3. When satisfied: \`emailr templates create --name "Template Name" --subject "Subject" --html-file ./new-template.html\`
2353
+
2354
+ ## Common commands
2355
+
2356
+ ### Sending emails
2357
+ - Plain text: \`emailr send --to user@example.com --from no-reply@example.com --subject "Hi" --text "Hello"\`
2358
+ - HTML: \`emailr send --to user@example.com --from no-reply@example.com --subject "Hi" --html "<h1>Hello</h1>"\`
2359
+ - With template: \`emailr send --to user@example.com --from no-reply@example.com --template tmpl_xxx --template-data '{"name":"Ada"}'\`
2360
+
2361
+ ### Templates
2362
+ - List: \`emailr templates list --format json\`
2363
+ - Get: \`emailr templates get <id> --format json\`
2364
+ - Preview: \`emailr templates preview <id>\`
2365
+ - Create: \`emailr templates create --name "Name" --subject "Subject" --html-file ./template.html\`
2366
+ - Update: \`emailr templates update <id> --html-file ./template.html\`
2367
+ - Delete: \`emailr templates delete <id>\`
2368
+ `;
2369
+ function isOpenCodeInstalled() {
2370
+ try {
2371
+ execSync("which opencode", { stdio: "ignore" });
2372
+ return true;
2373
+ } catch {
2374
+ return false;
2375
+ }
2376
+ }
2377
+ function installOpenCode() {
2378
+ console.log("Installing OpenCode AI agent...");
2379
+ try {
2380
+ execSync("npm install -g opencode-ai@latest", { stdio: "inherit" });
2381
+ return true;
2382
+ } catch {
2383
+ if (process.platform === "darwin") {
2384
+ try {
2385
+ execSync("brew install anomalyco/tap/opencode", { stdio: "inherit" });
2386
+ return true;
2387
+ } catch {
2388
+ return false;
2389
+ }
2390
+ }
2391
+ return false;
2392
+ }
2393
+ }
2394
+ function ensureSkillInstalled() {
2395
+ if (!fs5.existsSync(OPENCODE_SKILL_DIR)) {
2396
+ fs5.mkdirSync(OPENCODE_SKILL_DIR, { recursive: true });
2397
+ }
2398
+ const skillPath = path5.join(OPENCODE_SKILL_DIR, "SKILL.md");
2399
+ fs5.writeFileSync(skillPath, SKILL_MD, "utf-8");
2400
+ }
2401
+ function createAgentCommand() {
2402
+ const cmd = new Command10("agent").description(`Launch an AI agent with Emailr CLI expertise
2403
+
2404
+ This opens OpenCode (opencode.ai), an AI coding agent that knows how to use all Emailr CLI commands.
2405
+ The agent can help you:
2406
+ - Send emails and manage templates with live preview
2407
+ - Manage contacts, broadcasts, and segments
2408
+ - Configure domains and webhooks
2409
+
2410
+ The agent runs in your terminal with full access to the emailr CLI.`).option("--install", "Install OpenCode if not already installed").option("--model <model>", "Model to use (e.g., anthropic/claude-sonnet-4)").action(async (options) => {
2411
+ if (!isOpenCodeInstalled()) {
2412
+ if (options.install) {
2413
+ const installed = installOpenCode();
2414
+ if (!installed) {
2415
+ error("Failed to install OpenCode. Please install manually:");
2416
+ console.log(" npm install -g opencode-ai@latest");
2417
+ console.log(" # or");
2418
+ console.log(" brew install anomalyco/tap/opencode");
2419
+ process.exit(1);
2420
+ }
2421
+ } else {
2422
+ error("OpenCode AI agent is not installed.");
2423
+ console.log("\nInstall it with one of:");
2424
+ console.log(" emailr agent --install");
2425
+ console.log(" npm install -g opencode-ai@latest");
2426
+ console.log(" brew install anomalyco/tap/opencode");
2427
+ process.exit(1);
2428
+ }
2429
+ }
2430
+ try {
2431
+ ensureSkillInstalled();
2432
+ success("Emailr CLI skill loaded");
2433
+ } catch (err) {
2434
+ warn(`Could not install skill: ${err instanceof Error ? err.message : String(err)}`);
2435
+ }
2436
+ const args = [];
2437
+ if (options.model) {
2438
+ args.push("--model", options.model);
2439
+ }
2440
+ console.log("\nStarting Emailr AI Agent...");
2441
+ console.log("The agent has the emailr-cli skill loaded.");
2442
+ console.log("Ask it to help with emails, templates, contacts, or broadcasts.\n");
2443
+ const opencode = spawn("opencode", args, {
2444
+ stdio: "inherit",
2445
+ env: process.env
2446
+ });
2447
+ opencode.on("error", (err) => {
2448
+ error(`Failed to start agent: ${err.message}`);
2449
+ process.exit(1);
2450
+ });
2451
+ opencode.on("exit", (code) => {
2452
+ process.exit(code ?? 0);
2453
+ });
2454
+ });
2455
+ return cmd;
2456
+ }
2457
+
2325
2458
  // src/index.ts
2326
- var program = new Command10();
2459
+ var program = new Command11();
2327
2460
  program.name("emailr").description("Emailr CLI - Send emails and manage your email infrastructure").version("1.0.0");
2328
2461
  program.addCommand(createSendCommand());
2329
2462
  program.addCommand(createContactsCommand());
@@ -2334,4 +2467,5 @@ program.addCommand(createWebhooksCommand());
2334
2467
  program.addCommand(createSegmentsCommand());
2335
2468
  program.addCommand(createConfigCommand());
2336
2469
  program.addCommand(createLoginCommand());
2470
+ program.addCommand(createAgentCommand());
2337
2471
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "emailr-cli",
3
- "version": "1.4.2",
3
+ "version": "1.5.0",
4
4
  "description": "Command-line interface for the Emailr email API",
5
5
  "type": "module",
6
6
  "bin": {