This project’s future depends on community support. Become a sponsor today.
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
For more information about croc, see my blog post or read a recent interview I did.
You can download the latest release for your system, or install a release from the command-line:
curl https://getcroc.schollz.com | bashUsing Homebrew:
brew install crocUsing MacPorts:
sudo port selfupdate
sudo port install crocYou can install the latest release with Scoop, Chocolatey, or Winget:
scoop install crocchoco install crocwinget install schollz.crocYou can install the latest release with Nix:
nix-env -i crocYou can add this to your configuration.nix:
environment.systemPackages = [
pkgs.croc
];First, install dependencies:
apk add bash coreutils
wget -qO- https://getcroc.schollz.com | bashInstall with pacman:
pacman -S crocInstall with dnf:
dnf install crocInstall with portage:
emerge net-misc/crocInstall with pkg:
pkg install crocInstall with pkg:
pkg install crocYou can install from conda-forge globally with pixi:
pixi global install crocOr install into a particular environment with conda:
conda install --channel conda-forge crocAdd the following one-liner function to your ~/.profile (works with any POSIX-compliant shell):
croc() { [ $# -eq 0 ] && set -- ""; mkdir -p "$HOME/.config/croc"; docker run --rm -it --user "$(id -u):$(id -g)" -v "$(pwd):/c" -v "$HOME/.config/croc:/.config/croc" -w /c -e CROC_SECRET docker.io/schollz/croc "$@"; }You can also just paste it in the terminal for current session. On first run Docker will pull the image. croc via Docker will only work within the current directory and its subdirectories.
If you prefer, you can install Go and build from source (requires Go 1.22+):
go install github.com/schollz/croc/v10@latestThere is a 3rd-party F-Droid app available to download.
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.
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 more than 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 run a pool-based relay network where:
- a main node provides relay discovery APIs,
- community relay nodes register themselves,
- senders and receivers automatically discover relays from the pool.
Pool endpoints:
POST /registerPOST /heartbeatPOST /relays
There are two common deployment types.
Built-in defaults:
- Pool URL:
http://croc.schollz.com:9000 - Relay password default:
pass123
Use these commands:
# Community relay node joins default public pool
# Note: for relay node mode, place flags before the trailing "node" argument
croc relay node
# Sender (default pool is used automatically)
croc send log.txt
# Receiver (default pool is used automatically)
croc RELAYID-PIN-WORD-WORD-WORDUse these commands:
# 1) Start main node (pool API)
croc relay main --listen 0.0.0.0:9000
# 2) Start a community relay node and register to the pool
# Note: for relay node mode, place flags before the trailing "node" argument
croc relay --pool http://POOL_IP:9000 --pass YOUR_POOL_PASS --ports 9009,9010,9011,9012,9013 node
# 3) Sender uses pool discovery
croc --pool http://POOL_IP:9000 send log.txt
# 4) Receiver uses the transfer code from sender
croc --pool http://POOL_IP:9000 RELAYID-PIN-WORD-WORD-WORDExample transfer code format:
12ca-1571-friday-brown-fluid
Notes:
- If
--poolis omitted, croc uses the built-in default pool URL. - If pool discovery fails, croc falls back to legacy relay behavior.
- Legacy direct relay mode with
--relaycontinues to work unchanged.
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]croc has evolved through many iterations, and I am thankful for the contributions! Special thanks to:
- @warner for the idea
- @tscholl2 for the encryption gists
- @skorokithakis for proxying two connections
And many more!

