--- /dev/null
+#!/bin/zsh -e
+
+usage() {
+cat <<EOF
+Usage: $0 DATASET@SNAPPREFIX snap-initial
+ $0 DATASET@SNAPPREFIX snap
+ $0 DATASET@SNAPPREFIX sync-initial DST
+ $0 DATASET@SNAPPREFIX sync DST
+ $0 DATASET@SNAPPREFIX clean COUNT
+EOF
+exit 1
+}
+
+enccmd="gpg --compress-level 0 --encrypt --recipient offline --cipher-algo AES-128"
+
+[ $# -ge 2 ] || usage
+
+what="$1"
+action="$2"
+
+now=$(date "+%Y%m%d%H%M")
+snaps=$(zfs list -t snap -d 1 -o name -H | grep $what | sort -nr)
+latest=$(echo $snaps | sed -n 1p)
+
+case "$action" in
+ snap-initial)
+ zfs snap -r $what-$now
+ echo $what-$now
+ ;;
+ snap)
+ [ -n "$latest" ]
+ [ "$what-$now" != "$latest" ]
+ zfs snap -r $what-$now
+ echo $what-$now
+ ;;
+ sync-initial)
+ dst="$3"
+ [ -d "$dst" ] || usage
+ set PIPE_FAIL
+ zfs send -Rv $latest | zstd | ${=enccmd} > $dst/$latest.zfs.zst.gpg
+ sync
+ touch $dst/$latest.from
+ ;;
+ sync)
+ dst="$3"
+ [ -d "$dst" ] || usage
+ latest_dst=$(find $dst -type f -name "*.from" | sort -rn | sed -n 1p)
+ [ -n "$latest_dst" ]
+ latest_dst=$(basename ${latest_dst%.from})
+ [ "$latest_dst" != "$latest" ]
+ set PIPE_FAIL
+ zfs send -Rv -i $latest_dst $latest | zstd | ${=enccmd} > $dst/$latest.zfs.zst.gpg
+ sync
+ echo "$latest_dst" > $dst/$latest.from
+ ;;
+ clean)
+ count="$3"
+ [ -n "$count" ] || usage
+ count=$(( $count + 1 ))
+ for snap in $(echo $snaps) ; do
+ count=$(( $count - 1 ))
+ [ $count -le 0 ] || continue
+ zfs destroy -Rv $snap
+ done
+ ;;
+ *)
+ usage
+ ;;
+esac