@rujit/rshare
v0.1.1
Published
Send files and folders between computers on the same network: fast, encrypted, one command.
Maintainers
Readme
rshare
Send files and folders from one computer to another (Windows, macOS or Linux) with one command on each side: across the room or across the country. Fast, end-to-end encrypted, no accounts.
computer A computer B
$ rshare add .
$ rshare share
rshare receive 04fccatxfc… ──────► $ rshare receive 04fccatxfc…
✓ Received 505 files (1.0 GB) in 9.4sInstall
npm install -g @rujit/rshareThe package is called @rujit/rshare on npm, and it installs the rshare command. This needs
Node.js 16 or newer. The package contains a small native program for Windows,
macOS and Linux (x64 and ARM), and Node is only used to start it. pip install rdrop is
planned.
Use
On the computer that has the files:
cd my-project
rshare add . # stage the folder you're in
rshare add ~/notes.pdf # stage more files or folders, from anywhere
rshare sharershare share prints a command like rshare receive 04fccatxfcqn51s22qkh0x33crye0sbz00003g8g
and copies it to your clipboard. Send it to the other person any way you like (chat, email),
and they run it on their computer:
rshare receive 04fccatxfcqn51s22qkh0x33crye0sbz00003g8gThe files land in the folder where they ran the command (or in --out <folder>).
On the same network the two computers connect directly. To send to someone on a different network (a friend at their home, say), you need a relay. Set it up once, as described in Sharing over the internet.
Commands
| Command | What it does |
|---|---|
| rshare add <path>... | Stage files or folders. . is the current folder. Wildcards work (rshare add *.pdf), even in cmd and PowerShell. |
| rshare list | Show what's staged, with sizes. |
| rshare remove <path or #> | Unstage something, by path or by its number in list. |
| rshare clear | Unstage everything. |
| rshare share [path...] | Share the staged items, or only the paths given (rshare share movie.mp4). |
| rshare receive <code> | Download everything the other computer is sharing. |
| rshare config | Show settings. rshare config relay <address> sets the relay to use. |
| rshare relay | Run a relay server (see below). |
| Option | |
|---|---|
| share --keep | Keep sharing after the first download. By default a code works once. |
| share --relay <address> | Use this relay for this share. |
| share --local | Don't use the relay this time. |
| share --relay-only | Skip the direct connection and always go through the relay. |
| share --port <n> | Port to listen on locally (default 7878, or any free port if that's taken). |
| share --host <ip> | Listen only on this local address. |
| receive --out <dir> | Where to save files. |
| receive --overwrite | Replace files that differ instead of saving the new copy as name (1).ext. |
| add/share --force | Allow sharing your home folder or another broad folder. |
Good to know
- Interrupted transfers resume. Run the same
rshare receivecommand again. Finished files are skipped and a half-finished file continues where it stopped. This also works with a new code if the sender restartedrshare share. - Nothing gets overwritten. If the receiver already has a different file with the same
name, the new one is saved as
name (1).ext. Identical files are skipped. - Safe folders only.
rshare add .won't share your home folder (where a new terminal opens) unless you add--force, and it never shares a whole drive or an operating-system folder. - Left out: shortcuts/symlinks and OS clutter (
.DS_Store,Thumbs.db,desktop.ini). File names that Windows can't store (what?.txtfrom a Mac) are adjusted on arrival. - Firewalls (same-network sharing). The first time you share on Windows, Windows Defender Firewall asks whether to allow rshare: allow it on Private networks. If your Wi-Fi is marked as a Public network, other computers on it can't connect; switch it to Private in Settings → Network & internet. macOS may ask to accept incoming connections: click Allow. Sharing through a relay needs no firewall changes, because both computers connect out.
Sharing over the internet
Two computers in different homes usually can't connect to each other: home routers block incoming connections, and many internet providers put whole neighborhoods behind one shared address (carrier-grade NAT). The fix that always works is a relay: a small server both computers can reach, which passes the data between them. Tools like croc and AnyDesk work the same way.
The relay is built into rshare (rshare relay). You run it once on a server with a public
address, then point rshare at it:
rshare config relay wss://your-relay.example.com # on each computer that sharesThat's all. rshare share now prints a code that works from anywhere, and the receiver
doesn't configure anything, because the code says where the relay is. When both
computers turn out to be on the same network, they still connect directly, which is faster
and doesn't touch the relay.
The relay can't read anything. The encryption runs end to end between the two computers, straight through it, and the relay never sees the code's secret. It does see both computers' IP addresses, when a transfer happens and how big it is.
Where to run the relay
Pick whichever suits you. The relay uses very little memory or CPU. What it does use is bandwidth: every byte sent goes through it once in and once out.
A. Any small Linux server. This means a VPS ($4–6/month at DigitalOcean, Hetzner, Vultr and others), the free Oracle Cloud VM, or a home server with a port forwarded.
# from this repository, after `npm run build` (use linux-arm64 for ARM servers):
scp packages/npm/dist/linux-x64/rshare you@SERVER:/tmp/rshare
ssh you@SERVER
sudo install -m 755 /tmp/rshare /usr/local/bin/rshare
rshare relay # try it; Ctrl+C to stopTo keep it running and have it start on boot, copy
deploy/relay/rshare-relay.service (in the source repository) to
/etc/systemd/system/ and run sudo systemctl enable --now rshare-relay. Then open port
8080 in the provider's firewall ("security group"), and on your computer:
rshare config relay ws://SERVER_IP:8080B. Render, free, with no server to manage. Push this repository to GitHub, then on
render.com choose New → Blueprint and pick the repository. It reads
render.yaml, builds the relay and gives you an address like
https://rshare-relay-abcd.onrender.com. Then run:
rshare config relay wss://rshare-relay-abcd.onrender.comFree Render services go to sleep after about 15 minutes without traffic. The first share after that waits up to a minute while it wakes up, and the free plan has a monthly bandwidth allowance. Any other host that runs Docker images and supports WebSockets works too (Railway, Fly.io, Koyeb…).
C. Docker, anywhere:
docker build -f deploy/relay/Dockerfile -t rshare-relay .
docker run -d -p 8080:8080 --restart unless-stopped rshare-relayMake it the default for everyone
Put the relay's address in the DEFAULT_RELAY file, run npm run build,
and publish. Every copy of rshare installed from that build uses your relay automatically:
nobody runs rshare config, and share codes stay short because they don't need to spell out
the address.
Keeping your relay to yourself
An open relay lets anyone relay through it. They still can't read anyone else's files, but they would use your bandwidth. To restrict it, start it with a key and include the key in the address:
rshare relay --key s3cret # or set RSHARE_RELAY_KEY
rshare config relay wss://your-relay.example.com/?key=s3cretThe key travels inside share codes, so receivers don't need to know it. (If you publish a
build with the key in DEFAULT_RELAY, assume it's public.)
No server at all?
If both people install Tailscale (free for personal use), their computers behave as if they were on the same network. rshare then connects directly without a relay.
Security
- Each
rshare sharecreates a new random 128-bit secret. It exists only inside the code. Without it nobody can download anything, and it can't be guessed. - Everything is encrypted with TLS 1.3. Both sides also prove they know the secret, tied to
that particular encrypted connection. So nobody in the middle (including a relay) can read
the traffic or pretend to be the sender. (Details:
core/internal/transfer/secure.go.) - On the local network, the sender listens only on private addresses (192.168.x.x, 10.x.x.x, 172.16–31.x.x, 100.64–127.x.x for VPNs like Tailscale, 169.254.x.x for direct cables), never on a public internet address. Across networks it connects out to the relay; nothing is opened up on your router.
- The relay knows a share only by a one-way hash of its secret, so it can't work the secret out. Someone who learned that hash could knock on the share, but without the secret the sender turns them away.
- A receiver can only download what was shared. It can't browse the sender's disk. Incoming file names are checked so a malicious sender can't write outside the destination folder.
- While a share is running, treat the code like a password.
How it works, and why it's fast
- The core is one native program written in Go: no runtime to install, about 8 MB, and it starts instantly. The npm package is a thin launcher for it, and the pip package will wrap the same program.
- On the same network the computers connect directly, so the speed is set by your network and disks. Over loopback it moved 1 GB (encrypted) at about 500 MB/s. Through a relay, the limit is usually the sender's upload speed.
- The code contains all of the sender's local addresses plus the relay. The receiver tries the direct addresses at once and the relay a moment later, then uses whichever works first. Nobody has to work out which IP address to use.
- Big files stream in large chunks. Folders full of small files are fetched in batches over 4 parallel connections, so they don't crawl.
- If the connection drops, the receiver reconnects and resumes mid-file by itself.
- The relay speaks WebSocket, so it can sit behind ordinary HTTPS web hosting on port 443. Even strict office and campus networks allow that.
Develop
You need Go 1.22+ and Node.js 16+.
npm run build:dev # build for this machine only
npm test # Go unit and end-to-end tests (including the relay)
npm run build # cross-compile all 6 platforms into packages/npm/dist
npm run pack # build, then create packages/npm/rujit-rshare-<version>.tgzTo try the packed tarball: npm i -g ./packages/npm/rujit-rshare-0.1.1.tgz.
To release: bump VERSION, run npm run build, then cd packages/npm && npm publish.
core/ Go source of the rshare program (all the logic)
cmd/rshare/ entry point
internal/cli/ commands and output
internal/config/ per-user settings (which relay to use)
internal/relay/ the relay server, and the client side senders/receivers use
internal/stage/ staging list, and the "don't share my whole drive" guard
internal/transfer/ share codes, encryption, sender, receiver
internal/ui/ colors, progress bar, clipboard
deploy/relay/ Dockerfile and systemd service for running a relay
packages/npm/ npm package: launcher + prebuilt binaries (dist/ is generated)
packages/python/ pip package skeleton (not published yet)
scripts/build.mjs cross-compiles core/ for every platform
VERSION one version number for every package
DEFAULT_RELAY relay address built into every copy (empty = none)
render.yaml one-click relay deployment on RenderRoadmap
pip install rdrop(one wheel per platform; the skeleton is inpackages/python)- Direct connections between different networks (NAT hole punching) where routers allow it, so the relay is only the fallback
- One npm package per platform, so an install downloads only the binary it needs
