CLI
The dropper command drops .html files or whole directories from your terminal. Directories are zipped client-side before upload, so the server only ever sees a single file.
The dropper command drops .html files or whole directories from your terminal. Directories are zipped client-side before upload, so the server only ever sees a single file.
macOS only (casks are), Apple Silicon and Intel — Homebrew fetches the cask from the dtolb/tap tap and upgrades it with the rest of your packages.
brew install --cask dtolb/tap/droppermacOS and Linux — the installer picks the binary for your machine, verifies its SHA-256 against the published checksums and puts it in ~/.local/bin without sudo; Linux needs glibc (not Alpine/musl), anything else builds from source below.
curl -fsSL https://dropp.sh/install.sh | shThe same archives the installer fetches: one dropper binary per platform, SHA-256 listed for a manual check. Only the current version is downloadable from this deployment. macOS marks a browser download as quarantined — clear it with xattr -d com.apple.quarantine dropper, or use one of the commands above instead.
| Platform | Size | SHA-256 | Download |
|---|---|---|---|
macOS · Apple Silicon dropper-darwin-arm64.tar.gz | 26.1 MB | 2a9aec0b4cd6… | Download |
macOS · Intel dropper-darwin-x64.tar.gz | 28.7 MB | d4e2d3436a19… | Download |
Linux · x64 dropper-linux-x64.tar.gz | 36.5 MB | 65c9ab418ef9… | Download |
Linux · arm64 dropper-linux-arm64.tar.gz | 36.5 MB | 780385b8291c… | Download |
git clone https://gitlab.tolbbox.com/tolbnet/dropper.git
cd dropper/cli && npm ci && npm run build
node dist/index.js --helpdropper loginwith your server's URL is the whole setup. Your browser opens, you sign in with Authelia as you do on the dashboard and approve "Dropper CLI" once, and the CLI keeps the server URL and the login in ~/.config/dropper/config.json, refreshing it on its own. Check it with dropper whoami; dropper logout forgets it.
dropper login https://dropp.sh
# your browser opens: sign in, approve "Dropper CLI" once, come back
# → logged in to https://dropp.sh as alice
dropper whoamiScripts, CI jobs and machines without a browser use a personal API key instead — mint one on the dashboard's API Keys page. DROPPER_TOKEN wins whenever it is set and not empty, over a login and over the config file, and DROPPER_URL beats "url" in the config file. "token" in the config file still works and answers when there is no login for that server; a login is used only for the server it was made against. The local stdio MCP server reads the same file but never uses a login, so it still needs a key.
export DROPPER_URL=https://dropp.sh
# a personal API key, minted on the dashboard's API Keys page;
# while it is set it wins over a dropper login
export DROPPER_TOKEN=your-api-key{
"url": "https://dropp.sh",
"token": "your-api-key"
}Agents with a shell use this CLI rather than the MCP server. The dropper-cli skill teaches them to use it well — install it in Claude Code as the dropper-kit plugin, or give any other agent one SKILL.md: Coding agents.
Sign in with your browser. url is the Dropper server, defaulting to DROPPER_URL and then "url" in the config file; naming a different one makes it the configured server, unless the config file holds an API key ("token"): that "url" stays with its key, which the local stdio MCP server sends along, and login says how to use the new login instead. The CLI registers itself with the server as "Dropper CLI" (again after a login to another server), sends you to sign in and approve it, and catches the answer on a one-off listener at 127.0.0.1 — so the browser has to run on the same machine; on a remote or headless box, use an API key. The login URL is always printed too, and waiting gives up after five minutes. The server URL and the login’s tokens go into the config file (mode 0600); the CLI refreshes the login on its own and only ever sends it to the server that issued it. While DROPPER_TOKEN is set it keeps precedence, and login says so.
| Name | Type | Description |
|---|---|---|
--no-browser | flag | Print the login URL instead of opening a browser |
dropper login https://dropp.sh
# Opening your browser to log in to https://dropp.sh. If it does not open, visit:
# https://dropp.sh/api/auth/oauth2/authorize?response_type=code&client_id=…
# Waiting for the browser (Ctrl-C to cancel)...
logged in to https://dropp.sh as aliceForget the login: revoke its refresh token on the server (best effort) and remove the tokens from the config file. The server URL, any API key and the CLI’s registration stay, and when an API key remains — DROPPER_TOKEN or "token" in the config file — logout says the CLI uses it from now on. "Dropper CLI" stays listed under Connected apps on the API Keys page until you disconnect it there. Not being logged in is not an error.
dropper logout
Logged out of https://dropp.sh: removed the stored login tokens and revoked the refresh token on the server.Show which account and server the CLI is using: your handle, name, email and live role, the server URL, the credential, and where it came from. A login shows as credential oauth; an API key shows by its name and masked start, as the API Keys page shows it. The source is the config file followed by (dropper login), the DROPPER_TOKEN environment variable, or the config file’s path alone for its "token". Exits 0 when signed in; otherwise prints one line on stderr saying why — not logged in, a rejected login or key, a suspended account, an unreachable server, or a server older than whoami — and exits 1.
| Name | Type | Description |
|---|---|---|
--json | flag | Print the same facts as one JSON object for scripts: server, source, handle, name, email, role and credential |
dropper whoami
handle alice
name Alice Example
email alice@example.com
role user
server https://dropp.sh
credential oauth
source /home/alice/.config/dropper/config.json (dropper login)
# with an API key, the credential line names the key:
key laptop (hYqTbc…) · created 2026-09-10
source DROPPER_TOKEN environment variableUpload an .html page, a .md Markdown file, or a directory of a static site. Directories are zipped client-side before upload; a .md drop renders as a styled page in a browser and serves its source to curl and to ?raw=1.
| Name | Type | Description |
|---|---|---|
--slug <slug> | string | Custom slug for the URL |
--name <name> | string | Display name — shown in the drops list and used as the title of a rendered Markdown page (a trailing .md is dropped). Defaults to the file or directory name, and it never changes the kind — that comes from the uploaded filename |
--password <password> | string | Protect the drop with this access code |
--gen-password | flag | Protect with a generated correct-horse style passphrase (printed after the URL) |
--public | flag | List the drop in the public gallery. Discoverability only — the URL is reachable either way |
--private | flag | Keep the drop out of the gallery — the default; combining it with --public is an error |
--description <text> | string | Short public summary, at most 200 characters — shown under the name and on the gallery |
--label <path> | string | Label path, e.g. acme or acme/site: up to three names of lowercase letters, digits and hyphens joined by /. Repeat it for more, at most 20; a label that does not exist yet is created. Label every drop with the project it belongs to |
dropper drop page.html
dropper drop notes.md # renders at the URL, ?raw=1 is the source
dropper drop ./site --slug demo
dropper drop page.html --gen-password
dropper drop ./site --slug demo --public # feature it in the gallery
dropper drop ./site --slug demo --label acme/site --description "Launch page draft"
# → https://dropp.sh/d/alice/demo/
# → password: correct-horse-battery-stapleRename a drop, change its display name, description or labels, set or clear its access code, or replace its content. Options combine in one call; a replacement file keeps the name, description, labels, access code and visibility.
| Name | Type | Description |
|---|---|---|
--slug <slug> | string | Rename to a new slug |
--name <name> | string | Set the display name — shown in the drops list and used as the title of a rendered Markdown page (a trailing .md is dropped); on its own it is a valid edit, and a replacement file no longer renames the drop |
--password <password> | string | Set an access code |
--gen-password | flag | Set a generated passphrase |
--clear-password | flag | Remove the access code |
--public | flag | List the drop in the public gallery (omitting both flags leaves visibility unchanged) |
--private | flag | Remove the drop from the gallery — combining it with --public is an error |
--file <path> | string | Replacement .html file, .md file or directory |
--description <text> | string | Set the short public summary, at most 200 characters; a blank one is refused — use --clear-description |
--clear-description | flag | Remove the description |
--label <path> | string | Label path, repeatable, as on drop — the given paths replace the drop’s whole label set |
--clear-labels | flag | Remove every label from the drop |
dropper edit demo --slug demo2 # rename
dropper edit demo2 --password hunter2 # protect
dropper edit demo2 --clear-password # unprotect
dropper edit demo2 --public # list in the gallery (--private delists)
dropper edit demo2 --name "Release notes" # display name only
dropper edit demo2 --file ./site # replace content
dropper edit demo2 --label acme/site --label personal # now exactly these two labels
dropper edit demo2 --clear-description --clear-labelsList your drops, one line each: slug (padded to the longest in the list), kind, protection and gallery markers, file count, creation time and URL, then the drop’s label paths, comma-joined, when it has any. With --public, list every user’s gallery-public drops instead, without labels. Prints no drops when nothing matches.
| Name | Type | Description |
|---|---|---|
--public | flag | List every user’s public drops (the gallery) instead of your own |
--label <path> | string | Only your drops carrying this label or one of its sublabels — --label acme lists acme/site too. Not with --public |
dropper list
# demo2 zip locked public 12 files 2026-08-27T12:00:00.000Z https://dropp.sh/d/alice/demo2/ acme/site,personal
# notes md 1 files 2026-08-28T09:15:00.000Z https://dropp.sh/d/alice/notes/
dropper list --label acme # acme and its sublabels
dropper list --public # the cross-user galleryDelete a drop. The URL stops working and the slug frees up at once, but the drop sits in your trash for 30 days — restore it from the dashboard (Profile → Deleted drops) or POST /api/trash/<id>.
dropper rm demo2
# deleted demo2See and reorganise your labels. rename, move, color and rm name a label by its path and print one line; a path that names no label is an error (no label: <path>). ls lists the tree with each label’s drop count, sublabels counted in, and its colour. rename and move never touch a drop’s files: its drops and sublabels go along. color sets a top-level label’s colour (blue, green, purple, orange, cyan, red, gold, magenta, lime or grey), which its sublabels show. rm deletes a label and moves its drops and sublabels to its parent; a top-level label just comes off its drops and its sublabels become top-level. On rm, a sublabel that lands beside a label of the same name merges into it, drops included; rename and move refuse a name already taken there (label already exists: <path>). Labels come into being by labelling a drop (--label on drop and edit).
dropper labels ls
# acme 12 drops blue
# acme/site 3 drops blue
dropper labels rename acme/site web # renamed acme/site to acme/web
dropper labels move acme/web / # moved acme/web to web ("/" is the top level)
dropper labels color acme green # recoloured acme to green
dropper labels rm acme/docs # deleted acme/docs; its drops and sublabels moved to acme
dropper labels rm personal # deleted personal; removed from its drops, its sublabels moved to the top level