Share text, images, and files between your devices and your dev machine. Built with Bun.
drop is a bidirectional content bridge for your dev machine. Run it on your workstation, open the URL on your phone, and share content in both directions:
- Phone to computer: drop files, text, and clipboard content into a filesystem inbox for agents and scripts.
- Computer to phone: upload files and text via CLI, then download or copy them on your phone.
Tailscale gives you secure reachability to your dev machine. drop turns that reachability into a practical inbox for text, images, and files.
Works on plain LAN out of the box. Pair it with Tailscale to reach your dev machine from anywhere on your tailnet -- no port forwarding, no certs, no auth layer to build.
- Mobile-friendly web UI on
0.0.0.0:3939(configurable) - Accepts file uploads, text snippets, and clipboard content (text or images) via REST API
- CLI commands to upload files (
drop cp) and send text (drop send) from your workstation - Frontend supports downloading files and copying text content with one tap
- Saves everything to
~/.drop/inbox/with timestamped filenames - Auto-cleans items older than 24 hours
- Shows full filesystem paths so you can feed them to agents or scripts
Taildrop solves file transfer between devices. drop solves content intake into a dev workflow:
- Taildrop transfers files.
dropalso handles text snippets and clipboard content (paste an image, paste a code block). - Taildrop delivers files to a download folder.
dropdelivers to a structured inbox with timestamped filenames, filesystem paths you can copy, and auto-cleanup. - Taildrop requires the Tailscale client on both ends.
droponly needs a browser on the sending device.
They're complementary: Tailscale handles secure connectivity, drop handles the last mile of getting arbitrary content into your working directory.
bun install
bun start # foreground modeOutput:
drop - LAN inbox for coding agents
Local: http://localhost:3939
LAN: http://192.168.x.x:3939
Inbox: /home/you/.drop/inbox
Open the LAN URL on your phone to start dropping files.
The drop CLI manages the server as a background process (PID file at ~/.drop/drop.pid) and provides commands to share content from your workstation.
# Start / stop / check
bun run drop start # start in background
bun run drop start --port 4000 # custom port
bun run drop start --dir ~/inbox # custom inbox directory
bun run drop stop # stop the background server
bun run drop status # check if running
# View server logs
bun run drop log # last 20 lines
bun run drop log --lines 50 # last 50 linesUpload files or send text to the inbox, then download or copy them on your phone via the web UI.
# Upload files (downloadable on phone)
drop cp photo.jpg notes.pdf
drop cp ~/Desktop/config.yaml
# Send text (copyable on phone)
drop send "The WiFi password is hunter2"
echo "export API_KEY=..." | drop send # pipe from stdin
pbpaste | drop send # send clipboard contentsThe cp and send commands require a running server (they act as HTTP clients). The server port is auto-detected from the server log.
| Command | Description |
|---|---|
drop start |
Start server in background, write PID to ~/.drop/drop.pid |
drop stop |
Stop the background server |
drop status |
Check if the server is running |
drop log |
Show recent server log output (~/.drop/drop.log) |
drop cp <files...> |
Upload files to inbox (downloadable from phone) |
drop send [text] |
Send text to inbox; reads stdin if no argument (copyable from phone) |
Path handling notes:
--dirandDROP_DIRaccept either an absolute path or~/...- Literal
~values are expanded bydropbefore use HOMEmust be set to an absolute path whendropneeds it- Invalid home-style paths such as
~otheruser/inboxare rejected - Broken path config fails fast instead of silently creating relative directories
To install drop as a global command:
npm link # creates a global symlink to this directory
drop start # now available everywhereNote:
bun install -gonly supports registry packages, not local directories.npm linkis the standard way to register a local package's bin as a global CLI command. It symlinkssrc/cli.ts(which has a#!/usr/bin/env bunshebang) into your global bin directory, so the CLI still runs via Bun.
To uninstall:
npm unlink -g drop| Flag | Applies to | Description |
|---|---|---|
--port <port> |
start |
Override server port (default: 3939) |
--dir <path> |
start |
Override inbox directory (default: ~/.drop/inbox) |
--lines <n> |
log |
Number of log lines to show (default: 20) |
For foreground mode with auto-reload:
bun dev| Env var | Default | Description |
|---|---|---|
DROP_PORT |
3939 |
Server port (auto-increments if in use) |
DROP_DIR |
~/.drop/inbox |
Inbox directory on disk; accepts an absolute path or ~/... |
Notes:
- If
DROP_DIRis unset,dropuses$HOME/.drop/inbox HOMEmust be an absolute path; invalid values are rejected at startup
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/upload |
Upload a file (multipart) |
POST |
/api/text |
Save a text snippet (JSON) |
POST |
/api/clipboard |
Save clipboard content (text or image) |
GET |
/api/items |
List all inbox items |
DELETE |
/api/items/:id |
Delete a single item |
DELETE |
/api/items |
Clear all items |
GET |
/raw/:id |
Serve raw file content |
GET |
/ |
Web UI (single-page HTML) |
Upload a file:
curl -F "file=@screenshot.png" http://localhost:3939/api/uploadSend text:
curl -H "Content-Type: application/json" \
-d '{"text":"hello from the terminal"}' \
http://localhost:3939/api/textList items:
curl http://localhost:3939/api/itemssrc/
cli.ts CLI entry point -- start/stop/status/log/cp/send commands
index.ts Server entry point -- starts server, prints URLs
server.ts HTTP server with REST API + static frontend
storage.ts Filesystem-backed store (save, list, delete, auto-cleanup)
frontend.html Single-file mobile web UI (no build step)
__tests__/
cli.test.ts
server.test.ts
storage.test.ts
Key design decisions:
- No database -- files go straight to disk, metadata is derived from filenames and
stat() - No build step -- the frontend is a single HTML file with inline CSS and JS
- Filename-based typing -- item type (file/text/clipboard) is inferred from filename patterns like
-snippet.txtand-clipboard - Path traversal protection -- filenames are sanitized, and
basename()is applied before deletion
bun test- Bun runtime