systemd/agent-watcher.service: --user unit with on-failure restart, ProtectSystem=strict, ProtectHome=read-write, NoNewPrivileges=yes, PrivateTmp=yes. JSON logs to journald. Survives reboot via 'loginctl enable-linger'. examples/collector.yaml: working starter config for both sources with inline comments, per-route examples, and the spec §3.1.2 schema for drop files. install.sh: idempotent installer following the agent-ping pattern. Builds the binary, installs it + the unit, drops the example config if absent, reloads systemd, enables, and (unless --no-start) starts the service. Adds drop-folder lifecycle artifacts (*.tmp, .dead-letter/) to workspace .stignore so they don't replicate during processing. Skips Syncthing-related steps gracefully when ~/Nyx/workspace is not present. INSTALL.md: prerequisites, install, configure, verify (drop-file + webhook end-to-end probes), survive-logout, uninstall, troubleshooting table. README.md: rewritten to reflect actual status — v0 working with 43 tests, packaging ready, Layer 2 in progress on Bob's side. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3.3 KiB
INSTALL — agent-watcher Collector (Layer 1)
The MCP Watcher (Layer 2) has its own install path; this file covers Layer 1 only.
Prerequisites
- Linux with systemd
- Go 1.22+ (
sudo apt install golang-goon Ubuntu/Mint) - An existing agent-ping install on this host (the Collector writes to its inbox dir)
Install
Per CLAUDE.md rule #2, Angus runs the install commands — agents do not modify their own configuration.
git clone https://git.botbought.ai/foreman/agent-watcher ~/agent-watcher
cd ~/agent-watcher
./install.sh
The script builds, installs to ~/.local/bin/agent-watcher, drops the systemd unit into ~/.config/systemd/user/, copies the example config to ~/.config/agent-watcher/collector.yaml (if absent), reloads systemd, and starts the service.
To install without auto-starting (so you can edit the config first):
./install.sh --no-start
Configure
Edit ~/.config/agent-watcher/collector.yaml. The example has both sources configured for agent: foreman with placeholder routes — adapt to this host. At least one of webhook: or drop_folder: must be configured.
After editing:
systemctl --user restart agent-watcher
Verify
# logs
journalctl --user -u agent-watcher -f
# health
curl http://127.0.0.1:18790/health
# end-to-end via drop folder
echo '{"recipient":"bob","type":"INFO","payload":"hello from drop"}' \
> ~/Nyx/workspace/incoming/test.json
# end-to-end via webhook
curl -X POST http://127.0.0.1:18790/forgejo/push \
-H 'Content-Type: application/json' \
-d '{"repo":"agent-ping","actor":"angus"}'
# the lines should appear in the recipient's inbox
tail -2 ~/Nyx/workspace/pings/bob.inbox
Survive logout
systemctl --user units stop when the user logs out. To keep the Collector running across logouts:
sudo loginctl enable-linger $USER
Uninstall
systemctl --user disable --now agent-watcher
rm ~/.local/bin/agent-watcher
rm ~/.config/systemd/user/agent-watcher.service
systemctl --user daemon-reload
# config and example left behind; remove if desired:
# rm -rf ~/.config/agent-watcher
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
journalctl shows config: ... is required |
YAML field missing | Match the example, save, restart. |
systemctl --user status shows address already in use |
port 18790 taken by something else | Edit webhook.listen to a free port. |
| Drop file disappears but no inbox line | check .dead-letter/ for the file + .reason sidecar |
Schema validation failed — fix the producer. |
| Webhook returns 404 | path doesn't match a configured route | Routes must match exactly; check trailing slashes. |
| Service won't start across reboot | linger not enabled |
sudo loginctl enable-linger $USER |
| Drop file syncs back from another host before processing | drop folder is in Syncthing scope | This is intended (lets producers on other hosts deliver). Lifecycle artifacts (.tmp, .dead-letter/) are excluded by install.sh. |
What this does NOT install
- The agent-ping system. Install that first (
~/agent-ping/install.sh <name>). - Layer 2 (MCP Watcher). Different binary, different runtime, different unit — separate install when it lands.
- Caddy / reverse-proxy webhook auth. v1 is loopback-only; v2 will document the upgrade path.