Motivation
When working with Apache Pulsar there are often situations in which you want to quickly access topics - for example for debugging, testing or automating message flows. The existing clients and UIs are powerful, but often heavy or not optimized for straightforward use in the shell.
pulsar-cli closes this gap:
A compact command line tool that exposes the basic Pulsar operations directly: Reader, Consumer and Producer - without setup, containers or external dependencies.
Implementation in Go
The choice was consciously made in favor of Go because it allows statically linked, cross-platform binaries to be created - a significant advantage for tools that are intended to function portably and independently.
A simple cross-compiling is enough:
GOOS=linux GOARCH=amd64 go build -o pulsar-cli
GOOS=darwin GOARCH=arm64 go build -o pulsar-cli
GOOS=windows GOARCH=amd64 go build -o pulsar-cli.exe
The result is standalone programs for Linux, macOS and Windows - without shared libraries, without a runtime environment, without an installation process. Copy a binary, set environment variables, get started.
Architecture and construction
The tool follows a clear structure:
pulsar-cli/
├── LICENSE
├── Makefile
├── README.md
├── go.mod
└── main.go
All logic is in one file (main.go).
The CLI is implemented via spf13/cobra and uses the official Pulsar Go client for communication.
When started, the tool registers three commands:
reader– reads messages from a certain point in the topicconsumer– receives messages via a subscriptionproducer– sends messages entered viastdin
The configuration is done exclusively via environment variables:
export PULSAR_URL=pulsar+ssl://broker.example.org:6651
export PULSAR_JWT=<token> # optional
Example: Reading news
The Reader command can be used to retrieve messages from a topic. Metadata (topic, message ID, timestamp) is output on stderr, the payload on stdout.
pulsar-cli reader -t persistent://public/default/test
Output example:
INFO[0000] Reading from topic persistent://public/default/test ...
INFO[0001] received message msgID=0001 publishAt=2025-10-19T20:10:00Z
{"event":"status","value":"ok"}
This allows the payload to be further processed in a targeted manner:
pulsar-cli reader -t mytopic | jq '.event'
Example: Consuming news
The Consumer works with a Pulsar subscription and automatically confirms messages after successful receipt. The same applies here: log output on stderr, user data on stdout.
pulsar-cli consumer -t persistent://public/default/test -s demo-sub
Example output:
INFO[0000] Consuming from topic persistent://public/default/test with subscription demo-sub ...
INFO[0002] received message msgID=0002 publishAt=2025-10-19T20:15:04Z
{"metric":"cpu_load","value":0.23}
The output can be integrated directly into monitoring or testing pipelines.
Example: Send messages
The Producer reads line-by-line data from stdin and sends it to the specified topic. Each successfully sent message is confirmed with metadata.
echo '{"event":"deploy","status":"ok"}' | pulsar-cli producer -t persistent://public/default/test
Log output to stderr:
INFO[0000] Producing messages to topic persistent://public/default/test (Ctrl+D to quit)
INFO[0000] sent message topic=persistent://public/default/test time=2025-10-19T20:30:00Z
This means that pulsar-cli can be seamlessly integrated into scripts or CI/CD processes - for example as part of automated tests, data feeds or health checks.
UNIX best practices
pulsar-cli consistently follows the classic UNIX principles:
| Stream | Content | Example |
|---|---|---|
| stdout | User data – i.e. messages or JSON content | `pulsar-cli consumer … |
| stderr | Diagnosis, status, logging | INFO[0001] received message ... |
This separation allows:
- stable use in shell pipelines
- machine-readable further processing
- clean logging without mixing the data streams
The behavior is based on tools like curl or jq:
stdout belongs to content, stderr belongs to observation.
Conclusion
pulsar-cli is a practical tool for anyone who wants to integrate Pulsar into existing automation or diagnostic processes.
A single binary is enough – no setup, no runtime dependencies, no additional components. The CLI is clearly structured Behavior predictable and script-friendly. With just a few lines of Go code This creates a tool that measurably simplifies Pulsar workflows - fast, portable and transparent.
🔗 Source code: https://forge.ext.d2ux.net/OpenLab/pulsar-cli
Image credit: The Pulsar logo is a registered trademark of the Apache Software Foundation. Use in the context of editorial reporting in accordance with the ASF trademark and logo guidelines.