Cron jobs, CI, and AI agents drive the same engine the app uses.
Read this first. kd's exit code is 0 even when a command fails; it is 1 only when the daemon socket is unreachable. Scripts test the ok field of the JSON response, not $?.
if kd pull report.pdf /out/report.pdf | jq -e '.ok' >/dev/null; then echo "pulled" else echo "pull failed" >&2 fi
kd start runs in the foreground and is configured by environment variables set before it (list). Under systemd:
[Service] Environment=KD_SAVE_PATH=/srv/kd/received KD_NO_FUSE=1 ExecStart=/usr/local/bin/kd start Restart=on-failure
Ctrl-C, SIGTERM, and kd stop all shut it down cleanly: disconnect, unmount, exit.
With a saved contact on both sides, a nightly push is four commands:
#!/bin/sh set -e kd quick-connect "$PEER_FP" | jq -e '.ok' >/dev/null kd add /srv/backups/nightly.tar.zst | jq -e '.ok' >/dev/null # leave the session up, or: kd disconnect >/dev/null
The peer sees nightly.tar.zst offered and pulls it, or, in FUSE mode, reads it from the shared folder.
kd list | jq -r '.data.remote_files[]?.name' kd pull build-1234.zip /artifacts/build-1234.zip | jq -e '.ok'
A pull that gets interrupted keeps its partial data and resumes on the next identical pull. kd progress <name> reports 0-100 while it runs, and kd bench-pull measures the link with a throwaway transfer.
The daemon queues events; kd poll-event pops one per call, non-blocking:
while :; do ev=$(kd poll-event | jq -r '.data.event') [ -n "$ev" ] && echo "event: $ev" sleep 2 done
The queue holds 64 events and drops the oldest on overflow, so poll at least every few seconds while connected. The event names are listed in the kd reference.
quick-connect then needs no human step. Both sides must have saved each other once.reconnected: and gave_up: events.