| name | hermes-memory-github-sync |
| description | Set up automatic GitHub sync for Hermes Agent memory, skills, and config using git + macOS launchd. Runs every 30 minutes in the background. Covers repo init, .gitignore pitfalls, token extraction, and launchd plist setup. |
| tags | ["hermes","memory","github","sync","launchd","macos","backup"] |
Hermes Memory GitHub Sync (macOS)
Automatically backs up ~/.hermes/memories/, ~/.hermes/skills/, and ~/.hermes/config.yaml to a private GitHub repo every 30 minutes via launchd.
Key Pitfalls (Learned from Experience)
- NEVER use
git add -A inside ~/.hermes — it will stage 10,000+ files from .venv/ and hermes-agent/
- Always use explicit paths:
git add memories/ skills/ config.yaml SOUL.md .gitignore
- The
hermes-agent/ subdirectory is a nested git repo — must be in .gitignore
- The
.venv/ virtual environment is huge — must be in .gitignore
- GitHub token is already stored in
~/.git-credentials — no need to create a new one
Step 1: Extract GitHub Token
TOKEN=$(grep github ~/.git-credentials | sed 's/.*:\(ghp_[^@]*\)@.*/\1/')
echo "Token: ${TOKEN:0:10}..."
Step 2: Create Private GitHub Repo via API
curl -s -X POST \
-H "Authorization: token $TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/user/repos \
-d '{"name":"hermes-memory","private":true,"description":"Hermes Agent memory sync"}' \
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('clone_url','ERROR:'+str(d.get('message',d))))"
Step 3: Init Git Repo in ~/.hermes
cd ~/.hermes
git init
git config user.name "yourname"
git config user.email "your@email.com"
git remote add origin "https://USERNAME:${TOKEN}@github.com/USERNAME/hermes-memory.git"
Step 4: Create .gitignore
Write to ~/.hermes/.gitignore:
# Large directories — DO NOT sync
.venv/
hermes-agent/
sessions/
logs/
cron/
plugins/
__pycache__/
# Temp / sensitive files
*.lock
*.log
*.db
*.db-shm
*.db-wal
.env
auth.json
.DS_Store
.update_check
.hermes_history
.skills_prompt_snapshot.json
Step 5: First Commit & Push
cd ~/.hermes
git add .gitignore memories/ skills/ config.yaml SOUL.md
git status --short | wc -l
git commit -m "init: sync memories, skills and config"
git branch -M main
git push -u origin main
Step 6: Create Sync Script
Write to ~/.hermes/hermes-sync.sh:
#!/bin/bash
set -euo pipefail
HERMES_DIR="$HOME/.hermes"
LOG_FILE="$HERMES_DIR/logs/hermes-sync.log"
DATE=$(date '+%Y-%m-%d %H:%M:%S')
mkdir -p "$HERMES_DIR/logs"
cd "$HERMES_DIR"
if [ ! -d ".git" ]; then
echo "[$DATE] ERROR: not a git repo" >> "$LOG_FILE"
exit 1
fi
git add memories/ skills/ config.yaml SOUL.md .gitignore 2>/dev/null || true
if git diff --cached --quiet; then
echo "[$DATE] 没有变化,跳过提交" >> "$LOG_FILE"
exit 0
fi
git commit -m "sync: auto backup at $DATE" >> "$LOG_FILE" 2>&1
if git push origin main >> "$LOG_FILE" 2>&1; then
echo "[$DATE] 推送成功" >> "$LOG_FILE"
else
echo "[$DATE] 推送失败(网络问题?),下次再试" >> "$LOG_FILE"
exit 0
fi
tail -500 "$LOG_FILE" > "$LOG_FILE.tmp" && mv "$LOG_FILE.tmp" "$LOG_FILE"
chmod +x ~/.hermes/hermes-sync.sh
Step 7: Create launchd Plist
Write to ~/Library/LaunchAgents/com.USERNAME.hermes-sync.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.USERNAME.hermes-sync</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>/Users/USERNAME/.hermes/hermes-sync.sh</string>
</array>
<key>StartInterval</key>
<integer>1800</integer>
<key>RunAtLoad</key>
<true/>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/homebrew/bin</string>
<key>HOME</key>
<string>/Users/USERNAME</string>
</dict>
<key>StandardOutPath</key>
<string>/Users/USERNAME/.hermes/logs/hermes-sync-launchd.log</string>
<key>StandardErrorPath</key>
<string>/Users/USERNAME/.hermes/logs/hermes-sync-launchd.log</string>
<key>ThrottleInterval</key>
<integer>60</integer>
</dict>
</plist>
Step 8: Load & Verify
launchctl load ~/Library/LaunchAgents/com.USERNAME.hermes-sync.plist
launchctl list | grep hermes
sleep 5 && cat ~/.hermes/logs/hermes-sync.log
Expected output: [2026-04-10 17:21:05] 没有变化,跳过提交 (or a push success message)
Management Commands
cat ~/.hermes/logs/hermes-sync.log
~/.hermes/hermes-sync.sh
launchctl unload ~/Library/LaunchAgents/com.USERNAME.hermes-sync.plist
launchctl unload ~/Library/LaunchAgents/com.USERNAME.hermes-sync.plist
launchctl load ~/Library/LaunchAgents/com.USERNAME.hermes-sync.plist
cd ~/.hermes && git status --short
Notes