rpipe bridges a local process (or stdin/stdout) with Redis pub/sub channels, enabling distributed message passing between processes across machines — with end-to-end encryption.
Process A (machine 1) Process B (machine 2)
+-----------------------+ +-----------------------+
| COMMAND stdout |---- channel "B" --->| COMMAND stdin |
| COMMAND stdin |<--- channel "A" ----| COMMAND stdout |
+-----------------------+ +-----------------------+
rpipe -name A -target B cmd rpipe -name B -target A cmd
rpipesubscribes to a Redis channel with its own name (-name)- Spawns (or acts as) a child process
- Publishes the child's stdout to the target Redis channel (
-target) - Feeds incoming Redis messages into the child's stdin
Messages are encrypted with PKI (RSA key exchange + AES symmetric encryption) by default.
Download the latest binary from the Releases page.
Available platforms:
linux/amd64darwin/amd64darwin/arm64(Apple Silicon)windows/amd64
Requires Go 1.24+.
git clone https://github.com/sng2c/rpipe.git
cd rpipe
go build -o rpipe .Rpipe V1.1.0
Usage: rpipe [flags] [COMMAND...]
Flags:
-blocksize int
blocksize in bytes (default 524288)
-c Chat mode: send as 'TARGET<message' (or '<message' if -target set), receive as 'SENDER>message'.
-chat
Chat mode: send as 'TARGET<message' (or '<message' if -target set), receive as 'SENDER>message'.
-n string
My channel name (env: RPIPE_NAME)
-name string
My channel name (env: RPIPE_NAME)
-nonsecure
Non-Secure rpipe.
-r string
Redis URL (env: RPIPE_REDIS, default: redis://localhost:6379/0) (default "redis://localhost:6379/0")
-redis string
Redis URL (env: RPIPE_REDIS, default: redis://localhost:6379/0) (default "redis://localhost:6379/0")
-t string
Target channel (env: RPIPE_TARGET).
-target string
Target channel (env: RPIPE_TARGET).
-v Verbose
-verbose
Verbose
Environment variables:
RPIPE_REDIS Corresponds to -redis flag
RPIPE_NAME Corresponds to -name flag
RPIPE_TARGET Corresponds to -target flag
Raw binary transfer. No message format required. Automatically sends an EOF signal when the input stream closes, terminating the receiver.
# Send a file to remote
cat file.tar.gz | rpipe -name alice -target bob
# Receive on the other side
rpipe -name bob -target alice > file.tar.gzSend format: TARGET<message — delivers to the TARGET channel.
When -target is set, use <message (target omitted) and the target is filled automatically.
Received messages are printed to stdout as SENDER>message.
# One-to-one chat: set -target and use <message
rpipe -name alice -target bob -chat
# Input: <hello → sent to bob
# Output: bob>hi ← message from bob
# Multi-channel: specify target per message
rpipe -name alice -chat
# Input: bob<hello → sent to bob
# Input: carol<hi → sent to carol
# Output: bob>hey ← message from bobWraps a child process. The child's stdout is published to Redis; incoming Redis messages are fed to the child's stdin.
rpipe -name alice -target bob ./my-programThe child process receives two environment variables:
RPIPE_NAME— this node's channel nameRPIPE_TARGET— the target channel name
Receiver:
rpipe -name receiver -target sender > received.tar.gzSender:
cat archive.tar.gz | rpipe -name sender -target receiverNode A:
rpipe -name alice -target bob -chatNode B:
rpipe -name bob -target alice -chatType <hello on node A — node B receives alice>hello.
Server (bob):
rpipe -name bob -target alice -chat bashClient (alice):
rpipe -name alice -target bob -chat
# Type: bob<ls -la
# Output: alice>total 12\n...rpipe -name alice -target bob -redis redis://user:password@myredis.host:6379/1By default, rpipe uses end-to-end encryption:
- Each node registers its RSA public key in Redis on startup
- A symmetric AES key is negotiated per channel pair
- All message payloads are AES-encrypted
Use -nonsecure to disable encryption (e.g. for debugging or trusted networks).
| Layer | Algorithm |
|---|---|
| Key exchange | RSA-2048 + OAEP (SHA-256) |
| Symmetric | AES-256-GCM |
| Key TTL | 1 hour (auto-rotated) |
Symmetric keys expire after 1 hour. When a key expires:
- The sender notifies the receiver (Control=1) to clear its cached key
- A new symmetric key is negotiated and stored in Redis
On the receiver side, if AES decryption fails (e.g. due to a race during rotation), the cached key is invalidated and re-fetched from Redis automatically.
v1.1.0 upgraded the encryption algorithms (PKCS1v15 → OAEP, AES-128-CFB → AES-256-GCM). All nodes communicating with each other must run the same major version. Upgrade all nodes simultaneously.
| Variable | Description |
|---|---|
RPIPE_REDIS |
Redis URL (corresponds to -redis flag) |
RPIPE_NAME |
My channel name (corresponds to -name flag) |
RPIPE_TARGET |
Target channel (corresponds to -target flag) |
See LICENSE.