XMC - Xenomorphic Message Client

February 27, 2026 ยท View on GitHub

Build Status Go Report Card GoDoc License

This project provides a unified command-line interface (CLI) for sending and receiving messages to/from different Message and Streaming Brokers. The broker backend is selected at build time using Go build tags. Each flavor produces its own binary with its own name and environment variable prefix.

Building for Different Brokers

Build CommandBinaryBrokerProtocolEnv Prefix
go build -tags artemis -o amc .amcApache ArtemisAMQP 1.0AMC_
./scripts/build-imc-in-container.shimcIBM MQIBM MQIMC_
go build -tags kafka -o kmc .kmcApache KafkaKafkaKMC_
go build -tags mqtt -o mmc .mmcMQTT BrokersMQTT 3.1.1/5.0MMC_
go build -tags nats -o nmc .nmcNATSNATS / JetStreamNMC_
go build -tags pulsar -o pmc .pmcApache PulsarPulsar nativePMC_
go build -tags rabbitmq -o rmc .rmcRabbitMQ v4+AMQP 1.0RMC_

Build all flavors for the platform matrix (linux/amd64, linux/arm64, darwin/arm64, windows/amd64):

./scripts/build-platform-matrix.sh

Artifacts are written under dist/<goos>-<goarch>/.

The goal of this project is to support a common set of features across the different protocols and brokers, comparable to the JMS API. See broker/BROKERS.md for more details.

Usage

After building for your chosen broker, the binary provides the same interface regardless of backend. In the examples below, xmc is used as a placeholder โ€” substitute it with the actual binary name (amc, imc, kmc, mmc, nmc, pmc, or rmc).

Connection Parameters

The following parameters and environment variables can be used for all commands:

  -s, --server string      server URL of the broker    [$<PREFIX>_SERVER]
  -u, --user string        username for SASL login     [$<PREFIX>_USER]
  -p, --password string    password for SASL login     [$<PREFIX>_PASSWORD]
  -v, --verbose            print verbose output

Environment variables are prefixed per flavor: AMC_ for Artemis, IMC_ for IBM MQ, KMC_ for Kafka, MMC_ for MQTT, NMC_ for NATS, PMC_ for Pulsar, RMC_ for RabbitMQ.

TLS / SSL

All brokers support TLS connections:

  --tls                    enable TLS connection
  --ca-cert string         path to CA certificate file
  --cert string            path to client certificate file
  --key-file string        path to client private key file
  --insecure               skip TLS certificate verification

TLS is auto-detected when using amqps:// or kafka+ssl:// URL schemes.

Queue Commands

send

Send a message to a queue:

xmc send <queue> <message>
xmc send <queue> < message.dat           # read from stdin
echo -e "line1\nline2" | xmc send -l <queue>  # send each line as separate message

Flags:

  -T, --contenttype string     MIME type (default "text/plain")
  -C, --correlationid string   correlation ID
  -I, --messageid string       message ID
  -Y, --priority int           priority 0-9 (default 4)
  -d, --persistent             make message persistent
  -R, --replyto string         reply-to queue
  -P, --property strings       properties in key=value format
  -n, --count int              send the message N times (default 1)
  -E, --ttl int                time-to-live in milliseconds (0 = no expiry)
  -l, --lines                  read stdin line by line, send each as separate message

receive

Receive (destructive read) a message from a queue:

xmc receive <queue>
xmc receive -w <queue>             # wait for a message
xmc receive -n 10 <queue>          # receive 10 messages
xmc receive -J <queue>             # output as JSON
xmc receive -S "color='red'" <queue>  # filter by selector

Flags:

  -t, --timeout float32    seconds to wait (default 0.1)
  -w, --wait               wait endlessly for a message
  -q, --quiet              show data only, suppress properties
  -n, --count int          number of messages to receive (default 1)
  -J, --json               output as JSON
  -S, --selector string    JMS-style message selector expression

peek

Peek at a message without removing it (non-destructive read):

xmc peek <queue>
xmc peek -n 5 -J <queue>          # peek 5 messages as JSON

Same flags as receive except messages are never consumed.

request

Send a message and wait for a reply (request-reply pattern):

xmc request <queue> <message>
xmc request -R my-reply-queue <queue> <message>
xmc request -J <queue> <message>   # output reply as JSON

Flags:

  -R, --replyto string     reply queue (default "xmc.reply")
  -t, --timeout float32    seconds to wait for reply (default 30)
  -J, --json               output reply as JSON
  -q, --quiet              show data only

Plus all send flags for the outgoing message.

Topic Commands

publish

Publish a message to a topic:

xmc publish <topic> <message>
xmc publish -n 100 <topic> <message>   # publish 100 times

Same flags as send, plus:

  -K, --key string         message key for partitioning (Kafka)

subscribe

Subscribe and receive a message from a topic:

xmc subscribe <topic>
xmc subscribe -n 10 -J <topic>        # receive 10 as JSON
xmc subscribe -D <topic>              # durable subscription
xmc subscribe -S "type='order'" <topic>  # with selector

Same flags as receive, plus:

  -g, --group string       consumer group ID (default "xmc-consumer-group")
  -D, --durable            create a durable subscription

Management Commands

Broker management operations (available for Artemis, RabbitMQ, Kafka):

xmc manage list                    # list queues/topics
xmc manage purge <queue>           # remove all messages from a queue
xmc manage stats <queue>           # show queue statistics

Application Properties

You can set properties (metadata) for the message:

xmc send <queue> -P key1=value1 -P key2=value2 <message>

If a message has properties, receive shows them automatically. Use -q to suppress.

Working with Files and Redirection

The message can be read from file:

xmc send <queue> < message.dat

By redirecting the output of receive, the message data (and only the data) will be written to a file:

xmc receive <queue> > message.dat

The file will be exactly the same as it was sent. Without redirection the binary adds a newline character at the end of the message data for better readability.

JSON Output

Use -J to get structured JSON output from receive, peek, subscribe, and request:

$ xmc receive -J test-queue
{"data":"hello world","messageId":"ID:123","properties":{"env":"prod"}}

Version

Print the version of the binary:

xmc version

Testing

Unit tests (no broker required):

go test ./cmd/ ./log/ ./broker/amqpcommon/

Integration tests are based on the bats testing framework (included) and depend on a local Artemis broker with its default settings.

If you have Docker you can spin up an Artemis container like so:

docker run --name artemis -d \
    -p 8161:8161 -p 5672:5672 \
    apache/activemq-artemis:latest-alpine

Port 5672 is the default port of the AMQP 1.0 protocol. Port 8161 provides access to the Artemis web console, where you can check the queues and messages manually. Default credentials are artemis/artemis.

Then you can start the tests:

./run-tests.sh

Integration Tests (testcontainers)

Integration tests start real broker containers automatically via testcontainers-go. Requires Docker.

Run all broker integration tests:

./run-integration-tests.sh

Run a single broker:

go test -tags "artemis integration" -timeout 120s -v ./broker/artemis/

Integration tests are tagged with both the broker build tag and integration:

//go:build artemis && integration

IBM MQ is built in a Docker container that downloads the IBM MQ Redistributable SDK and compiles imc without requiring local MQ headers. This requires a working Docker installation.

If you prefer building IBM MQ locally (with IBM MQ SDK already installed), you can still use:

go build -tags ibmmq -o imc .

For platform matrix builds, IBM MQ has these constraints:

  • linux/amd64: built in Docker via scripts/build-imc-in-container.sh.
  • linux/arm64: requires native Linux ARM64 runner with IBM MQ SDK/client installed (public redistributable feed currently provides Linux X64 package).
  • darwin/arm64: requires native macOS arm64 build host with IBM MQ Dev Toolkit installed.
  • windows/amd64: requires native Windows x64 build host with IBM MQ SDK installed.

Contributing

Contributions are welcome. Please open an issue or submit a pull request. Use the latest version of Go and run tests with Artemis.

License

This project is licensed under the MIT License - see the LICENSE file for details