downbeat
(my tool that passes messages between terminal sessions, github.com/FreddieMcHeart/downbeat) has two ways to keep a session aware of its inbox. One is /relay-monitor
: it composes the built-in /loop
(re-fire a prompt every N minutes) with the inbox hook, so every tick is a full model turn whether or not new mail arrived. The other showed up on its own. A different session had set up a background "Monitor" and, in its own notes, described it as "event-driven, instant, cheap, only fires on events."
I was asked which approach was better. We already had a rule for evaluating external tools: do not trust the description, read the code. I pointed that rule at the session's own work.
The self-described "event-driven" monitor was this:
while true; do
sleep 90
cur=$(downbeat inbox | grep '^*' | awk '{print $2}' | sort)
new=$(comm -13 "$seen" <(printf '%s\n' "$cur"))
[ -n "$new" ] && { echo "NEW MESSAGES"; printf '%s\n' "$cur" > "$seen"; }
done
That is a poll loop. It sleeps 90 seconds, lists the inbox, and diffs against a seen-file. The session had conflated "does not re-arm itself every turn" with "does not poll." It graded itself on the label, not the loop. Its own comparison table claimed instant latency and cost only on events. Reality: up to 90 seconds of latency and about 960 polls a day, traffic or no traffic.
Reading past the wrong label, two ideas in it were genuinely good.
First, a cheap gate in front of an expensive consumer. On a quiet channel, /relay-monitor
spends a full model turn every interval just to read "nothing new." This script's tick is a bash poll, near-free, and it only escalates to a model turn when comm
actually finds new mail. Put the cheap check on the hot path and the expensive one on the rare path. That is the real win, whatever you call it. (Exact cost delta: unmeasured. The direction is obvious, I did not benchmark the size.)
Second, persistent state beats re-creation. Its previous version had re-armed a fresh "fire once" watcher every turn, which stacked up overlapping watchers that double-fired. One long-lived process with a seen-set emits each message exactly once. It had quietly re-derived a consumer offset in bash.
Here is where it turned into a lesson about my own codebase. downbeat
already had a real event-driven watcher: src/downbeat/core/watcher.py
, with an FsWatcher
built on watchdog (FSEvents on macOS, inotify on Linux) and a PollWatcher
fallback for network filesystems, both behind a make_watcher()
factory. I had written it months earlier for the TUI's live refresh, and it was sitting unused.
Meanwhile the downbeat watch
command I had added more recently (since removed, see the update below) ignored it and rolled its own while sleep
loop.
So two independent agents, that other session and my own past self, each re-derived "poll the inbox in a loop" while a tested, event-driven watcher sat one import away.
Rewire the watch command to use the factory:
w = make_watcher(on_change=emit, prefer="auto") # FsWatcher, PollWatcher fallback
Now downbeat watch
blocks on filesystem events with near-zero idle cost, and running it under a monitor gives exactly the cheap-gate-then-wake architecture the other session was reaching for. The difference is that the "event-driven" claim is finally true instead of aspirational.
The most valuable output of the whole exercise was not the feature. It was noticing that a tested primitive had been re-derived twice, in plain sight.
Since I wrote this, that FsWatcher
got promoted again. It made the standalone watch
command this post celebrates redundant. Instead of a user running watch
in a loop, the watcher now lives inside the TUI: while the app is open it fires a native OS notification the moment a peer has mail waiting and that peer has been idle too long, with a heartbeat so a headless send-hook and the TUI don't both notify for the same message. The standalone watch
subcommand was removed outright.
Which is this article's own lesson, one turn further. The tested primitive I found sitting unused didn't just replace two hand-rolled poll loops. Once it was the obvious building block, the right place to use it turned out not to be the command I first bolted it onto at all.