Skip to content
topiq logo

topiq

Browse a topic, filter it with a real grammar or raw JS, and replay a message byte for byte — without leaving the terminal.
Terminal window
brew install candril/tap/topiq # or: nix run github:candril/topiq
topiq --demo # an offline demo cluster — no config, no broker

The README demo

Open a topic and the latest 50 messages are there, newest first, with columns inferred from the decoded payload — nested fields become customer.tier, arrays become [3 items]. Every Avro long is a BigInt: an order id above 2^53 is printed exactly, never rounded, which is the bug this tool was written to not have.

The message table

/ opens the filter bar. field:value, field>x, ranges, regex literals, negation, nested paths — typed by the field’s decoded type, so key:12345 matches a BigInt key. Fields autocomplete from what is actually loaded, one dotted segment at a time.

/ value.customer.tier:PRO value.total>200 two terms, implicit AND
/ value.customer.email:/@example\.com$/ a regex on the rendered value
/ -value.channel:STORE negation

= switches to a raw predicate — (m) => m.value.items.length > 2 — that runs locally on your own credentials. No sandbox to fight, no server-side filter language.

The filter bar with suggestions

f follows the topic. Arrivals land at the top; the buffer is capped and every evicted or dropped row is counted in the header, because a silently truncated tail is a lie about what the topic contained. space pauses without disconnecting.

Following a topic

A window holds 10,000 rows at most, and the filter narrows that. ⇧S turns it around: every message in the range streams through the filter and only the hits are kept, so “the order with this id, somewhere in the last four million” is one keystroke after b. The header shows how far the scan got and how fast; ⇧S again stops it, esc returns to the window. Nothing is dropped on the way — when decoding falls behind, the fetch waits.

A scan of a whole topic

p re-produces the message under the cursor to its own topic: the raw key, value and headers, verbatim. No decode, no re-encode, so the embedded schema id stays valid and the bytes are provably identical. e decodes it into $EDITOR first, validates the edit against the message’s own schema, and re-encodes. ⇧N crafts a new message from the subject’s latest schema.

The replay confirm dialog

y copies a message to another cluster. Schema ids are registry-local, so this is never a byte copy: topiq decodes against the source registry, re-encodes against the destination’s, and the dialog names both subjects, both versions and both ids before you confirm. A prod destination is sorted last and coloured — and must be typed by name.

The cross-cluster copy dialog

Consumer groups, and the one write with no undo

Section titled “Consumer groups, and the one write with no undo”

c on a topic lists the groups consuming it: state, members, lag per partition. Undefined lag renders , never 0. o moves a group’s committed offsets to an offset, a timestamp, the beginning or the end — only when the group is Empty, checked again at the instant of the write.

Consumer groups with lag

Read-only by default

allow_write is off on every profile. With it off, write commands are drawn disabled with the reason — never absent, never failing at the broker.

One confirm dialog

Every write names the action, cluster, environment, topic and message age. A prod target must be typed by name. y-on-Enter-by-reflex is not possible.

No secret on disk

password_cmd shells out to your vault on demand. The password lives in memory for the session and is never logged or written.

Cluster families

Profiles carry group and env. The picker groups them, the header colours prod, and “copy to the other environment” is one keystroke with the topic prefix mapped.

Ranges that make sense

Latest N (watermark arithmetic, all BigInt), from an offset, from a timestamp, from the beginning. Kafka only reads forward; topiq does the maths.

Columns you control

h/l walk the columns, s sorts by the selected one (BigInt compares as BigInt), - hides it, c opens the picker, * filters by the cell under the cursor.

Command palette

^P lists every action for the current screen with its key; a gated write is listed dimmed with the reason. ? shows the whole keymap.

Try it offline

topiq --demo is a seeded in-memory cluster with real Avro, BigInt keys, a tombstone, a decode failure and live arrivals. Writes work and are forgotten on exit.

The command palette

Terminal window
brew install candril/tap/topiq # or: nix run github:candril/topiq
curl -fsSL https://raw.githubusercontent.com/candril/topiq/main/scripts/install.sh | bash

See the installation guide for the Nix flake, the installer’s variables, requirements and first run.