MadQTT
Live TUI for the claude-prime hooks MQTT + MongoDB stream — turn the firehose into something a Mad Tinker can read.
┌ Sessions ─────────────┬ Session 4c0f8355 · madnessDesktop ──────────┐
│▶ 4c0f… madnessDesktop │ 01:06:36 Bash grep -n private async… │
│ ae97… element-dupe │ 01:06:38 Bash ✓ 1.5s │
│ 9439… Inventorium │ 01:06:42 Read lib/api.ts │
│ 6465… madnessDesk │ 01:06:44 Read ✓ 2.2s │
│ failures: 3 │ 01:06:51 Bash grep -rn ^export.func… │
│ active: 4 │ 01:06:52 Bash ✗ failure │
└───────────────────────┴─────────────────────────────────────────────┘
[s]essions [p]rojects [t]opics [c]hat [f]ilter [v]iew [m]sg [q]uit
Install
pip install madqtt # from PyPI
madqtt # run it
Or for local dev from a checkout:
uv venv .venv
uv pip install -p .venv/bin/python -e .
If your global uv cache has root-owned subdirs from a past
sudoinstall, route around it:UV_CACHE_DIR=.uv-cache uv pip install -p .venv/bin/python -e .
Run
.venv/bin/python -m madqtt # live: broker + Mongo backfill
.venv/bin/python -m madqtt --replay dataset1.txt # replay a mosquitto_sub -v capture
.venv/bin/python -m madqtt --host eaws --port 1883
Where the data comes from
MadQTT is the consumer. It renders a stream that something else has to produce: Claude Code hooks that publish to an MQTT broker and (optionally) mirror to MongoDB. No producer running → empty timeline.
The contract MadQTT subscribes to:
| source | what | shape |
|---|---|---|
MQTT status/<device>/activity/# |
every tool call (pre/post) | {tool, target, session, project, ts} |
MQTT status/<device>/claude/# |
session/compact/idle lifecycle | per-topic payloads |
Mongo claudehooks_<project> |
backfill on startup so history survives a cold broker | same events |
<device> is the DeNa env var on the publishing host (default macbook).
The full topic + payload reference is in the docs (--docs, below).
Just want to see it work? No broker, no Mongo, no hooks needed — replay a captured stream:
madqtt --replay dataset1.txt # a mosquitto_sub -v capture, ships in the repo
Wiring up a live producer. The reference producer is the claude-prime
hook set in the Madness workshop — a
bundle of Claude Code PreToolUse/PostToolUse/SessionStart/… hooks that
mosquitto_pub the events above. It's workshop-coupled (dvttestkit, a
hooks_config.json of feature flags), so treat it as a worked example of the
contract rather than a drop-in: any hook that publishes those topics in that
shape will light up MadQTT. Point it at your broker with:
export MADNESS_MQTT_HOST=your-broker # default localhost
export MADNESS_MQTT_PORT=1883
export CLAUDE_MONGO_URI=mongodb://localhost:27017/ # optional backfill
madqtt
Documentation
Everything else — keys, configuration, architecture, the full topic & payload reference — lives in the docs site:
uv pip install -p .venv/bin/python -e '.[docs]'
.venv/bin/python -m madqtt --docs
Spawns mkdocs serve on a free port and opens your browser.
Optional extras
| extra | install | what you get |
|---|---|---|
[docs] |
uv pip install -e '.[docs]' |
mkdocs-material site behind --docs |
[web] |
uv pip install -e '.[web]' |
textual-serve "python -m madqtt" exposes the TUI in a browser |
Dev
.venv/bin/python -m pytest tests/ -q # parser regression against dataset1.txt
.venv/bin/python scripts/smoke_replay.py # headless: all views, SVG captures
.venv/bin/python scripts/smoke_live.py # live: backfill + 4 synthetic publishes
.venv/bin/python -m mkdocs build --strict # build docs site to ./site
Project layout
madqtt/ package
├── events.py Event dataclass + topic parser
├── store.py EventStore + ring + per-session/topic rollups + Mongo backfill
├── ingest.py aiomqtt subscriber + replay
├── app.py Textual App, key bindings, view switching
├── docs.py --docs implementation
├── config.py env-var Config
└── widgets/ sessions, projects, topics, chat, filter, transcript, message
docs/ mkdocs-material site (built behind --docs)
tests/ parser regression
scripts/ smoke_replay.py, smoke_live.py
Status
| feature | shipped |
|---|---|
| Sessions + Projects + Topics views | v1.0 |
| Filter modal (project/topic/idle) | v1.0 |
| Filter chips actually prune views | v1.1 |
Transcript viewer (v) |
v1.1 |
Swarm chat pane (c) |
v1.1 |
Write-back (m) to swarm/chat_in |
v1.2 |
Fleet Mongo (MADQTT_MONGO_URIS) |
v1.2 |
| Browser exposure (textual-serve) | v1.2 |
Docs site + --docs CLI |
v1.3 |
| Persistent memory (UI state + log) | v1.4 |
| tool_failure toast + fail/hr counter | v1.5 |
Per-session task list (T) |
v1.6 |
| Pinned sessions + unread counts | v1.7 |
| Inline transcript jumping | v1.8 |
Export filtered transcript (e) |
v1.9 |
Global transcript search (/) |
v1.10 |
Event inspector modal (enter, i) |
v1.11 |
Agent control panel (a) |
v1.12 |
Roadmap candidates: "open cwd in editor" key, per-tool aggregate stats view.
Persistent memory
Two files under ~/.madqtt/ (override with MADQTT_STATE_DIR, disable with
MADQTT_NO_PERSIST=1):
state.json— last view, filter chips, idle toggle, last selected session. Restored on launch, saved on quit + every 30s.events.jsonl— append-only mirror of every Event. Replayed into the ring on startup so the timeline survives broker + Mongo being down.
Metadata
Release files for madqtt 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| madqtt-0.1.2.tar.gz | 62.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| madqtt-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 113.2 kB
Release files / madqtt-0.1.2.tar.gz
| Download URL | madqtt-0.1.2.tar.gz |
|---|---|
| Size | 62.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ae11d51127c1eb97b090340f7cc5c4366259ce6e6d55dc48ea29a634246d2cb1
|
|
BLAKE2b-256 checksum How to use checksums |
73f367c8361fbba21ca895d501294ff8de45e230e768cde5c3996f481b93a0a3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.3
|
Release files / madqtt-0.1.2-py3-none-any.whl
| Download URL | madqtt-0.1.2-py3-none-any.whl |
|---|---|
| Size | 51.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dbd199833611d231495f2e8734a6c8915a59fa86f6b31f2e7606f9aece72e97a
|
|
BLAKE2b-256 checksum How to use checksums |
b9c0ddf0aafe5d401901a9c0c63b5130dc9a28f050b5616650a2572c51079422
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.3
|