feat: claude-memory-sync — back up Claude Code auto-memory to its own private repo

Auto-memory (~/.claude/projects/*/memory, 774 files across 49 projects) goes to
gitea vh/claude-memory, not this repo. The git dir is ~/claude-memory.git and its
work tree is ~/.claude/projects, and exclude rules admit only memory/ folders, so
transcripts stay local and nothing is added inside ~/.claude.

- home_root/.local/bin/claude-memory-sync: commit, rebase onto origin, push, under
  a flock; --status; --init for a fresh machine. Every run records its result
  for the drift check.
- home_config/systemd/user/claude-memory-sync.{service,timer}: hourly with
  Persistent=true. Linked but not yet enabled.
- link-dotfiles --check now also reports uncommitted changes (a stale session
  can write old content back through an intact link) and a failed or stale
  (>3h) memory sync.
- CLAUDE.md and README document the backup and the never-put-credentials-in-memory rule.
This commit is contained in:
vh
2026-09-24 10:56:09 -07:00
parent fe63a67672
commit 59458f40ce
6 changed files with 179 additions and 2 deletions
+23 -1
View File
@@ -41,7 +41,29 @@ if [ "${1:-}" = "--check" ]; then
echo "✗ links into dotfiles whose target is gone:"
printf '%s\n' "$dangling" | sed 's/^/ /'
fi
[ "$drift" -eq 0 ] && echo "✓ no drift: every tracked file is linked, and no dotfiles link dangles."
# A link can stay intact while its content moves: an app that holds a stale copy
# in memory (a long-running Claude Code session with settings.json) writes it
# straight back through the link. That shows up only as an uncommitted change.
dirty="$(git -C "$repo" status --porcelain -- home_root home_config 2>/dev/null || true)"
if [ -n "$dirty" ]; then
drift=1
echo "✗ live config differs from the last commit (not backed up yet):"
printf '%s\n' "$dirty" | sed 's/^/ /'
fi
# Auto-memory backup (claude-memory-sync), checked only on machines that have it.
if [ -d "$HOME/claude-memory.git" ]; then
last="$HOME/.claude/state/claude-memory-sync.last"
if [ ! -f "$last" ]; then
drift=1; echo "✗ claude-memory-sync has never completed a run on this machine"
else
read -r ts result detail < "$last"
age=$(( ($(date +%s) - ts) / 60 ))
if [ "$result" != ok ] || [ "$age" -gt 180 ]; then
drift=1; echo "✗ claude-memory-sync: last run ${age} min ago — $result${detail:+ ($detail)}"
fi
fi
fi
[ "$drift" -eq 0 ] && echo "✓ no drift: every tracked file is linked and committed, no dotfiles link dangles, auto-memory backup is current."
exit "$drift"
fi