mqhole

AMQP powered wormhole

mqhole

mqhole is a small Crystal CLI for moving bytes between two parties that know the same CloudAMQP team API key and wormhole name. It provisions or reuses one shared LavinMQ CloudAMQP subscription, then uses AMQP(S) durable queues as the transport.

This is a transport tool, not a PAKE/encryption implementation like upstream magic-wormhole. The shared name is hashed into a queue name; anyone with the CloudAMQP API key can access the same broker.

Requirements

  • Crystal 1.20.2 or newer
  • A CloudAMQP team API key

Install dependencies and build:

make

The binary is written to bin/mqhole.

CloudAMQP

Set the API key in the environment:

export CLOUDAMQP_API_KEY=...

The send and receive commands default to scaleway::nl-ams, which CloudAMQP currently reports as supporting shared plans. List regions with shared plans and pass one with --region if you want a different broker location:

bin/mqhole regions --shared-only
bin/mqhole regions scaleway

mqhole creates an instance named after the selected region, for example mqhole-lavinmq-scaleway-nl-ams, and reuses it on later runs.

Usage

Send stdin:

printf 'hello\n' | bin/mqhole send demo

Receive and echo to stdout:

bin/mqhole receive demo

By default, receive exits after one transfer. Use --listen to keep receiving until you stop it, for example with Ctrl-C:

bin/mqhole receive demo --listen

In listen mode, transfer errors such as a bad decryption passphrase are logged and the failed transfer is dropped so later transfers can still be received.

Send and receive a file:

bin/mqhole send demo --file ./payload.bin

bin/mqhole receive demo --output ./received.bin --no-echo

Send encrypted data:

bin/mqhole send demo --encrypted --file ./payload.bin

The sender prints a generated passphrase as a logfmt line:

at=info event=encryption_passphrase passphrase=...

On an interactive terminal, send updates transfer progress in place on stderr. Use --verbose to write progress as logfmt lines instead. File and --data payloads include a known total size; stdin payloads report bytes and rate without a total:

at=info event=send_progress transfer_id=... bytes=... total=... percent=... rate=... rate_human=".../s"
at=info event=receive_progress transfer_id=... bytes=... total=... percent=... rate=... rate_human=".../s"

Receive progress is reported in verbose mode.

Receive encrypted data:

bin/mqhole receive demo --encrypted --output ./received.bin --no-echo

The receiver prompts for the passphrase without echoing it, then prints *** after the passphrase has been read. If encrypted data is received without --encrypted, or if the passphrase is wrong, mqhole exits with a clear error and leaves the AMQP messages unacknowledged so the receive can be retried.

Run a hook with the temporary payload path:

bin/mqhole receive demo --hook 'sha256sum' --hook-mode file --no-echo

Run a hook with the payload as one process argument:

bin/mqhole receive demo --hook 'printf %s' --hook-mode argument --no-echo

Argument hook mode is intended for text payloads. It rejects payloads containing NUL bytes because those cannot be represented safely as process arguments.

Payloads sent to the same name must be sent sequentially. The current protocol expects each transfer's AMQP messages to stay contiguous in the queue, so concurrent sends to the same name can fail with a transfer id mismatch. Use different names if you need overlapping transfers.

Development

Run the checks used by CI:

make check

The live smoke test used during development sent and received data through a real CloudAMQP LavinMQ instance in scaleway::nl-ams.

Repository

mqhole

Owner
Statistic
  • 0
  • 0
  • 0
  • 0
  • 2
  • about 3 hours ago
  • June 29, 2026
License

MIT License

Links
Synced at

Thu, 20 Aug 2026 18:10:53 GMT

Languages