Herdling is a macOS menu bar companion for Herdr. It shows local and SSH-hosted Herdr agents, keeps their status current, and opens the selected session in Ghostty.
- Groups agents by machine, session, Space, and worktree while preserving Herdr order.
- Activity prioritizes normally followed agents: blocked, done, working, then the three most recently updated idle agents. Sources opens the full directory; expand one source or keep them all closed.
- Check Mute in an agent's secondary actions menu to keep its live status without adding blocked/done to attention counts. Muted rows use lighter title and status ink, without an extra badge; Activity moves them below normal agents immediately. Unmuting restores normal priority. Mouse actions keep the viewport in place; keyboard focus follows the selected target. Running counts, navigation and the Sources hierarchy remain unchanged; the choice is saved locally.
- Keeps rows in place while browsing, with live status; reopen to rebuild the list. Failed jumps retain their target for retry.
- Updates local and remote sessions through Herdr's socket event stream, with discovery and CLI fallback where needed.
- Reuses an existing Ghostty Herdr client when possible. New clients open in a tab by default; Settings can switch this to a window.
- Reads SSH hosts from
~/.ssh/config, includingIncludefiles. - Supports Launch at Login, keyboard shortcuts, VoiceOver labels, light/dark appearance, and Reduce Motion.
- macOS 15 or later
- Swift 6.2 toolchain
- Herdr installed locally and on each enabled SSH host
- Ghostty for opening and focusing sessions
- Key-based or otherwise non-interactive SSH access for remote hosts
Herdling finds herdr through HERDR_BIN_PATH or common Homebrew/system paths. Remote commands run through the host's login shell.
There are no signed or notarized binary releases yet. Build the app from source:
git clone https://github.com/JinJieBeWater/herdling.git
cd herdling
bash scripts/build-app.sh release
open .build/Herdling.appThe script creates an ad-hoc-signed app at .build/Herdling.app. Move it to a stable location such as /Applications before enabling Launch at Login.
For a development build:
bash scripts/build-app.sh
open .build/Herdling.app- Start at least one Herdr session.
- Open Herdling from the menu bar.
- Open Settings with
⌘,or by right-clicking the menu bar item. - Enable required aliases under SSH Sources.
- Choose whether new Ghostty clients open as tabs or windows.
- Optionally record a global panel shortcut in Settings. No combination is assigned by default.
The first Ghostty action may trigger a macOS Automation permission prompt. Permission status appears in Settings.
Herdling uses named Host entries from ~/.ssh/config. Wildcard and negated entries are ignored. Each enabled host must:
- connect without an interactive password prompt;
- expose
herdrthrough its login shell; - provide
ncwith Unix-domain socket support.
Check the connection before enabling it:
ssh -o BatchMode=yes my-server '$SHELL -lc "herdr session list --json"'| Action | Result |
|---|---|
| Left-click menu bar item | Open or close roster |
| Right-click menu bar item | Open Refresh/Settings/Quit menu |
| Right-click an agent | Select it for inspection and open its fixed-corner actions menu; toggle Mute without navigation or a seen change |
| Click a machine in Sources | Toggle its directory; expanding one closes the previous source |
| Click an agent, worktree, Space, or session | Focus it in Ghostty |
| Global panel shortcut (when configured) | Toggle panel; select a target without navigating |
↑ / ↓ |
Select a row without navigating |
Enter |
Open selected target; source rows only toggle their directory |
← / → in Sources |
Return to parent / collapse or expand a source |
Tab / Shift-Tab |
Move among native controls |
⌘, |
Open Settings |
Esc in roster |
Close panel |
⌘Q |
Quit Herdling |
Herdr focus can mark every pane in the destination tab as seen and affect all shell clients in that session. A failed jump may already have changed focus; it does not imply rollback or that a task was handled. Recent idle rows come from Herdr's state timestamps, not navigation history.
Run tests:
swift testTreat warnings as errors:
swift test -Xswiftc -warnings-as-errorsBuild release app:
bash scripts/build-app.sh release- AppKit owns
NSStatusItemand a nonactivatingNSPanel; SwiftUI renders panel content. - Local and remote monitors maintain one NDJSON socket stream per Herdr session.
- Periodic discovery finds added or removed sessions. CLI polling remains a fallback when a stream is unavailable.
- Ghostty activation uses AppleScript plus terminal/process validation to reuse the correct client and avoid duplicate tabs or windows.
- No local sessions: confirm
herdr session list --jsonworks in a new shell. SetHERDR_BIN_PATHif Herdr is installed elsewhere. - SSH source stays offline: run the BatchMode command above. Fix host keys, authentication, remote
PATH, or missingncbefore retrying. - Ghostty does not open or focus: check System Settings → Privacy & Security → Automation and allow Herdling to control Ghostty.
- Launch at Login is unavailable: run Herdling from
.build/Herdling.appor another app bundle, not throughswift run.
Herdling itself does not currently declare a software license. The bundled Herdr mark is covered by third-party notices and the bundled Apache License 2.0 text.