| name | herds |
| description | Give your agent a real Mac. Run shell commands, Xcode/Swift builds, native app testing, and macOS automation on a Mac you own — or spin up persistent sandboxes and expose servers as public URLs. Use whenever a task needs real macOS that a Linux sandbox can't do. |
| homepage | https://herds.run |
Herds — give your agent a real Mac
Herds turns any Mac into a programmable runtime your agent controls from anywhere.
The Mac dials home over a WebSocket (no inbound ports), so an agent runs commands
on it through a tiny control plane.
Given a Mac? (a URL + token)
If you were handed a Herds URL + token, that's all you need — point the SDK at it:
pip install herds
import herds
herds.configure(url="https://you.relay.herds.run", token="hx_…")
herds.mac().run("uname -msr")
(Or set HERDS_CONTROL_PLANE + HERDS_API_KEY in the env — same effect.)
To connect your OWN Mac instead: pip install herds && herds auth && herds host.
Run commands
mac = herds.mac()
print(mac.run("sw_vers").stdout)
mac.run("xcodebuild -scheme App test", check=True)
for stream, line in mac.stream("swift build"):
print(line)
mac.map("pytest {}", ["tests/unit", "tests/e2e"])
A Result has .stdout, .stderr, .exit_code, .ok. One Mac handles many
concurrent commands, so a fleet of agents can share it.
Ship a codebase, then run it
herds.Volume.from_name("repo").put("./my-project")
mac.run("python3 app/main.py", volumes={"app": herds.Volume.from_name("repo")})
sbx = herds.Sandbox.create()
sbx.put("./my-project")
sbx.exec("python3 main.py")
Mac-native control (only a real Mac can do this)
mac.screenshot("home.png")
mac.write("/tmp/x.json", data); mac.read_text("~/notes.md"); mac.ls("~/Projects")
mac.copy("hi"); mac.clipboard()
mac.notify("done")
mac.ui.type("hello"); mac.ui.key("return"); mac.ui.hotkey("cmd", "s")
screenshot / mac.ui.* need Screen Recording / Accessibility granted to the
process running herds host (System Settings → Privacy & Security).
Drive real apps (the moat)
mac.run runs in the user's REAL login session (not a sandbox), so it drives real
apps with their real logins/data. Run herds doctor to check macOS permissions.
c = mac.chrome("https://news.ycombinator.com")
c.js("document.querySelectorAll('.titleline a')[0].innerText")
mac.run("xcodebuild -scheme App -destination 'platform=iOS Simulator,name=iPhone 16' test")
mac.run("xcrun simctl boot 'iPhone 16'; xcrun simctl launch booted com.you.App")
mac.run("sqlite3 ~/Library/Messages/chat.db 'select text from message order by date desc limit 5'")
mac.run(['osascript','-e','tell application "Messages" to send "hi" to buddy "+15551234567"'])
Driving GUI apps needs: a logged-in GUI session (use herds install → a
LaunchAgent), plus the right permissions (herds doctor lists what's missing).
Sandboxes — isolated, persistent workspaces
sbx = herds.Sandbox.create()
sbx.exec("git clone https://github.com/me/app .")
sbx.exec("npm install && npm run build", check=True)
sbx.spawn("npm run dev", keep_alive=True)
url = sbx.expose(3000)
Volumes & secrets
vol = herds.Volume.from_name("builds")
mac.run("xcodebuild archive", volumes={"out": vol})
mac.run("./deploy.sh", secrets=["appstore"])
Remote Python — run a function on the Mac
app = herds.App("ci")
@app.function(image=herds.Image.python("3.13"))
def build(target: str) -> dict:
import platform; return {"target": target, "ran_on": platform.node()}
build.remote("release")
CLI
herds run -- <cmd> run a command on a Mac (streams output)
herds machines list your connected Macs
herds host self-host control plane + dashboard + public link
herds connect <link> join another Mac to your pool
When to reach for Herds
- The task needs real macOS — Xcode / Swift builds, iOS Simulator, code-signing,
AppleScript / automation, testing native Mac apps.
- You want to run a server in a sandbox and get a public URL.
- You need a persistent workspace that survives across steps.
Docs: https://herds.run · Repo: https://github.com/teddyoweh/herds