From d3457f31c4f10613e5f9bd7d066a5fe42d5ce60d Mon Sep 17 00:00:00 2001 From: prompt.ac/@jeffrey Date: Sun, 16 Aug 2026 14:44:10 +0000 Subject: [PATCH] juke-sync: the missing channel for finished tracks — pop/**/out/*.mp3 finals converge across the fleet through s3://shelf-sync/juke (git keeps carrying scores + tools, stems stay home per pop/.gitignore); up/down/both verbs plus a launchd install that runs both every 20 minutes, newest wins --- pop/bin/juke-sync.sh | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file(s) changed, 68 insertion(s)(+), 0 deletion(s)(-) diff --git a/pop/bin/juke-sync.sh b/pop/bin/juke-sync.sh new file mode 100644 --- /dev/null +++ b/pop/bin/juke-sync.sh @@ -0,0 +1,68 @@ +#!/bin/sh +# juke-sync — keep finished pop tracks (pop/**/out/*.mp3) converged across +# the fleet through the shelf-sync Space, shared prefix s3://shelf-sync/juke/. +# +# pop/bin/juke-sync.sh up push local finals newer than the Space +# pop/bin/juke-sync.sh down fetch finals the Space has and we lack +# pop/bin/juke-sync.sh both up then down (default) — run on each +# machine and the fleet converges, newest wins +# pop/bin/juke-sync.sh install write + load a launchd agent that runs +# `both` every 20 minutes on this machine +# +# Scope is deliberately mp3 finals only: stems, wavs, and raw renders stay on +# the machine that made them (pop/.gitignore keeps them out of git for size +# and sample-licensing reasons; neo runs tight on disk). aws s3 sync is +# incremental — unchanged tracks cost nothing. + +set -e +set -f # no globbing: $FILTERS carries literal aws --include/--exclude patterns + +POP_DIR="$(cd "$(dirname "$0")/.." && pwd)" +BUCKET="s3://shelf-sync/juke" +AWS_ARGS="--endpoint-url https://sfo3.digitaloceanspaces.com --region sfo3" +FILTERS='--exclude * --include */out/*.mp3' + +up() { + # shellcheck disable=SC2086 + aws s3 sync "$POP_DIR" "$BUCKET" $AWS_ARGS $FILTERS +} + +down() { + # shellcheck disable=SC2086 + aws s3 sync "$BUCKET" "$POP_DIR" $AWS_ARGS $FILTERS +} + +install_agent() { + plist="$HOME/Library/LaunchAgents/computer.aesthetic.juke-sync.plist" + cat > "$plist" < + + + + Labelcomputer.aesthetic.juke-sync + ProgramArguments + + /bin/sh + $POP_DIR/bin/juke-sync.sh + both + + StartInterval1200 + StandardOutPath/tmp/juke-sync.log + StandardErrorPath/tmp/juke-sync.log + EnvironmentVariables + PATH/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin + + +EOF + launchctl unload "$plist" 2>/dev/null || true + launchctl load "$plist" + echo "juke-sync agent loaded (every 20 min): $plist" +} + +case "${1:-both}" in + up) up ;; + down) down ;; + both) up; down ;; + install) install_agent ;; + *) echo "usage: juke-sync.sh [up|down|both|install]" >&2; exit 2 ;; +esac -- tangled.sh