sandbox-snapshot
Erstellt rotierende Verzeichnis-Snapshots (GreyHack-DB, Tool-Repos) mit rsync+hardlink und liefert einen Diff-Report für Änderungs-Detection. Trigger bei cron-gesteuerten Backups oder vor größeren Änd
SKILL.mdskills/sandbox-snapshot/SKILL.md
GitHubsandbox-snapshot
Rotierende, platzsparende Verzeichnis-Snapshots nach dem rsync+hardlink-Prinzip
(wie snapper/timeshift-Light). MaxClaw nutzt das, um GreyHack-Spielstände,
Tool-Repos und beliebige Workspace-Ordner ohne Deduplizierungs-Filesystem
rückwirkend wiederherstellbar zu halten.
When to use
- Cron-Trigger: stündlich/täglich ein inkrementeller Snapshot von
~/.local/share/GreyHack/und~/maxclaw-tools/. - Pre-Mutation: vor
greybel build,git reset --hard, DB-Migrationen oder Repo-Updates. - Recovery: wenn ein Build rot, eine Config überschrieben oder ein Sandbox-Test das Repo zugemüllt hat → Snapshot zurückspielen.
Pattern
1. Snapshot-Script (scripts/snapshot.sh)
#!/usr/bin/env bash
# snapshot.sh — rotierende Verzeichnis-Snapshots (rsync + hardlinks)
# Nutzung: snapshot.sh <QUELLE> [ANZAHL=24]
set -euo pipefail
SRC="${1:?Usage: snapshot.sh <source> [keep]}"
KEEP="${2:-24}"
NAME="$(basename "${SRC%/}")"
DEST="${SNAPSHOT_BASE:-$HOME/.local/share/maxclaw/snapshots}/$NAME"
mkdir -p "$DEST"
# neuester Snapshot als Referenz (Hardlink-Basis)
latest="$(ls -1dr "$DEST"/snap-* 2>/dev/null | head -1 || true)"
link_dest=()
[[ -n "$latest" ]] && link_dest=(--link-dest="$latest")
TS="$(date +%Y%m%d-%H%M%S)"
new="$DEST/snap-$TS"
mkdir -p "$new"
# Spiegelung; --link-dest macht unveränderte Dateien zu Hardlinks
rsync -a --delete "${link_dest[@]}" "$SRC/" "$new/"
# Alte Schnappschüsse außerhalb KEEP entfernen
mapfile -t old < <(ls -1dt "$DEST"/snap-* | tail -n +$((KEEP + 1)))
rm -rf "${old[@]:-}"
echo "snapshot ok: $new (behalte $KEEP)"
2. Diff-Engine (scripts/snapshot-diff.sh)
#!/usr/bin/env bash
# snapshot-diff.sh — Änderungen zwischen zwei Snapshots listen
set -euo pipefail
A="${1:?old-snapshot}"; B="${2:?new-snapshot}"
# rsync --dry-run + -i liefert pro Datei Status-Codes (cd>/.+ etc.)
rsync -anic --delete "$A/" "$B/" | grep -v '^\.' | head -200
3. Wiederherstellung
# Restore: Snapshot-Inhalt zurück nach $SRC
rsync -a --delete /path/to/snap-20260704-120000/ "$SRC/"
Pitfalls
- ❌ Pfad ohne Trailing-Slash → rsync legt ein Unterverzeichnis an. Immer
"$SRC/". - ❌ Snapshots auf demselben FS wie Source ist OK (hardlinks), aber nicht
auf einem Netz-Mount —
--link-destwird dort zur Full-Copy. - ❌ Hardlink auf Filesystem ohne reflink (ext4 ok, NFS nicht) —
--link-destfunktioniert nur auf POSIX-Hardlink-fähigen FS; sonst wird's Vollkopie. - ✅
--deletenur in der Spiegelung, niemals in der Restore-Richtung ohne Backup dahinter. - ✅
SNAPSHOT_BASEals eigene Variable → Backup-Festplatte tauschen ohne Skriptänderung.
Cron-Beispiel
# stündlich: Sandbox + GreyHack-DB
0 * * * * /home/bratan/.openclaw/skills/sandbox-snapshot/scripts/snapshot.sh \
/home/bratan/.local/share/GreyHack 24
0 * * * * /home/bratan/.openclaw/skills/sandbox-snapshot/scripts/snapshot.sh \
/home/bratan/maxclaw-tools 24