# goglobal-proxy-routing Skill installer for Windows PowerShell 5.1+ / PowerShell 7. # It ONLY: downloads the tarball + .sha256, verifies SHA-256, extracts to a temp dir (tar.exe, built into Windows 10+), # and copies skills\goglobal-proxy-routing into your agent skill dir(s). It runs nothing else. # # irm https://www.paibaowork.com/skills/goglobal-proxy-routing/install.ps1 | iex # $env:GGPR_AGENT='all'; irm https://www.paibaowork.com/skills/goglobal-proxy-routing/install.ps1 | iex # & ([scriptblock]::Create((irm https://www.paibaowork.com/skills/goglobal-proxy-routing/install.ps1))) -Agent all # # -Agent claude|agents|all claude = %USERPROFILE%\.claude\skills ; agents = %USERPROFILE%\.agents\skills ; all = both # -Version vYYYY.MM.DD pinned version instead of latest # -Sha256 also require this exact SHA-256 # -File offline: local tarball (needs .sha256 next to it, or -Sha256) param( [string]$Agent = $env:GGPR_AGENT, [string]$Version = '', [string]$Sha256 = '', [string]$File = '' ) $ErrorActionPreference = 'Stop' $ProgressPreference = 'SilentlyContinue' try { [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 } catch {} $Base = 'https://www.paibaowork.com/skills/goglobal-proxy-routing' $Name = 'goglobal-proxy-routing' $Tarball = 'goglobal-proxy-skill.tar.gz' function Fail($m) { Write-Host "error: $m" -ForegroundColor Red; throw $m } if ($Version) { if ($Version -notmatch '^v\d{4}\.\d{2}\.\d{2}(\.\d+)?$') { Fail "bad -Version: $Version" } $UrlBase = "$Base/$Version" } else { $UrlBase = "$Base/latest" } if ($Sha256) { $Sha256 = $Sha256.ToLower(); if ($Sha256 -notmatch '^[0-9a-f]{64}$') { Fail '-Sha256 must be 64 hex chars' } } $HomeDir = $env:USERPROFILE; if (-not $HomeDir) { $HomeDir = $HOME } $ClaudeRoot = if ($env:CLAUDE_CONFIG_DIR) { $env:CLAUDE_CONFIG_DIR } else { Join-Path $HomeDir '.claude' } $ClaudeDir = Join-Path $ClaudeRoot 'skills' $AgentsDir = Join-Path (Join-Path $HomeDir '.agents') 'skills' if (-not $Agent) { try { Write-Host 'Install for which agent?' Write-Host " 1) Claude Code -> $ClaudeDir" Write-Host " 2) Codex/Cursor/OpenCode/Copilot/other -> $AgentsDir" Write-Host ' 3) both (default)' $ans = Read-Host 'Enter 1/2/3 [3]' } catch { $ans = '' } switch ($ans) { '1' { $Agent = 'claude' } '2' { $Agent = 'agents' } default { $Agent = 'all' } } } switch -Regex ($Agent) { '^(claude|claude-code)$' { $Targets = @($ClaudeDir) } '^(agents|universal|codex|cursor|opencode|copilot|github-copilot)$' { $Targets = @($AgentsDir) } '^(all|both)$' { $Targets = @($ClaudeDir, $AgentsDir) } default { Fail "-Agent must be claude, agents or all (got: $Agent)" } } if (-not (Get-Command tar.exe -ErrorAction SilentlyContinue)) { Fail 'tar.exe not found (needs Windows 10 1803+)' } $Tmp = Join-Path ([IO.Path]::GetTempPath()) ("ggpr-" + [guid]::NewGuid().ToString('N')) New-Item -ItemType Directory -Path $Tmp | Out-Null try { $Tgz = Join-Path $Tmp $Tarball; $ShaFile = "$Tgz.sha256" if ($File) { if (-not (Test-Path -LiteralPath $File)) { Fail "file not found: $File" } Copy-Item -LiteralPath $File -Destination $Tgz if (Test-Path -LiteralPath "$File.sha256") { Copy-Item -LiteralPath "$File.sha256" -Destination $ShaFile } elseif (-not $Sha256) { Fail "offline mode needs $File.sha256 or -Sha256 " } } else { Write-Host "downloading: $UrlBase/$Tarball" Invoke-WebRequest -UseBasicParsing -Uri "$UrlBase/$Tarball" -OutFile $Tgz Invoke-WebRequest -UseBasicParsing -Uri "$UrlBase/$Tarball.sha256" -OutFile $ShaFile } $Got = (Get-FileHash -Algorithm SHA256 -LiteralPath $Tgz).Hash.ToLower() if (Test-Path -LiteralPath $ShaFile) { $Pub = ((Get-Content -LiteralPath $ShaFile -TotalCount 1) -split '\s+')[0].ToLower() if ($Got -ne $Pub) { Fail "SHA-256 mismatch: got $Got, .sha256 says $Pub" } } if ($Sha256 -and $Got -ne $Sha256) { Fail "SHA-256 mismatch: got $Got, expected $Sha256" } Write-Host "SHA-256 verified: $Got" -ForegroundColor Green $List = & tar.exe -tzf $Tgz if ($LASTEXITCODE -ne 0) { Fail 'cannot read tarball' } if ($List | Where-Object { $_ -match '^(/|[A-Za-z]:)|(^|[\\/])\.\.([\\/]|$)' }) { Fail 'tarball has unsafe paths, refusing' } $X = Join-Path $Tmp 'x'; New-Item -ItemType Directory -Path $X | Out-Null & tar.exe -xzf $Tgz -C $X if ($LASTEXITCODE -ne 0) { Fail 'extract failed' } $Src = Join-Path $X "goglobal-proxy-skill\skills\$Name" if (-not (Test-Path -LiteralPath (Join-Path $Src 'SKILL.md'))) { Fail 'SKILL.md not found in tarball' } # Backups go OUTSIDE the skills dir so agents don't load two copies of the same skill. $Stamp = Get-Date -Format 'yyyyMMdd-HHmmss' $Backups = Join-Path (Join-Path (Join-Path $HomeDir '.config') 'goglobal-proxy') 'skill-backups' $i = 0 foreach ($d in $Targets) { $i++ New-Item -ItemType Directory -Force -Path $d | Out-Null $Dest = Join-Path $d $Name if (Test-Path -LiteralPath $Dest) { New-Item -ItemType Directory -Force -Path $Backups | Out-Null $Bk = Join-Path $Backups "$Name-$Stamp-$i" Move-Item -LiteralPath $Dest -Destination $Bk Write-Host "previous copy kept: $Bk" } Copy-Item -Recurse -LiteralPath $Src -Destination $Dest Write-Host "installed: $Dest" -ForegroundColor Green } Write-Host '' Write-Host 'Done. Open your agent (Claude Code / Codex / Cursor ...) and say:' Write-Host ' Use the goglobal-proxy-routing skill and walk me through network setup from S0, one step at a time.' } finally { Remove-Item -Recurse -Force -LiteralPath $Tmp -ErrorAction SilentlyContinue }