A timesaver: move a file from one computer to another with two short commands, without a chat app, an upload site or ssh keys, with every command run for real.
▶Prefer to watch? This short video explains what croc is for, then sends a file and a folder between two terminals on a real Ubuntu 24.04 machine, with on-screen captions and no voiceover. Click to play, or watch it on YouTube.
croc: send a file, a folder or some text to another computer with a short code phrase.
croc send FILE on the sender: prints a code phrase like three-random-words
croc on the receiver: asks for the phrase, then for a yes
croc send --text "..." send a line of text instead of a file
croc send --zip FOLDER zip a folder on the way
croc is a command-line tool for moving files between two computers that cannot easily reach each other. The sender runs one command and gets a code phrase of three words. The receiver runs another command and types the phrase. Both computers only connect out, to a relay server, so there is no port to open on either side and no account to make. The project describes the transfer as end-to-end encrypted, with the code phrase as the shared secret. It is useful for sending something to a colleague, or to your own other machine, once, in a few seconds.
This page is the written version of the Timesavers video. Every command below was run for real, in an Ubuntu 24.04 container with croc 11.5.5. The sender and the receiver were two terminal panes in that one container (the laptop above, the server below), with different folders, and the data went through the project's public relay on the internet, so it travelled the normal route. The sample files are made of random bytes. The address croc prints for the machine on the "Sending" and "Receiving" lines was my own public address, and it is shown as 203.0.113.7 on this page (an address set aside for examples). The section "What was not run" lists what was not tried.
What croc is for
Use croc when you need to get something from one computer to another, once, and the usual ways are in the way:
a file to a colleague no chat attachment limit, no upload site, no account on either side
a file to your own machine from a server to your laptop, or between two servers, without ssh keys between them
a whole folder it arrives as a folder, with its files
a line of text a password, a command or a URL, with --text
It does not replace rsync, scp or a shared drive for regular or large jobs: it is for one-off transfers. The default relay is run by the project, so the data passes through a server you do not control (the project says it is encrypted so the relay cannot read it, from its README, and that part was not tested here). You can run your own relay with croc relay, which was not run.
Install
The project's README gives an install script and several other routes (package managers, release files). The script is long, so read it before you run it. What it does, in short: it finds your system, downloads the release archive and a checksums file from GitHub, checks the checksum, unpacks the one binary and installs it into /usr/local/bin. In the lab it printed that the checksum was verified:
$ curl -fsSL https://getcroc.schollz.com -o getcroc.sh
$ sudo bash getcroc.sh
== Checksum of croc_v11.5.5_Linux-64bit.tar.gz verified
== Installed croc to /usr/local/bin/
$ croc --version
croc version 11.5.5
The two computers can run different operating systems, since the program is the same on Linux, macOS and Windows (from the README, not tried here).
Send a file
Two commands, one on each computer. On the sender, croc send and the file name. It prints the code phrase, three words, and waits:
$ croc send invoice-2026-10.pdf
On the receiver, run croc with no arguments. It asks for the code phrase, then asks if you accept the file. Type the phrase, then y. These are the real screens from the lab at the end of the transfer, the sender on top and the receiver below:
ubuntu@laptop:~/send$ croc send invoice-2026-10.pdf
On the other computer, run:
croc point-crane-thank
Or open:
https://getcroc.com/?code=point-crane-thank
Sending 'invoice-2026-10.pdf' (84.0 kB)
Sending (203.0.113.7->172.17.0.5)
invoice-2026-10.pdf 100% |████████████████████| (86/86 kB, 136 MB/s)
ubuntu@laptop:~/send$
ubuntu@server:~/recv$ croc
Enter receive code: point-crane-thank
Accept 'invoice-2026-10.pdf' (84.0 kB)? (Y/n) y
Receiving (172.17.0.5<-203.0.113.7)
invoice-2026-10.pdf 100% |████████████████████| (86/86 kB, 35 MB/s)
ubuntu@server:~/recv$ ls -lh
total 84K
-rw-r--r-- 1 ubuntu ubuntu 84K Oct 20 19:33 invoice-2026-10.pdf
ubuntu@server:~/recv$
Notice that the receiver does not give the phrase on the command line: it is typed at the prompt. In the lab, putting the phrase after croc did not work in this version (see the last section), and croc's own help calls the old way, with the code on the command line, insecure because of a local attack vector. A new phrase is made for every send.
The sender is told when the transfer is done and its prompt comes back. The file arrived with the same size (84 kB) and the same name.
Send a folder
The same two commands work for a folder. The receiver asks if it accepts "3 files and 1 folders" and creates the folder in the current directory:
$ croc send photos
$ croc
croc ruin-line-stray
Or open:
https://getcroc.com/?code=ruin-line-stray
Sending 3 files and 1 folders (1.3 MB)
Sending (203.0.113.7->172.17.0.5)
beach.jpg 100% |████████████████████| (430/430 kB, 411 MB/s) 1/3
dog.jpg 100% |████████████████████| (510/510 kB, 511 MB/s) 2/3
hike.jpg 100% |████████████████████| (380/380 kB, 527 MB/s) 3/3
ubuntu@laptop:~/send$
Accept 3 files and 1 folders (1.3 MB)? (Y/n) y
Receiving (172.17.0.5<-203.0.113.7)
beach.jpg 100% |████████████████████| (430/430 kB, 148 MB/s) 1/3
dog.jpg 100% |████████████████████| (510/510 kB, 190 MB/s) 2/3
hike.jpg 100% |████████████████████| (380/380 kB, 148 MB/s) 3/3
ubuntu@server:~/recv$ ls -lh photos
total 1.3M
-rw-r--r-- 1 ubuntu ubuntu 420K Oct 20 19:33 beach.jpg
-rw-r--r-- 1 ubuntu ubuntu 499K Oct 20 19:33 dog.jpg
-rw-r--r-- 1 ubuntu ubuntu 372K Oct 20 19:33 hike.jpg
ubuntu@server:~/recv$
There is one progress bar for each file, with the speed. The numbers (400 MB/s and more) are high because the lab runs both ends in one machine and the relay was close. A real link between two computers will show its own speed.
A bigger file, and a speed limit
A 12 MB file of random bytes. The global option --throttleUpload limits the upload speed, so a transfer does not use all of a shared connection. It goes before send:
$ croc --throttleUpload 2M send db-dump.sql.gz
ubuntu@laptop:~/send$ croc --throttleUpload 2M send db-dump.sql.gz
On the other computer, run:
croc sweat-jeep-sling
Or open:
https://getcroc.com/?code=sweat-jeep-sling
Sending 'db-dump.sql.gz' (12.0 MB)
Sending (203.0.113.7->172.17.0.5)
db-dump.sql.gz 100% |████████████████████| (13/13 MB, 2.5 MB/s)
ubuntu@laptop:~/send$
ubuntu@server:~/recv$ croc
Enter receive code: sweat-jeep-sling
Accept 'db-dump.sql.gz' (12.0 MB)? (Y/n) y
Receiving (172.17.0.5<-203.0.113.7)
db-dump.sql.gz 100% |████████████████████| (13/13 MB, 2.5 MB/s)
ubuntu@server:~/recv$ ls -lh
total 13M
-rw-r--r-- 1 ubuntu ubuntu 12M Oct 20 19:33 db-dump.sql.gz
-rw-r--r-- 1 ubuntu ubuntu 84K Oct 20 19:33 invoice-2026-10.pdf
drwxr-xr-x 2 ubuntu ubuntu 4.0K Oct 20 19:35 photos
ubuntu@server:~/recv$
The bar shows 2.5 MB/s on both sides for the 12 MB file, so it took about five seconds. Without the option the same file was done in under a second in the lab.
Send a line of text
--text sends a message instead of a file. The receiver is asked if it wants to display it:
$ croc send --text "the wifi password is on the fridge"
$ croc
ubuntu@laptop:~/send$ croc send --text "the wifi password is on the fridge"
On the other computer, run:
croc purse-batch-dodge
Or open:
https://getcroc.com/?code=purse-batch-dodge
Sending 'text' (34 B)
Sending (203.0.113.7->172.17.0.5)
ubuntu@laptop:~/send$
ubuntu@server:~/recv$ croc
Enter receive code: purse-batch-dodge
Display text message (34 B)? (Y/n) y
Receiving (172.17.0.5<-203.0.113.7)
the wifi password is on the fridge
ubuntu@server:~/recv$
It is a quick way to pass a password or a long command from one terminal to another without a chat window. Anyone who has the phrase can read it, so send the phrase to the other person by a different route than the text, if the text is sensitive.
Zip a folder, leave files out
--zip packs a folder into one zip file for the trip, and the receiver unpacks it again. On the sender:
$ croc send --zip photos
On the other computer, run:
croc doll-clamp-print
Or open:
https://getcroc.com/?code=doll-clamp-print
Sending 'photos.zip' (1.3 MB)
Sending (203.0.113.7->172.17.0.5)
photos.zip 100% |████████████████████| (1.3/1.3 MB, 1.3 GB/s)
Removing photos.zip
ubuntu@laptop:~/send$
ubuntu@server:~/recv$ croc
Enter receive code: doll-clamp-print
Accept 'photos.zip' (1.3 MB)? (Y/n) y
Receiving (172.17.0.5<-203.0.113.7)
photos.zip 100% |████████████████████| (1.3/1.3 MB, 442 MB/s)
Unzipping file photos/hike.jpg
ubuntu@server:~/recv$ ls
photos
ubuntu@server:~/recv$
The sender made photos.zip, sent it and removed it again ("Removing photos.zip"). The receiver ended with the photos folder. --exclude takes a comma-separated list of strings, and leaves out any file whose path contains one of them. Here hike is left out, and the receiver was told about 2 files instead of 3:
$ croc send --exclude hike photos
$ croc --out incoming
ubuntu@laptop:~/send$ croc send --exclude hike photos
On the other computer, run:
croc goofy-eel-oval
Or open:
https://getcroc.com/?code=goofy-eel-oval
Sending 2 files and 1 folders (918.0 kB)
Accept 2 files and 1 folders (918.0 kB)? (Y/n) y
Receiving (172.17.0.5<-203.0.113.7)
beach.jpg 100% |████████████████████| (430/430 kB, 186 MB/s) 1/2
dog.jpg 100% |████████████████████| (510/510 kB, 188 MB/s) 2/2
ubuntu@server:~/recv$ ls -R incoming
incoming:
photos
incoming/photos:
beach.jpg dog.jpg
ubuntu@server:~/recv$
--out (a global option, before the code) chose the folder the files arrive in. Here it is incoming. There is also --git, which respects a .gitignore so that ignored files are not sent. It was not run.
Choose your own code phrase
A generated phrase is the safe default. If you want to say the phrase over the phone, or choose it yourself, set it in the environment variable CROC_SECRET on both sides. There is also a --code option on the sender, which was not run: croc's own message says that on Unix you need the variable CROC_SECRET to send with a custom phrase. The phrase must have at least 6 characters, and a short or common one is easier to guess, so do not use a word from a dictionary on its own:
$ CROC_SECRET=my-own-phrase-77 croc send invoice-2026-10.pdf
$ CROC_SECRET=my-own-phrase-77 croc
ubuntu@laptop:~/send$ CROC_SECRET=my-own-phrase-77 croc send invoice-2026-10.pdf
On the other computer, run:
croc my-own-phrase-77
Or open:
https://getcroc.com/?code=my-own-phrase-77
Sending 'invoice-2026-10.pdf' (84.0 kB)
ubuntu@server:~/recv$ CROC_SECRET=my-own-phrase-77 croc
Accept 'invoice-2026-10.pdf' (84.0 kB)? (Y/n) y
Receiving (172.17.0.5<-203.0.113.7)
invoice-2026-10.pdf 100% |████████████████████| (86/86 kB, 38 MB/s)
ubuntu@server:~/recv$
With the phrase in the variable the receiver is not asked for it, only for the yes. A phrase typed into a command line can end up in your shell history, so a generated phrase is the better default.
Say no, and a wrong phrase
The receiver is asked before anything is written. Answer n and nothing arrives; croc says so on the receiver:
ubuntu@laptop:~/send$ croc send invoice-2026-10.pdf
On the other computer, run:
croc sky-stout-stand
Or open:
https://getcroc.com/?code=sky-stout-stand
Sending 'invoice-2026-10.pdf' (84.0 kB)
ubuntu@laptop:~/send$
ubuntu@server:~/recv$ croc
Enter receive code: sky-stout-stand
Accept 'invoice-2026-10.pdf' (84.0 kB)? (Y/n) n
refused files
ubuntu@server:~/recv$
A wrong phrase does not give an error. The receiver shows "waiting for sender..." and keeps waiting until you press Ctrl+C:
ubuntu@server:~/recv$ croc
Enter receive code: wrong-code-here
waiting for sender...
The same screen is what you get when the sender has not started yet, or has already gone, so if nothing happens check the phrase and that the sender is still running.
Options at a glance
The options of croc send, from croc send -h in the lab (the long descriptions are cut to fit):
OPTIONS:
--zip zip folder before sending (default: false)
--code value, -c value codephrase used to connect to relay (at least 6 characters)
--transport value sender file data transport (auto, derp, relay) (default: "auto")
--hash value hash algorithm (xxhash, imohash, md5, highway) (default: "xxhash")
--text value, -t value send some text
--no-local disable local relay when sending (default: false)
--no-multi disable multiplexing (default: false)
--git enable .gitignore respect / don't send ignored files (default: false)
--port value base port for the relay (default: 9009)
--transfers value number of ports to use for transfers (default: 4)
--qrcode, --qr show the web receive URL as a qrcode (default: false)
--exclude value exclude files if they contain any of the comma separated strings
--exclude-file value exclude files matching any of the comma separated relative paths exactly
--socks5 value SOCKS5 proxy address (relay DNS is resolved by the proxy) [$SOCKS5_PROXY]
--connect value add a http proxy [$HTTP_PROXY]
--store upload encrypted files for a finite lifetime or a limited number of verified downloads (default: fals
--store-downloads value number of verified downloads allowed in stored mode (default: 1)
--store-expiration value stored lifetime after upload (for example 90m, 12h, 3d, or 2w) (default: "1d")
--store-url value stored-transfer service origin (default: "https://getcroc.com") [$CROC_STORE_URL]
--help, -h show help (default: false)
The global options (from croc --help), which go before the word send:
GLOBAL OPTIONS:
--internal-dns use a built-in DNS stub resolver rather than the host operating system (default: false)
--classic toggle between the classic mode (insecure due to local attack vector) and new mode (secure) (default: f
--remember save these settings to reuse next time (default: false)
--debug toggle debug mode (default: false)
--yes automatically agree to all prompts (default: false)
--stdout redirect file to stdout (default: false)
--no-compress disable compression (default: false)
--ask make sure sender and recipient are prompted (default: false)
--local force to use only local connections (default: false)
--ignore-stdin ignore piped stdin (default: false)
--overwrite do not prompt to overwrite or resume (default: false)
--rename receive files that already exist under a new name instead of prompting (default: false)
--testing flag for testing purposes (default: false)
--quiet disable all output (default: false)
--disable-clipboard disable copy to clipboard (default: false)
--extended-clipboard copy full command with secret as env variable to clipboard (default: false)
--revoke value revoke a stored transfer using its local sender receipt
--multicast value multicast address to use for local discovery (default: "239.255.255.250")
--curve value choose an encryption curve (p521, p256, p384, siec, ed25519) (default: "p256")
--ip value set sender ip if known e.g. 10.0.0.1:9009, [::1]:9009
--relay value address of the relay (default: "croc.schollz.com:9009") [$CROC_RELAY]
--relay6 value ipv6 address of the relay (default: "croc6.schollz.com:9009") [$CROC_RELAY6]
--out value specify an output folder to receive the file (default: ".")
--pass value password for the relay (default: "pass123") [$CROC_PASS]
--socks5 value SOCKS5 proxy address (relay DNS is resolved by the proxy) [$SOCKS5_PROXY]
--connect value add a http proxy [$HTTP_PROXY]
--throttleUpload value throttle the upload speed e.g. 500k
--help, -h show help (default: false)
Most of these were not run. The ones that were are in the sections above: --text, --zip, --exclude, --throttleUpload, --out, --yes (answer yes without asking) and CROC_SECRET.
What was not run in the lab
Only the commands shown above were run. These were not: sending between two real computers on different networks (the sender and receiver were two panes in one container, going through the public relay); a transfer that was cut and then resumed (the project says croc can resume, and the options --overwrite and --rename deal with files that already exist); your own relay with croc relay; stored transfers (--store, croc store, --revoke), which upload an encrypted copy to the project's service for later download; croc ssh (sharing a terminal); the local-only mode (--local); the QR code (--qr); the --code option on its own; --git; --exclude-file; --zip with a very large folder; the proxy options (--socks5, --connect); the encryption curve (--curve); and the upgrade command. The claim that the relay cannot read the data is from the project's README and was not tested. Windows and macOS were not tried. Everything ran on Ubuntu 24.04 with croc 11.5.5.
Common problems and tips
The receiver says "waiting for sender...". Check the phrase, that the sender is still running (it stops when the transfer is done or when you press Ctrl+C), and that the phrase was typed whole, with its hyphens.
croc followed by the phrase does not work. In this version (11.5.5) the lab showed that the phrase has to be typed at the prompt, or set in CROC_SECRET. To go back to the old behaviour, croc --classic exists, but its own help calls that mode insecure because of local attacks.
It asks "Accept ...? (Y/n)" every time. That is the point of the prompt: you decide what is written to your disk. --yes answers yes for you in scripts.
The file already exists on the receiver. croc asks what to do. --overwrite and --rename choose the answer beforehand (not run).
My firewall blocks it. croc connects out to the relay, by default on port 9009 (the default shown in croc --help), so a firewall that only allows web traffic may block it. This was not tested. Another relay port can be set with --relay.
Tips. Send the phrase by a different route than the file when the file matters. Treat the phrase like a password for one transfer: do not post it in a public channel. For anything you do every day, use rsync or a shared drive, and keep croc for the one-off.