Broker Testing

HiveMQ MQTT CLI: Test Any Broker from the Terminal

Use the open-source HiveMQ MQTT CLI to test any broker: install it, publish and subscribe, use the interactive shell and run mqtt test to probe broker features.

Updated · 8 min read

HiveMQ MQTT CLI: Test Any Broker from the Terminal

The HiveMQ MQTT CLI (mqtt-cli) is an open-source, Java-based command-line client that works against any MQTT broker. Its command is simply mqtt, and four subcommands cover nearly every terminal test: mqtt pub, mqtt sub, the interactive mqtt shell, and mqtt test, which probes what a broker supports.

This guide shows how to install it, connect to a real broker with TLS and credentials, use MQTT 5 properties, and run the feature test — with commands you can paste.

Install mqtt-cli

PlatformCommand
macOS (Homebrew)brew install hivemq/mqtt-cli/mqtt-cli
Dockerdocker run --rm -it hivemq/mqtt-cli <command>
Debian / Ubuntu, RPMPackages from the GitHub releases page of hivemq/mqtt-cli
Any OS with JavaDownload the mqtt-cli-<version>.jar and run java -jar mqtt-cli-<version>.jar

Recent releases also ship native binaries, so Java is not always required. Check the installation with mqtt --version. With Docker, the image's entry point is the CLI, so docker run --rm -it hivemq/mqtt-cli pub -h ... replaces mqtt pub -h ....

Publish and subscribe

Open two terminals. Start the subscriber first so it is listening when the message arrives:

Terminal 1 — subscribe and show topics
mqtt sub -h broker.connectmq.com -p 1883 \
  -t 'testmqtt/cli/#' -q 1 -T
Terminal 2 — publish
mqtt pub -h broker.connectmq.com -p 1883 \
  -t 'testmqtt/cli/hello' -m 'Hello from mqtt-cli' -q 1

-T (--showTopics) prints the topic before each payload, which you need when subscribing with wildcards. The options you will use most:

OptionMeaning
-h, -pHost and port (defaults: localhost, 1883)
-tTopic (pub) or topic filter (sub); repeat -t to subscribe to several
-mMessage payload; -m:file payload.json reads it from a file
-qQoS 0, 1 or 2
-rPublish as retained
-iClient identifier
-u, -pwUsername and password (note: -pw, not -P)
-V 3 / -V 5Protocol version; MQTT 5 is the default
-d, -vDebug and verbose logging, including the packets exchanged

Two subscriber flags are useful in scripts: -J (--jsonOutput) prints each message as a JSON object with topic, QoS and payload, and -of messages.log (--outputToFile) appends everything to a file. Pipe the JSON into jq and you have a quick assertion tool.

Credentials and TLS

Authenticated publish over TLS (port 8883)
mqtt pub -h broker.connectmq.com -p 8883 -s \
  -u "$MQTT_USER" -pw "$MQTT_PASS" \
  -t 'testmqtt/cli/secure' -m 'over TLS'

-s (--secure) enables TLS with the system trust store. For a broker with a private CA add --cafile ca.pem; for mutual TLS add --cert client.pem --key client.key. A failing handshake prints a Java SSL exception — see testing the TLS connection to isolate certificate problems with openssl first.

WebSocket

Browser apps reach the broker over WebSocket, and proxies sometimes break exactly that path. Test it directly:

Subscribe over secure WebSocket
mqtt sub -h broker.connectmq.com -p 8084 -s \
  -ws -ws:path /mqtt \
  -t 'testmqtt/cli/#' -T

If this works but your web app does not, the problem is in the browser (mixed content, CORS, wrong URL), not the broker.

MQTT 5 properties

mqtt pub exposes the MQTT 5 PUBLISH properties as flags, which makes it handy for checking that a broker forwards them:

Publish with MQTT 5 properties
mqtt pub -h broker.connectmq.com -p 1883 \
  -t 'testmqtt/cli/props' -m '{"cmd":"reboot"}' -q 1 \
  -up 'source=ci' -up 'trace-id=abc123' \
  -ct application/json \
  -e 60 \
  -rt 'testmqtt/cli/replies' -cd 'req-42'

That sets two user properties, a content type, a 60-second message expiry, a response topic and correlation data. Run the subscriber with -J and the properties appear in its output. The MQTT 5 features testing guide explains what each property should do and how to verify it.

The interactive shell

mqtt shell starts a REPL where you can hold several connected clients at once and switch between them — perfect for reproducing interactions such as session takeover or no-local subscriptions without opening five terminals.

mqtt shell session
mqtt> con -i sensor-1 -h broker.connectmq.com -p 1883
sensor-1@broker.connectmq.com> sub -t testmqtt/cli/commands -q 1
sensor-1@broker.connectmq.com> con -i backend-1 -h broker.connectmq.com -p 1883
backend-1@broker.connectmq.com> pub -t testmqtt/cli/commands -m 'restart'
backend-1@broker.connectmq.com> switch sensor-1
sensor-1@broker.connectmq.com> ls
sensor-1@broker.connectmq.com> dis
mqtt> exit

con connects a new client and makes it the active context; pub, sub and unsub act on the active client; switch changes context; ls lists connected clients; dis disconnects. Messages received by a subscribed client are printed in the shell as they arrive. A quick experiment: connect a second client with the same -i sensor-1 and watch the first one get disconnected — the classic duplicate client ID symptom.

mqtt test: probe what the broker supports

mqtt test connects to a broker and reports which MQTT features work. It is the quickest way to answer "does this broker support MQTT 5, QoS 2, retained messages and shared subscriptions?"

Run the feature test
mqtt test -h broker.connectmq.com -p 1883 -u "$MQTT_USER" -pw "$MQTT_PASS"

The output has one section per protocol version. Its exact layout depends on the CLI version, but it looks like this (values vary by broker and configuration):

Shape of the output
MQTT 3: OK
	- Maximum topic length: ... bytes
	- QoS 0: Received .../10 publishes in ...ms
	- QoS 1: ...
	- QoS 2: ...
	- Retain: OK
	- Wildcard subscriptions: OK
	- Shared subscriptions: OK
	- Payload size: >= ... bytes
	- Maximum client id length: ... bytes
MQTT 5: OK
	- Connect restrictions:
		> Retain: OK
		> Wildcard subscriptions: OK
		> Shared subscriptions: OK
		> Subscription identifiers: OK
		> Maximum QoS: 2
		> Receive maximum: ...
		> Maximum packet size: ... bytes
		> Topic alias maximum: ...
		> Session expiry interval: ...
		> Server keep alive: ...

The MQTT 5 "connect restrictions" come straight from the CONNACK properties the broker sends; the MQTT 3 lines are measured by actually publishing and subscribing. Add -a (--all) to also run the MQTT 3 tests when MQTT 5 succeeds, and -V 3 or -V 5 to limit the test to one version. If you need the same information inside your own tooling, test which MQTT features a broker supports shows how to build the probe in Python.

Defaults and scripting

Typing -h broker.connectmq.com -p 8883 -s gets old. mqtt-cli reads defaults such as host, port, protocol version and client ID prefix from a properties file in ~/.mqtt-cli/ — check the documentation for your version for the exact keys. With defaults set, mqtt pub -t x -m y goes to your broker.

A minimal smoke test for a shell script or CI job:

smoke.sh
#!/usr/bin/env bash
set -euo pipefail
TOPIC="testmqtt/cli/smoke-$RANDOM"

mqtt pub -h broker.connectmq.com -p 1883 -t "$TOPIC" -m 'ping' -r -q 1
# a retained message is delivered immediately on subscribe; listen for 5 s
OUT=$(timeout 5 mqtt sub -h broker.connectmq.com -p 1883 -t "$TOPIC" -q 1 || true)
echo "$OUT" | grep -q 'ping' && echo "OK" || { echo "FAIL: '$OUT'"; exit 1; }
# clear the retained message
mqtt pub -h broker.connectmq.com -p 1883 -t "$TOPIC" -m '' -r

The retained message makes the test independent of timing: the subscriber receives it as soon as the subscription is active. For more patterns see MQTT bash scripting and mosquitto_pub and mosquitto_sub examples; the online client is a quick way to watch the same topic from a browser while the script runs.

Watch mqtt-cli traffic in the browser

mqtt-cli is a solid default terminal client: complete MQTT 5 flags, a shell for multi-client scenarios and a built-in broker feature test. Keep a few commands in your repository and every teammate can reproduce a broker issue the same way.

Frequently asked questions

Does the HiveMQ MQTT CLI only work with HiveMQ?

No. The pub, sub, shell and test commands are plain MQTT clients and work with any standards-compliant broker, including Mosquitto, EMQX, VerneMQ and managed services. Only the hivemq and swarm subcommands are specific to HiveMQ products.

Why does mqtt sub print nothing?

Usually the topic filter does not match, the broker rejected the subscription because of an ACL, or the publisher used a different broker or port. Add -T to show topics, use -d for debug output and check the SUBACK reason code.

What is the difference between mqtt-cli and mosquitto_pub?

Both publish and subscribe from the terminal. mqtt-cli adds an interactive shell with several named clients, a feature test for brokers, JSON output and full MQTT 5 property flags, while mosquitto_pub and mosquitto_sub are smaller and installed almost everywhere Mosquitto is.