param( [string]$OutputDir = "D:\notatnik-ai\codex", [string]$SourceCodexHome = (Join-Path $env:USERPROFILE ".codex") ) $ErrorActionPreference = "Stop" function New-CleanDirectory { param([Parameter(Mandatory = $true)][string]$Path) if (Test-Path -LiteralPath $Path) { Remove-Item -LiteralPath $Path -Recurse -Force } New-Item -ItemType Directory -Path $Path -Force | Out-Null } function Copy-DirectoryContents { param( [Parameter(Mandatory = $true)][string]$Source, [Parameter(Mandatory = $true)][string]$Destination ) New-Item -ItemType Directory -Path $Destination -Force | Out-Null Get-ChildItem -LiteralPath $Source -Force | ForEach-Object { Copy-Item -LiteralPath $_.FullName -Destination $Destination -Recurse -Force } } if (-not (Test-Path -LiteralPath $SourceCodexHome)) { throw "Codex home not found: $SourceCodexHome" } $timestamp = Get-Date -Format "yyyyMMdd-HHmmss" $archiveBaseName = "codex-backup-$timestamp" $stagingRoot = Join-Path $env:TEMP $archiveBaseName $payloadDir = Join-Path $stagingRoot "payload" $toolsDir = Join-Path $stagingRoot "tools" $sourceScriptsDir = $PSScriptRoot New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null New-CleanDirectory -Path $stagingRoot New-Item -ItemType Directory -Path $payloadDir -Force | Out-Null New-Item -ItemType Directory -Path $toolsDir -Force | Out-Null Copy-DirectoryContents -Source $SourceCodexHome -Destination (Join-Path $payloadDir ".codex") $profileCodexFiles = Get-ChildItem -LiteralPath $env:USERPROFILE -Force -File -ErrorAction SilentlyContinue | Where-Object { $_.Name -like ".codex*" -and $_.FullName -ne $SourceCodexHome } foreach ($file in $profileCodexFiles) { Copy-Item -LiteralPath $file.FullName -Destination (Join-Path $payloadDir $file.Name) -Force } Copy-Item -LiteralPath (Join-Path $sourceScriptsDir "codex-import.ps1") -Destination (Join-Path $toolsDir "codex-import.ps1") -Force Copy-Item -LiteralPath (Join-Path $sourceScriptsDir "codex-import.cmd") -Destination (Join-Path $toolsDir "codex-import.cmd") -Force $files = Get-ChildItem -LiteralPath $payloadDir -Force -Recurse -File $manifest = [ordered]@{ kind = "codex-local-backup" createdAt = (Get-Date).ToString("o") sourceCodexHome = $SourceCodexHome sourceUserProfile = $env:USERPROFILE payloadRoot = "payload" tools = @( "tools/codex-import.ps1", "tools/codex-import.cmd" ) fileCount = @($files).Count totalBytes = [int64](($files | Measure-Object -Property Length -Sum).Sum) } $manifest | ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $stagingRoot "manifest.json") -Encoding UTF8 $zipPath = Join-Path $OutputDir "$archiveBaseName.zip" if (Test-Path -LiteralPath $zipPath) { Remove-Item -LiteralPath $zipPath -Force } Compress-Archive -Path (Join-Path $stagingRoot "*") -DestinationPath $zipPath -Force Remove-Item -LiteralPath $stagingRoot -Recurse -Force Write-Output $zipPath