Docs / How-to guides

Automate Transfers with kd

Cron jobs, CI, and AI agents drive the same engine the app uses.

Check results correctly

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

Run the daemon

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.

Push a file on a schedule

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.

Pull a build artifact

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.

React to events

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.

Run unattended