Receive files from the command line
Last updated: 2026-08-06
Sending is only half the story — sooner or later you're on the receiving end: a colleague wants to hand you a file across the internet, one of your own machines wants to hand off to another, or you want to reach out and grab something from a server you administer. The Relayium CLI covers all three with a different command for each, and none of them need an account.
Pick receive when someone else is pushing to you by pairing code, serve when you want a standing inbox that trusted machines can push to any time, and pull when you're the one reaching out to a server you can already ssh into.
Three ways to receive, and when each applies
Which command you run depends on who's starting the transfer and how the two machines know each other:
- relayium receive <code> [destdir] — someone sends to you across networks using a pairing code their CLI minted and passed to you out of band. Direct peer-to-peer, with a SAS code you can compare.
- relayium serve [--dir D] [--port N] [--once] [--allow-delete] — this machine listens for daemon-direct relayium:// pushes, on port 9031 by default.
- relayium pull [user@]host:src <dest> — you reach out over SSH to a server you can already log into and fetch files back.
receive: someone sends you a file across networks
What you need before step 1
- The CLI on this machine. relayium version prints a version string; a shell that answers command not found means it is not installed here yet.
- A sender who is signed in and at their terminal right now. Only they need an account — you never sign in to receive.
- The six digits, passed to you out of band. They live five minutes from the moment their CLI minted them, so agree on the moment first.
- A way to read six more digits back to them afterwards: the SAS is compared out loud, not on screen.
- The other end must be the CLI. A browser cannot join a CLI pairing code — if that is what you have, ask for a relayium up link instead.
This is the receiving half of relayium send. The other person runs relayium send <path> on their end (after relayium login); their CLI mints a 6-digit code, good for 5 minutes, and prints it. They tell you what it is over any channel you both trust — a call, a chat message. You run receive with that code:
relayium receive 483920
# or into a specific directory
relayium receive 483920 ./downloads
Agree with the sender on when they will run send. The code starts expiring the moment it is minted, not the moment you get it.
Take the six digits over a channel you both trust — a call, a chat window, the room you are both in.
Run receive from the directory where the files should land, or name one explicitly.
relayium receive 483920relayium receive 483920 ./downloadsWhen both terminals print a verification code, read yours aloud and check it matches theirs. It is not the pairing code, and it is the only thing that rules out a substituted endpoint.
Leave the terminal alone until it returns to the prompt. This is one live session: closing either end stops the transfer.
What a successful receive looks like
The connection is announced as direct, and both terminals print the SAME verification code. Different codes are the one result you must not accept — stop and check with the sender which machine they are on.
$ relayium receive 483920
verification code (SAS): 271044 — not the pairing code; compare it on both ends to rule out a substituted endpoint
path: direct- The connection is direct, peer-to-peer, and end-to-end encrypted; both terminals print the same SAS (short authentication string) once connected. Compare it out of band to confirm that the pinned TLS certificate fingerprints were not substituted and the rendezvous service did not impersonate either endpoint. The SAS authenticates the endpoints; it does not prove every network hop.
- No destination given: files land in the current directory.
- Same direct-only rule as send: if no direct path can be found between the two networks, the transfer fails rather than routing through a relay.
- This is the CLI's own pairing-code protocol — CLI codes pair CLI to CLI. It doesn't interoperate with the browser's pairing code or QR flow at relayium.com today; that's a possible future addition, not something you can rely on yet. If you only have a browser, ask the sender for a relayium up download link instead.
- The receiver never needs an account, on any network. Only the sender signs in, so their CLI can mint the code.
serve: turn this machine into a listening drop box
serve works the other way around: instead of you reaching out, other machines push straight to you over relayium:// — built for machines you already trust, like your own laptop pushing to a NAS, or a build server dropping artifacts on a box you own — over a pinned TLS 1.3 connection, no SSH, no rendezvous.
relayium serve
# a specific directory, port, and allowing delete requests
relayium serve --dir ~/incoming --port 9031 --allow-delete
Start the listener, naming the directory pushes should land in.
relayium serve --dir ~/incomingWhen a new machine pushes for the first time, serve shows its address and fingerprint and asks. Approve it once and later pushes from that fingerprint go through silently.
If this listener will run without a terminal, do not rely on that prompt — nobody is there to answer it, and an unrecognised pusher is rejected outright. Pre-authorize instead, as the next section describes.
- The first time a new machine pushes to you, serve (running in a terminal) shows its address and fingerprint and asks you to approve it once; after that, pushes from the same fingerprint go through silently.
- Without a terminal — a systemd service, a script with no TTY — there's no one to ask, so an unrecognized pusher is rejected outright. Pre-authorize it instead, using the fingerprint the pusher prints with relayium id:
Pre-authorize for unattended serve
For a serve that runs unattended (systemd, a background script), have the pusher run relayium id to print its fingerprint, then approve it ahead of time from the receiving side:
relayium authorize <fingerprint>
- --dir sets where files land (default the current directory); --once accepts a single transfer and exits; --allow-delete lets an incoming --delete (mirror) request actually remove files here, and is off by default.
- --config-dir (default ~/.config/relayium) is where this host's identity and its authorized-fingerprints list live — override it if you're running serve as a dedicated service.
pull: reach out and fetch from a server you can ssh into
pull is the mirror of push: instead of waiting for someone to send you something, you reach out over your existing SSH access and fetch files back.
relayium pull user@host:/path/to/files ./local-dest
Confirm the remote actually has the CLI. pull runs relayium on the far end, and unlike push there is no tar fallback, so a missing binary fails the whole command.
ssh user@host command -v relayiumIf it is missing, install it there first.
curl -fsSL https://relayium.com/install.sh | shPull the files back over your existing SSH access. -i and -p behave like ssh's own.
relayium pull user@host:/path/to/files ./local-dest
- Unlike push, pull always needs relayium already installed on the remote — there's no tar fallback for pulling from a bare server. If the remote doesn't have it yet, install it there first with curl -fsSL https://relayium.com/install.sh | sh.
- Files are verified with a per-file SHA-256 check and resume automatically if interrupted (add --no-resume to disable).
- -i and -p behave like ssh's own -i/-p, for a specific identity file or port.
When it doesn't work
Five failures cover nearly every unsuccessful receive. Which command you were running decides which of them applies, and each has a line to read or a command to run that settles it.
Symptom, check, fix
- You type the code and the rendezvous refuses it.
relayium receive 483920 # the rendezvous refuses the codeAlmost always the five minutes elapsed — the code expires from the moment the sender's CLI minted it, not from when you were told. Ask them to run send again and read you the fresh digits straight away. A mistyped digit looks identical from here, so re-read it back before assuming it lapsed.
- The transfer completes but you cannot find the files.
relayium receive 483920 ./downloadsWith no destination, receive writes into the directory you ran it from, which is rarely where you were looking. Pass one explicitly, or run pwd first and be sure.
- It fails with "no direct connection to the peer (both ends behind strict NAT?)".
relayium receive 483920 # no direct connection to the peer (both ends behind strict NAT?): …The CLI pairing path is direct-only by design: when no direct route exists it fails rather than routing your file through a relay. Nothing on your side fixes that. Ask the sender for a relayium up download link instead, or, between machines you both control, use daemon-direct or push over SSH.
- pull fails immediately, complaining that relayium was not found.
ssh user@host command -v relayium # (no output)pull runs relayium on the remote — it is the sender in that exchange — and there is no tar fallback the way push has one. Install the CLI on the remote first, then re-run the pull.
- A machine pushes to your serve listener and is rejected without ever prompting you.
relayium serve --dir ~/incomingThe prompt only exists when serve has a terminal. Under systemd, in a script, or behind a pipe there is nobody to ask, so an unknown fingerprint is refused outright. Have the pusher run relayium id and pre-authorize it here with relayium authorize <fingerprint>, using the same --config-dir the listener runs under.
Frequently asked questions
Do I need an account to receive files?
No. All three ways — receive, serve, and pull — are completely free and need no Relayium account on your side. The one sign-in anywhere is the sender's in receive mode, so their CLI can mint the pairing code.
Does relayium receive interoperate with the browser's pairing code?
No. The CLI's pairing-code protocol is separate from the browser's join-link and QR flow at relayium.com — they use different handshakes and don't talk to each other today, so a CLI code only pairs with another CLI. That's on the roadmap, not something you can rely on yet. Until then, a browser recipient wants a relayium up link rather than a code.
What happens if an unknown machine pushes to my serve listener?
In a terminal, you're prompted to approve it by address and fingerprint on its first push, and the approval is remembered. Without a terminal — a systemd service, a cron job — there's no one to ask, so an unrecognized pusher is rejected; pre-authorize it first with relayium authorize <fingerprint>.
Can I pull from a server that doesn't have relayium installed?
No. pull always needs relayium on the remote end; there's no tar fallback the way there is for push. Install relayium there first.
Where does relayium keep my identity and trusted peers?
In ~/.config/relayium by default — override the location with --config-dir on any command that touches identity or trust.
Ready to receive your first transfer? Install the CLI and pick receive, serve, or pull.
Get the CLI