Skip to content
fedeyaPublic

About

Your coding agents as a herd of animated pixel-art critters on a Stream Deck + (herdr). Switchable themes: farm, kingdom.

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Latest commit

Β 

History

23 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Corral

Your coding agents as a herd of pixel-art critters on a Stream Deck +.
See who's working, who needs you and who's done at a glance. Tap one to jump straight to it.

Corral's kingdom theme on a Stream Deck +: pawns chopping trees, mining gold and waiting for orders

MIT license Stream Deck + macOS herdr


Each agent from herdr becomes a little character that keeps the same look for its workspace, so you know who's who without reading. Every key is one agent. The touch strip shows the whole herd together, each critter standing right under its key.

What you see
🟀 Working Busy: walking, chopping wood, mining, hammering
πŸ”΄ Needs you Hopping with a blinking ! bubble, front and centre
🟒 Done Showing off its work with a βœ“ and sparkles
⚫ Idle Dimmed and resting, so it stays out of the way

Agents that need you come first, then finished ones, then working, then idle.

Themes

Turn the last dial to switch. Your choice is remembered.

Kingdom

Every workspace gets a pawn with a job (lumberjack, miner, builder or butcher) and a team colour. Working pawns haul wood, gold and meat back to the castle, and the island changes with the time of day.

Kingdom theme

Farm

Goats, sheep, cows, pigs, llamas and chickens grazing in a field, under a sky that follows your clock, with stars at night.

Farm theme

Ramen / Cocina

An included, original pixel-art kitchen: chefs carry steaming stockpots while working, open recipe books when blocked, and serve finished ramen with a checkmark. Idle chefs put their utensils away; unknown states show ?. Aprons keep the agent's identity colour. No downloaded sprites or invented cooking-progress percentages. See Ramen theme.

Invitado: your own mascot

Install a local two-frame, five-status PNG atlas and attribution JSON, restart Corral, and INVITADO joins the theme cycle. The original MIT Luma example is included under examples/mascot-packs/luma; follow mascot pack installation and format. Packs are data only, live outside the plugin bundle, and cannot execute code. Invalid or missing packs leave the built-in themes available.

Want to make one? See Adding a theme. It's one file, and there's a working template to start from.

Controls

Tap a key On release, focus that agent in herdr and bring the terminal forward
Hold a key for at least 500 ms, then release Pin/unpin that agent to that physical action key, without focusing
Tap the touch strip Focus the critter you tapped
Long-touch a character on the strip Pet it: one second of pixel hearts, without focusing or changing task state
Push any dial Jump to the agent that needs you most
Turn dials 1–3 Page through agents when there are more than keys
Turn dial 4 Switch theme

Pinned agents

A yellow pixel pushpin and PIN mark a pinned key. Its agent stays there when another agent needs you, when status/priority changes, and when you turn pages. Unpinned keys keep the usual urgency order; pinned agents are excluded from those keys and from their page count, so the same pane never appears twice. The strip uses the same resolved layout and its tap targets update immediately after a pin or page change.

If a pinned pane disappears, its key stays reserved with PIN / MISSING instead of silently showing another agent. The strip leaves that position vacant. If the same pane ID returns it reclaims its key. Hold and release the reserved key to free it; a short tap alerts without focusing anything. A tap captures the pane at press time, so a poll or page change while you press cannot redirect it to a different agent. Missing panes and focus failures alert.

Pins are session-only, keyed by the Stream Deck action ID and herdr pane ID, not by roster position or workspace name. Restarting the plugin clears them. Removing an action, switching away from its profile, or disconnecting its device (the SDK action disappears) also releases its pin and cancels an unfinished press. No pin settings are written to disk.

With every key pinned, paging has no free slots and does nothing; release a pin to browse other agents. With no agent keys configured anywhere, the strip retains its first-eight-agent preview and paging is inert. Multiple devices share one ordered key roster/page (device ID, then row and column); each device's strip shows only its own keys, with separate animation and tap targets. A pane can be pinned once across that roster. Duplicate pane/action IDs are first-wins. Multi-actions and keys without physical coordinates are excluded.

Offscreen attention beacon

The rightmost strip segment shows a beacon when blocked agents are absent from that device's current keys, including when every key is pinned. The count includes distinct hidden panes, and the displayed target stays stable across priority reordering. Tap the beacon to focus exactly that still-blocked hidden agent without moving pins or pages. If the target disappeared or became visible, the tap does not silently redirect to another agent. Disconnected/held touches cannot focus; Showcase keeps the safe alias but disables opening.

Petting

Long-touch a visible character to show three original pixel hearts for one second. Short touches retain their usual focus behavior. Petting also works in Showcase, never changes an agent's state, and stays local to the touched device. Effects expire without replaying and are cleared when a pane disappears or the theme changes. The attention beacon takes precedence over characters underneath it.

Showcase / Vidriera (camera mode)

Drag the optional Showcase / Vidriera action from the Corral category onto a spare key. Press it before filming. Its camera icon says CAMERA ON, and every agent key and touch-strip segment shows a yellow camera / SHOWCASE badge. Press the same key again to resume normal labels and controls. The toggle key does not count as an agent slot.

While enabled:

  • Workspace, title and subtitle captions become AGENT A, AGENT B, AGENT C, etc. (after Z: AA, AB, …). Aliases are assigned by paneId, not priority or key position. Paging, reordered agents, temporary disappearance, status updates and toggling off/on do not rename an existing pane. New panes receive the next unused alias.
  • Both Farm and Kingdom keep their original appearance seeds, species/coats, jobs/team colours, focused borders and live status animations. Polling continues against your current herdr session; this is not a pretend session.
  • Key holds still pin/unpin agents without focusing, and pins keep their safe aliases and PIN badges.
  • Agent keys, touch taps and dial pushes cannot focus agents or bring the terminal forward. Dial rotation still pages and switches themes. The toggle itself never focuses. For one second after toggling, focus events are ignored to absorb queued/trailing gestures; press deliberately again after that interval to focus.
  • A focus request already waiting for herdr is permanently invalidated by a toggle, so its completion cannot later bring the terminal forward. A command already sent to herdr cannot be undone.
  • Error captions are fixed public messages (herdr off / HERDR IS DOWN), never exception text or private labels.

Mode and aliases are process-session local, not persisted to global settings. Restarting the plugin resets aliases and starts with camera mode off; check CAMERA ON before each recording. Removing/re-adding the toggle or agent actions does not reset aliases while the plugin process is still running.

This protects Corral's built-in on-device captions and focus gestures, not your desktop, terminal contents, logs, Stream Deck configuration UI, external tools or third-party themes that draw identity seeds as text. Canonical agents remain private, unmodified data internally; the renderer receives a separate presentation projection. Choose a capture region that excludes those other surfaces. Demo mode below is separate: it creates pretend agents and still allows focus.

Showcase tests (no hardware)

bun install --frozen-lockfile
bun run test:plugin
bun run --cwd apps/plugin typecheck
bun run build:plugin

The plugin test script uses Bun file isolation so the pins and Showcase SDK/CLI fixtures cannot share cached modules. Type-checking includes the tests as well as the plugin and scripts.

Tests exercise the real action handlers, state, herdr subprocess adapter and pixel renderers. Only the unavailable Stream Deck SDK connection is mocked. A local fake herdr executable supplies synthetic private captions and records focus calls. Farm uses the shipped artwork. Kingdom uses original procedural test sheets in the scratch directory, not the unredistributable Tiny Swords assets; the real Kingdom drawing code still runs. Physical hardware delivery and macOS terminal activation require a separate device smoke test.

Install

You need:

Then build the plugin and register it with the Stream Deck app:

git clone https://github.com/fedeya/corral
cd corral
bun install
bun run build:plugin
bun run link

In the Stream Deck app, open the Corral category. Drag Agent slot onto every key you want to use, and Agents strip onto all four dials.

Note

The herdr path (/opt/homebrew/bin/herdr) and the terminal (Ghostty) are hard-coded in apps/plugin/src/herdr.ts for now.

Enabling the kingdom theme

The kingdom art can't be redistributed, so it isn't in the repo:

  1. Download Tiny Swords by Pixel Frog. It's free.
  2. Copy the sprites into apps/plugin/dev.fedeya.corral.sdPlugin/imgs/kingdom/: pawns for each team colour, trees, castle, houses, gold stone, bushes, sheep, stump, meat and wood. The exact file names are in apps/plugin/src/themes/kingdom.ts.

The theme appears as soon as the files are there.

Website

The Desk landing page lives in apps/web. From the repository root, run bun run dev to start it locally or bun run build:web to produce the static site in apps/web/dist/.

The website includes public/favicon.svg and a 1200Γ—630 public/og.png. Set CORRAL_SITE_URL to the public deployment URL when building so the Open Graph and Twitter image tags contain an absolute URL (for example, CORRAL_SITE_URL=https://your-domain.example/ bun run build:web). Without it, local previews use /og.png; no production domain is assumed. The browser scene and agent conversations are simulated.

Development

This Bun monorepo contains @corral/plugin in apps/plugin and the website in apps/web. Install dependencies once with bun install at the repository root. All commands below run from that root; plugin wrappers set the plugin working directory and forward arguments.

Command
bun run build Build both workspaces
bun run build:plugin Bundle the Stream Deck plugin
bun run build:web Build the website
bun run watch Rebuild the plugin on changes
bun run restart Reload it in the Stream Deck app (needs streamdeck dev)
bun run preview <theme> --open Render keys and touch strip to a PNG, no device needed
bun run media Re-render the GIFs in docs/media/
bun run demo on / off Pretend agents in a separate herdr session, for recordings (see below)
bun run typecheck Type-check both workspaces
bun run test Run both workspace suites (not root test autodiscovery)
bun run test:plugin Run isolated layout, gesture, real-render and SDK action-path tests
bun run test:web Run website tests
bun run validate Validate the Stream Deck plugin

The plugin polls herdr agent list every second and focuses agents with herdr agent focus. Logs go to apps/plugin/dev.fedeya.corral.sdPlugin/logs/.

Tests exercise real layout, gestures, PNG rendering and herdr subprocess calls. Only the Stream Deck SDK dispatch / device transport is mocked; a test-only herdr CLI fixture supplies synthetic panes. Tests do not prove physical hardware timing or terminal activation (macOS open -a is not available in Linux CI). Runtime fixture files are created under TMPDIR and removed on completion.

Demo mode

bun run demo on starts a separate herdr session, corral-demo, with pretend agents that look like a coding agent at work. They follow a script (apps/plugin/scripts/demo-story.ts): they start working, some finish, some stop and ask you to confirm (press 1). The plugin switches to that session, so tapping a key opens the pretend agent. Your real herdr session isn't touched.

Open the demo in Ghostty with herdr --session corral-demo. Run bun run demo on again to restart the story, and bun run demo off when you're done.

Credits

About

Your coding agents as a herd of animated pixel-art critters on a Stream Deck + (herdr). Switchable themes: farm, kingdom.

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages