Command-line client

recado pub publishes a message, recado sub prints messages until interrupted. Both work with any MQTT broker.

To administer a broker, use mercurioctl.

Publishing

# A message, at QoS 1
recado pub -t sensors/kitchen -m 21.5 -q 1

# From standard input
echo '{"temp": 21.5}' | recado pub -t sensors/kitchen --content-type application/json

# Each new log line as a message
tail -F /var/log/app.log | recado pub -t logs/app -l

# A binary file, such as an image or a firmware image
recado pub -t cameras/door/snapshot -f snapshot.jpg

# Retained, so new subscribers get it at once
recado pub -t status/door -m open -r

# An MQTT 5 request, with properties
recado pub -t requests/lamp -m on --response-topic replies/me \
    --correlation-data 42 --user-property source=cli --message-expiry 60
OptionMeaning
-t, --topicTopic to publish to (required)
-m, --messagePayload, as text. Without it or -f, standard input is published byte for byte
-f, --file PATHPublish the contents of a file, binary or not
-l, --linePublish each line of standard input as its own message as it comes, on one connection. The line feed, and a carriage return before it, are left out; empty lines are skipped
-q, --qos0, 1 or 2 (default 0)
-r, --retainRetain the message on the broker
--content-typeContent type of the payload, such as a MIME type
--response-topicTopic a reply should be published to
--correlation-dataData that ties a reply to its request, as text
--correlation-data-hexThe same as bytes, in hex, such as 00ff7a
--message-expirySeconds the broker keeps the message for subscribers yet to get it
--utf8Mark the payload as UTF-8 text
--user-property key=valueUser property; may be repeated
--will-topic and the other will optionsAs for sub, below; useful with -l, which keeps the connection open

Subscribing

# Print payloads, with their topics
recado sub -t 'sensors/#' -T

# Several filters
recado sub -t 'sensors/#' -t 'alerts/#' -T

# In a script: the device's retained status, or status 4 after 10 s
recado sub -t devices/7/status -C 1 -W 10

# A persistent subscriber that survives broker restarts and network loss
recado sub -t 'alerts/#' -i monitor -c -x 3600 --reconnect 5 -q 1

# With a will, published if the subscriber disappears
recado sub -t 'cmd/#' --will-topic status/monitor --will-message offline --will-retain
OptionMeaning
-t, --topicTopic filter; may be repeated (required)
-q, --qosQoS of the subscriptions (default 0)
-T, --print-topicPrint the topic and : before each message
--format text|jsontext prints each payload byte for byte, then a line feed; json prints one JSON object per line (below)
--no-localDon't receive messages this client publishes itself
--retain-as-publishedKeep the retain flag messages were published with
--retain-handlingRetained messages on subscribing: 0 always, 1 only for new subscriptions, 2 never
--subscription-idIdentifier the broker attaches to messages matching these subscriptions
-C, --count NExit after N messages, retained ones included
-W, --timeout SECONDSAs mosquitto_sub's -W: exit with status 4 if still running this long after connecting. With -C, that means fewer than N messages came; without it, sub always ends this way
--reconnect SECONDSReconnect after losing the connection, waiting this long between attempts
--will-topic, --will-messageWill published by the broker if the client disconnects unexpectedly
--will-qos, --will-retain, --will-delayQoS, retain flag and delay (MQTT 5) of the will

JSON lines

With --format json, each message is one line holding a JSON object:

$ recado sub -t 'sensors/#' --format json
{"payload":"21.5","payload_base64":"MjEuNQ==","qos":0,"retain":false,"topic":"sensors/kitchen"}
FieldHolds
topic, qos, retainAlways there
payload_base64The payload in base64; always there
payloadThe payload as text, only when it is valid UTF-8
content_type, response_topic, message_expiry, payload_is_utf8The MQTT 5 properties of the same name, when the message has them
correlation_data_base64The correlation data in base64, when there is some
user_properties[name, value] pairs in the order they came, when there are some; a name may repeat
subscription_idsThe identifiers of the matching subscriptions that have one
# The payloads of binary messages, decoded
recado sub -t 'cameras/#' --format json | jq -r .payload_base64 | base64 -d

Connection options

Both commands take these:

OptionMeaningDefault
-H, --hostBroker host namelocalhost
-p, --portBroker port1883
--unix PATHConnect through this Unix socket instead of TCP; not with -H, -p or the TLS options
-i, --client-idClient id. Left out, it is empty and the broker assigns one; MQTT 3.1 takes no empty id, so there recado sends a random recado- idassigned by the broker
-u, --username, -P, --passwordCredentials. The password can also come from RECADO_PASSWORD, which other users can't see in ps; -u alone asks for it when standard error is a terminal
--auth-method scram-sha-256Log in with SCRAM-SHA-256 instead of sending the user name and password in CONNECT: the password, from the same sources, never reaches the broker, and the broker must prove it knows it. Needs -u and MQTT 5
--auth-method scram-sha-256-plusAs scram-sha-256, and bind the login to the TLS connection (SCRAM-SHA-256-PLUS). Needs TLS 1.3 to a broker that terminates it; it fails before CONNECT is sent otherwise, with "channel binding needs a TLS 1.3 connection"
-k, --keep-aliveKeep-alive, in seconds60
-c, --no-clean-startKeep the session after disconnecting. Needs -i, as with mosquitto: a session kept under an id nobody knows could never be resumed
-x, --session-expirySeconds the broker keeps the session after the connection closes (MQTT 5)0
-V, --protocol-version5, 311 or 31; also 3.1.1, 3.1 and mosquitto's mqttv5, mqttv311, mqttv31. Anything else is an error5
--tlsConnect with TLS, verifying the broker with the operating system's certificate store (on Linux the system CA bundle, such as /etc/ssl/certs; the Keychain on macOS; the certificate store on Windows), or, when that holds no usable certificate, the Mozilla roots bundled with the client
--cafileCA certificates (PEM) to verify the broker with, the only ones then trusted; implies --tlsthe operating system's store
--insecureSkip certificate verification, for testing only; implies --tls
--cert PATH, --key PATHClient certificate and its private key, both PEM, for brokers that authenticate clients by certificate; each needs the other, and they imply --tls
--ws, --ws-path PATHSpeak MQTT over a WebSocket on the host and port, wss:// with the TLS options, at this path; not with --unix/mqtt
-v, --verboseVerbose output
# Over TLS, as alice; asks for the password
recado sub -H broker.example.com -p 8883 --cafile ca.crt -u alice -t '#'

# In a script, with the password out of ps
RECADO_PASSWORD="$(cat ~/.mqtt-password)" recado pub -u alice -t status -m up

# Without the password crossing the network
recado pub --auth-method scram-sha-256 -u alice -t status -m up

# MQTT 3.1.1
recado pub -V 311 -t test -m hello

# Through a Unix socket listener
recado sub --unix /run/mercurio/mqtt.sock -t 'sensors/#' -T

Shell completions

recado completions <shell> prints a completion script for bash, zsh, fish, elvish or powershell:

recado completions bash > ~/.local/share/bash-completion/completions/recado
recado completions zsh > "${fpath[1]}/_recado"

Exit status

recado uses the exit statuses of mercurioctl, and 4 for sub -W:

StatusMeans
0Success, or sub stopped by Ctrl-C, SIGTERM or its reader going away. On Ctrl-C and SIGTERM it disconnects cleanly, so the broker drops its will
1The broker refused a subscription, or a QoS 1 or 2 message; the message names the filter and the reason
2The broker couldn't be reached, refused the login, or closed the connection; with --reconnect, when the broker refuses the reconnection for good, as for bad credentials or a ban, and the message says why
3Wrong usage, such as an unknown option or a QoS above 2
4sub -W ran out of time, such as before -C's messages all arrived

Messages and logs go to standard error, so standard output carries only the payloads.