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

@zorinto/dropvi-cli

v0.6.0

Published

Send, fetch, list and revoke Dropvi transfers from the command line

Readme

@zorinto/dropvi-cli

Send, fetch, list and revoke Dropvi transfers from the command line. Built for people at a terminal and for agents running headless. No runtime dependencies; Node 22.2 or later.

Every transfer dropvi send creates is end-to-end encrypted (format e2e-v1): the contents, names, types, title, message and sender name are all encrypted before upload, with the key held only in the share link, never stored on the server. Dropvi still sees the file count and sizes, the recipient email addresses passed to --to, the expiry and download limit, and, for a protected transfer, the PIN itself, which the server checks before issuing a download token. Nothing here claims the metadata above is hidden, or that this is "zero knowledge": it means only that file contents, names, types and the sender's text are unreadable without the key.

pnpm add -g @zorinto/dropvi-cli      # or: pnpm dlx @zorinto/dropvi-cli <command>
dropvi login                 # once; sending needs a free account (or set DROPVI_TOKEN)
dropvi send report.pdf       # prints the share URL

Commands

dropvi login                       Interactive only. Opens dropvi.com/cli/login to approve, stores the token.
dropvi send <path...>              Create a transfer and upload. Prints the share URL.
dropvi send --resume <id>          Continue an interrupted send. Takes no paths.
dropvi get <id|url> [-o DIR]       Download every file in a transfer.
dropvi list                        The signed-in account's transfers (the 50 most recent).
dropvi rm <id|url>                 Revoke a transfer and delete its files. Never prompts.
dropvi logout                      Revoke this CLI's own token and forget it.

Global options: --json, --quiet, --no-input, --api <url>, --help, --version (or -V, -v). --dry-run is available on send and rm, the two commands that change something; it makes no network call and redacts the PIN and tokens. On send, the printed request body is the encrypted one the server would actually receive (ciphertext file sizes, encryptedMeta, keySalt and, for a protected transfer, pinSalt), with the PIN itself redacted; part geometry follows the ciphertext size, which is larger than the plaintext.

Anywhere an id is accepted, a full share URL on dropvi.com or a branded subdomain works too.

dropvi --help --json and dropvi <command> --help --json print a manifest of every command and flag, with types and which flags are secrets, so an agent can check an invocation before running it.

send

--to <email> (repeatable, or several addresses separated by commas, up to 50), --title, --message, --from-name, --expiry-days <n>, --max-downloads <n>, --password-stdin, --password-file <path>, --password <pin>, --resume <id>, --dry-run.

  • A directory is sent with its folders, as a browser sends a chosen folder: dropvi send Photos sends every file under Photos, each in its folder starting with Photos. The folders are sealed into the encrypted metadata, so Dropvi cannot read them. A symbolic link to a directory, or to a file outside the directory being sent, is refused, and so is a folder more than 16 deep, longer than 255 characters, or with a name another computer cannot recreate (such as CON, a name ending in a dot or a space, or one with a colon, a backslash or a question mark in it).
  • dropvi send needs a signed-in account (dropvi login, or DROPVI_TOKEN). Signed out, it exits 3 (not_authenticated) before reading any file or making any request, --dry-run included. Dropvi accepts a send without an account only from a browser that has passed its security check. --max-downloads needs Business Pro or Teams & Suite.
  • --title is at most 200 characters, --message 2000 and --from-name 100, all checked after trimming, before any request. They are sealed into the encrypted metadata, so the API no longer bounds them itself.
  • SHA-256 and CRC-32 are always computed and sealed into the transfer, so an encrypted transfer always carries checksums. --no-hash is no longer accepted: passing it is a usage error.
  • Earlier versions could send without an account and stored each such transfer's deletion token in the config file. dropvi rm still uses a stored token, then forgets it, so repeating the rm reports the transfer as deleted (exit 5).
  • Free accounts share an upload budget of 100 GB in any 24 hours with everyone sending from the same network without an account; when it is used up, send exits 7 (rate_limited) at once rather than retrying. Every account also has a limit on the storage its live transfers hold.

Keys and links

dropvi send always prints the full share link, https://dropvi.com/t/<id>#k=<key>, whether or not --to was given. The key is never stored on the server, only the link key salt and (for a protected transfer) the PIN salt are. Losing the fragment after # loses the transfer. Because that link contains the key, treat it (and data.url under --json, which is the same link) as a secret in its own right, the way you would a password or a token: anyone who has it can open the transfer, so share it, log it or paste it somewhere only where the intended recipients, and no one else, will see it.

With --to, the email Dropvi sends those recipients contains the full link with the key, so they open the files with one click. To write it, dropvi sends the key to Dropvi as each file finishes uploading; Dropvi uses it only for that email and does not store it, but at that moment Dropvi could open the transfer, and anyone who can read the email can open it too. To keep the key from Dropvi entirely, leave out --to and send the printed link yourself. Output is the same either way: one line with the full link, or data.url and data.key under --json. A branded subdomain link works the same way.

get

-o, --out <dir> (default ., created if missing), --key-stdin, --password-stdin, --password-file <path>, --password <pin>.

  • Files are downloaded one at a time and each file counts as one download. If a transfer has a download limit too small for one download per file, get refuses before fetching anything and points at the browser ZIP, which counts once.
  • Every file name from the server is checked. A name with a path separator, a drive letter, .. or a NUL is refused and nothing is downloaded.
  • Files sent in folders are written into those folders under the output directory. A folder that would put a file anywhere else (.., an absolute path, a drive letter, a backslash) is refused before anything is downloaded, and an existing symbolic link where a folder goes is never followed. Each folder is checked just before its file is moved into place, which leaves a short window in which someone else writing to the same output directory could swap a folder for a link, so download into a directory only you can write to.
  • An existing file is never overwritten without a yes at the prompt. Under --no-input, or with no terminal, the new file gets a suffix such as report (1).pdf.
  • SHA-256 is verified against the checksum the sender's client sealed with each file. A mismatch deletes the file and exits 9.

Every transfer is end-to-end encrypted and needs its key, tried in this order: the #k= fragment of the share link, then --key-stdin, then DROPVI_KEY. --key-stdin and --password-stdin cannot both be used, since both read stdin; combine --key-stdin with --password-file or DROPVI_TRANSFER_PIN, or DROPVI_KEY with --password-stdin. The key is resolved as soon as the transfer is found, before any PIN attempt or file is downloaded, so a missing key never spends a PIN attempt: with no key at all, get is a usage error naming --key-stdin. A key that does not open the transfer, or a malformed one, is wrong_key (exit 2, not retryable). A tampered, truncated or otherwise inconsistent transfer is integrity (exit 9): if the sealed metadata, a digest or a size fails to check out, nothing is written at all; if a file's own body fails to decrypt partway through a multi-file download, only that file's partial download is removed and files already written earlier in the run are left in place.

The transfer PIN

A PIN or password is 6 to 128 characters; anything shorter or longer is a usage error (exit 2), checked before any request.

Prefer --password-stdin. --password-file and DROPVI_TRANSFER_PIN also work. Plain --password works with a warning, because the PIN is then visible in process listings and shell history. Surrounding whitespace is trimmed from every source, matching the browser, so a PIN typed or pasted with leading or trailing spaces still derives the same key.

On a protected transfer, the PIN itself is sent to Dropvi's server so it can be checked before a download token is issued; Dropvi stores it only as a salted hash, never as typed. A resume state file records the link key, key salt and PIN salt, but never the PIN, so send --resume on a PIN-protected transfer asks for the PIN again, and refuses with wrong_pin before uploading another byte if it does not match.

Output

stdout carries results; everything else goes to stderr. dropvi send x.zip | pbcopy copies the URL and nothing else.

Without --json, dropvi list prints a table for a person to read (a header row, then one row per transfer with its status, file count, size, downloads, whether it has a PIN, and its title where Dropvi knows one), and dropvi rm prints Deleted <id>. Scripts should parse --json instead; the text layout is not a contract.

With --json, exactly one object is printed to stdout:

{ "schemaVersion": 1, "ok": true,
  "data": { "transferId": "...", "url": "https://dropvi.com/t/...#k=...", "key": "..." } }
{ "schemaVersion": 1, "ok": false,
  "error": { "code": "transient", "message": "...", "retryable": true,
             "transferId": "...", "resume": "dropvi send --resume ...", "discard": "dropvi rm ..." } }

data.url always carries the full link, including the key, whether or not --to was used: handle it as a secret, the same as a password or a token, since anyone holding it can open the transfer. data.key repeats the same key on its own, for a script that needs the bare key value apart from the link.

error.code is the stable contract. resume and discard are present when a send failed after creating its transfer; resume is left out when the send cannot be continued. An error never includes the key of the link it concerns, even when the reference passed to dropvi carried one.

Exit codes and error codes

| Exit | Meaning | Agent action | | ---- | -------------------------------------------------------------------------------- | -------------------------------------- | | 0 | Success | Continue | | 1 | Unexpected error | Report, do not retry | | 2 | Usage error, local validation failed, wrong PIN or wrong key | Fix the invocation | | 3 | Not authenticated | Re-authenticate | | 4 | Refused: plan or ownership | Never retry | | 5 | Gone: not found, deleted, expired, or no longer accepting uploads | Never retry | | 6 | Limit reached: download quota | Never retry | | 7 | Rate limited | Retry after the delay, if one is given | | 8 | Transient failure, retries exhausted | Retry later | | 9 | Integrity failure: a file or its checksum was altered, cut short or inconsistent | Investigate, do not retry | | 130 | Interrupted by SIGINT or SIGTERM | Resume if a resume command is given |

| error.code | Exit | Retryable | | ----------------------- | ---- | -------------------------- | | usage | 2 | no | | not_authenticated | 3 | no | | wrong_pin | 2 | no | | wrong_key | 2 | no | | pin_required | 2 | no | | pin_locked | 7 | no (carries lockedUntil) | | plan_required | 4 | no | | forbidden | 4 | no | | verification_required | 3 | no | | not_found | 5 | no | | deleted | 5 | no | | expired | 5 | no | | upload_window_closed | 5 | no | | not_ready | 5 | no | | quota_exhausted | 6 | no | | rate_limited | 7 | yes | | transient | 8 | yes | | integrity | 9 | no | | source_changed | 1 | no | | internal | 1 | no | | interrupted | 130 | no |

Authentication

DROPVI_TOKEN wins over the stored token. dropvi login stores its token in $XDG_CONFIG_HOME/dropvi/config.json (default ~/.config/dropvi/config.json; on Windows %APPDATA%\dropvi\config.json) with mode 0600 in a 0700 directory. The token is only ever sent as a header and is never printed.

dropvi login signs in through the browser. It shows a code such as KXQR-7MWD and opens https://dropvi.com/cli/login. Sign in there, type the code and approve it; the CLI then stores its token. The code is typed rather than put in a link, so nobody can send you a link that approves a sign-in for their own CLI: approve only a code your own terminal shows. If no browser opens (over SSH, say), go to that address on any device. A request lasts 10 minutes; a denied or expired one exits 3.

For scripts and CI, create a token at https://dropvi.com/cli/token and set it as DROPVI_TOKEN.

A token is a full 30-day session. Each token is its own session, separate from the browser's, so revoking one does not sign the browser out.

dropvi logout revokes the token this CLI holds and forgets it. It keeps the stored deletion tokens, so anonymous transfers stay removable. A token supplied through DROPVI_TOKEN is revoked server-side, but the CLI cannot unset the variable in your shell and says so.

Deleting the config file on its own revokes nothing. A token you no longer hold cannot be revoked either, because nothing lists an account's sessions, so use a separate account for CI.

Resume

A send writes its state to $XDG_STATE_HOME/dropvi/uploads/<id>.json (default ~/.local/state/dropvi/uploads; on Windows %LOCALAPPDATA%\dropvi\uploads) before uploading a byte, with mode 0600. It holds the link key, the key salt and, for a protected transfer, the PIN salt, so it is as sensitive as the share link itself; it never holds the PIN. After a failure or an interrupt, dropvi send --resume <id> continues from the first part not yet stored, as long as the files are unchanged; a PIN-protected transfer asks for the PIN again first, and refuses with wrong_pin before uploading anything if it is not the one the transfer was sent with. The server prunes an unfinished transfer about 24 hours after it was created, plus an hour for every 5 GiB; after that only dropvi rm <id> is left. A finished send removes its state file, so --resume on it is a usage error naming the transfer's keyless share URL: use the full link, including the part after #, that was printed when the send finished. A resume state file written by a 0.1.x plain send is unusable after upgrading, since it holds no key; --resume treats it as absent and reports that the transfer cannot be continued from this machine.

Environment

DROPVI_TOKEN, DROPVI_API, DROPVI_TRANSFER_PIN, DROPVI_KEY, DROPVI_JSON, DROPVI_QUIET and DROPVI_NO_INPUT. A flag wins over its variable. NO_COLOR and FORCE_COLOR are honoured.

DROPVI_KEY is the last-resort source of the key for dropvi get on an end-to-end encrypted transfer, tried after the link's own #k= fragment and --key-stdin.

DROPVI_TRANSFER_PIN applies to send as well as get, so a send made with it set is PIN-protected; send warns when that happens. --api and DROPVI_API must be https, except http to localhost for local development, because the token travels in a header.

Licence

MIT. See LICENSE.

The licence covers this command-line client only. The Dropvi service it talks to, and the rest of the repository this package is built from, are not open source.