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

@postinger/cli

v0.2.1

Published

Postinger command-line interface

Readme

@postinger/cli

Postinger command-line interface. Node.js >=24.15.0 required. Install with npm install -g @postinger/cli, or use the local build below.

Release archives can be prepared with pnpm pack:cli and tested outside the repository with pnpm test:package. The release includes @postinger/api-client, the CLI executable and skills/postinger/SKILL.md. See release instructions. The session login described here requires CLI 0.2.0 and the matching backend deployment.

The default cloud API is https://api.postinger.dev. After installation, postinger auth login needs no URL flag for this server. A saved custom server remains the default for that saved login; use --api-url or POSTINGER_API_URL to choose another server explicitly.

To replace an earlier development login with a production login, run postinger --api-url https://api.postinger.dev auth login. Updating the CLI preserves the server URL of existing saved credentials.

Get started

From the repository root, with your backend and frontend already running:

pnpm install --frozen-lockfile
pnpm build:tools
export POSTINGER_API_URL=http://localhost:8080
pnpm cli auth login
pnpm cli accounts list
pnpm cli upload ./photo.jpg
pnpm cli posts create --content "Hello" --account ACCOUNT_ID --media MEDIA_ID

auth login opens a browser and prints a matching code. Sign in, check the code, choose a project if needed, then click Connect. CLI and MCP use the same consent layout. A single project is shown by name; multiple projects get a switcher. The device is named automatically (for example, Postinger CLI · MacBook-Pro). --name "Work laptop" overrides it. Only project admins can authorize access. Login requests expire after ten minutes; --no-browser prints the link without opening it.

Browser login creates a device session managed in Project settings → Connected apps, alongside MCP connections. It grants account/analytics reads, media uploads and post reads/creation/editing/publishing; deleting posts is excluded. Access tokens last at most one hour and are renewed automatically within a session lasting at most 90 days. Disconnect immediately invalidates both access and renewal. For a different permission set or expiry, create an API key in API keys and use auth login --key-stdin.

The device receives an access token and a refresh secret; the backing API key never leaves the backend. Tokens are delivered only to the initiating CLI, saved before final confirmation, and never printed. If confirmation is interrupted, run auth login again promptly to finish. Unconfirmed connections are revoked after the ten-minute login window. Normal login/status output shows the project and server; --json retains diagnostic metadata.

Deploy 20260925190000_cli_sessions.sql before the new backend and CLI. CLI 0.1.0 continues to receive keys from the legacy login protocol. Existing stored API keys continue to work. Old CLI keys are moved to Connected apps only when their origin can still be proved from a retained login request; older keys whose requests were already cleaned up remain under API keys. Signing in again with CLI 0.2.0 creates a device session; remove any superseded old connection/key in its existing dashboard location. Downgrading the CLI after a session login requires signing in again with that version.

Backend setup requires the CLI authorization migration, configured Unkey key creation, and TOKEN_ENCRYPTION_KEY. The approval link uses CLI_AUTH_APP_URL when set, otherwise APP_URL. For local use set CLI_AUTH_APP_URL=http://localhost:3000 in the backend environment; that frontend's NEXT_PUBLIC_API_URL must point to the same backend the CLI uses. Production should use its deployed frontend URL. Deploy the migration before the backend. No services are started by CLI login.

API key login and automation

An existing customer key works without browser approval:

export POSTINGER_API_URL=http://localhost:8080
# Obtain POSTINGER_API_KEY from your project's API keys page.
printf '%s' "$POSTINGER_API_KEY" | node packages/cli/dist/bin.js auth login --key-stdin
node packages/cli/dist/bin.js auth status
node packages/cli/dist/bin.js auth logout

Alternatively, set POSTINGER_API_KEY and skip login entirely. Never use a provider/root key. POSTINGER_API_KEY overrides saved credentials; the CLI warns about this during login. The API URL comes from --api-url, POSTINGER_API_URL, or the saved URL. A saved key cannot silently be sent to a different URL.

Credentials are written atomically to $XDG_CONFIG_HOME/postinger/config.json or ~/.config/postinger/config.json, with mode 0600. This is an owner-readable plaintext file, not keychain storage. auth status verifies the key against the server and reports its project, expiry and effective permissions without requiring account-read access. For browser device sessions, auth logout revokes that device on the server before deleting the file. If the server cannot confirm revocation, credentials are retained so logout can be retried. auth logout --local deliberately removes only the local file (also useful for corrupt config recovery); disconnect remotely in Connected apps if needed. For manually supplied or legacy API keys, logout removes the local file without revoking the key. Environment variables are never cleared.

doctor checks the Node.js runtime, installed CLI version, API/authentication and effective permissions. Failures include a suggested remedy; doctor --json returns {ok, checks, project?, expiresAt?} and exits 1 on failure. It does not look up the latest npm version or change your configuration. Session checks require a backend that supports /public/v1/auth/session; older servers are reported as incompatible instead of falsely verified.

When POSTINGER_API_KEY is set without a URL, it uses the default cloud API and ignores the saved credential file. Pair it with POSTINGER_API_URL for a custom server.

Using the same login with MCP

For hosted MCP, connect to the backend /mcp URL and approve access in your browser; no CLI login is needed. See remote setup.

The local @postinger/mcp server can read this saved login when launched as the same OS user (and with the same XDG_CONFIG_HOME, if customized). No key needs to be copied into the host configuration. Restart the MCP server after changing login/project or logging out; running servers retain the device/project loaded at startup, while renewing its access token as needed. Disconnecting that device also stops access from stdio MCP processes sharing it. Explicit environment keys still take priority. See the MCP setup, including optional local media uploads.

Output

Default output uses readable tables for lists and labeled fields for details. Upload progress and login instructions go to stderr. --json emits one JSON result on stdout with no progress text mixed into it. API commands preserve the full {data, meta} envelope and any generated idempotency key. Local auth commands return their own status object, never credentials.

node packages/cli/dist/bin.js accounts list --json
node packages/cli/dist/bin.js upload ./photo.jpg --json
node packages/cli/dist/bin.js analytics report --from 2026-09-01 --to 2026-09-24 --json

pnpm cli is a repository convenience command. For scripts that need stdout containing only JSON, run node packages/cli/dist/bin.js directly, without a package-manager wrapper. Errors go to stderr; with --json they have { error: { code, message, ... } }. Exit code 0 means success, 2 invalid command/input, 1 API/configuration/transport failure. Scripts parsing the previous default JSON output should add --json and read data.

Media upload

upload FILE (also media upload FILE) handles JPEG/PNG up to 8 MB and MP4/MOV up to 1 GB. It reserves an upload, transfers bytes directly to storage, and completes backend validation. Large videos use three concurrent multipart transfers. The API key is never sent to storage. Bytes are streamed from disk; videos are not loaded fully into memory. The backend validates the actual file contents.

The result includes the ready media id and url. Pass the ID to posts create --media ID; creating a post defaults to a draft. No content is published by upload or draft creation. Publishing needs posts-publish and explicit posts publish ID --yes.

Transient storage transfers and idempotent upload steps are retried with bounded backoff; API rate limits can pause a large upload. An uncertain upload creation is not automatically retried. On failure the CLI reports the media ID. If all bytes arrived, retry media complete ID; for multipart uploads, first inspect media multipart ID --operation list, then complete multipart when all parts exist. Interrupted transfers are not automatically resumed; start another upload or use the low-level commands. Cancel an unfinished multipart reservation with media multipart ID --operation abort.

Commands

  • auth login [--no-browser] [--name TEXT] or auth login --key-stdin
  • auth status, auth logout [--local]
  • doctor [--json]
  • accounts list
  • accounts capabilities ACCOUNT_ID — current publishing limits, option schema, media requirements and account availability; requires accounts-read
  • upload FILE, media upload FILE
  • posts list [--limit 25] [--after UUID] [--status draft] [--platform instagram] [--q text]
  • posts get ID
  • posts create --content TEXT [--account UUID ...] [--media UUID ...] [--scheduled-at ISO] [--idempotency-key KEY]
  • posts create --file post.json (or --file - for stdin). Cannot combine with individual post fields.
  • posts update ID --file patch.json (or stdin). Only provided fields change.
  • posts publish ID --yes [--account-id UUID] [--idempotency-key KEY]
  • posts delete ID --yes
  • media create-upload --filename image.jpg --content-type image/jpeg --size-bytes 1024
  • media get ID, media complete ID
  • media multipart ID --operation list|sign|complete|abort [--part-number N]
  • analytics capabilities
  • analytics report --from YYYY-MM-DD --to YYYY-MM-DD [--account-id UUID] [--platform instagram]
  • analytics account ID --from YYYY-MM-DD --to YYYY-MM-DD
  • analytics posts [--days 30] [--from DATE --to DATE] [--limit 25] [--cursor VALUE] [--account-id UUID] [--platform instagram]
  • analytics history POST_ID ACCOUNT_ID

Use --help on any command. Publish success means accepted by the backend; poll posts get for the final outcome. Analytics reads stored measurements only. Reuse an idempotency key only for retries of the same logical create/publish operation; change it for a new operation. Other mutations are not automatically retried after uncertain failures.