This is a hardened fork of schollz/croc with improved resilience, modern cryptography, and better support for large multi-hour transfers.
croc is a tool that allows any two computers to simply and securely transfer files and folders. AFAIK, croc is the only CLI file-transfer tool that does all of the following:
- Allows any two computers to transfer data (using a relay)
- Provides end-to-end encryption (using PAKE)
- Enables easy cross-platform transfers (Windows, Linux, Mac)
- Allows multiple file transfers
- Allows resuming transfers that are interrupted
- No need for local server or port-forwarding
- IPv6-first with IPv4 fallback
- Can use a proxy, like Tor
- Automatic retry with exponential backoff — dropped connections are retried up to 5 times by default (configurable with
--retry) - Activity-based timeouts — connections stay alive as long as data is flowing (no more hard 3-hour ceiling killing your movie library transfer)
- TCP keepalive — detects dead connections and prevents NAT/firewall timeouts
- Modern cryptography — Argon2id KDF (replaces PBKDF2 with 100 iterations) + XChaCha20-Poly1305 (replaces AES-GCM) + 16-byte salts + HKDF key rotation for long sessions
- Per-file completion tracking — multi-file transfers write a
.croc-progressmanifest so retries and restarts skip already-finished files - Configurable cipher/KDF —
--cipherand--kdfflags let you choose between modern and legacy crypto
For more information about the original croc, see the blog post or read this interview.
Download the latest release for your system from the releases page.
Invoke-WebRequest -Uri "https://github.com/pynchroid/croc/releases/latest/download/croc_Windows-64bit.zip" -OutFile "$env:TEMP\croc.zip"
Expand-Archive -Path "$env:TEMP\croc.zip" -DestinationPath "$env:USERPROFILE\croc" -Force
Write-Host "croc installed to $env:USERPROFILE\croc\croc.exe"To add it to your PATH permanently:
$crocPath = "$env:USERPROFILE\croc"
$currentPath = [Environment]::GetEnvironmentVariable("Path", "User")
if ($currentPath -notlike "*$crocPath*") {
[Environment]::SetEnvironmentVariable("Path", "$currentPath;$crocPath", "User")
Write-Host "Added $crocPath to PATH. Restart PowerShell to use 'croc' from anywhere."
}curl -sL https://github.com/pynchroid/croc/releases/latest/download/croc_macOS-ARM64.tar.gz | tar xz
sudo mv croc /usr/local/bin/For Intel Macs, replace macOS-ARM64 with macOS-64bit.
curl -sL https://github.com/pynchroid/croc/releases/latest/download/croc_Linux-64bit.tar.gz | tar xz
sudo mv croc /usr/local/bin/Other architectures: replace Linux-64bit with Linux-ARM64, Linux-ARM, or Linux-RISCV64.
Requires Go 1.25+:
git clone https://github.com/pynchroid/croc.git
cd croc
go build -o croc .On Windows (PowerShell):
git clone https://github.com/pynchroid/croc.git
cd croc
go build -o croc.exe .To send a file, simply do:
$ croc send [file(s)-or-folder]
Sending 'file-or-folder' (X MB)
Code is: code-phraseThen, to receive the file (or folder) on another computer, run:
croc code-phraseThe code phrase is used to establish password-authenticated key agreement (PAKE) which generates a secret key for the sender and recipient to use for end-to-end encryption.
Retry and long-session support is built in — no flags needed. Just run croc send and it handles the rest:
- 20 automatic retries with exponential backoff (3s → 6s → 12s → ... → 5min cap)
- 2-hour idle timeout that resets on every successful read/write, so active transfers run indefinitely
- Per-file progress tracking via
.croc-progressmanifest — interrupted multi-file transfers automatically skip already-completed files on retry
# Just works — retry and timeout are built in
croc send my-movie-library/
croc <code-phrase>To customize the defaults:
| Flag | Default | Description |
|---|---|---|
--retry |
20 |
Number of retry attempts on connection failure (0 = no retry) |
--retry-wait |
3 |
Base wait in seconds between retries (exponential backoff) |
--timeout |
120 |
Inactivity timeout in minutes (resets on every successful read/write) |
By default, this fork uses Argon2id for key derivation and XChaCha20-Poly1305 for encryption. To use legacy cryptography (for compatibility with upstream croc):
# Both sender and receiver must use the same settings
croc --cipher aes-gcm --kdf pbkdf2 send file.txt
croc --cipher aes-gcm --kdf pbkdf2 <code-phrase>| Flag | Default | Options |
|---|---|---|
--cipher |
xchacha20 |
xchacha20 (recommended), aes-gcm (legacy) |
--kdf |
argon2id |
argon2id (recommended), pbkdf2 (legacy) |
Note: Both sender and receiver must use the same
--cipherand--kdfsettings. This fork is not compatible with upstream croc by default due to the cryptography changes. Use--cipher aes-gcm --kdf pbkdf2for backward compatibility.
On Linux and macOS, the sending and receiving process is slightly different to avoid leaking the secret via the process name. You will need to run croc with the secret as an environment variable. For example, to receive with the secret ***:
CROC_SECRET=*** crocFor single-user systems, the default behavior can be permanently enabled by running:
croc --classicYou can send with your own code phrase (must be at least 6 characters):
croc send --code [code-phrase] [file(s)-or-folder]To automatically overwrite files without prompting, use the --overwrite flag:
croc --yes --overwrite <code>To exclude folders from being sent, use the --exclude flag with comma-delimited exclusions:
croc send --exclude "node_modules,.venv" [folder]You can pipe to croc:
cat [filename] | croc sendTo receive the file to stdout, you can use:
croc --yes [code-phrase] > outTo send URLs or short text, use:
croc send --text "hello world"You can send multiple files directly by listing the files and/or folders:
croc send [file1] [file2] [file3] [folder1] [folder2]To show QR code (for mobile devices), use:
croc send --qr [file(s)-or-folder]You can send files via a proxy by adding --socks5:
croc --socks5 "127.0.0.1:9050" send SOMEFILETo choose a different elliptic curve for encryption, use the --curve flag:
croc --curve p521 <codephrase>For faster hashing, use the imohash algorithm:
croc send --hash imohash SOMEFILEBy default, the code phrase is copied to your clipboard. To disable this:
croc --disable-clipboard send [filename]To copy the full command with the secret as an environment variable (useful on Linux/macOS):
croc --extended-clipboard send [filename]This copies the full command like CROC_SECRET="code-phrase" croc (including any relay/pass flags).
To suppress all output (useful for scripts and automation):
croc --quiet send [filename]You can run your own relay:
croc relayBy default, it uses TCP ports 9009-9013. You can customize the ports (e.g., croc relay --ports 1111,1112), but at least 2 ports are required.
To send files using your relay:
croc --relay "myrelay.example.com:9009" send [filename]You can also run a relay with Docker:
docker run -d -p 9009-9013:9009-9013 -e CROC_PASS='YOURPASSWORD' docker.io/schollz/crocTo send files using your custom relay:
croc --pass YOURPASSWORD --relay "myreal.example.com:9009" send [filename]To use custom ports, set CROC_PORTS (comma-separated) or CROC_PORT (base port):
docker run -d -p 9010-9011:9010-9011 -e CROC_PORTS='9010,9011' -e CROC_PASS='YOURPASSWORD' docker.io/schollz/crocThis fork is based on the excellent work of @schollz and the original croc project. Special thanks to:
- @schollz for creating croc
- @warner for the idea
- @tscholl2 for the encryption gists
- @skorokithakis for proxying two connections
And many more!

