How Shane works with AI agents

A walkthrough of the setup: how the agents are organised, how work reaches them, how they talk to Shane, and the small tools that hold it together. Written for a friend who asked. Machine names, addresses and work details are left out on purpose.

1. The short version

Shane runs a lot of coding agents at once (Claude Code mostly, plus Codex, Pi and OpenCode). Each one has a single job: one repo, one machine, or one role. They all live in the Herdr app, a desktop app for running agents, with panels Shane wrote himself. Any agent can find another by a stable address, send it a message and read its reply. He checks in from his desk or from a phone app.

Around that sit a handful of small tools he wrote. Review Desk makes sure a review request, a review comment or a failed check lands with the agent that owns that code. sidediff is where he reads what agents changed. Whatever an agent produces shows up on the screen he is actually looking at. Every agent gets credentials that last an hour instead of forever. And all of his tools come from one Homebrew tap that keeps every machine up to date on its own.

2. One agent per job

The rule is simple: every piece of work has exactly one agent that owns it. An agent with one repo in its head has a small, clean context, knows that repo's conventions, and can be handed a message like "CI is red on your branch" without any explanation of which branch or why.

Shane

chief of staff

desktop manager

Mac mini manager

homelab agent

project agents

The setup. The chief of staff keeps track of everyone; each agent below it owns one thing.

All four agent programs follow one shared rulebook; see One rulebook for every agent.

3. reach: every agent has an address

Agents find each other through reach, which gives every agent a stable address made of its machine, its space and its name (say desktop/homelab/homelab). reach send delivers a message to exactly that agent, waking it if it was asleep and waiting if it is busy. An address that matches nothing, or more than one agent, is refused rather than guessed, so a message never lands with the wrong agent.

reach ls                                   every agent, its state and where it runs
reach send desktop/homelab/homelab "..."   deliver a message (wakes it if asleep)
reach read desktop/web/web --lines 40      the bottom of its screen
reach pin desktop/web/main desktop/web/web give an agent the address it keeps

reach keeps no registry of its own: each time it is asked, it asks the hosts the agents run in, so it always knows what is alive, asleep or ended right now. Review Desk and nudge both deliver through it.

4. The Herdr app: where everything lives

Every agent and terminal runs in the Herdr app. It has two halves: herdr-core, a background server that runs the terminals and keeps them alive when the window closes or updates, and the window itself, which arranges them into spaces, tabs and panes. Agents use the same server from the command line: hc ls lists every terminal and agent with what it is doing, hc send hands one a message, hc read reads its screen. The app recognises each agent and knows whether it is working, idle, done or blocked on a question.

Shane's mods

The app's panels are small JavaScript mods, and Shane wrote his own on top of the stock ones:

Alongside those he uses stock panels such as Peek (a look at a sub-agent over its parent's tab), Files, Changes and worktrees, plus a third-party browser mod that draws a real Chrome page into a pane next to the agent.

The Herdr app: threads sidebar on the left, a Claude thread in the middle, and the Highlights panel on the right
Threads on the left, a Claude thread in the middle, Highlights on the right. Staged demo projects.
The markup editor: a pricing card screenshot with a circle, an arrow, a squiggle and a note
Markup: the picture gets a circle, an arrow and a note, then goes back to Claude with Send.
The options picker: three versions of a pricing card in a grid, with choices on the right
Options: Claude's choices as pictures. The pick goes back to the thread.
The secret prompt dialog over a thread, asking for a test key
Secret prompt: the token goes to a private file, never into the chat.

sth-mux is in progress: Shane's own build of the Herdr app on the Moonframe toolkit. It reads the same herdr-core state and runs his Threads mod natively, so the two can be used side by side while it matures. The older terminal version of Herdr still exists, but the app is where the agents live now.

The phone app

The phone app is how Shane keeps up when he is away from the desk. A small connector on each machine reports its agents to a hub, and the phone shows them grouped by what they need ("Needs you" first), each conversation with tool runs folded away, and lets him queue a message for after an agent's current turn. Prompts are saved the moment they are sent and delivered exactly once, so a patchy connection neither loses nor repeats one.

Herdr phone app: agents grouped into Needs you, Running and Idle Herdr phone app: a conversation with an agent fixing two failing tests
The phone app, shown here with demo agents: the fleet view and one agent's conversation.

5. Review Desk: work reaches the right agent

An agent that pushes a branch shouldn't have to sit polling CI, and Shane shouldn't have to copy review comments from one window into another. Review Desk is the piece that routes all of it, and it carries a lot of the day.

scheduled textreachsth-seatHerdr app

reviews and CI

Review Desk

owning agent

nudge

other agents

Shane

How messages reach an agent, and how it reaches Shane.

Agents do the first rounds of code review with each other, and Shane gets a queue of what is ready for a person:

Needs you also lists everything else waiting on him, each with the reason: a review no agent covers, an author who changed code under his comment without replying, his own pull requests that a person commented on, that are ready to merge or whose CI failed with no agent on it, and @mentions in his repositories. A failed check on a branch an agent is working on goes straight to that agent, which reads the log, fixes the cause and pushes. A menu bar item shows how many things need him.

ShaneDeskGit hostAgentShaneDeskGit hostAgentfix and pushpush branch1CI and reviews2routed to owner3labelled reply4ready for you5approve, merge6
A pull request's round trip. Agents handle the back and forth; approving and merging stay with Shane.

Agents never speak for Shane

This is a hard rule. Any comment an agent writes on his accounts carries a visible label saying it was written by an AI, and whether Shane directed it or not. An agent never replies to a person on its own: it drafts the text, shows Shane, and posts only once he says so. Review Desk is the one standing exception, and even there every comment goes through the desk with the label "AI agent review, not yet read by Shane". Agents there never approve, request changes, merge or resolve threads. Text from a pull request or a mention is treated as data, never as instructions to an agent.

6. sidediff: reviewing what agents write

sidediff is the tool Shane reads code in, all day. It is a GitHub-style diff viewer in the browser (file tree, split or unified view, "viewed" checkboxes with a progress bar) with a third column of notes aligned to the lines they describe. It watches the working tree, so the page updates as the agent edits, commits or switches branches.

What makes it work with agents is that the agent is in the review with him:

This is a real screenshot of a review of one small change in one of his repos (the command that pins an agent to an address in reach), at the ultra-wide size he works at. Click it to open it full size.

sidediff ultra-wide: the explainer with an architecture diagram on the left, the file tree, the split diff with highlighted lines and a tour comment in the middle, and the agent's notes on the right
All three at once. Left: the explainer the agent wrote for this change, with an architecture diagram of the new command. Middle: the diff, where the agent has stopped the tour on the clash check, highlighted it and left a sentence under it. Right: the agent's notes, each next to the line it explains, with a § link to the matching part of the explainer.
A comment thread: the agent's tour sentence, Shane's question, and the agent's answer
A two-way thread. Shane asked a question in the page; the agent, which was listening, answered it in the same thread a few seconds later.

Between Review Desk deciding what needs him and sidediff showing him exactly what changed and why, Shane spends his attention on judgement rather than on finding things.

7. Handoff and Screen Organizer

Handoff is a menu bar panel for the files agents produce: reports, HTML pages like this one, charts, screenshots. An agent never prints a file path at Shane. It hands the file over, and it shows up in the panel with a preview, is put on the clipboard (paste into a chat and you get the file, paste into a terminal and you get the path), and opens. Each file is delivered once, when it is finished, on whichever machine Shane is using (see sth-seat below).

Screen Organizer is a small menu bar app for the screenshots and screen recordings that end up in prompts and bug reports. It compresses new screenshots in place, compresses and moves screen recordings to their own folder, and can sort both into a folder per day, so what he drags into an agent is small and easy to find.

8. tether: a durable agent platform

tether is Shane's own platform for agents that run without him at a terminal. It runs on the homelab, and each piece of work is a durable workflow: a run survives restarts, waits out a model's usage limit and carries on, and can take days. Its steps are fixed commands, calls to the Git server and to chat, and agents working inside a sandboxed box.

Everything it writes on his repos is labelled as an AI's, and its changes arrive as pull requests for him to approve.

9. sth-seat: every machine feels like the one he's at

Most agents run on the headless Linux desktop, but Shane sits at the Mac mini. sth-seat is why that never feels like two computers. Things just show up where he is:

How it works

A small hub on the homelab knows when each machine last saw keyboard or mouse input; the machine with the most recent input is the seat. A daemon on every machine keeps a connection to the hub and does what it is sent: open a link in the default browser, put a file into Handoff, show a notification, show a prompt. Agents call the hub with the sth-seat command or as tools on the MCP router, and never need to know which machine Shane is at.

Machines can also act on each other directly: sth-seat run and cp run a command or copy a file on another machine in place of SSH, and send leaves a message in another machine's inbox. Every one of these is signed with the sending machine's own key, and the receiving machine checks it against its own policy file, which says exactly what it accepts from whom. Every command is logged where it ran, and nothing in a message is ever run. On the Mac the daemon is a signed app, so macOS remembers its permissions across upgrades.

MacHubAgentMacHubAgentnewest inputin Handoffas localhostopen report1deliver file2open dev server3via tunnel4ask secret5hidden prompt6saved as file7
Three deliveries end to end: a file into Handoff, a dev server through the tunnel, and a secret that goes to the agent's machine as a file.
The Handoff panel with four delivered files: a usage report, a homepage screenshot, a CSV and a screen recording
The Handoff panel with files agents delivered: click one to open it, drag it into Slack or a prompt, or copy it. This is the real panel, rendered offscreen with made-up items.
A browser window at localhost:5173 showing a demo homepage
A dev server running on the desktop, opened by its localhost address. The page is a real local server; the browser frame around it is drawn for the picture.

10. One tap, updated every hour

Every tool on this page that Shane wrote ships from one Homebrew tap, seethruhead/tap: sth-seat, Review Desk, sidediff, Handoff, nudge, reach, sth-dictate, sth-mcp, Screen Organizer and the rest. A dev build is only for testing a change; once it is released, the machine goes back to the brew version.

sth-update keeps every machine current. Every hour it refreshes only that tap, upgrades only the tap's tools that are out of date, one at a time, and restarts the services that run an upgraded tool so they pick up the new binary. It notifies him only when something fails. It never restarts the programs that host terminals and agents; those are upgraded and take effect on their next restart. A release reaches every machine within the hour, with nothing to paste.

nudge is a plain scheduler: it sends an agent a fixed, pre-written message on a schedule ("check CI on main every 30 minutes"), waiting until the agent is idle. That is all it does.

11. CI/CD he owns

Every repo lives on a self-hosted Gitea, and every pipeline runs on Gitea Actions on Shane's own hardware. Agents push; CI checks, builds, releases and deploys; nobody deploys by hand.

merge to maintagged release

agent pushes

runner on desktop

ci-cache

Dagger pipeline

image in registry

pin in homelab repo

deploy

brew tap

sth-update on every machine

From a push to running code: one runner, Dagger pipelines, and the homelab repo as the only way anything is deployed.

One runner, on the desktop

There is exactly one Actions runner, on the 96 GB desktop, taking four jobs at a time. Its labels decide where a job runs: app checks and image builds run on the host; homelab and deploy jobs run in containers on the desktop's Docker. Jobs run as a separate ci user that can't read Shane's code checkouts or keys.

Pipelines in Dagger, tasks in moon

Pipelines are written in Dagger, so the same pipeline runs on an agent's machine and in CI; "it passed locally" means the same thing in both places. Inside a repo, moon runs the tasks (typecheck, lint, tests, builds) and only the ones a change affects, with a remote cache on the homelab so a task that already passed for the same inputs isn't run again. Agents only ever run a repo's own scripts, never a tool binary directly, so they use the same flags and config CI does.

CI that works with the internet down

On 13 November outside DNS failed, and the deploy that would have fixed it couldn't run, because CI downloaded its tools from the internet on every run. Since then CI pulls everything through a cache stack on the homelab, which keeps serving what it holds when the upstream, or DNS itself, is down:

Every cache name resolves from the homelab's own DNS. It was proven with a test DNS server that answers only local names: with the rest of the internet unreachable, the pipelines still check, build and deploy.

Deploys only through CI

A merge to main builds the service's image and publishes it to Gitea's registry. CI then commits that image's exact digest to the homelab repo (a "pin" commit), and the homelab repo's own pipeline validates the stacks and deploys the change. That repo is the single record of what runs where; agents never change a running service by hand.

Releases to the tap

Shane's tools are released by tagging a version; the release's formula or cask in seethruhead/tap is updated to point at it, and sth-update installs it on every machine within the hour.

The hosted CI he tried: boat.dev

Before the desktop runner took everything, CI ran on boat.dev, a hosted service of sandbox boxes that can be stopped, resumed and forked. Shane wrote a controller that listened to Gitea's job events, woke a box (or forked a warm one) for each queued job and parked idle boxes again. It worked, but it was a constant fight:

Moving every job onto the desktop runner made CI faster, cheaper and predictable. boat.dev is now only a fallback, used for app checks when the desktop is booted into Windows or off.

12. One rulebook for every agent

Shane uses four agent programs (Claude Code, Codex, Pi and OpenCode), and all of them follow the same rules:

A few of the invariants, to give the flavour: never add AI attribution to a commit; never post a comment that reads as if Shane wrote it; one heavy command at a time; wrap anything that can hang in a short timeout; deliver finished files once, through Handoff; plain English, no em dashes.

13. How code is held to a standard

14. Worktrees, tickets and memory

15. Observability-driven development

The homelab runs a full Grafana stack (Prometheus for metrics, Loki for logs, Tempo for traces, Alloy to collect), and Shane's services send OpenTelemetry to it. The point is that agents debug from evidence:

16. Credentials: nothing long-lived in an agent's hands

Agents never hold long-lived secrets. The secrets live in OpenBao, an open-source fork of HashiCorp Vault running on the homelab, and agents get short-lived credentials from it through a small helper, sth-bao.

OpenBaosth-baoAgentOpenBaosth-baoAgentone-hour userdb login1machine login2one-hour token3db login4user, password5on stdin6
An agent asking for a one-hour database login. The secret goes to the tool through standard input, never on the command line.

Machine tokens are only accepted from the home network or the private VPN, and every request is written to an audit log.

17. The homelab and how machines trust each other

private VPNseat, secrets, toolsseat, secrets, tools

phone

homelab server

Omarchy desktop

Mac mini

The machines and what passes between them.

The MCP router and sth-mcp

The homelab runs several MCP servers that agents use as tools: the wiki, sth-ingest (web search, page reading, video transcripts and the saved library), sth-seat, health data from his phone, habits, a budget, a wish list and a hotel search. Rather than configure each one in every agent, they all sit behind one router, which holds a couple of hundred tools. Each machine has its own token for it.

The sth-mcp CLI sits in front of the router. Each command is one fresh request with no session held open, so restarting the router or any server behind it never means restarting an agent. An agent searches for a tool by a few words, reads that one tool's help and calls it, which keeps hundreds of tool descriptions out of its context.

The wiki

A self-hosted wiki holds the state of the homelab, the plans and handoff notes. Agents read it before answering questions about the setup and write down what they learn, so the next agent starts from what the last one found out.

18. Voice and reading: Whisper, sth-dictate, sth-ingest

A lot of Shane's prompts are spoken, not typed. whisper.cpp runs on the desktop's NVIDIA card with the large-v3-turbo model, as a service that starts at boot and offers the standard OpenAI transcription API on the home network. Transcription is fast enough that dictation feels immediate.

hotkey and mic

sth-dictate

saved video

sth-ingest

whisper.cpp on GPU

text at cursor or agent

transcript library

One transcription server, two uses.

sth-dictate

sth-dictate is a small dictation app, on the Mac as a menu bar app and on Linux too: tap a hotkey to start, tap again to stop, and the text is pasted at the cursor. Double tap and it streams, sending each sentence as you pause. The part that matters for agents: it can be pinned to Herdr, so dictation goes straight into the focused agent through the Herdr app itself, followed by Return, while Shane keeps working in another app. Talking to an agent becomes as quick as talking to a person across the room.

sth-ingest and the Chrome extension

sth-ingest gives agents what a person can read or watch, as tools on the MCP router: web search, pages read in a real browser on the homelab, and videos. A video with no captions is transcribed by the same Whisper server. A Chrome extension adds a "Send to Ingest" button on YouTube videos and a popup that sends any page's text, as the tab shows it, to a saved library. An agent can then "watch" a talk by reading its timestamped transcript and pulling frames at the moments that matter, or read a page Shane saved for it.

19. The machines

sth-vitals is a small daemon on each machine that sends CPU, memory, GPU, disk and sensor readings to the homelab's Grafana stack, so a slow machine can be looked at with real numbers. The working rule for agents is just as simple: heavy work (test suites, builds, installs) runs one command at a time, full browser suites belong in CI, and anything that might hang runs under a short timeout so it never sits there for ten minutes.

20. The principles underneath