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

@millionsend/cli

v0.2.2

Published

Migrate an email account to MillionSend: contacts, segments, topics, templates, webhooks, domains and suppressions — read from the source provider, written to your MillionSend instance, re-run safe

Readme

@millionsend/cli

Moves an email account to MillionSend: contacts, segments, topics, properties, templates, webhooks, domains and suppressions. Reads from the source provider, writes to your MillionSend instance (Cloud or self-hosted), and is safe to run again — a second run right before cutover syncs what changed since the first.

npx @millionsend/cli migrate --from resend                    # interactive: connect, choose, plan, confirm, apply, summary
npx @millionsend/cli migrate plan --from resend --out plan.json   # read-only; exit 0 nothing to do, 2 changes, 1 error
npx @millionsend/cli migrate apply plan.json --yes
npx @millionsend/cli migrate status
npx @millionsend/cli migrate rollback                         # deletes only what the tool created

Node 18 or newer; no dependencies.

What moves

| Resource | How | | --- | --- | | Contacts | Upserted by email through the batch endpoint; unsubscribed and topic opt-outs are preserved, never re-subscribed. Topic subscriptions and properties follow in two per-contact passes that run after everything else, so the account is sendable before they finish. | | Segments, topics, properties | Matched by name / name / key: created when missing, updated when different, left alone when equal. Segment memberships follow the contacts. | | Templates | Name, alias, subject, html, text. From, reply-to and variables cannot be stored — listed as manual steps. | | Webhooks | Endpoint and events. Signing secrets are copied so receivers keep verifying (--fresh-webhook-secrets mints new ones, shown once). Events MillionSend also emits carry over (email.*, contact.created, contact.updated, contact.deleted); the rest are dropped per webhook and listed. | | Suppressions | Bounces, complaints and manual entries, with their origin. | | Domains | Created with return path and tracking settings, in the one SES region your MillionSend instance serves (MillionSend Cloud: sa-east-1) — the Resend region does not carry over. DNS records must be added again (DKIM keys are per provider); the report prints a copy-ready table. Both providers can stay verified side by side. | | Broadcasts | Drafts and scheduled ones import as drafts; sent ones are skipped unless --include-sent. | | API keys | Not recreated (the source only exposes names); the report lists them as a to-do. |

Audiences (deprecated in Resend) are skipped — segments cover them.

Environment

| Variable | Meaning | | --- | --- | | RESEND_API_KEY | Source key (full access; the tool only ever reads). Alternatives: --from-key-stdin, or a masked prompt in a terminal. | | MILLIONSEND_API_KEY | MillionSend key (full access). Alternatives: --to-key-stdin, or a masked prompt. | | MILLIONSEND_BASE_URL | API URL of a self-hosted MillionSend instance. Same as --to-url. Unset, the target is MillionSend Cloud (https://api.millionsend.com), like the SDKs; a terminal asks. | | NO_COLOR | Disables ANSI colors. | | DO_NOT_TRACK | Honored as a no-op: the tool sends no telemetry, never phones home and never checks for updates. |

Flags

millionsend --help lists every flag. The ones that change what happens:

  • --only a,b / --skip a,b — resource names: domains, properties, topics, segments, contacts, enrichment, broadcasts, templates, webhooks, suppressions, api-keys. enrichment is the per-contact pass (topic subscriptions, then properties) that runs last.
  • --rps N — requests per second against the source (default 8). Resend's team limit is 10, shared with your production sending; the CLI prints the limit it detects and warns above it. Go past 10 (up to 100) only after Resend raised your limit.
  • --on-conflict upsert|skip|error — contacts that already exist on the target (default upsert).
  • --include-sent, --fresh-webhook-secrets, --fresh (ignore the state file).
  • --yes, --non-interactive (automatic when stdin is not a terminal), --json (JSON on stdout, progress on stderr), --verbose, --color auto|always|never (--no-color = never).

Exit codes: 0 ok · 1 error · 2 plan has changes (plan only) · 3 partial, some items failed (details in the report).

Files

.millionsend/migrate-state.json (every id created, resume cursors, the plan hash) and .millionsend/migrate-report.{json,md} are written next to where you run the tool, mode 0600. .millionsend/ is appended to .gitignore when one exists there. No file ever contains a key.

Security

Your Resend key never leaves your machine — the tool only ever contacts api.resend.com and your MillionSend API. Against Resend it sends GET requests only, to documented endpoints. Keys live in memory for the duration of the run: they are never written to a file and are redacted from every log line. There is no telemetry, no update check, no third party.

Re-running and rolling back

Every run is a diff: existing rows are updated when they differ and left alone when they match. Run millionsend migrate --from resend again right before cutover to sync the contacts that arrived in between.

millionsend migrate rollback deletes only the ids the tool created (never rows it merely updated), in reverse dependency order, after showing the list and asking for confirmation.


Resend is a trademark of Plus Five Five, Inc. MillionSend is not affiliated with or endorsed by Resend.