Show MiMo Code agent state in
herdr's agents sidebar — idle /
working / blocked / done, labeled mimo — without modifying herdr.
herdr has no native MiMo Code support: it identifies agents by process name and ships integrations only for the agents it knows. This plugin uses the two extension points that need no herdr changes:
- MiMo Code loads user plugins from
~/.config/mimocode/plugin/ - herdr's socket API (
pane.report_agent) accepts custom agent labels
./install.sh # symlinks the plugin into ~/.config/mimocode/plugin/
./install.sh --copy # copies instead, if you don't want a symlink to this clone
./install.sh --uninstallThen restart any running mimo inside herdr. The label appears as soon as
the TUI starts.
Requirements: macOS or Linux, nc with Unix-socket support (preinstalled on
macOS), herdr with the pane.report_agent socket API.
The plugin listens to MiMo's event bus and reports semantic state to the
herdr socket ($HERDR_SOCKET_PATH) for the pane it runs in
($HERDR_PANE_ID). Several non-obvious problems shape the design:
Aggregate state machine, not 1:1 event translation. During a run MiMo
re-emits busy for the main session (progress messages) while subagent child
sessions emit unguarded idle when they finish. Translating events directly
makes the sidebar flicker working/idle mid-run. The plugin tracks the set of
busy sessions and reports only when the aggregate
(blocked > working if any busy > idle) actually changes.
Crash-proof release via a detached watchdog. MiMo runs plugins in a
worker thread that is terminate()d on quit and has no shutdown hook, and
herdr only auto-clears labels for agents it knows natively — a custom label
would outlive the process forever. The plugin spawns a detached /bin/sh
watchdog holding a pipe; the kernel closes that pipe on any death (quit,
crash, kill -9), and the watchdog then sends pane.release_agent. Its seq
is stamped at fire time +1s so it outranks every report the dead process made
(herdr arbitrates per source by monotonic seq) while losing to any mimo
started later.
Subprocess guard. A mimo spawned by another agent's tool call (e.g. a
Claude Code Bash session) inherits the pane's HERDR_* env and would hijack
that pane's label. The plugin stays silent when CLAUDECODE is set.
Instant claim. A fresh TUI sitting on the home screen emits no session
events, so the plugin reports idle once at startup to claim the pane
immediately.
- No label: the plugin only loads at mimo startup — restart mimo after
installing. Check
~/.local/share/mimocode/log/for aloading plugin ... mimo-herdr-state.jsline. - Stale label after
kill -9of herdr itself: the release targets the socket; if the herdr server was down at that moment the label persists until the pane is reused. Re-running mimo in the pane re-claims it. - Pane started under an older herdr server:
HERDR_PANE_IDis injected at pane creation; if herdr was since replaced and the pane id no longer resolves, reports are rejected (pane_not_found). Open a fresh pane.
MIT