# update.ps1 -- Full uplift cycle for claude-skills on Windows (PowerShell) # # Steps: # 1. git pull --ff-only in claude-skills repo # 2. Conditionally rebuild projects-meta-mcp (if source changed) # 3. Conditionally rebuild interns-mcp (if source changed) # 4. Install all skills via install.ps1 # 5. Show version diff (before -> after) # 6. Print reload hints # # Usage: update.ps1 [-Yes] # -Yes -- skip confirmation prompts (assume yes) [CmdletBinding()] param( [switch]$Yes ) $ErrorActionPreference = 'Stop' # -- Paths ------------------------------------------------------------------- $root = Split-Path -Parent $PSScriptRoot $skillsSrc = Join-Path $root 'skills' $target = if ($env:CLAUDE_SKILLS_DIR) { $env:CLAUDE_SKILLS_DIR } else { Join-Path $env:USERPROFILE '.claude\skills' } $commonRoot = if ($env:COMMON_ROOT) { $env:COMMON_ROOT } else { Join-Path $env:USERPROFILE 'projects\.common' } $metaMcp = Join-Path $commonRoot 'lib\projects-meta-mcp' $internsMcp = Join-Path $commonRoot 'lib\interns-mcp' # -- Collect before-versions -------------------------------------------------- $beforeVersions = @{} if (Test-Path $target) { Get-ChildItem -Path $target -Directory -ErrorAction SilentlyContinue | ForEach-Object { $vf = Join-Path $_.FullName 'SKILL.md' if (Test-Path $vf) { $match = Select-String -Path $vf -Pattern '^version:\s*(\d+\.\d+\.\d+)' -ErrorAction SilentlyContinue | Select-Object -First 1 $ver = if ($match) { $match.Matches.Groups[1].Value } else { '?' } $beforeVersions[$_.Name] = $ver } } } # -- Step 1: git pull --------------------------------------------------------- Write-Host "`n[update] Pulling claude-skills repo..." -ForegroundColor Cyan Push-Location $root $dirty = git status --porcelain 2>$null if ($LASTEXITCODE -ne 0) { $dirty = $true } if ($dirty) { Write-Host "[warn] Working tree has uncommitted changes. Stashing..." -ForegroundColor Yellow git stash push -m 'update-ps1-auto-stash' if ($LASTEXITCODE -ne 0) { Write-Error "Cannot stash changes"; Pop-Location; exit 1 } $stashed = $true } else { $stashed = $false } git pull --ff-only if ($LASTEXITCODE -ne 0) { Write-Error "git pull --ff-only failed (diverged or no upstream)" Pop-Location; exit 1 } Write-Host "[ok] Repo updated." -ForegroundColor Green if ($stashed) { Write-Host "[update] Popping stashed changes..." -ForegroundColor Cyan git stash pop 2>$null if ($LASTEXITCODE -ne 0) { Write-Host "[warn] Could not pop stash -- resolve manually" -ForegroundColor Yellow } } # -- Step 2: projects-meta-mcp ----------------------------------------------- $mcpRebuilt = $false if (Test-Path (Join-Path $metaMcp '.git')) { Write-Host "[update] Checking projects-meta-mcp..." -ForegroundColor Cyan Push-Location $metaMcp $preSha = git rev-parse HEAD git pull --ff-only 2>$null if ($LASTEXITCODE -ne 0) { Write-Host "[warn] projects-meta-mcp: pull failed or no upstream" -ForegroundColor Yellow } $postSha = git rev-parse HEAD if ($preSha -ne $postSha) { Write-Host "[update] Source changed, rebuilding projects-meta-mcp..." -ForegroundColor Cyan npm run build 2>$null if ($LASTEXITCODE -ne 0) { npm install; npm run build } Write-Host "[ok] projects-meta-mcp rebuilt." -ForegroundColor Green $mcpRebuilt = $true } else { Write-Host "[ok] projects-meta-mcp: up to date." -ForegroundColor Green } Pop-Location } else { Write-Host "[warn] projects-meta-mcp not found at $metaMcp -- skipping." -ForegroundColor Yellow } # -- Step 3: interns-mcp ----------------------------------------------------- if (Test-Path (Join-Path $internsMcp '.git')) { Write-Host "[update] Checking interns-mcp..." -ForegroundColor Cyan Push-Location $internsMcp $preSha = git rev-parse HEAD git pull --ff-only 2>$null if ($LASTEXITCODE -ne 0) { Write-Host "[warn] interns-mcp: pull failed or no upstream" -ForegroundColor Yellow } $postSha = git rev-parse HEAD if ($preSha -ne $postSha) { Write-Host "[update] Source changed, reinstalling interns-mcp..." -ForegroundColor Cyan pip install -e . 2>$null if ($LASTEXITCODE -ne 0) { pip3 install -e . } Write-Host "[ok] interns-mcp reinstalled." -ForegroundColor Green $mcpRebuilt = $true } else { Write-Host "[ok] interns-mcp: up to date." -ForegroundColor Green } Pop-Location } else { Write-Host "[warn] interns-mcp not found at $internsMcp -- skipping." -ForegroundColor Yellow } # -- Step 4: Install skills --------------------------------------------------- Pop-Location Write-Host "[update] Installing skills..." -ForegroundColor Cyan & "$root\scripts\install.ps1" Write-Host "[ok] Skills installed." -ForegroundColor Green # -- Step 5: Version diff ----------------------------------------------------- Write-Host "[update] Version diff:" -ForegroundColor Cyan $changes = $false Get-ChildItem -Path $target -Directory -ErrorAction SilentlyContinue | ForEach-Object { $vf = Join-Path $_.FullName 'SKILL.md' if (Test-Path $vf) { $match = Select-String -Path $vf -Pattern '^version:\s*(\d+\.\d+\.\d+)' -ErrorAction SilentlyContinue | Select-Object -First 1 $after = if ($match) { $match.Matches.Groups[1].Value } else { '?' } $before = $beforeVersions[$_.Name] if (-not $before) { $before = 'new' } if ($before -ne $after) { Write-Host " $before -> $after ($($_.Name))" $changes = $true } } } if (-not $changes) { Write-Host ' (no version changes)' } # -- Step 6: New setup-skills hint ------------------------------------------- $newSetup = @() Get-ChildItem -Path $skillsSrc -Directory | ForEach-Object { $name = $_.Name if ($name -like 'setup-*' -and -not (Test-Path (Join-Path $target $name))) { $newSetup += $name } } if ($newSetup.Count -gt 0) { Write-Host '' Write-Host '[update] New setup skills available:' -ForegroundColor Cyan $newSetup | ForEach-Object { Write-Host " - $_" } Write-Host ' Run the setup skill to configure it.' } # -- Step 7: Reload hints ---------------------------------------------------- Write-Host '' Write-Host '[ok] Update complete!' -ForegroundColor Green if ($mcpRebuilt) { Write-Host ' -> Run /reload-mcp to reload MCP servers (source changed)' } Write-Host ' -> Start a new Claude session for skill changes to take full effect'