
There’s a moment that every developer knows too well. You’re staring at a terminal, a file server at your office, and a laptop at home, and you need to get a 2GB database dump from one to the other. USB drive? The office policy blocks them. Cloud storage? Uploading 2GB through a congested fiber connection takes twenty minutes and half a cup of coffee. SCP? You’d need to set up SSH keys, open ports on your router, and pray your ISP hasn’t put you behind CGNAT.
I hit this wall a few months ago while trying to transfer a dataset between my work machine and my homelab server. The dataset was too big for email, too sensitive for a random file-sharing site, and SSH just wasn’t cooperating because my home connection uses carrier-grade NAT. The file sat there for three days while I figured out a workaround. Turns out I should have just used croc.
What Is Croc?
Croc is an open-source, cross-platform CLI tool that lets you send files and folders between any two computers with end-to-end encryption. It works without port forwarding, without a cloud service, and without signing up for anything. You download it, run a single command on the sending machine, get a code phrase, and type that same code phrase on the receiving machine. That’s it.
The project was created by Zack Schollz back in 2017, and it’s been steadily growing ever since. At the time of writing, it has over 37,000 stars on GitHub and is one of the most practical CLI tools I’ve come across in years. It’s written in Go, uses a relay server for the initial connection handshake, and encrypts everything end-to-end using PAKE (Password-Authenticated Key Agreement).
What makes croc stand out from other file-transfer tools is that it checks all the boxes: any two computers can transfer data, it provides genuine end-to-end encryption, it works on Windows, Linux, and macOS, it handles multiple files and folders, it supports resuming interrupted transfers, and you don’t need to configure your router or open any ports.
Security First: How Croc Encrypts Your Files
Before jumping into the commands, it’s worth understanding why croc is safe to use. The tool uses PAKE — specifically a protocol called PAKE2 — to establish a shared secret between the sender and receiver. The code phrase you share (like “kangaroo-jazz-hammer-42”) isn’t the encryption key itself. It’s used to derive a cryptographic key through the PAKE handshake, which means even the relay server that facilitates the connection cannot read your files.
This is fundamentally different from services like WeTransfer or Dropbox, where the cloud provider holds the decryption keys. With croc, the relay server only sees encrypted blobs passing through. The actual encryption uses XChaCha20-Poly1305, a modern authenticated encryption scheme that provides both confidentiality and integrity. If someone intercepts the data in transit, all they’ll see is gibberish.
This matters more than ever. Tools like HeimWall exist to catch secrets before you paste them into AI coding tools, but croc handles the transport layer itself — your data stays encrypted from the moment it leaves your machine until it arrives at the receiver’s. In an era where supply chain attacks and data interception are becoming routine, having a tool that treats privacy as a default rather than an afterthought is refreshing.
Installing Croc
One of croc’s strengths is how easy it is to install on any platform. Here’s the quickest way to get it running:
Linux (any distro)
curl https://getcroc.schollz.com | bash
Or via your package manager depending on your distro:
# Arch Linux
sudo pacman -S croc
# Fedora
sudo dnf install croc
# Ubuntu/Debian — download the latest .deb from the releases page
wget https://github.com/schollz/croc/releases/latest/download/croc_linux_amd64.deb
sudo dpkg -i croc_linux_amd64.deb
macOS
brew install croc
Windows
# Using Scoop
scoop install croc
# Or using Winget
winget install schollz.croc
Once installed, verify with croc --version. You should see something like croc v10.x.x.
Basic Usage: Sending and Receiving Files
Here’s the simplest workflow. On the machine that has the file, run:
croc send project-backup.tar.gz
Croc will output something like:
Sending 'project-backup.tar.gz' (1.2 GB)
Code is: elephant-giraffe-tango-84
On the receiving machine, just run:
croc elephant-giraffe-tango-84
The file transfers directly through croc’s relay server — but remember, the relay never sees the unencrypted data. The code phrase is ephemeral, so once the transfer completes or you close the session, it’s useless to anyone else.
Useful Tricks and Customizations
The basic send-and-receive pattern is powerful on its own, but croc has several features that make it even more useful in real-world scenarios.
Custom Code Phrases
If “elephant-giraffe-tango-84” is hard to communicate over a phone call, you can set your own:
croc send --code "my-secret-project" project-backup.tar.gz
The code phrase must be at least six characters. Using something memorable makes coordination easier when you’re guiding a colleague through the receiving process.
Sending Folders
Croc handles directories natively — just point it at a folder and it’ll zip and transfer everything inside:
croc send ./my-project/
Excluding Files
When sending a project folder with node_modules, virtual environments, or build artifacts, use the --exclude flag:
croc send --exclude "node_modules,.venv,target" ./my-project/
Sending Multiple Files
You can send several files in one command without zipping them first:
croc send report.pdf screenshot.png data.json
Sending Text
For quick snippets, passwords, or URLs:
croc send --text "ssh -i key.pem [email protected]"
The recipient gets the text displayed in their terminal — no file created, just the raw output.
Pipe Mode
Croc works with Unix pipes, making it great for streaming data:
# On the sending machine
cat important.db | croc send
# On the receiving machine
croc --yes code-phrase > important.db
This is perfect for one-off transfers where you don’t want to leave a file on disk afterwards.
QR Codes for Mobile
If you’re transferring to a mobile device, croc can display a QR code:
croc send --qr ./photo.jpg
Scan it with the crocgui app (available on F-Droid) and the transfer starts automatically. This is incredibly handy for getting screenshots or documents off your phone without plugging in a cable.
Resuming Interrupted Transfers
Network drops happen. Croc supports resuming interrupted transfers — just run the same receive command and it picks up where it left off, saving you from restarting a multi-gigabyte transfer from scratch.
Self-Hosting Your Own Relay
While croc’s default relay works fine for most use cases, you might want to run your own for privacy or performance reasons. This is especially relevant if you’re transferring files within a private network or handling sensitive data that shouldn’t touch public infrastructure.
Running a relay is surprisingly simple:
croc relay
By default, it listens on TCP ports 9009-9013. If you’re running it on a server with a public IP, make sure those ports are open in your firewall. For Docker users:
docker run -d -p 9009-9013:9009-9013 \
-e CROC_PASS='your-secure-password' \
docker.io/schollz/croc
Then send files through your relay:
croc --pass your-secure-password --relay "your-server.com:9009" send sensitive-doc.pdf
Self-hosting your relay gives you full control over the infrastructure, which aligns with the broader trend I discussed in my tutorial on setting up a self-hosted Dynamic DNS server with Knot DNS — owning your network services rather than relying on third parties.
Practical Use Cases
Here are three scenarios where croc genuinely saved me time:
1. Sharing log files during debugging sessions. I was pair-debugging a production issue with a colleague who works remotely. Instead of pasting log snippets into Slack (which reformats them) or setting up a shared S3 bucket, I sent the entire log directory with croc send ./logs/, and they had it in seconds.
2. Moving a database export between environments. That 2GB database dump I mentioned earlier? I compressed it, sent it through croc to my homelab server, and it took about four minutes. No cloud upload, no SSH configuration, no headaches.
3. Sharing configuration files with a new team member. When onboarding a junior developer, I used croc to transfer SSH configs, .env templates, and Docker Compose files. The built-in encryption meant I didn’t have to worry about sensitive keys leaking through the relay.
Limitations Worth Knowing
No tool is perfect, and croc has a few gotchas worth mentioning:
- The relay is a bottleneck. Since all traffic passes through the relay server, transfer speeds are limited by the relay’s bandwidth. For LAN transfers, you’re better off using SCP or a direct SMB share. The
croc --relayflag with a local relay address solves this if you want to keep using croc’s workflow. - Large file transfers can stall. Some users have reported freezes during multi-gigabyte transfers. The v10 release has improved reliability, but for truly massive datasets, consider splitting the file first with
splitor using rsync over a direct connection. - No Web UI. Croc is purely a CLI tool. If you need a graphical interface, the Android apps (crocgui and croc-app) are available, but there’s no desktop GUI for Windows, macOS, or Linux.
Bottom Line
Croc is one of those tools that doesn’t try to do everything — it just does one thing remarkably well. It solves the fundamental problem of getting a file from point A to point B without needing an account, a cloud subscription, or a networking degree. In the current landscape where we’re all thinking more carefully about where our data goes and who has access to it, having a tool that encrypts everything by default and doesn’t store anything long-term is a quiet win.
Install it today. You won’t need it every week, but when that moment comes — when you’re staring at a file and a distant machine and wondering how to bridge them — you’ll be glad it’s in your toolbox.
If you found this useful, you might also enjoy my guide on building a simple RAG system with Ollama and Gemma — another tool that simplifies a traditionally complex setup into a handful of terminal commands.