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

stormgtm

v0.6.0

Published

StormGTM CLI (stormgtm, sgtm) and typed client — qualify leads with Barometer before you send. MIT; source: https://github.com/marginsystems/stormgtm-cli

Readme

stormgtm

CLI and typed client for StormGTM. Barometer reviews an email lead before you send: give it an address plus whatever you know about the person, and get a verdict (deliverable, risky, undeliverable, unknown), a 0-100 score and plain-language reasons. Send the leads that pass from your own connected mailboxes.

Requires Node.js 22+.

Install

npm install -g stormgtm
stormgtm login
# the short alias runs the same binary:
sgtm whoami

Or the installer, which checks Node 22+ and runs npm install -g stormgtm:

curl -fsSL https://stormgtm.com/install.sh | bash

Add -s -- --mcp to also install the MCP server for agents.

Sign in

stormgtm login          # opens your browser, confirm the code, done
stormgtm login --key    # paste an sgtm_live_... key (input is hidden)
stormgtm whoami         # email, credits, key prefix, API URL (alias: status)
stormgtm logout         # remove the stored key
stormgtm keys           # open the API keys page in the dashboard
stormgtm config         # where the key and API URL come from
stormgtm config set api-url http://localhost:8787   # or: config unset api-url

The key is stored in ~/.stormgtm/config.json (mode 0600) as { "apiKey": "...", "apiUrl": "..." }. Environment variables win over the file:

| Variable | Meaning | | --- | --- | | STORMGTM_API_KEY | API key (sgtm_live_...) | | STORMGTM_API_URL | API base URL (default https://stormgtm.com) |

Commands

stormgtm check [email protected] --name "Jane Doe" --company Acme
stormgtm check [email protected] --deep --json
stormgtm batch leads.csv --wait
stormgtm batch-status <batch-id>
stormgtm outcome [email protected] bounced --detail "550 no such user"   # free; works for email sent by any means
stormgtm send --mailbox <mailbox-id> --to [email protected] --subject "Hello" --text "Hi Jane"
stormgtm send --from [email protected] --to [email protected] --subject "Hello" --text "Hi Jane"
stormgtm mailboxes
stormgtm mailbox-test <mailbox-id>
stormgtm mailbox-domains
stormgtm domains
stormgtm domain-health <domain-id>
stormgtm emails
stormgtm sequences
stormgtm sequence <sequence-id>
stormgtm enroll <sequence-id> leads.csv
stormgtm inbox --unread
stormgtm inbox --folder sent --search pricing
stormgtm thread <thread-id> --full
stormgtm reply <thread-id> --text "Thanks, here is the pricing."
echo "Thanks!" | stormgtm reply <thread-id>
stormgtm read <thread-id> <thread-id>
stormgtm unread <thread-id>
stormgtm archive <thread-id>
stormgtm unarchive <thread-id>
stormgtm spam <thread-id>
stormgtm unspam <thread-id>
stormgtm counts
stormgtm me

Radar (beta) finds people to email from a website or a description of your ideal customer:

stormgtm radar acme.io                       # progress on stderr, one lead per line on stdout, then a summary
stormgtm radar "CTOs at seed-stage dev tools startups" --chat <chat-id> --json
stormgtm leads [--chat <chat-id>]            # leads Radar saved, with verdicts once qualified
stormgtm leads --csv > leads.csv             # the same leads as a CSV file, free
stormgtm leads --after 0 --json              # only leads after a cursor, oldest first, as { leads, nextAfter }; pass nextAfter next time
stormgtm qualify-leads <lead-id> <lead-id> [--deep]
stormgtm add-leads leads.csv                 # your own leads, free; CSV with email plus name, title, company, notes

radar costs 1 credit per new lead. Leads you add with add-leads and searches that find nobody are free. A search needs at least 1 credit to start and stops when credits run out. radar exits 2 when it finds nobody. A search can take a minute or two. Qualify the leads before you send to them.

leads --csv prints name, email, title, company, company site, source URL, note, verdict and found date. Exporting is free. Cells that start with =, +, - or @ get a leading ' so a spreadsheet does not run them as formulas.

send goes out from a connected mailbox: pass --mailbox <id>, or --from with the mailbox address. Set each domain's unsubscribe host in the dashboard first; mailbox-domains shows where each one stands.

reply answers an existing thread only, goes to the thread's participant and costs 1 credit. In a terminal it asks before sending; pass --yes to skip the question.

check exits 2 when the lead is undeliverable, so it drops into shell pipelines.

| Exit code | Meaning | | --- | --- | | 0 | Success | | 1 | Error (API or network) | | 2 | Lead undeliverable, nothing was sent or enrolled, or Radar found no leads | | 3 | Usage error | | 4 | Not enough credits | | 6 | Not logged in, or the API key was rejected | | 7 | Rate limited | Add --json to any command for machine-readable output. CSV files for batch need an email column; name, company, companyDomain, title, githubLogin and other context columns are passed along.

Agent skills

stormgtm skill install --claude
stormgtm skill install --cursor --agents --json

Writes the stormgtm-gtm and stormgtm-send skills into .claude/skills/, .cursor/skills/ and/or .agents/skills/ of the current project (the git toplevel, else the current directory). Existing copies are overwritten; the command refuses to write through symlinks.

Library

import { StormGTM, clientFromEnv } from "stormgtm";

const stormgtm = clientFromEnv();
const result = await stormgtm.check({ email: "[email protected]", context: { company: "Acme" } });
if (result.verdict === "deliverable" && result.policy.allowed) {
  await stormgtm.send({ from: "Ada <[email protected]>", to: "[email protected]", subject: "Hello", text: "Hi Jane" });
}
await stormgtm.reportOutcome({ email: "[email protected]", kind: "delivered" });

clientFromEnv() reads the environment, then ~/.stormgtm/config.json.

Inbox:

const { threads, nextCursor } = await stormgtm.threads({ folder: "inbox", unread: true, q: "pricing" });
const thread = await stormgtm.thread(threads[0].id);
await stormgtm.reply(thread.id, { text: "Thanks, here is the pricing.", idempotencyKey: `reply-${thread.id}` });
await stormgtm.markRead([thread.id]);
await stormgtm.archiveThreads([thread.id]);
await stormgtm.spamThreads([thread.id]);
const counts = await stormgtm.inboxCounts();

Radar:

const { chatId, answer, leads } = await stormgtm.findLeads({
  content: "acme.io",
  onEvent: (event) => {
    if (event.type === "tool" && event.phase === "start") console.error(event.summary);
  },
});
const { leads: checked } = await stormgtm.qualifyRadarLeads(leads.map((lead) => lead.id));
const deliverable = checked.filter((lead) => lead.verdict === "deliverable");

findLeads creates a chat unless you pass chatId, streams the search and resolves when it finishes. It throws StormGTMError on an API error (for example insufficient_credits) or when the search fails. radarChats, createRadarChat, radarMessages, radarLeads, radarLeadsAfter (only leads after a cursor), deleteRadarLead and cancelRadarChat cover the rest of the Radar API.

MCP server

See stormgtm-mcp: claude mcp add stormgtm -- npx -y stormgtm-mcp.

Source

Public source (MIT): github.com/marginsystems/stormgtm-cli. Tags match npm versions.

git clone https://github.com/marginsystems/stormgtm-cli.git
cd stormgtm-cli
npm install
npm run build
node dist/cli.js --help