npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

elastic-email-cli

v0.3.0

Published

Interactive CLI for the Elastic Email API

Readme

Key Features

  • Interactive mode. Run elastic-email with no arguments to get a keyboard-driven TUI: browse everything, pick with arrows, and send email through a guided wizard.
  • Script-friendly. Every command supports --json, exit codes are stable, and piped/CI output carries no banner or decorations.
  • Full sending toolkit. From transactional emails, saved templates, and campaigns to whole lists or segments.

Requirements

  • Node.js 20 or newer
  • An Elastic Email account and API key (dashboard → Settings → API)
  • A verified sending domain. Elastic Email only sends from verified domains, so your --from address must use one.

Getting Started

Install the elastic-email-cli package from npm:

npm install -g elastic-email-cli
elastic-email --help

or run it without installing:

npx elastic-email-cli --help

Install from source

git clone https://github.com/ElasticEmail/elasticemail-cli.git
cd elasticemail-cli
npm install
npm run build
npm link                                # makes the elastic-email command available globally
elastic-email --help

Authentication

The API key is resolved in this order: --api-key flag → ELASTIC_EMAIL_API_KEY environment variable → local config file.

elastic-email auth set-key              # interactive, masked prompt
elastic-email auth set-key <key>        # non-interactive (CI)
elastic-email auth set-key <key> --default-from [email protected]
elastic-email auth status               # where the key comes from + live connection test
elastic-email auth clear                # remove the local config

⚠️ auth set-key stores the key in plaintext at ~/.elastic-email-cli/config.json with 0600 permissions. Convenient, but not an OS keychain - treat the file as a secret and prefer the ELASTIC_EMAIL_API_KEY environment variable in shared or CI environments. The key is never printed to logs or errors (only a masked form).

Interactive mode

A bare invocation in a terminal opens the interactive mode (also available as elastic-email tui):

elastic-email
  • ↑/↓ move · Enter open/select · ←/→ pages · Space multi-select · Esc back · q quit.
  • Browse templates, lists (and their contacts), contacts, segments (and their contacts), delivery events, verification results, sender domains, statistics, and account info.
  • Guided send wizard: sender (with verified-domain hints), recipients - addresses, or multi-selected lists/segments on Marketing-plan accounts - content (text, HTML, or a saved template), review, send.
  • Verify an email address interactively; forget me (f in Account info) removes the local config after confirmation.
  • Prompts for an API key on first run.

In pipes, redirects, and CI (no TTY), a bare invocation prints plain help instead - interactive mode never breaks scripted usage.

Demo

elastic-email auth set-key
elastic-email emails send --to [email protected] --subject "Hello" --text "It works!" --from [email protected]
elastic-email emails status <transactionid>
elastic-email templates create "Welcome" --html-file welcome.html --subject "Welcome!"
elastic-email emails send --to-list Newsletter --template "Welcome" --from [email protected]

JSON output

Add --json to any command for clean, machine-readable output:

elastic-email account info --json
elastic-email emails send --to [email protected] --subject Hi --text Hello --from [email protected] --json | jq '.messageId'

Dry run

emails send --dry-run validates the input and prints the exact request that would be sent — no API call is made:

elastic-email emails send --to [email protected] --subject Hi --text Hello --from [email protected] --dry-run

Commands

Auth

elastic-email auth set-key [key]        # store the API key (interactive without [key])
elastic-email auth status               # key source + live connection test
elastic-email auth clear                # remove the local config (asks for confirmation)

Sending

elastic-email emails send --to <email> --subject <s> --text <t> --from <email>
                                        # send a transactional email
elastic-email emails send --to <email> --subject <s> --html "<b>Hi</b>" --from <email>
                                        # HTML body (combine with --text for both parts)
elastic-email emails send --to "[email protected],[email protected]" ...
                                        # multiple recipients (or repeat --to)
elastic-email emails send --to <email> --template <name> --from <email>
                                        # send a saved template (--subject optional)
elastic-email emails send --to-list <list> --template <name> --from <email>
                                        # send to a whole list (creates an Active campaign)
elastic-email emails send               # interactive compose form on a TTY
elastic-email emails send ... --dry-run # validate + preview without sending
elastic-email emails status <transactionid>
                                        # delivery counts for a sent email
elastic-email emails status <transactionid> --recipients
                                        # include per-recipient address lists

--from is required for every send unless you configured a default sender (elastic-email auth set-key <key> --default-from [email protected]).

Templates

elastic-email templates list            # sendable email templates
elastic-email templates list --all      # every type (landing pages etc.)
elastic-email templates get <name>      # metadata (--body prints the full body)
elastic-email templates create <name> --html-file <path>
                                        # create an HTML template ("-" reads stdin)
elastic-email templates create <name> --html "<h1>Hi</h1>" --subject <s>
elastic-email templates delete <name>   # asks for confirmation (--yes to skip)

Contacts & lists

elastic-email contacts list             # all contacts
elastic-email contacts get <email>
elastic-email contacts add <email> --first-name <n> --list <list>
elastic-email contacts add "[email protected],[email protected]" --list <list>
                                        # comma-separated batch
elastic-email contacts delete <email>   # asks for confirmation (--yes to skip)
elastic-email lists                     # your contact lists
elastic-email lists contacts <name>     # contacts that belong to a list
elastic-email lists create <name> --allow-unsubscribe
elastic-email lists delete <name>       # contacts are kept; asks for confirmation

Segments

elastic-email segments list             # segments with their rules
elastic-email segments contacts <name>  # contacts matching a segment

Suppressions

elastic-email suppressions list         # all suppressed addresses
elastic-email suppressions list --type bounces --search <text>
elastic-email suppressions add <email> --type unsubscribes
elastic-email suppressions delete <email>
                                        # allow sending again; asks for confirmation

Delivery events & verification

elastic-email events list               # recent sends, opens, clicks, bounces...
elastic-email events list --from 2026-06-01T00:00:00 --limit 50
elastic-email verify <email>            # deliverability check for one address
elastic-email verifications list        # past verification results

Domains & account

elastic-email domains list              # sender domains + SPF/DKIM/MX/DMARC status
elastic-email domains get <domain>
elastic-email account info              # account name, plan, limits, account-wide BCC
elastic-email account stats             # sending statistics (default: last 30 days)
elastic-email account stats --days 7

Pagination

Every list command (contacts list, templates list, segments list, events list, suppressions list, lists, ...) paginates the same way - fetch the next page by incrementing --page:

elastic-email contacts list --page 1 --page-size 50   # first page (default: page 1, 20 items)
elastic-email contacts list --page 2 --page-size 50   # next page
elastic-email templates list --page 3 --page-size 10

elastic-email contacts list --limit 10 --offset 20    # or raw limit/offset style

An empty result means you've paged past the last item. In interactive mode use ←/→ to switch pages.

Destructive commands

contacts delete, lists delete, templates delete, suppressions delete and auth clear ask before they act:

$ elastic-email contacts delete [email protected]
Delete contact [email protected]? This cannot be undone. [y/N]

Enter or n cancels, y proceeds. Pass --yes (or -y) to skip the question.

When there is no terminal to ask — CI, a pipe, or --json — the command refuses rather than guessing, and nothing is deleted:

$ elastic-email contacts delete [email protected]     # in CI
Error: Refusing to delete contact [email protected] without confirmation
       — not an interactive terminal. Pass --yes to confirm.

So automation has to state the intent explicitly:

elastic-email contacts delete [email protected] --yes

This also makes destructive steps greppable in a pipeline: every place that deletes something carries a visible --yes.

Exit codes

| Exit | error.code (JSON) | Meaning | | ---- | ----------------------- | ---------------------------------------------------- | | 0 | — | Success | | 1 | general | Unexpected error | | 2 | missing_api_key | No API key found | | 3 | invalid_input | Invalid input: bad email, missing field, unknown flag | | 4 | api_error | Elastic Email API / network error | | 5 | confirmation_required | Destructive command blocked (no --yes, no terminal) | | 130| interrupted | Interrupted: Ctrl+C (at a prompt or while running) or SIGINT | | 143| terminated | Terminated by SIGTERM (e.g. a CI timeout) |

A destructive command refused for lack of confirmation exits 5, so automation can stop and escalate for human approval instead of treating it as bad input and retrying.

With --json, errors are printed to stdout in a fixed shape, and the process exits with the same code:

{
  "error": {
    "code": "confirmation_required",
    "exitCode": 5,
    "message": "Refusing to delete template \"Old\" without confirmation — not an interactive terminal. Pass --yes to confirm."
  }
}

code names are stable — branch on them rather than on message. A signal in --json mode also produces this body (interrupted / terminated), so stdout is never left empty.

Configuration via env

ELASTIC_EMAIL_API_KEY                   # API key (overridden only by --api-key)
ELASTIC_EMAIL_CLI_CONFIG_DIR            # config directory (default ~/.elastic-email-cli)

Shell autocomplete

elastic-email autocomplete              # install instructions
elastic-email autocomplete zsh          # or bash / fish

Contributing

npm install
./bin/dev.js --help                     # run from TypeScript source, no build needed
npm run dev -- <command>                # same via npm (the -- is required)
npm test

Architecture notes, project layout, and development gotchas live in CLAUDE.md. See CONTRIBUTING.md for how to report bugs and open pull requests, and please follow our Code of Conduct.

Issues & Feedback

Feel free to contact us if you encounter any issues with the library. Please leave comments, concerns and requests on the Issues page.

License

MIT