croc has shipped for eight years with an empty bug list

croc file transfer sends a file between any two computers using a short code phrase, with end-to-end encryption and no port forwarding. The surprise is the maintenance record. After eight years, the project has closed 597 issues and merged 332 pull requests. The tracker holds five open issues, zero open pull requests, and no open bug reports.
Key Takeaways
- croc sends a file between any two computers using a short code phrase.
- Both sides get end-to-end encryption, and neither needs a router change.
- After eight years the tracker holds five open issues and no waiting pull requests.
- A stored mode lets you send files when the other person is offline.
- On Linux and macOS, pass the code through an environment variable to hide it.
How croc file transfer actually moves a file
The sender runs croc send on a file or a folder. croc
then prints a short code phrase made of a number and a few words. The receiver types croc plus that phrase on the other machine, and the transfer starts.
That phrase never travels anywhere as a password. It seeds a password-authenticated key agreement , or PAKE, which lets both machines work out the same secret key without either one sending it. A relay in the middle carries encrypted bytes and can read none of them.
The relay exists to introduce two machines that can’t reach each other directly, and it stores nothing. Unlike a share-a-link workflow, there is no account to create, no upload step, and no router setting to change.
The tool handles more than one file at a time and resumes an interrupted transfer. It tries IPv6 before falling back to IPv4, and it pipes through stdin and stdout. A SOCKS5 proxy such as Tor works too. croc is written in Go, MIT licensed, and runs on Windows, Linux, macOS, and Android through community F-Droid apps.
There is also a browser client at getcroc.com
that speaks the same protocol as the command line. Its WebAssembly runtime ships inside every croc binary, so croc serve will host the whole site locally. Add --qr to a send and croc prints a QR code that opens the web client in receive-only mode.
The empty backlog, counted
The repository went public in 2017 and has been shipping ever since.
| Measure | Count |
|---|---|
| Open issues | 5 |
| Open pull requests | 0 |
| Closed issues | 597 |
| Merged pull requests | 332 |
| Contributors | 130+ |
Two of the five open issues are feature requests filed a day apart. One asks for machine-readable JSON event output, the other for a croc doctor command, and both already carry a maintainer reply. Another two ask for Debian packaging and for sharing one file with several people. The fifth is a long discussion thread about who pays for relay hosting. Every open item is a feature request or a conversation, and none is a bug report.
The release cadence rules out an abandoned project. Three releases landed inside eight days, taking croc from v10.5.0 to v10.7.0, each crediting outside contributors in its notes. A report that the getcroc.com site was down was opened and closed the same day.
A closed issue isn’t always a fixed issue, though, and some projects keep a tidy tracker by closing anything that goes quiet. The recent closures here read as real work, with fixes traceable to named contributors in the release notes. Either way, file a bug here and a human will read it.
The stored mode that lets you send to someone offline
For most of its life croc needed both people online at the same moment, because nothing was stored anywhere. Run croc send --store photo.jpg document.pdf and your machine encrypts the files first. It uploads only ciphertext, then prints a browser link plus a command-line token. The transfer expires after 24 hours, or as soon as one receiver downloads and verifies every file, whichever comes first.
The design detail worth stealing is in the link itself, which looks like https://host/s/<id>#v1.<key>. Browsers never put the part after # into an HTTP request or a Referer header. So the service logs the transfer id and never sees the decryption key, as the stored-transfer design guide
explains.
Treat the full link as a secret anyway. Anyone holding it can claim the single allowed download. You can pull a transfer back before pickup with croc --revoke <transfer-id>, which uses a receipt saved locally with mode 0600.
The receiving side checks every chunk as it arrives and verifies each finished file with SHA-256 before committing the download. Stored mode stays opt-in and separate from normal live transfers, and --store-url points it at your own service.
The secret leak that changed how you type the code
On Linux and macOS, any other user on the machine can list running processes together with their arguments. A code phrase typed straight onto the command line is readable by all of them, which is exactly what the vulnerability catalogue recorded.
An issue was discovered in Croc through 9.6.5. The shared secret, located on a command line, can be read by local users who list all processes and their arguments.
croc’s answer was to change the recommended usage. On those two platforms you now pass the secret through the environment, as CROC_SECRET=*** croc, so it stays out of the process list. Automation uses the same trick for stored transfers with CROC_STORE_TOKEN.
If you run a single-user machine and want the old behaviour back, croc --classic turns it on for good. The clipboard helper follows the same logic. Run croc --extended-clipboard send and it copies a full command with the secret already in an environment variable. The receiver then pastes the safe form.
In any command-line tool you write, a secret passed as an argument is a secret shared with everyone logged in.
Installing croc without piping the internet into bash
The project’s front-door install fetches a script from the web and runs it through bash. That line sits in the README if you want it. Every platform also has a packaged alternative that never hands your shell to a URL.
| Platform | Command |
|---|---|
| macOS (Homebrew) | brew install croc |
| macOS (MacPorts) | sudo port install croc |
| Windows | scoop install croc, choco install croc, or winget install schollz.croc |
| Arch | pacman -S croc |
| Fedora | dnf install croc |
| Gentoo | emerge net-misc/croc |
| FreeBSD and Termux | pkg install croc |
| Nix | nix-env -i croc |
| conda-forge | pixi global install croc |
| From source | go install github.com/schollz/croc/v10@latest |
On NixOS, add pkgs.croc to environment.systemPackages instead. Source builds want Go 1.22 or newer.
croc against magic-wormhole and LocalSend
| Tool | Best at | Across different networks | Ships as |
|---|---|---|---|
| croc | Machine to machine, anywhere | Yes, through a relay | One Go binary plus a browser client |
| magic-wormhole | Reference PAKE implementation | Yes, through a relay | Python package |
| LocalSend | Phone to laptop on one network | No | Desktop and mobile apps |
croc borrowed the core idea from magic-wormhole and says so in its acknowledgements, crediting @warner directly. magic-wormhole remains the Python original that cryptography people point to. croc is easier to install, shipping as a single static binary that a dozen package managers carry, with a browser fallback behind it.
LocalSend is the better answer on a shared network, with device discovery and a phone-friendly interface. A cloud drive beats both when the file has to still be there next week, at the price of a copy sitting on someone else’s disk.

For scripting, croc pulls ahead of the other two. Quiet mode, stdin and stdout piping, --exclude patterns, and an environment-variable secret make it usable inside automation with no prompts.
There’s one caveat before you standardise on it. The maintainer runs the public relay and funds it through GitHub sponsorship
, which is what that open hosting discussion is about. So if you depend on croc, run croc relay yourself. It uses TCP ports 9009-9013 by default and needs at least two of them. There’s a Docker image if you’d rather not manage the binary.
Botmonster Tech