Files
blackroad/scripts/local-sync.sh
Alexa Amundson 78fbe80f2a Initial monorepo — everything BlackRoad in one place
bin/       230 CLI tools (ask-*, br-*, agent-*, roadid, carpool)
scripts/   99 automation scripts
fleet/     Node configs and deployment
workers/   Cloudflare Worker sources (roadpay, road-search, squad webhooks)
roadc/     RoadC programming language
roadnet/   Mesh network (5 APs, WireGuard)
operator/  Memory system scripts
config/    System configs
dotfiles/  Shell configs
docs/      Documentation

BlackRoad OS — Pave Tomorrow.

RoadChain-SHA2048: d1a24f55318d338b
RoadChain-Identity: alexa@sovereign
RoadChain-Full: d1a24f55318d338b24b60bad7be39286379c76ae5470817482100cb0ddbbcb97e147d07ac7243da0a9f0363e4e5c833d612b9c0df3a3cd20802465420278ef74875a5b77f55af6fe42a931b8b635b3d0d0b6bde9abf33dc42eea52bc03c951406d8cbe49f1a3d29b26a94dade05e9477f34a7d4d4c6ec4005c3c2ac54e73a68440c512c8e83fd9b1fe234750b898ef8f4032c23db173961fe225e67a0432b5293a9714f76c5c57ed5fdf35b9fb40fd73c03ebf88b7253c6a0575f5afb6a6b49b3bda310602fb1ef676859962dad2aebbb2875814b30eee0a8ba195e482d4cbc91d8819e7f38f6db53e8063401649c77bb994371473cabfb917fb53e8cbe73d60
2026-03-14 17:08:41 -05:00

133 lines
4.5 KiB
Bash
Executable File

#!/bin/bash
# BlackRoad Local Sync — backs up working files to blackroad-os-inc/local
# Usage: ~/local-sync.sh [--dry-run]
# Cron: */30 * * * * ~/local-sync.sh >> /tmp/local-sync.log 2>&1
set -e
PINK='\033[38;5;205m'
GREEN='\033[38;5;82m'
AMBER='\033[38;5;214m'
RESET='\033[0m'
LOCAL_DIR="$HOME/local"
DRY_RUN=false
[[ "$1" == "--dry-run" ]] && DRY_RUN=true
log() { echo -e "${PINK}[local-sync]${RESET} $(date '+%H:%M:%S') $1"; }
# Dirs/files to sync (working files not in other repos)
SYNC_SOURCES=(
# Loose scripts
"$HOME/*.sh"
"$HOME/*.py"
"$HOME/*.html"
"$HOME/*.css"
"$HOME/*.json"
# Key working dirs (small, active, no own repo)
"$HOME/bin/"
"$HOME/roadnet/"
"$HOME/roadc/"
"$HOME/config/"
"$HOME/memory/"
"$HOME/archive/scripts/"
"$HOME/archive/modelfiles/"
"$HOME/archive/yaml/"
# Cron and dotfiles
"$HOME/.zshrc"
"$HOME/.zprofile"
"$HOME/.gitconfig"
"$HOME/.claude/CLAUDE.md"
"$HOME/.claude/projects/"
"$HOME/CLAUDE.md"
)
# Dirs to EXCLUDE from rsync (already in dedicated repos or too large)
EXCLUDE_ARGS=(
--exclude='.git/'
--exclude='node_modules/'
--exclude='__pycache__/'
--exclude='.next/'
--exclude='dist/'
--exclude='.DS_Store'
--exclude='*.pyc'
--exclude='package-lock.json'
--exclude='.env'
--exclude='.env.*'
--exclude='*.pem'
--exclude='*.key'
)
mkdir -p "$LOCAL_DIR/scripts" "$LOCAL_DIR/bin" "$LOCAL_DIR/dotfiles" "$LOCAL_DIR/config" "$LOCAL_DIR/roadnet" "$LOCAL_DIR/roadc" "$LOCAL_DIR/memory" "$LOCAL_DIR/archive"
log "Starting sync..."
# 1. Loose scripts and files from ~/
rsync -a --update "${EXCLUDE_ARGS[@]}" --include='*.sh' --include='*.py' --include='*.html' --include='*.css' --exclude='*/' --exclude='*.db' --filter='- */' "$HOME/"*.sh "$LOCAL_DIR/scripts/" 2>/dev/null || true
rsync -a --update "${EXCLUDE_ARGS[@]}" "$HOME/"*.py "$LOCAL_DIR/scripts/" 2>/dev/null || true
# 2. ~/bin/ tools
rsync -a --update "${EXCLUDE_ARGS[@]}" "$HOME/bin/" "$LOCAL_DIR/bin/" 2>/dev/null || true
# 3. Dotfiles
cp -p "$HOME/.zshrc" "$LOCAL_DIR/dotfiles/zshrc" 2>/dev/null || true
cp -p "$HOME/.zprofile" "$LOCAL_DIR/dotfiles/zprofile" 2>/dev/null || true
cp -p "$HOME/.gitconfig" "$LOCAL_DIR/dotfiles/gitconfig" 2>/dev/null || true
cp -p "$HOME/CLAUDE.md" "$LOCAL_DIR/dotfiles/CLAUDE.md" 2>/dev/null || true
# 4. Claude memory
rsync -a --update "${EXCLUDE_ARGS[@]}" "$HOME/.claude/projects/" "$LOCAL_DIR/claude-projects/" 2>/dev/null || true
# 5. Config dir
[ -d "$HOME/config" ] && rsync -a --update "${EXCLUDE_ARGS[@]}" "$HOME/config/" "$LOCAL_DIR/config/" 2>/dev/null || true
# 6. RoadNet & RoadC
[ -d "$HOME/roadnet" ] && rsync -a --update "${EXCLUDE_ARGS[@]}" "$HOME/roadnet/" "$LOCAL_DIR/roadnet/" 2>/dev/null || true
[ -d "$HOME/roadc" ] && rsync -a --update "${EXCLUDE_ARGS[@]}" "$HOME/roadc/" "$LOCAL_DIR/roadc/" 2>/dev/null || true
# 7. Memory
[ -d "$HOME/memory" ] && rsync -a --update "${EXCLUDE_ARGS[@]}" "$HOME/memory/" "$LOCAL_DIR/memory/" 2>/dev/null || true
# 8. Archive (scripts, modelfiles, yaml only — skip repos/images)
[ -d "$HOME/archive/scripts" ] && rsync -a --update "${EXCLUDE_ARGS[@]}" "$HOME/archive/scripts/" "$LOCAL_DIR/archive/scripts/" 2>/dev/null || true
[ -d "$HOME/archive/modelfiles" ] && rsync -a --update "${EXCLUDE_ARGS[@]}" "$HOME/archive/modelfiles/" "$LOCAL_DIR/archive/modelfiles/" 2>/dev/null || true
[ -d "$HOME/archive/yaml" ] && rsync -a --update "${EXCLUDE_ARGS[@]}" "$HOME/archive/yaml/" "$LOCAL_DIR/archive/yaml/" 2>/dev/null || true
# 9. Crontab snapshot
crontab -l > "$LOCAL_DIR/dotfiles/crontab.txt" 2>/dev/null || true
# 10. Homebrew bundle
brew list --formula > "$LOCAL_DIR/dotfiles/brew-formulae.txt" 2>/dev/null || true
brew list --cask > "$LOCAL_DIR/dotfiles/brew-casks.txt" 2>/dev/null || true
# Git commit and push
cd "$LOCAL_DIR"
git add -A
CHANGES=$(git diff --cached --stat)
if [ -z "$CHANGES" ]; then
log "${GREEN}No changes to sync${RESET}"
exit 0
fi
FILE_COUNT=$(git diff --cached --numstat | wc -l | tr -d ' ')
TIMESTAMP=$(date '+%Y-%m-%d %H:%M')
if $DRY_RUN; then
log "${AMBER}[DRY RUN] Would commit $FILE_COUNT files${RESET}"
git diff --cached --stat
git reset HEAD -- . > /dev/null 2>&1
exit 0
fi
git commit -m "sync: $TIMESTAMP$FILE_COUNT files from Alexandria" --quiet
git push origin main --quiet 2>/dev/null || git push origin master --quiet 2>/dev/null || {
# First push — set up branch
git branch -M main
git push -u origin main --quiet
}
log "${GREEN}Synced $FILE_COUNT files${RESET}"