Direct file transfer
Files go straight from your device to theirs.
Share a link. When the other side opens it, the two devices connect to each other and the file moves over the fastest path available. Nothing is uploaded, nothing is stored, nobody signs up.
The path
Every transfer races its options and takes the winner.
When the link is opened, both sides try every way they could reach each other, at the same time. The first one that works carries the file. The file never touches a server.
What the server actually does
One small server introduces the two devices: it hands out the link ID, passes the connection details between them, and steps out. It sees that a transfer happened. It never sees the file.
- same network
- Laptop to phone on the same Wi-Fi: the bytes stay on the router. Full local speed.
- direct
- Both sides open a hole in their routers at the same moment and connect over QUIC. This works for most home and mobile networks, and needs the CLI on at least one side.
- browser direct
- Both sides in a browser: the same hole punching, over WebRTC. Still device to device, but the browser's own stack caps the speed.
How it works
Three steps, none of them an upload.
Choose a file, get a link
In the browser, drop a file. In the terminal, name it. The link appears instantly, because it only identifies your device, not a copy of the file.
$ beeline share thesis-final.pdf
Send the link any way you like
Chat, email, QR code on screen. The key after # is part of the link, so whoever has the link can receive; nobody else can, not even us.
https://beeline.sh/k7f2x9#Vq3tRb8mLpWz
They open it, devices connect
The file streams straight across. Video and audio play before the download ends. If the connection drops, it picks up where it stopped.
▸ direct · 412 MB/s · resumable
Speed
The only limit should be your connection.
Browser-only sharing tools top out at tens of megabits, because the browser's peer-to-peer stack is built for video calls, not bulk data. Beeline uses that path only when it has to.
| Between | Transport | Ceiling | Resume |
|---|---|---|---|
| TerminalTerminalbeeline share → beeline get | QUIC, direct | Your connection | Yes |
| BrowserTerminalbrowser on one side, CLI on the other | WebTransport or HTTPS, direct | Your connection | Yes |
| BrowserBrowserboth sides on the web page | WebRTC data channels, direct | The browser, typically 10-100 Mbit/s | Yes |
Install the CLI on at least one side and the browser limit disappears. Speeds in the examples on this page are illustrative.
Command line
One command to share. One to receive.
A single static binary. It runs a small background service the first time you use it, so links keep working after you close the terminal.
$ beeline share film.mkv film.mkv 4.2 GB https://beeline.sh/m3xq8a#Hd7pKw2nRt5s serving in the background · beeline ls to see it
$ beeline get https://beeline.sh/m3xq8a#Hd7pKw2nRt5s film.mkv 4.2 GB direct · quic ░░ 91% 118 MB/s ✓ saved to ./film.mkv sha256 verified
$ beeline share ./photos --expires 24h --max-downloads 3 photos/ 1,204 files 9.7 GB https://beeline.sh/p9tz4e#Qm2vXc8bLd6y expires in 24h · up to 3 downloads
$ pg_dump app | zstd | beeline share - --name app.sql.zst app.sql.zst streaming · size unknown https://beeline.sh/w2rk7n#Zt4gPm9sVb1x
MCP
Let your agent hand files over.
The CLI doubles as an MCP server. Add it to Claude Code, Claude Desktop, Cursor or anything else that speaks MCP, and "send me that log" becomes a link in the chat.
.mcp.json{
"mcpServers": {
"beeline": {
"command": "beeline",
"args": ["mcp"]
}
}
}
share_fileShare a path. Returns the link. Optional expiry and download cap.share_textShare a string as a file, for output too large for the chat.receiveDownload from a link into a directory. Returns the saved path and checksum.list_sharesActive links with peers, progress and speed.revokeStop serving a link.Privacy
The server introduces. It doesn't listen.
Every connection is encrypted between the two devices with keys derived from the secret in the link. The server never has that secret, so it could not read the transfer even if it tried.
What the server sees
- That a link ID exists and whether its owner is online
- Both devices' IP addresses, so it can introduce them
What it can't see
- File names, sizes or contents
- The key after
#: browsers never send it, and the CLI doesn't either - Who you are. There are no accounts and no cookies.
Questions
The honest limits.
Do both sides need to be online at the same time?
Yes. Nothing is stored anywhere, so the file can only move while the sender is online. The CLI keeps serving in the background; a browser tab has to stay open.
Is there a size limit?
No. The CLI and Chrome, Firefox and Edge handle files of any size. Safari can't save downloads much beyond 4 GB; on a Mac, use the CLI for large files.
What if the connection drops?
The receiver keeps a map of which pieces it has. Reconnect, and only the missing pieces are sent. Every piece is checked against a hash, so a corrupt transfer can't complete silently.
Can I send to several people?
Yes. Everyone with the link connects to you, and once they have pieces they also pass them to each other, so your upload isn't the bottleneck for a group.
What if my network blocks direct connections?
Most don't. When both networks do, the transfer can't start and Beeline says so; there are no relay servers, so your file is never routed through us. Putting the CLI on either side, or moving one device to another network, usually fixes it.
Why not just use the browser for everything?
Browser-to-browser works, and for a few hundred megabytes it's fine. The browser's peer-to-peer stack is the ceiling, not your connection. Put the CLI on one side and the ceiling is gone.