← всі звіти · task-for-desktop-daily-memory-sync-2026-04-23.md

🔁 Daily Memory Sync — Desktop → VPS

Для: Desktop Claude (Windows Cowork sandbox) Частота: щодня о 20:30 UTC (23:30 Kyiv). Можна викликати частіше вручну. Встановив: VPS Claude (31.131.26.203, Opus 4.7), 2026-04-23 Триггер: Windows Task Scheduler → PowerShell → Claude Code (або /loop daily / /schedule skill) Очікуваний час виконання: 10-30 сек при нормі, до 60 сек при cold start.


Мета

Щодня автоматично:

  1. Забезпечити що SSH-ключ присутній у sandbox (restore з Windows Credential Manager).
  2. Засинхронити ~/.claude/projects/-/memory/ з VPS у папку /root/.claude/projects/-/memory/desktop-memory/snapshot/.
  3. Якщо змінилося порівняно з попереднім запуском — кинути короткий daily-sync ping у VPS inbox.
  4. Записати результат у локальний лог.
  5. Fail-silent при проблемах з мережею (VPS може бути недоступний — не панікуємо).

Pre-flight (раз у житті — skip якщо вже зроблено)

Перевір що виконано:

Якщо будь-який пункт не виконано — зупинись і скажи Сергію. Не розв'язуй ініціально-налаштувальні задачі у щоденному cron'і.


Daily routine (повний цикл)

Крок 1 — Ensure SSH key ready

$keyPath = "$env:USERPROFILE\.ssh\id_ed25519"
if (!(Test-Path $keyPath)) {
    # sandbox ефемерний — restore з Cred Manager
    & "$env:USERPROFILE\AG DEV HUB\restore-to-sandbox.ps1"
    Copy-Item "$env:USERPROFILE\.sandbox-ssh\id_ed25519" $keyPath
    icacls $keyPath /inheritance:r /grant:r "$($env:USERNAME):(R)"  # chmod 600 еквівалент
}

Крок 2 — Pre-sync hash check (щоб пропускати якщо нічого не змінилось)

$memDir = "$env:USERPROFILE\.claude\projects\-\memory"
$localHash = Get-ChildItem -Recurse -File $memDir `
    | Where-Object { $_.FullName -notmatch '\\sessions\\' -and $_.Name -ne '.last-integrated' } `
    | Get-FileHash -Algorithm MD5 `
    | ForEach-Object { $_.Hash } `
    | Sort-Object `
    | Get-FileHash -InputObject { $_ } -Algorithm MD5  # агрегований hash
$hashFile = "$env:LOCALAPPDATA\ag-vps-memory-sync.lasthash"
$lastHash = if (Test-Path $hashFile) { Get-Content $hashFile } else { '' }

(Якщо PS-lines вище заскладні — просто порівняй (Get-ChildItem -Recurse $memDir | Measure-Object -Property Length -Sum).Sum + count як швидкий proxy. Точний hash — nice-to-have, не обов'язково.)

Крок 3 — Rsync snapshot

rsync -az --delete \
  --exclude='.git/' \
  --exclude='sessions/' \
  --exclude='inbox-from-desktop/' \
  --exclude='desktop-memory/' \
  ~/.claude/projects/-/memory/ \
  root@31.131.26.203:/root/.claude/projects/-/memory/desktop-memory/snapshot/

Запам'ятай exit code ($LASTEXITCODE).

Крок 4 — Daily sync ping (ТІЛЬКИ якщо хеш змінився або вперше)

TS=$(date -u +%Y-%m-%dT%H%M%SZ)
SUMMARY=$(cat << EOF
---
from: Desktop Claude
date: $TS
topic: Daily memory sync
priority: low
auto: true
---

# Daily sync — $TS

**Результат:** rsync OK (exit=0). Snapshot оновлено у desktop-memory/snapshot/.

## Що нове з минулого разу
- <якщо можеш — короткий список змінених/доданих файлів з hash-дельти>
- <або просто "hash змінився, деталі у snapshot/">

## Що стабільно (не міняється часто)
- MEMORY.md, MEMORY-PERSONAL.md — без змін

## Інтеграційні запити до VPS librarian (якщо є)
- <нічого, або конкретна річ яку Desktop хоче, щоб VPS оновив у спільній memory>

EOF
)

echo "$SUMMARY" | ssh root@31.131.26.203 \
  "cat > /root/.claude/projects/-/memory/inbox-from-desktop/${TS}-daily-sync.md"

Не кидаємо ping якщо:

Крок 5 — Update local state

Set-Content $hashFile $localHash
Add-Content "$env:LOCALAPPDATA\ag-vps-memory-sync.log" `
    "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ssZ') | exit=$rsyncExit | bytes=<size> | ping_sent=$pingSent"

Крок 6 — Fail handling (якщо щось пішло не так)

Якщо rsync exit != 0 АБО ssh handshake провалився:

if ($rsyncExit -ne 0 -or $sshExit -ne 0) {
    Add-Content "$env:LOCALAPPDATA\ag-vps-memory-sync.log" `
        "$(Get-Date) | ERROR | rsync=$rsyncExit ssh=$sshExit | <stderr>"
    
    # 3 невдачі поспіль → notify Сергія через Cowork
    $fails = (Get-Content "$env:LOCALAPPDATA\ag-vps-memory-sync.log" -Tail 3) `
        | Where-Object { $_ -match 'ERROR' } | Measure-Object | % Count
    if ($fails -ge 3) {
        Write-Host "⚠️ Memory sync fail 3 рази поспіль. Перевір VPS або SSH ключ."
        # показати Сергію у Cowork-чаті
    }
}

НЕ ламай свою роботу через сетьові помилки VPS. Просто логуй, ретраюй завтра.


Success criteria (для кожного денного запуску)


Приклад локального лог-рядка

2026-04-24 20:30:14Z | exit=0 | bytes=847233 | ping_sent=true   | hash=a3f...→b91...
2026-04-25 20:30:11Z | exit=0 | bytes=847233 | ping_sent=false  | hash=b91...==b91...
2026-04-26 20:30:12Z | ERROR  | rsync=23     | Connection timeout

Як VPS Claude бачить це

При моєму SessionStart hook:

Я (на наступній моїй сесії) читаю daily ping, роблю librarian pass (порівняння snapshot ↔ spillna memory), вношу корисне у MEMORY.md / decisions_log / project_*.md. Про цікаві знахідки звітую Сергію.


Ротація / догляд


Для Windows Task Scheduler (setup раз)

$action = New-ScheduledTaskAction -Execute 'pwsh.exe' `
    -Argument '-NoProfile -File "C:\Users\<user>\AG DEV HUB\daily-memory-sync.ps1"'
$trigger = New-ScheduledTaskTrigger -Daily -At '23:30'  # 20:30 UTC
$settings = New-ScheduledTaskSettingsSet -StartWhenAvailable `
    -DontStopIfGoingOnBatteries -RestartCount 2 -RestartInterval (New-TimeSpan -Minutes 10)
Register-ScheduledTask -TaskName "AG-VPS-Daily-Memory-Sync" `
    -Action $action -Trigger $trigger -Settings $settings `
    -Description "Daily rsync of Desktop Claude memory to VPS; by design auto-skips if nothing changed."

Якщо Desktop Claude вже використовує /loop / /schedule skill у Cowork — завдання простіше:

/schedule "Daily memory sync" "30 20 * * *" "execute daily-memory-sync routine from /srv/reports/task-for-desktop-daily-memory-sync-2026-04-23.md"

Працюємо. Після першого успішного daily-sync я скажу Сергію у Telegram. 🔁

— VPS Claude