From 04a26bd0990b1fbe67935b5f2fcc60936cdb4fed Mon Sep 17 00:00:00 2001 From: zumayaaustin-creator Date: Tue, 23 Jun 2026 08:37:06 -0700 Subject: [PATCH] Add Windows backup restore scripts --- README.md | 22 ++++++++++++++++++++-- backup.ps1 | 42 ++++++++++++++++++++++++++++++++++++++++++ restore.ps1 | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 backup.ps1 create mode 100644 restore.ps1 diff --git a/README.md b/README.md index cc209ea..7b48f5b 100644 --- a/README.md +++ b/README.md @@ -149,7 +149,8 @@ agentic-os/ ├── requirements.txt # Python dependencies ├── install.sh # One-command installer ├── start.sh # Launch dashboard -├── backup.sh / restore.sh # Disaster recovery +├── backup.sh / restore.sh # Unix disaster recovery +├── backup.ps1 / restore.ps1 # Windows disaster recovery │ ├── dashboard/ # Web frontend (SPA) │ ├── index.html # Entry point + sidebar @@ -259,6 +260,23 @@ Create cron jobs: heartbeat (5 min), memory consolidation (weekly), daily standu ### Cost Analytics Track spending per provider/model/agent. Free-tier alerts warn when nearing limits. +### Disaster Recovery +Create and restore local snapshots of `brain/`, `skills/`, `agents/`, `data/`, `registry/`, `standards/`, and `prompts/`. User-specific `data/settings.json` is excluded from backups. + +**Unix/macOS/Linux** +```bash +./backup.sh +./restore.sh +``` + +**Windows PowerShell** +```powershell +.\backup.ps1 +.\restore.ps1 +``` + +Run the restore command without a backup file to list available backups. + ### Kanban Board (v0.2.0) Drag tasks across columns, filter by priority/category, click to view details. Block tasks when blocked, mark complete when done. @@ -294,7 +312,7 @@ Browse opencode session logs by date and size. Click "Replay" to view all messag | **Memory** | Obsidian vault (external) | Built-in brain/ + SQLite FTS5 | | **Scheduler** | Not shown | APScheduler cron jobs | | **Cost Tracking** | Not shown | Built-in per-provider analytics | -| **Backup/Restore** | Not shown | One-click tar.gz snapshots | +| **Backup/Restore** | Not shown | One-click Unix tar.gz and Windows zip snapshots | | **Audit Trail** | Not shown | Full activity log | | **Standards System** | Not shown | Discover/inject conventions | | **Client Timeout** | Not shown | 200s AbortController | diff --git a/backup.ps1 b/backup.ps1 new file mode 100644 index 0000000..969ae93 --- /dev/null +++ b/backup.ps1 @@ -0,0 +1,42 @@ +[CmdletBinding()] +param() + +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +$RootDir = $PSScriptRoot +$BackupDir = Join-Path $RootDir 'backups' +$Timestamp = Get-Date -Format 'yyyyMMdd_HHmmss' +$BackupFile = Join-Path $BackupDir "agentic-os-$Timestamp.zip" +$IncludeDirs = @('brain', 'skills', 'agents', 'data', 'registry', 'standards', 'prompts') + +New-Item -ItemType Directory -Path $BackupDir -Force | Out-Null + +$StagingDir = Join-Path ([System.IO.Path]::GetTempPath()) "agentic-os-backup-$Timestamp-$PID" +New-Item -ItemType Directory -Path $StagingDir -Force | Out-Null + +try { + foreach ($Dir in $IncludeDirs) { + $Source = Join-Path $RootDir $Dir + if (Test-Path -LiteralPath $Source) { + Copy-Item -LiteralPath $Source -Destination $StagingDir -Recurse -Force + } + } + + $SettingsFile = Join-Path $StagingDir 'data\settings.json' + if (Test-Path -LiteralPath $SettingsFile) { + Remove-Item -LiteralPath $SettingsFile -Force + } + + Write-Host "Creating backup: $BackupFile" + Compress-Archive -Path (Join-Path $StagingDir '*') -DestinationPath $BackupFile -Force + + $BackupSize = (Get-Item -LiteralPath $BackupFile).Length + Write-Host ("Backup created: {0:N2} MB" -f ($BackupSize / 1MB)) + Write-Host "Path: $BackupFile" +} +finally { + if (Test-Path -LiteralPath $StagingDir) { + Remove-Item -LiteralPath $StagingDir -Recurse -Force + } +} diff --git a/restore.ps1 b/restore.ps1 new file mode 100644 index 0000000..17dca11 --- /dev/null +++ b/restore.ps1 @@ -0,0 +1,47 @@ +[CmdletBinding()] +param( + [Parameter(Position = 0)] + [string]$BackupFile +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +$RootDir = $PSScriptRoot +$BackupDir = Join-Path $RootDir 'backups' + +if ([string]::IsNullOrWhiteSpace($BackupFile)) { + Write-Host 'Available backups:' + $Backups = Get-ChildItem -Path $BackupDir -Filter '*.zip' -File -ErrorAction SilentlyContinue | Sort-Object LastWriteTime -Descending + if ($Backups) { + $Backups | ForEach-Object { Write-Host " $($_.FullName)" } + } + else { + Write-Host " No backups found in $BackupDir" + } + Write-Host '' + Write-Host 'Usage: .\restore.ps1 ' + exit 1 +} + +if (-not [System.IO.Path]::IsPathRooted($BackupFile)) { + $BackupFile = Join-Path $RootDir $BackupFile +} + +if (-not (Test-Path -LiteralPath $BackupFile -PathType Leaf)) { + Write-Error "Backup file not found: $BackupFile" + exit 1 +} + +Write-Host "Restoring from: $BackupFile" +Write-Host 'WARNING: This will overwrite current brain\, skills\, agents\, data\, registry\, standards\, prompts\' + +$Confirm = Read-Host 'Continue? (y/N)' +if ($Confirm -notin @('y', 'Y')) { + Write-Host 'Cancelled.' + exit 0 +} + +Expand-Archive -LiteralPath $BackupFile -DestinationPath $RootDir -Force + +Write-Host 'Restore complete!'