Live herdr agent status on your Elgato Stream Deck.
See which of your AI coding agents are running, busy, blocked, or finished — at a glance, on physical keys. Press a key to jump straight to that agent's pane and bring your terminal to the foreground. No more hunting through tabs to find the agent that's waiting on you.
- One key per agent. Each key mirrors a live herdr agent: project label + status color + a monochrome logo of the agent type (Claude, Codex, …).
- Status at a glance — color and glyph encode
working/blocked/done/idle(see the table below). - Press = focus. A short press runs
herdr agent focusfor that pane and raises the host terminal app, so the agent is actually on screen even if the terminal was in the background. - Long-press = pin. Holding a key pins the agent — it jumps to the front, stays visible even when it goes idle, and gets a pushpin badge. Pins are in-memory (reset when the plugin restarts).
- Morphing pager key. When any agent needs attention it becomes a "jump to the next blocked/done agent" key (cycles on repeat presses); otherwise it pages through the agent grid. One key, both jobs — fits the 6-key Mini.
- Active notifications. When an agent flips to
blockedordoneyou get a herdr notification with a sound (request/done) and the key flashes — even when you're not looking at the deck. - Idle agents are hidden so the deck only shows agents that matter.
- Instant updates. Refreshes on herdr socket events (push), with a slow safety-net poll as a backstop — no busy 1-second polling.
| status | color | glyph | meaning |
|---|---|---|---|
| working | orange | ● | running now |
| blocked | red | ▲ | wants you |
| done | green | ✓ | finished, unseen |
| idle | grey | ○ | waiting (hidden) |
| unknown | near-black | · | — |
| empty | black | no agent in slot |
- Stream Deck Mini (6 keys)
- macOS 26 (Apple Silicon)
- Elgato Stream Deck app 7.4.2
- herdr 0.7.0
The plugin is keypad-only and works on any Stream Deck model with keys. The default layout assumes the 6-key Mini, but you can place the two actions on a deck of any size.
- macOS 12 or newer
- Elgato Stream Deck app 7.1+
- herdr 0.7.0+ installed and running (
herdron yourPATH) - To build from source: Bun and Node.js 24
git clone https://github.com/timvdhoorn/stream-deck-herdr-plugin.git
cd stream-deck-herdr-plugin
bun install
bun run build
# enable Stream Deck developer mode (one-time), then link + start the plugin
bunx streamdeck dev
bunx streamdeck link dev.timvdhoorn.herdr-agents.sdPlugin
bunx streamdeck restart dev.timvdhoorn.herdr-agentsProduce a double-clickable .streamDeckPlugin installer:
bun run build
bunx streamdeck pack dev.timvdhoorn.herdr-agents.sdPluginThis writes dev.timvdhoorn.herdr-agents.streamDeckPlugin — double-click it to
install into the Stream Deck app.
In the Stream Deck app, drag the two actions from the herdr category onto your keys. The recommended 6-key Mini layout:
[ Agent Slot 0 ][ Agent Slot 1 ][ Agent Slot 2 ]
[ Agent Slot 3 ][ Agent Slot 4 ][ Pager ]
- Agent Slot — set its
slotIndex(0–4) in the Property Inspector. Each slot shows one agent.- Short press → focus that agent's pane + raise the terminal.
- Long press → pin/unpin the agent.
- Pager — jumps to the next agent needing attention, or pages the grid when none do.
Prefer a flat, no-paging layout? Place six Agent Slot keys (slotIndex 0–5)
and skip the pager.
| Env var | Default | Purpose |
|---|---|---|
HERDR_DECK_TERMINAL_APP |
iTerm |
AppleScript name of the terminal app that hosts herdr. Set it to e.g. Terminal, Ghostty, or WezTerm so "press = focus" brings the right app to the front. |
A single store polls/streams herdr agent list, normalizes the agents, and
notifies both actions to re-render. All herdr I/O is isolated in
src/herdr/* (injected run for tests), the pure logic lives in src/core/*
(unit-tested with bun test), and the Stream Deck actions in src/actions/* are
thin glue. Key images are rendered as SVG data URIs for crisp text on the 80×80
keys.
bun test # run the unit tests
bunx tsc --noEmit # type-check
bun run build # bundle to …/bin/plugin.js
bun run watch # rebuild + restart the plugin on changeMIT © Tim van der Hoorn
