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

ninepm

v0.30.0

Published

CLI for deploying built apps to 9pm.ai.

Readme

9pm.ai CLI

CLI for deploying built applications to 9pm.ai.

This package contains only client-side deploy code. It does not include the 9pm.ai control plane, infrastructure provisioning code, migrations, staging config, operator tokens, or smoke-test scripts.

Install

npm i -g ninepm        # persistent `9pm` binary
npx ninepm <args>      # run without installing

Configure

Authenticate in your own browser. The CLI stores the token in native protected storage: macOS Keychain, Windows DPAPI, or Linux Secret Service when available. If native storage is unavailable, plaintext file storage is opt-in with --allow-file-credential-store or NINEPM_ALLOW_FILE_CREDENTIAL_STORE=1.

9pm login
9pm whoami
9pm doctor

For CI, set NINEPM_API_KEY yourself in the CI secret store. --token and NINEPM_API_KEY still override the stored login token.

Inventory

List the apps you have on 9pm.ai before deploying or modifying:

9pm apps
9pm apps --json

The slug column is the handle you pass to access, delete, and files --project.

Versioning

Check installed vs published CLI version:

9pm --version       # installed
9pm latest          # installed vs latest, prints update one-liner when behind
9pm doctor          # surfaces the same drift line alongside credential/account health

Upgrade:

npm i -g ninepm@latest

Deploy

Deploy a static directory:

9pm deploy . --name my-app --slug my-app

Deploy a built framework output directory:

npm run build
9pm deploy ./dist --check
9pm deploy ./dist --name my-app --slug my-app

Deploy with a managed SQL database:

9pm deploy ./dist --name my-app --slug my-app --with-db

Attach an optional short description to the deploy (shown next to the version in the dashboard; up to 200 characters):

9pm deploy ./dist --name my-app --slug my-app --description "Fix login redirect"

The CLI prints the public app URL after upload and finalization.

Store and share working files:

9pm files put ./report.pdf
9pm files share <file-id> --expires 24h
9pm files put ./notes.md --project my-app --path notes/release.md
9pm files share <file-id> --project my-app --login-required

Personal files and project files both count toward the account file storage limit. Share links expire and are capped at 7 days. Login-required links are owner-only.

Deploy a first-class Worker runtime app:

9pm deploy ./examples/worker-app --name worker-app --slug worker-app --runtime worker --entry src/index.js --with-db

The --runtime worker entry must be a bundled fetch-compatible JavaScript module with a default export. With --with-db, the app receives env.DB and should use SQLite-compatible prepared statements.

Deploy a container app from a local Docker build:

9pm deploy . --check --runtime container --port 8080
9pm deploy . --name container-app --slug container-app --runtime container --port 8080 --health-path /health --region auto

Container deploys require Docker locally. The CLI builds a linux/amd64 image, exports it, checks image size against the per-app limit and account retained-image quota, uploads through a short-lived session, and finalizes a queued deployment. The container must listen on 0.0.0.0:$PORT or the selected --port; set --health-path when the app has a cheap readiness endpoint.

Use --with-db when the container needs managed SQL. The app receives NINEPM_SQL_URL and NINEPM_DB_BINDINGS; send POST requests to NINEPM_SQL_URL with { "binding": "DB", "sql": "SELECT 1", "params": [] }. For local development, use the app's normal local database adapter behind a repository layer and keep deployed SQL compatible with SQLite.

Regions are provider-neutral: auto, us-east, us-west, europe, asia, south-america, middle-east, oceania, africa.

When a container app fails to come up or you want to investigate it after the fact, retrieve its recent logs:

9pm logs my-app                # recent container logs + the failure reason, if any
9pm logs my-app --lines 50     # last N lines
9pm logs my-app --json         # machine-readable

9pm logs reports the latest container deployment's status, health, the failure reason, and the captured startup output when a deploy failed to come up. It is read-only and does not affect deploys.

Delete an app, its managed database, managed container app, and retained image:

9pm delete my-app --confirm my-app

Access Modes

Apps are public by default.

One-time PIN with email/domain allowlist:

9pm access allow email my-app [email protected]
9pm access allow domain my-app example.com
9pm access otp my-app
9pm access revoke email my-app [email protected]
9pm access revoke domain my-app example.com

Identity provider access:

9pm access idp my-app --provider google

Machine access:

9pm access service create my-app --name backend

Return to public:

9pm access public my-app

Create an app-scoped runtime token for server-side allowlist management:

9pm access token create my-app --name production-app-server

Use 9pm_app_... runtime tokens only from server-side code. They can list, add, and remove email/domain grants for one app. They cannot deploy, create databases, create API keys, or manage another app. Service token secrets returned by access service create are also server-side secrets.

Commands

9pm --version
9pm deploy [directory] --name <name> [--slug <slug>] [--with-db]
9pm deploy [directory] --check [--runtime worker --entry <path>]
9pm deploy [directory] --runtime container --port 8080 [--health-path /health] [--region auto] [--with-db]
9pm signup
9pm login
9pm logout
9pm doctor [--json]
9pm whoami
9pm apps [--json]
9pm latest [--json]
9pm files list [--project <site>]
9pm files put <local-path> [--path <remote-path>] [--project <site>]
9pm files get <file-id> [--output <path>] [--project <site>]
9pm files share <file-id> [--expires 24h] [--login-required] [--project <site>]
9pm files delete <file-id> [--project <site>]
9pm deploy [directory] --runtime worker --entry <path> [--with-db]
9pm delete <site> --confirm <slug>
9pm access show <site>
9pm access public <site>
9pm access otp <site>
9pm access idp <site> [--provider google|github|entra]
9pm access allow email <site> <email>
9pm access allow domain <site> <domain>
9pm access revoke email <site> <email>
9pm access revoke domain <site> <domain>
9pm access service create <site> [--name <name>] [--duration 8760h]
9pm access service revoke <site> <service-token-id>
9pm access token create <site> [--name <name>]
9pm access token revoke <site> <token-id>

Options:

  • --api-url <url> overrides NINEPM_API_URL
  • --token <key> overrides NINEPM_API_KEY
  • --allow-file-credential-store permits plaintext fallback storage for login and signup when native protected storage is unavailable
  • --name <name> sets the app display name
  • --slug <slug> sets the URL-safe app slug
  • --with-db requests managed storage for the app
  • --database-name <name> customizes the requested database name
  • --binding <name> customizes the database binding name
  • --environment <name> sets deployment environment metadata
  • --runtime <static|worker|container> selects static asset hosting, app-owned Worker code, or local Docker container deployment
  • --entry <path> selects the Worker runtime server entry file
  • --port <port> selects the HTTP port exposed by a container app
  • --health-path <path> optionally lets 9pm.ai check container health before marking it healthy
  • --region <region> optionally selects provider-neutral container placement
  • --project <site> scopes file commands to an app
  • --path <remote-path> stores a file at a specific path
  • --output <path> writes a downloaded file to disk
  • --expires <duration> sets public share-link expiry, capped at 7 days
  • --login-required creates an owner-only share link
  • --confirm <slug> confirms app deletion by requiring the slug
  • --provider <google|github|entra> selects a configured identity provider
  • --duration <duration> sets a service token duration

Access command options:

  • --api-url <url> overrides NINEPM_API_URL
  • --token <key> overrides NINEPM_API_KEY
  • --name <name> names an app-scoped runtime token
  • --expires-at <iso-date> optionally expires an app-scoped runtime token