Every few months I want to send a file to someone and realise none of the options are quite right. Email has size limits. Cloud drives want accounts on both ends. Most “send a link” services promise privacy on a page full of tracking pixels. AirDrop is great until the recipient is on a different operating system or a different continent.

So I built TorDrop. It’s a native macOS menu bar app that turns any file on your disk into a .onion URL you can hand to someone. They open it in Tor Browser and download. You click Stop Sharing. The onion service, and its private key, cease to exist.

No accounts. No servers I run. No persistent keys anywhere.

The pitch

Click the menu bar icon, pick a file (or drag one onto the icon), and TorDrop gives you a .onion URL and a QR code. Send the URL to whoever needs the file, over whatever secure channel you already use to talk to them. They open it in Tor Browser and download. When you’re done, you click Stop Sharing and the onion service vanishes.

That’s the whole app.

It’s deliberately minimal. There’s no sign-in, no “my files” list, no history. Nothing is ever uploaded anywhere - the file stays on your disk the entire time, served directly from your machine through Tor.

How it works

File → local HTTP server (127.0.0.1:random) → tor → v3 onion service → Recipient

When you share a file, TorDrop starts a tiny HTTP server bound to a random loopback port on your machine. It then spawns tor, connects to its control port, and asks it to create an ephemeral v3 hidden service that forwards onion port 80 to the local HTTP port.

The magic bit is the ADD_ONION NEW:ED25519-V3 Flags=DiscardPK command. That tells tor to generate a fresh onion service keypair and not hand us the private key. The service exists only inside that running tor process. When you stop sharing, the process forgets it, and the .onion address is gone forever. There is nothing on disk to leak, back up, or forget to wipe.

Why native, why menu bar

I wanted sharing a file to feel like AirDrop, not like opening a webapp. It lives in the menu bar, it opens with one click, and it doesn’t need a browser tab of its own. Drag a file onto the icon and you’ve started sharing before you’ve thought about it.

The whole thing is SwiftUI in a popover with an NSStatusItem behind it. The popover has three states: idle, sharing, and error. That’s all the UI there is.

The surprising part: writing an HTTP server by hand

TorDrop has exactly one external dependency: the tor daemon itself. Everything else - the HTTP server, the Tor control-protocol client, the QR code renderer - is first-party code built on the macOS system frameworks.

This wasn’t philosophical purity. It’s that for something whose whole value proposition is “this is doing what it says on the tin,” auditability matters. A dependency tree a mile long undermines the pitch. If you can read the source in an afternoon, you can actually trust it.

So I wrote the HTTP server. It’s a small Network.framework listener that speaks just enough HTTP/1.1 to serve a directory listing and range-request downloads. I wrote the Tor control-protocol client too - it’s a line-oriented text protocol that’s genuinely pleasant to implement. Between the two, it’s a few hundred lines of Swift. Small enough to reason about, big enough that it definitely works.

There’s something grounding about writing the primitives yourself once in a while. You remember that HTTP is not magic, that a file server is just sockets and strings, that the stack you depend on every day is made of things a person wrote.

Security notes

TorDrop doesn’t try to add anything on top of what Tor itself provides. What it does try to do is not weaken it:

The usual Tor caveats still apply. If you need to be certain the URL reached the right person, confirm it through a channel you already trust.

What it’s for (and what it isn’t)

TorDrop is for one-off, person-to-person file handoffs where you care about not routing the file through somebody else’s infrastructure. Sending a keyfile to a colleague. Sharing a video with a family member abroad. Getting a big artifact off your machine and onto theirs without it being cached, indexed, or scanned along the way.

It is not a backup tool, not a sync client, not a hosting service. Your machine has to be on for the transfer to work. The moment you close the popover, it’s over.

Play with it

github.com/tuckerwales/tordrop - source, build instructions, and a Makefile that produces a .app. You’ll need brew install tor and macOS 13 or later.

If you try it, I’d love to hear how it went.