DEV Community

sadayuki matsuno
sadayuki matsuno

Posted on

Running Claude Code agents in parallel gave me a second job — babysitting them. So I built Shepherd

How many Claude Code sessions do you have running right now?

If you follow Claude Code's recent feature work, the direction is unmistakable: subagents, background workers, and Agent Teams, where multiple Claudes split into a lead and teammates. Anthropic themselves have written about building their research feature as an orchestrator model dispatching subtasks to parallel workers. We're moving from "a conversation with one smart assistant" to "orchestrating a fleet of agents, each running on the model tier its task deserves."

How we receive the results is changing too. Artifacts in Claude Code, announced in June 2026, lets a session publish its deliverable — a research report, a design doc, a dashboard — as a polished HTML page at a claude.ai URL. Instead of scrolling a wall of chat text, you get one link: readable from your phone, hosted on Claude's servers, same URL across updates. Once you get used to "hand the agent a job, get a URL back," there's no going back.

Parallel orchestration plus URL-shaped deliverables — that's the good future. But the moment you actually run agents in parallel, a new job quietly lands on you:

Watching them.

You switch to a terminal and find Claude stopped on "Should I do A, or B?" — and it's been sitting there for twenty minutes. More agents were supposed to mean more progress; what actually grew was the patrol route you walk to check which agent is working and which one is stuck. You delegated the writing of code, and picked up a babysitting shift in exchange.

So I built a tool whose only job is the watching: Shepherd.

Shepherd logo

The Shepherd board: one card turns orange the moment its agent blocks on a question, then goes back to green once answered

https://github.com/sadayuki-matsuno/shepherd

It's a Mac app — a small always-on-top panel (a HUD) that floats above your other windows and shows every Claude Code session on the machine on a single board.

What it does

Every session becomes a card, grouped into columns by repository. A card shows the state (working / needs input / idle), elapsed time, branch, changed-file count, issue and PR numbers with CI status, links to Artifacts the session published, the model it's running on, a context-window gauge, and a one-line "what Claude is doing right now." Agents that need input turn orange and sort to the front — you physically can't miss them.

To connect this back to the opening: I think of it as an instrument panel for the orchestration era. The model chips tell you at a glance which tier each agent runs on (if every chip on your board is the same color, that's a sign to revisit your model assignment), and the Artifact badges jump straight to what your agents produced.

  • Click to jump — attach a zellij session and focus its pane, or open a background worker's live TUI with claude attach in a new terminal window
  • Reply in place — answer a permission prompt or a question from a popover on the HUD, without opening the terminal at all
  • Screenshot-to-agent — "this UI looks broken" becomes one region-select screenshot sent straight to that agent
  • Drag & drop files onto a card — the paths (plus an optional message) go to that session
  • Family trees, not a flat list — teammates, subagents, and child sessions nest under their parent card
  • Stream Deck support — mirror the board onto physical keys: one key per repo column, press to drill into sessions, blocked agents blink

Install

brew install --cask sadayuki-matsuno/tap/shepherd
Enter fullscreen mode Exit fullscreen mode

The prebuilt binary is ad-hoc signed (no Apple Developer ID yet), so if macOS blocks the first launch, right-click Shepherd.app → Open once, or add --no-quarantine to the install.

You can also build from source. It's Swift + AppKit, but there's no Xcode project and no SwiftPM — just a build.sh that calls swiftc directly:

git clone https://github.com/sadayuki-matsuno/shepherd.git
cd shepherd
./build.sh          # builds + installs /Applications/Shepherd.app
open -a Shepherd
Enter fullscreen mode Exit fullscreen mode

It runs on macOS 13+. Ghostty is the preferred terminal (falls back to Terminal.app), and PR badges use gh. And one thing matters most: there is nothing to configure on the Claude Code side. No hooks, no edits to settings.json — you install Shepherd.app and the sessions already running on your machine appear on the board.

That "installs nothing" shape was not the plan from day one. The rest of this post is the detour that led there.

It started with herdr

To tell Shepherd's story I have to start with herdr.

A terminal called herdr had been making the rounds among Claude Code users — a terminal designed from the ground up for working alongside agents. People around me kept switching. I'd been developing in a terminal + nvim + zellij for years, but the "Claude just works better in it" reputation got me to try migrating too.

And honestly, the agent experience was excellent. Every running agent visible in one list, each one's state obvious at a glance. No more missing an agent stuck on a question. Built-in per-agent workspace management. And — this becomes important later — an external API that let you query what herdr knew and drive it from outside.

My hands had already memorized zellij

The problem was everything else. herdr is, for better or worse, designed around the mouse, and there was no way to bring in the keybindings, layouts, and pane reflexes I'd spent years burning into muscle memory with zellij. This wasn't a "tweak the config" gap; the two tools disagree about how a terminal should be driven.

I wanted the features. I couldn't give up the ergonomics. For a while I bounced between both, committed to neither.

So I decided to read herdr instead of using it

Then I reframed the problem. herdr's best quality is "agent state is always visible" — and nothing about that requires the state to be visible inside herdr's window. What if I hit herdr's API from outside and drew what it knows on my own HUD? I'd get herdr's best part without touching herdr.

That was the first Shepherd. I kept driving my sessions from zellij, exactly as before, with a board of herdr-sourced state floating in the corner of my eye. A shepherd watching the herd — that's where the name comes from.

It worked better than I'd hoped. My zellij workflow stayed intact, and every agent's state lived at the edge of my vision. Cards turn orange and float up when an agent needs input, so the twenty-minute abandonment physically stopped happening.

Could plain zellij sessions show up too?

One gap remained: the board only showed sessions launched through herdr. What about a claude I start in a plain zellij pane?

My first answer was hooks. Claude Code's hooks can run scripts on tool events, so I wrote state files from a hook and had the HUD read them. It worked — but the installer had to edit settings.json to register the hook, which raises the barrier to entry, and any session without the hook stayed invisible. Hooks only fire when Claude Code decides to show you something, and the events I wanted weren't all there. The approach was hitting its ceiling.

The breakthrough came while chasing an unrelated ghost: a finished background worker whose card kept duplicating and refusing to disappear. Deleting the state file didn't help; there was no process to kill. Debugging that forced me to inventory everything Claude Code itself records locally — and there it was. Everything I'd been pulling from herdr's API, Claude Code was already writing down on its own. Better, even: a superset of what my hook had been laboriously generating. And since state changes arrive as file updates, you don't even need to poll.

Wait — what am I still using herdr for?

With that, plain zellij sessions and background workers landed on the board with no herdr in the loop. Then one day it hit me: the amount of data Shepherd still gets from herdr is… zero?

Once I saw it, the rest was quick. I stripped out the herdr dependency and the hooks. One app to install, zero Claude Code configuration — the shape from the top of this post. Rebuilding the data layer along the way took a full board refresh from a worst-case 9 seconds down to a steady 0.2–0.3s, which changed how the app feels entirely.

Looking back, the arc is: fail to migrate to a tool, extract the one thing you loved about it by observation, then discover the ground truth was underneath all along — and quietly become independent of the tool you were observing. I'm genuinely grateful to herdr. It's what taught me how good "your agents' state is always in view" feels.

Closing

Once you keep a flock of agents, the bottleneck stops being agent capability and becomes the allocation of your own attention. Shepherd is a tool for spending that attention only on the cards that need it — without abandoning the terminal setup your hands already know. If you're a zellij/tmux person who never managed to leave the terminal behind, this one's for you.

The docs site also hosts The Herding Guide — my working notes on running multiple agents: choosing an execution shape per task, and tiering models per role (which can move your cost by up to 10x).

https://sadayuki-matsuno.github.io/shepherd/

Top comments (0)