No description
  • JavaScript 88.7%
  • Shell 11.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Tobi 0f596078f3
Allow the runtime PATH to be baked in by a packager
Herdr's server is long-lived and survives a NixOS rebuild, so the PATH it
inherited can name store paths that were since garbage collected. Ship an
empty nix_path_prefix that a package build substitutes, keeping a plain
plugin link working from PATH.
2026-08-28 20:46:51 +02:00
scripts Allow the runtime PATH to be baked in by a packager 2026-08-28 20:46:51 +02:00
.gitignore Add herdr topic-indicator plugin 2026-08-28 20:29:26 +02:00
config.env.example Add herdr topic-indicator plugin 2026-08-28 20:29:26 +02:00
herdr-plugin.toml Add herdr topic-indicator plugin 2026-08-28 20:29:26 +02:00
README.md Add herdr topic-indicator plugin 2026-08-28 20:29:26 +02:00

herdr-topic-indicator

A Herdr plugin that gives every agent pane a short topic label describing what it is actually working on, and shows it in the agent sidebar.

Instead of a sidebar that reads:

monday_discord_bridge
  claude
projects
  claude
~
  hermes

you get:

monday_discord_bridge
  claude
  Field block rendering review
projects
  claude
  Multi-repo dependency audit
~
  hermes
  Coolify deployed fork handling

How it works

Herdr already accepts display-only pane metadata (herdr pane report-metadata --token name=value) and can render it in the sidebar through a $name token. This plugin fills in that token:

  1. An event hook fires on pane.agent_status_changed and pane.agent_detected.
  2. The plugin reads the pane's recent output (herdr pane read).
  3. It hashes the tail of that output. If the hash is unchanged, it stops — no LLM call.
  4. Otherwise it asks claude -p --model haiku for a 2-5 word topic label.
  5. The label is reported back as the pane's topic metadata token.

A background watcher sweeps every 45s on top of the event hooks, because a long-running agent can work on three different things without its status ever leaving working. Sweeps are free for panes whose output has not changed.

Cost control, in order of effect: the output hash gate, a 20s per-pane cooldown, and haiku as the model. In practice a busy four-pane session costs a handful of haiku calls per minute, and an idle one costs zero.

Requirements

  • Herdr 0.8.0+
  • node on PATH
  • claude (Claude Code CLI) on PATH, authenticated

Install

git clone <this repo> ~/projects/herdr-topic-indicator
herdr plugin link ~/projects/herdr-topic-indicator

Then add the $topic token to your sidebar in ~/.config/herdr/config.toml:

[ui.sidebar.agents]
rows = [
  ["state_icon", "workspace", "tab"],
  ["agent"],
  [{ token = "$topic", fg = "#89b4fa", dim = true }],
]

Apply it and populate the labels:

herdr server reload-config
herdr plugin action invoke tobi.topic-indicator.refresh-all

A pane with no topic yet renders no third row, so the sidebar degrades cleanly.

Actions

Action What it does
tobi.topic-indicator.refresh Relabel the focused pane (ignores the cache)
tobi.topic-indicator.refresh-all Relabel every agent pane
tobi.topic-indicator.clear Remove all topic labels
tobi.topic-indicator.watch-start Start the background watcher
tobi.topic-indicator.watch-stop Stop the background watcher
tobi.topic-indicator.status Show watcher state and current topics

Invoke from the CLI:

herdr plugin action invoke tobi.topic-indicator.refresh-all

Actions run asynchronously, so the CLI returns before the work finishes. Read the result with:

herdr plugin log list --plugin tobi.topic-indicator

Or run the script directly, which is synchronous and prints the labels:

bash ~/projects/herdr-topic-indicator/scripts/topic-indicator.sh all
bash ~/projects/herdr-topic-indicator/scripts/topic-indicator.sh status

Keybinding

Bind on-demand relabelling of the focused pane:

[[keys.command]]
key = "prefix+t"
type = "plugin_action"
command = "tobi.topic-indicator.refresh"
description = "refresh pane topic"

Configuration

Copy config.env.example into the plugin config directory:

cp config.env.example "$(herdr plugin config-dir tobi.topic-indicator)/config.env"

Notable keys: model (default haiku), interval (watcher period, default 45), max_chars (default 40), agents (restrict to specific agents), watch=0 (event-driven only, no watcher).

Startup behaviour

Metadata tokens live in the Herdr server's memory, so a server restart clears them. The plugin's [[startup]] hook relabels every pane and restarts the watcher once the session is restored, so topics survive restarts and live handoff.

Troubleshooting

bash scripts/topic-indicator.sh status               # watcher + current topics
tail -f ~/.local/state/herdr/plugins/tobi.topic-indicator/topic-indicator.log
herdr plugin log list --plugin tobi.topic-indicator  # hook exit codes/stderr

Labels not appearing in the sidebar is almost always the config side rather than the plugin: confirm the tokens exist with

herdr api snapshot | grep -o '"topic":"[^"]*"'

If tokens are present but the sidebar is unchanged, the [ui.sidebar.agents] rows block is missing or herdr server reload-config was not run.