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

@dropthis/cli

v0.26.0

Published

Official CLI for Dropthis.

Readme

@dropthis/cli

Official CLI for dropthis -- the publish layer between AI and the internet. Built for humans, AI agents, and CI/CD pipelines.

Install

npm install -g @dropthis/cli

Requires Node.js >= 20.

Quick start

dropthis login
dropthis ./index.html         # publish is the default command

Authentication

Log in with email OTP:

dropthis login

The CLI prompts for your email and a one-time code. For non-interactive environments (agents, CI), use the two-step flow:

# Step 1: Request OTP
dropthis login request --email [email protected]

# Step 2: Verify OTP
dropthis login verify --email [email protected] --otp 123456

A failed verify prints Your code has expired (otp_expired) or That code is incorrect (otp_invalid) and exits non-zero.

Or pass both flags directly:

dropthis login --email [email protected] --otp 123456

Credentials resolve in this order:

  1. --api-key sk_... flag
  2. DROPTHIS_API_KEY environment variable
  3. Stored credential from dropthis login

If you run dropthis publish without credentials in an interactive terminal, the CLI prompts you to log in inline — no separate dropthis login step needed. Disable with --no-interactive.

dropthis whoami        # Check current auth status
dropthis logout        # Remove stored credentials
dropthis logout --revoke  # Remove and revoke the key on the server

Publish

publish is the default command — you can omit it and pass files directly:

# These are equivalent:
dropthis ./report.html
dropthis publish ./report.html
# HTML file
dropthis ./report.html

# Directory (static site)
dropthis ./dist

# Stdin
echo "<h1>Hello</h1>" | dropthis publish - --content-type text/html --path index.html

# Multiple files bundled into one drop
dropthis index.html styles.css app.js

# Print only the URL (recommended for agents)
dropthis ./dist --url

Publish options

dropthis publish ./dist \
  --title "Launch page" \
  --visibility unlisted \
  --entry index.html \
  --expires-at 2026-12-31T00:00:00Z

publish always creates a NEW drop with a new URL. To change a drop you already published, use update-content or update-settings with its drop_… id — never publish again.

Canonical vs raw URLs

Every drop has a canonical url — an always-branded human view (badge guaranteed). For a single non-HTML file (.pdf, .png, .json, a URL you asked the server to fetch, etc.), publish also prints a Raw: line: the file's exact bytes at a natural path, no wrapper. Hand the canonical url to people; hand the raw URL to agents or downstream tooling that needs the real bytes.

Publishing a bundle with remote assets (--manifest)

When an AI agent generates an HTML page that references external images or other files, use --manifest to publish everything as one drop without base64-encoding the assets. The server fetches remote files during publish so bytes never pass through your process.

dropthis publish --manifest bundle.json

bundle.json shape:

{
  "files": [
    {
      "path": "index.html",
      "content": "<html>...</html>"
    },
    {
      "path": "hero.jpg",
      "source_url": "https://cdn.example.com/hero.jpg"
    },
    {
      "path": "data.json",
      "content_base64": "eyJrZXkiOiJ2YWx1ZSJ9"
    }
  ]
}

Each file entry must have a path and exactly one content key:

| Key | Description | |-----|-------------| | content | UTF-8 text content (HTML, CSS, JSON, markdown, …) | | source_url | Public https:// URL — the server fetches the bytes server-side. Use this for images and other binary assets instead of base64-encoding them. | | content_base64 | Base64-encoded bytes (for binary files you already have in memory) |

Optional per-file keys: content_type (MIME type override).

The --manifest flag also works on update-content:

dropthis update-content drop_abc123 --manifest bundle-v2.json

Cannot be combined with a positional file/folder/URL argument.

All publish flags:

| Flag | Description | |------|-------------| | --title <title> | Drop title | | --visibility <public\|unlisted> | Drop visibility | | --password <password> | Require a password to view the drop (Pro plan) | | --noindex | Prevent search indexing | | --entry <path> | Entry file for directories | | --content-type <mime> | MIME type (required for stdin) | | --path <path> | Filename (required for stdin) | | --manifest <file> | Multi-file bundle JSON (see above) | | --expires-at <datetime> | Expiration datetime | | --metadata <json> | Metadata as JSON string | | --metadata-file <path> | Metadata from a JSON file | | --idempotency-key <key> | Idempotency key | | --url | Print only the URL, nothing else | | --json | Output full JSON response | | --dry-run | Validate without publishing |

Global flags

These flags are inherited by all commands:

| Flag | Description | |------|-------------| | --api-key <key> | Override API key for this invocation | | --api-url <url> | Override API base URL | | --json | Force JSON output | | -q, --quiet | Suppress status output and imply JSON | | --no-interactive | Disable interactive prompts (inline auth, confirmations) |

Update

Change an existing drop without creating a new URL. Content and settings are separate operations — pass the full drop_… id (not the slug):

# Replace the content at the same URL (ships a new deployment)
dropthis update-content drop_abc123 ./dist-v2

# Update from a manifest bundle (same --manifest format as publish)
dropthis update-content drop_abc123 --manifest bundle-v2.json

# Change settings only — title, visibility, password, expiry, metadata
dropthis update-settings drop_abc123 --title "New title"

# Optimistic concurrency (both accept --if-revision)
dropthis update-content drop_abc123 ./dist-v2 --if-revision 1

update-content replaces the files at the URL; update-settings changes title, visibility, password, noindex, expiry, or metadata. Creating a new drop is always publish — neither update command makes a new URL.

With --if-revision, a concurrent edit fails with a 409 instead of clobbering. The error shows the drop's current_revision and how to retry:

✗ Revision mismatch
  The drop changed since it was last read. Re-read it with GET /v1/drops/{drop_id} and retry with if_revision: 2 (sent as the If-Revision header).
  Current revision: 2 — retry with --if-revision 2

In JSON mode the same error carries current_revision and a next_action field.

Pull (read back)

Download what a drop is serving — by drop_… id, drop URL, or slug. URLs and slugs are resolved to your own drops; the local copy is also the rollback path (pull an old state, then update-content it back):

# By id, into ./drop_abc123/
dropthis pull drop_abc123

# By URL — resolves the slug to your drop, writes into ./abc123/
dropthis pull https://abc123.dropthis.app

# Choose the output directory
dropthis pull drop_abc123 -o ./site

Pull fetches the current deployment's file manifest and writes every file into the output directory. It is owner-side read-back via the API — it works regardless of any viewer password. Custom-domain URLs are not resolvable yet; use the drop_… id instead.

Commands

dropthis [input...]                          # Publish content (default command)
dropthis publish [input...]                  # Same as above, explicit form

dropthis update-content <drop-id> [input]    # Replace a drop's content (same URL)
dropthis update-settings <drop-id>           # Change title/visibility/password/expiry/metadata
dropthis pull <id|url|slug> [-o <dir>]       # Download a drop's files to a local directory
dropthis get <id|url|slug>                   # Show drop details
dropthis list                                # List your drops
dropthis list --domain reports.example.com   # Only drops on a custom domain
dropthis delete <id|url|slug>                # Delete a drop (--yes to confirm)

dropthis deployments                         # View deployment history

dropthis login                               # Authenticate with email OTP
dropthis login request --email <email>       # Request OTP (non-interactive)
dropthis login verify --email <email> --otp <code>   # Verify OTP
dropthis logout                              # Remove stored credentials
dropthis whoami                              # Show current auth status

dropthis account                             # Show account details
dropthis account update --display-name <name>  # Update your display name

dropthis api-keys create                     # Create an API key
dropthis api-keys list                       # List API keys
dropthis api-keys delete <key-id>            # Delete an API key (--yes to confirm)

dropthis upgrade                             # Update the CLI to the latest version
dropthis doctor                              # CLI diagnostics
dropthis commands                            # Machine-readable command metadata

Agent & CI/CD usage

The CLI is designed for non-interactive use. In non-TTY environments (pipes, CI, agents), output defaults to JSON automatically.

Environment variables:

export DROPTHIS_API_KEY=sk_live_...    # API key (same as --api-key)
export DROPTHIS_API_URL=https://...    # Override API base URL (same as --api-url)
export DROPTHIS_NON_INTERACTIVE=1      # Disable interactive prompts (same as --no-interactive)
export DROPTHIS_NO_UPDATE_NOTIFIER=1   # Disable the startup update notice (also auto-disabled in CI, non-TTY, --json/--quiet)
dropthis publish ./dist --url

Agent protocol:

  • Use --url to get only the published URL (cleanest for agents)
  • Use --json for the full structured response
  • Use --yes for destructive commands (delete, api-keys delete, account delete)
  • Use --no-interactive to disable inline auth prompts
  • All errors write to stderr as JSON with a next_action field

Exit codes:

| Code | Meaning | |------|---------| | 0 | Success | | 1 | API or generic error | | 2 | Invalid usage | | 3 | Auth required (no credential, or the API returned 401 — re-authenticate) | | 4 | Local input error (file or directory not found, too many files) | | 5 | Network error (could not reach the API) | | 6 | Domain verification pending (domains verify one-shot, not live yet) | | 7 | Domain verification timeout (domains verify --wait exceeded --timeout) |

JSON output shape:

{"ok":true,"drop":{"url":"https://dropthis.app/abc123","id":"drop_abc123"}}

Error shape (stderr):

{"ok":false,"error":{"code":"auth_error","message":"No API key found.","next_action":"Set DROPTHIS_API_KEY or run dropthis login."}}

Doctor

Run diagnostics to verify CLI health:

dropthis doctor

Reports CLI version, auth source (env, flag, storage, or missing), and credential storage backend (secure, insecure, or none).

{"ok":true,"version":"0.4.1","auth":{"source":"env"},"storage":{"backend":"secure"}}

Pricing tiers

  • Free — drops expire after 7 days, 5 MB per drop, 500 MB active storage, dropthis badge.
  • Pro — drops never expire, 100 MB per drop, 10 GB storage, no badge, 1 custom domain, password-protected drops. Pro is currently invite-only. Learn more at https://dropthis.app/pricing.

Connecting a custom domain (dropthis domains connect) requires the Pro plan (1 hostname). Domains already connected keep working regardless of plan.

dropthis account shows your active tier, its limits, and the workspace your key is bound to. If the workspace kind is team, your publishes land under the team's shared custom domain automatically — no extra flags needed.

Agent skills

For AI coding agents (Cursor, Claude Code, Windsurf, etc.), install the dropthis-skills package:

npx skills add dropthis-dev/dropthis-skills

Links