--- /dev/null
+#!/usr/bin/env zsh
+
+set -e
+setopt EXTENDED_GLOB
+
+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)
+
+[[ $# -ge 2 ]] || usage
+
+what=$1
+action=$2
+
+zmodload -F zsh/datetime b:strftime
+now=$(strftime %Y%m%d%H%M)
+[[ $what =~ / ]] && depth=1 || depth=${#${(s./.)what}}
+snaps=$(zfs list -t snap -d $depth -o name -H | grep $what | sort -nr)
+snaps=(${(f)snaps})
+latest=${snaps[1]}
+latest_filename=${latest:gs#/#%}
+
+case $action in
+ snap-initial)
+ zfs snap -r $what-$now
+ print $what-$now
+ ;;
+ snap)
+ [[ -n $latest ]]
+ [[ "$what-$now" != $latest ]]
+ zfs snap -r $what-$now
+ print $what-$now
+ ;;
+ sync-initial)
+ dst=$3
+ [[ -d $dst ]] || usage
+ setopt PIPE_FAIL
+ zfs send -Rv $latest | zstd | $enccmd > $dst/$latest_filename.zfs.zst.gpg
+ sync
+ touch $dst/$latest_filename.from
+ ;;
+ sync)
+ dst=$3
+ [[ -d $dst ]] || usage
+ latest_dst=($dst/*~$dst/.*(.L0Onn[1]))
+ [[ $latest_dst ]]
+ latest_dst=${latest_dst[1]}
+ latest_dst=${${latest_dst##*/}%.from}
+ [[ $latest_dst != $latest_filename ]]
+ setopt PIPE_FAIL
+ set -x
+ zfs send -Rv -i ${latest_dst:gs#%#/} $latest | zstd | $enccmd > \
+ $dst/$latest_filename.zfs.zst.gpg
+ set +x
+ sync
+ print $latest_dst > $dst/$latest_filename.from
+ ;;
+ clean)
+ count=$3
+ [[ -n $count ]] || usage
+ count=$(( $count + 1 ))
+ for snap in $snaps ; do
+ count=$(( $count - 1 ))
+ [[ $count -le 0 ]] || continue
+ zfs destroy -Rv $snap
+ done
+ ;;
+ *)
+ usage
+ ;;
+esac