Skip to content

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:

  1. Edit the plist, replacing every REPLACE_ME_* placeholder (repo root, dev credentials, owner email, Grafana URL/token/datasource UID — whichever the job needs).
  2. 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.