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

@distribute.you/cli

v0.2.0

Published

Command line interface for the distribute.you API

Readme

distribute.you CLI

Drive the distribute.you API from a shell. Authenticate once, then read and change the things the product is made of: brands, campaigns, leads, audiences, workflows, runs and billing. Anything the API can do, the CLI can send, so scripting the product does not mean writing an HTTP client first.

Results are JSON on stdout, failures are JSON on stderr, and the exit code says which kind of failure it was. The first reader of this tool is an agent, so that shape comes before pretty output.

Install

npx @distribute.you/cli --help          # no install
npm install -g @distribute.you/cli      # or keep it around as `distribute`

Then point it at your account once:

distribute auth login

The key is the one you create in the dashboard. It carries your organisation and user identity, so nothing else needs configuring.

No account yet? No human needed

An agent opens its own account with an email it can read and a phone number:

distribute signup --email [email protected] --phone +14155550100
# read the 6-digit code in that inbox, then:
distribute signup verify --email [email protected] --code 123456

signup verify stores a new API key and prints it (the MCP server takes the same key). Run it again for another key: there is no limit.

Free calls work right away. Every paid call is paid upfront, with automatic top-up so the work never stops:

distribute prepay --amount 10 --reload 15 --below 5   # dollars: min $10, reload min $15, under $5 or more
distribute prepay status

prepay returns a payment url: open it, or give it to your human. Until it is paid, a paid call exits 8 with payment_required and the same instructions. No free credit, no trial.

Authenticating

Create an API key in the distribute.you dashboard, then hand it over once:

echo "$MY_KEY" | distribute auth login
distribute auth status

The key is written to ~/.config/distribute/config.json, readable by its owner only. A key is read from --key first, then DISTRIBUTE_API_KEY, then that file, so CI can pass one through the environment and never write it to disk. auth status says which of the three answered, so a run that used the wrong key is diagnosable.

auth login calls the API before it stores anything. A key that does not work is refused here rather than three commands later.

Named commands

distribute whoami
distribute brands list
distribute campaigns list --brand "$BRAND_ID" --status active
distribute campaigns stats "$CAMPAIGN_ID"
distribute leads stats --brand "$BRAND_ID" --group-by campaignId
distribute leads list --brand "$BRAND_ID" --limit 50
distribute audiences list --brand "$BRAND_ID" --status active
distribute workflows list --feature sales-cold-email-outreach
distribute runs list --brand "$BRAND_ID" --status failed --limit 20
distribute billing balance

distribute help lists all of them.

Every other operation

The named commands cover the common ground. The rest of the API is one command away, and the list comes from the API itself rather than from anything committed here:

distribute ops --tag Campaigns
distribute ops --search audience
distribute describe POST /v1/orgs/audiences
distribute call POST /v1/orgs/audiences --body '{"brandId":"...","name":"Founders in Berlin"}'
distribute call GET /v1/leads --query brandId=... --query limit=10

call checks the method and path against the live description before sending anything, so a typo comes back as a typo instead of as a 404 from the gateway. --no-verify sends it regardless.

Bodies come from --body (inline JSON, @file, or - for stdin) or from repeated --data key=value pairs, which build a flat object. --data values are sent as the strings you typed: nothing here decides that true was meant as a boolean.

Destructive commands

Anything that deletes or stops asks first. With no terminal to ask in, which is how an agent runs it, the command refuses and names the flag that authorises it:

$ distribute audiences delete "$ID"
{"error":{"code":"confirmation_required","message":"... Re-run with --yes to authorise it.","exitCode":7}}
$ distribute audiences delete "$ID" --yes

Exit codes

| Code | Meaning | |------|---------| | 0 | It worked | | 1 | Something unexpected, with the message and the top of the stack | | 2 | The command line was wrong | | 3 | No key, or the API rejected the one sent | | 4 | The API answered 404 | | 5 | The API answered with another error status | | 6 | The request never reached the API | | 7 | A destructive command was not confirmed | | 8 | The call costs money and the balance is empty: run distribute prepay |

An API error carries the upstream body verbatim under error.details. The API writes its messages for people to read, and shortening them here would throw away the only explanation you get.

Flags

| Flag | What it does | |------|--------------| | --key <key> | Use this key instead of the stored one | | --api-url <url> | Point at a different API | | --query k=v | Add a query parameter, repeatable | | --header k=v | Add a request header, repeatable | | --body <json\|@file\|-> | Request body | | --data k=v | Build a flat JSON body, repeatable | | --include-status | Print the status and headers as well as the body | | --compact | One line of JSON instead of indented | | --yes | Confirm a destructive command up front | | --refresh | Refetch the API description instead of using the cached copy | | --timeout <ms> | Give up on a request after this long |

How it stays current

The command surface is read from GET /openapi.json on the API you are pointed at, cached for a day under ~/.config/distribute/, and refetched with --refresh. No copy of that document lives in this package. The API gains operations and renames them, and a snapshot baked in at build time would start lying the day after it shipped.

The named commands are the one hand written part, and tests/spec-conformance.test.ts reads the live document and fails if any of them names an operation that is not there.

MCP

Agents that speak MCP can use the server at https://mcp.distribute.you/mcp instead. It is the same product through a different door: MCP for an agent that discovers tools, this for a shell script or a CI job.

Developing

pnpm --filter @distribute.you/cli build      # bundle to dist/
pnpm --filter @distribute.you/cli test       # unit tests plus the live conformance check
pnpm --filter @distribute.you/cli typecheck

The CLI has no runtime dependencies. Installing it pulls one package and nothing else.