Host agents & launchd¶
Most of Jarvis runs inside Docker Compose, driven by the containerized
scheduler's crontab. A handful of jobs can't: they need something the
container doesn't have — LAN access to 192.168.1.x hosts, the owner's
~/.ssh keys, macOS Full Disk Access to read chat.db, or a plain stdio
pipe to talk JSON-RPC. Those run as host agents: plain Python
invocations, scheduled by macOS launchd on the owner's Mac instead of by
the container.
The connectors driving this are covered in depth on their own pages — iMessage / SMS and Homelab — this page is about the launchd mechanics common to all of them (the MCP server, covered on the next page, runs on demand rather than on a schedule and isn't a LaunchAgent).
The LaunchAgents¶
| Plist | Job | Cadence |
|---|---|---|
com.jarvis.capture.imessage-poll.plist |
capture_agent.poll --host — incremental iMessage/SMS poll |
Every 10 minutes |
com.jarvis.homelab.execute.plist |
homelab_agent.execute --host — apply owner-approved hl_proposals over SSH |
Every 5 minutes |
com.jarvis.homelab.scan-updates.plist |
homelab_agent.update_scan --host — scan docker stacks for image updates |
Monthly, 1st at 04:00 (under caffeinate) |
com.jarvis.homelab.update-execute.plist |
homelab_agent.update_execute --host — apply owner-approved hl_updates over SSH |
Every 10 minutes |
Install pattern¶
Every plist template lives under modules/<module>/agent/host/ and follows
the same install pattern:
- Edit the plist, replacing every
REPLACE_ME_*placeholder (repo root, dev credentials, owner email, Grafana URL/token/datasource UID — whichever the job needs). - Copy it into
~/Library/LaunchAgents/and load it:
cp modules/capture/agent/host/com.jarvis.capture.imessage-poll.plist ~/Library/LaunchAgents/com.jarvis.capture.imessage-poll.plist
launchctl load ~/Library/LaunchAgents/com.jarvis.capture.imessage-poll.plist
To stop a job, unload it:
launchctl unload ~/Library/LaunchAgents/com.jarvis.capture.imessage-poll.plist
(Swap in the matching plist filename from the table above for the other jobs.)
Don't double-apply¶
Never hand-run a host job while its LaunchAgent is loaded
None of the executors (homelab_agent.execute, homelab_agent.update_execute)
hold an atomic claim on the rows they're about to apply. If you hand-run
--host while the matching LaunchAgent is also loaded and due to fire,
both could pick up and apply the same approved proposal or update —
a double-apply race. Before running one of these by hand:
launchctl unload ~/Library/LaunchAgents/com.jarvis.homelab.execute.plist
Or only ever hand-run a job before installing its LaunchAgent in the first place.
Runbooks¶
Each host job has a full runbook covering one-time setup, running it once by hand for a shakedown, and troubleshooting:
modules/capture/agent/host/HOST_POLL.md— iMessage/SMS poll (FDA, connector row, cursor recovery).modules/homelab/agent/host/HOST_EXECUTE.md— homelab executor (approve → apply, SSH targets, safety model).modules/homelab/agent/host/HOST_UPDATES.md— monthly image-update scan/apply and manual rollback.