KubeMQ
Operate

kmq CLI

Drive KubeMQ from the terminal with the kmq command-line client — messaging, observability, contexts, roles, and the installable agent skill.

kmq is KubeMQ's command-line client — a single static Go binary that talks to the KubeMQ management API on port :8080 (the same API the web dashboard uses). It is built to be agent-native: predictable output, typed exit codes, and a self-describing command tree make it a first-class tool for AI coding agents as well as human operators.

Overview

kmq exposes every messaging pattern — Queues, Events, Events Store, and RPC (Commands/Queries) — plus full observability (status, metrics, connections, audit, connectors, agents) and a set of meta/discovery commands. Four properties make it suited to automated and agent-driven use:

  • Token-efficient — a kmq queue send is a few hundred tokens versus a multi-round exchange over a protocol like MCP.
  • Deterministic — typed exit codes and machine-readable json/ndjson output make results easy to branch on in a script or an agent loop.
  • Self-describingkmq schema emits the whole command tree, offline, with no network call.
  • Bounded by default — every stream/subscribe/replay command honors --count/--duration/--idle, so an agent can never loop forever waiting on it.

Scope

kmq is a client of the management API — it does not embed the broker, and it never talks to the message broker directly. Every action is an HTTP call to the :8080 management API. kmq mcp reads the server's registered MCP tools; it does not make kmq itself an MCP server.

Architecture

kmq never talks to the message broker directly. Every action is an HTTP call to the :8080 management API: one-shot actions dispatch via POST /api/request ({type, data}) or dedicated REST routes, and streaming commands use Server-Sent Events / WebSocket subscription endpoints. Meta commands (schema, cheat, skills) serve content compiled into the binary, so they work fully offline and never need the server.

Installation

# Primary — GitHub Releases (kubemq-io/kmq), no credentials
curl -sSfL https://raw.githubusercontent.com/kubemq-io/kmq/main/install.sh | sh

# Pin a version, or verify the cosign signature strictly
curl -sSfL https://raw.githubusercontent.com/kubemq-io/kmq/main/install.sh | sh -s -- --version v0.3.1
curl -sSfL https://raw.githubusercontent.com/kubemq-io/kmq/main/install.sh | sh -s -- --verify-signature

# Container image (no install)
podman run --rm europe-docker.pkg.dev/kubemq/images/kmq:latest version

install.sh detects OS (linux/darwin/windows) and architecture (amd64/arm64), resolves the version, downloads the archive plus checksums.txt, and performs a mandatory SHA-256 verification — the install aborts if it cannot verify the checksum. An optional cosign signature check runs on top of that (best-effort by default, strict when requested), and the binary installs to the first writable PATH directory.

Install env varPurpose
KMQ_VERSIONExplicit version to install (e.g. v0.3.1)
KMQ_INSTALL_DIRTarget directory for the kmq binary
KMQ_BASE_URLMirror/staging base URL (switches to mirror mode)
KMQ_PREFIXObject prefix for a mirror (default kmq)
KMQ_VERIFY_SIGNATURESet to 1 to require a valid cosign signature

Contexts & configuration

A context is a named connection profile (API address, token, TLS, defaults). Contexts live under $XDG_CONFIG_HOME/kmq/ (~/.config/kmq/ by default):

$XDG_CONFIG_HOME/kmq/
├── contexts/
│   ├── default.json
│   └── prod.json
└── current-context      # pointer file (active context name)
kmq context create default --api-address http://localhost:8080
kmq context create prod \
  --api-address https://kubemq.example.com:8080 \
  --token kmq_<keyid>_<secret> --tls
kmq context use prod
kmq context list          # (alias: ls) — current-context marked
kmq context current
kmq context edit prod --token kmq_<newkey>_<newsecret>
kmq context delete staging   # (aliases: rm, remove)

Configuration is resolved by precedence, highest to lowest:

PrecedenceSource
1 (highest)Persistent flags (--context, --api-address)
2Environment variables
3Active-context file
4 (lowest)Built-in defaults (http://127.0.0.1:8080)
Env varPurpose
KMQ_TOKENService-account Bearer key (kmq_<keyid>_<secret>) — preferred in CI
KMQ_CONTEXTActive context name (overrides the pointer file)
KMQ_API_ADDRESSManagement API URL

Authentication & roles

Authentication is opt-in on the server — see Security for the account model and roles. Check whether it is on with kmq doctor -o json | jq .auth (on/off). When auth is on, supply a service-account key via KMQ_TOKEN or the active context. Service-account roles gate what the CLI can do:

RoleGrants
read_onlylist/inspect, metrics, status, overview, schema, doctor, billing
read_writethe above + send/receive/stream/subscribe/purge, channel create/delete
adminthe above + audit, account management

Auth-exempt commands

A handful of commands and routes succeed with no token, even when server auth is on: kmq doctor, kmq metrics scrape, kmq billing (routes /ready, /health, /metrics, /billing, /api/v1/auth/status). Don't read the role table above as universal gating — these are the exceptions.

config set/revert and account management require the admin role. Service accounts never carry admin, so those operations are deliberate non-goals of the CLI.

Global flags & output discipline

Persistent flags are inherited by every subcommand:

FlagDefaultPurpose
-o, --outputjsonOutput format: json | ndjson | yaml | table
--contextUse a specific context (overrides current-context)
--api-addressTarget :8080 endpoint (overrides context)
--no-colorfalseDisable color in table output
--verbosefalseRequest timing to stderr (token redacted)
--yesfalseConfirm destructive operations without prompting
--dry-runfalseRender the action without executing
--fieldsProject output to these camelCase wire fields
--detailsummarysummary | full verbosity, for commands that support it

Output discipline:

  • Data → stdout, warnings/errors/diagnostics → stderr — safe to pipe.
  • One-shot commands default to compact json; streaming commands (queue stream, *subscribe, *replay, conn watch, command/query receive) default to ndjson (one record per line, flushed per record).
  • metrics scrape emits raw Prometheus text; cheat and skills get emit raw markdown — for those, -o is ignored.
kmq queue receive orders --count 10 -o ndjson | jq .body      # stream, per-line
kmq estore replay telemetry --from-first --count 100 -o json # buffer then array
kmq status --fields is_healthy,channels,clients

Exit codes

kmq returns typed exit codes so scripts and agents can branch deterministically. On error it also writes a JSON envelope to stderr: {"error":{"code":"...","message":"...","retryable":bool}}.

CodeNameMeaningRetry?
0OKSuccess
1GenericUnclassified errorNo
2UsageBad flags / usageNo
3NotFoundResource not foundNo
4AuthAuth required / failed / forbiddenNo
5ConnServer unreachableYes (server down?)
6TimeoutRequest timed outYes
7PartialPartial successCase-by-case
8RetryableServer initializing / too many attemptsYes — kmq auto-retries

Server wire codes map onto this table as follows: auth_required, auth_failed, forbidden, must_change, and tls_required all map to exit code 4; auth_initializing and too_many_attempts map to exit code 8 and are auto-retried; seed_read_only, duplicate, and service_admin_forbidden map to exit code 2; any empty or unknown wire code maps to exit code 1.

Command reference

Every send command reads its body from (in priority) a positional argument → --body-base64-f/--file → stdin, and accepts --message-id/--client-id/ --metadata/-M/--tag k:v (repeatable). Every stream/subscribe/replay/receive command accepts the bounding flags --count N, --duration 5m, --idle 30s — whichever fires first stops it; Ctrl-C also exits cleanly with code 0.

Messaging

PatternSendReceive / SubscribeNotes
Queuekmq queue send <ch> <body>kmq queue receive <ch> [--count N]persistent, at-least-once
Queue (peek)kmq queue peek <ch> [--count N]non-consuming
Queue (interactive)kmq queue stream <ch> [--visibility 60] [--wait 5] [--auto-ack]WS poll/ack/reject session
Queue (drain)kmq queue purge <ch> --yesdestructive
Eventskmq events send <ch> <body>kmq events subscribe <ch> [--group g]fire-and-forget pub/sub
Events Storekmq estore send <ch> <body>kmq estore subscribe <ch>persistent + replayable
Events Store (replay)kmq estore replay <ch> <offset-mode>historical replay — one offset mode: --new-only (default), --from-first, --from-last, --from-sequence N, --from-time <RFC3339>, --since-seconds N, plus --group
Command (RPC)kmq command send <ch> <body> --timeout 30kmq command receive <ch> [--respond-body '{}' | --command 'sh']request/ack
Query (RPC)kmq query send <ch> <body> --timeout 30kmq query receive <ch> [--respond-body '{}' | --command 'sh']request/data

Queue send extras: --max-receive-count, --dead-letter <ch>, --expiration-seconds, --delay-seconds.

RPC responders: receive with --respond-body '<json>' echoes a static reply; with --command '<shell>' the inbound body is piped to the command's stdin and its stdout becomes the reply; with neither, requests are printed for manual handling. --respond-body and --command are mutually exclusive.

Channels

kmq channel create <name> --type queues|events|events_store|commands|queries
kmq channel delete <name> --type queues --yes
kmq channel list [--type <t>]
kmq channel inspect <type> <name>          # full detail: clients, rates, totals
# per-family shortcuts also exist: kmq queue list / kmq queue inspect <name>

Cluster

kmq cluster info [--node]      # (alias: snapshot) cluster-merged, or --node for local
kmq cluster health            # /ready — leadership role, ready/healthy
kmq cluster nodes             # topology: node, type, unavailable nodes

Observability

kmq status                    # composite digest: /ready + snapshot, one-line health
kmq overview [--detail full]  # per-pattern rollups (queues / pubsub / request-reply / totals)
kmq metrics scrape            # raw Prometheus /metrics (auth-exempt)
kmq metrics history [--metric message_rate|volume_rate|error_rate|messages|bytes]
kmq conn list                 # active connections (first SSE snapshot)
kmq conn inspect <id>
kmq conn watch                # live SSE stream of connection events
kmq audit query  [--from ..] [--to ..] [--event-type queue.send] [--limit N] ...
kmq audit stats  [--group-by event_type|client_id|category|channel|transport]
kmq connector list            # aws / gcp / amqp / amqp10 / stomp / mqtt / ce
kmq connector inspect <name> [--operation <service/op>]
kmq agent list [--limit N] [--offset N]     # A2A agents
kmq agent inspect <id>
kmq mcp list                  # server's registered MCP tools
kmq mcp inspect <tool>

Kafka

kmq kafka probe --bootstrap host:port[,host:port]   # dial a source cluster, read-only
kmq kafka probe -b host:port --dial-timeout 30s   # override the 15s default
kmq kafka probe -b host:port \
  --aws-access-key <key> --aws-secret-key <secret> --aws-session-token <token>  # MSK IAM

kmq kafka probe dials a source Apache Kafka / MSK / Confluent cluster over the Kafka wire protocol and reports back the brokers plus their ApiVersions. It is read-only — it never produces, commits, or auto-creates topics — so it's safe to point at a production cluster. Flags: -b/--bootstrap host:port[,host:port...], --dial-timeout (default 15s), and AWS MSK-IAM auth via --aws-access-key/--aws-secret-key/--aws-session-token. Run it as a first connectivity check ahead of the Migration family below, or see Migrate from Kafka for the full workflow.

Migration

CommandFlagsNotes
kmq assess kafka--bootstrap, --tls, --sasl-mechanismRead-only fit assessment of an external Kafka cluster → per-topic READY/CAVEAT/UNKNOWN/BLOCKED + a T1–T4 verdict. Never writes to the source.
kmq migrate assess|replicate|translate|cutover--state, --dry-run, --forceBeta four-phase migration (assess → replicate → translate → cutover) from a Kafka cluster to KubeMQ.

For the full narrative (per-source auth, MirrorMaker 2 hybrid, rollback, staged dry-run) see Migrate from Kafka.

Meta & discovery

kmq version                   # binary version
kmq whoami                    # identity + role (auth on), or {"authenticated":false,"auth":"disabled"} (auth off)
kmq doctor                    # connectivity + auth check (no auth required)
kmq config get [--fields ..]  # server config (read-only, server-redacted)
kmq billing                   # usage/license (auth-exempt)
kmq schema -o json            # full command tree + roles + exit codes (offline)
kmq cheat [topic]             # embedded recipes (offline)
kmq docs [topic] [--open]     # signpost to the online docs + LLM corpus
kmq skills ...                # serve/install the agent skill (see next section)

kmq cheat topics (embedded, offline): queue, events, estore, rpc, drain, subscribe, health, auth, context, output.

kmq schema -o json is the machine-readable contract — the full command tree (path, description, required role, flags), the exit-code table, the server wire error-code catalogue, and the CLI/server versions — with no network and no auth. It is the recommended way for an agent to introspect the CLI.

Agent-skill distribution

Any coding agent can be taught to drive kmq with one command, and the instructions always match the installed binary version — the skill content is served straight from the binary, so it can never go stale between releases.

kmq skills                    # list skills (alias: kmq skills list)   → 'core'
kmq skills get core           # print the core skill (raw markdown)
kmq skills get core --full    # + the full command reference
kmq skills get --all          # every skill
kmq skills path [name]        # skills source dir, or '(embedded)'
kmq skills install [--global] [--force]   # install the stub locally (zero-Node)
Install pathCommandReach
Universal installernpx skills add kubemq-io/kmq70+ agents (Claude Code, Cursor, Codex, Gemini CLI, Windsurf, …)
Claude Code pluginclaude plugin marketplace add kubemq-io/kmqClaude Code
Zero-Node fallbackkmq skills installLocal Claude Code install; --global installs it for the current user

Server communication

kmq speaks to the management API over HTTP. One-shot actions dispatch as POST /api/request with {type, data} (or dedicated REST routes); the server replies HTTP 200 with an envelope:

{ "error": false, "error_string": "", "code": "", "data": {} }

error: false decodes data into the requested output; error: true maps the code field to an exit code via the wire-code table above. A handful of routes are auth-exempt (no Bearer needed) — the same ones called out in the Auth-exempt commands note above.

Retryable server states (auth_initializing, too_many_attempts) are auto-retried with exponential backoff, cancellable by SIGINT/SIGTERM. Streaming uses SSE/WebSocket subscription endpoints and stops on the first of --count/--duration/--idle or a signal. SIGINT/SIGTERM cancel the root context — streaming/waiting commands close gracefully and exit 0 on clean cancellation.

Was this page helpful?

On this page