$ErrorActionPreference = "Stop" $script:HomerAutoRun = $true $script:HomerEmbeddedArgs = @('--api-url','https://app.homer.tech/v1/check','--bundle-url','https://app.homer.tech/client-bundle.zip?v=20260909-completion-certainty','--all') function Install-Homer { param( [Parameter(ValueFromRemainingArguments = $true)] [string[]]$InstallerArgs ) $options = @{ ApiUrl = 'https://app.homer.tech/v1/check' BundleUrl = 'https://app.homer.tech/client-bundle.zip?v=20260909-completion-certainty' Version = '20260909-completion-certainty' Token = "" ApiKey = "" All = $false Cursor = $false ClaudeCode = $false Codex = $false DryRun = $false Update = $false ActivationAttemptId = "" DemoChallengeId = "" } for ($i = 0; $i -lt $InstallerArgs.Count; $i++) { $arg = $InstallerArgs[$i] switch -Regex ($arg) { '^--?all$' { $options.All = $true; continue } '^--?cursor$' { $options.Cursor = $true; continue } '^--?claude-code$' { $options.ClaudeCode = $true; continue } '^--?codex$' { $options.Codex = $true; continue } '^--?dry-run$' { $options.DryRun = $true; continue } '^--?api-url$' { $i++; $options.ApiUrl = $InstallerArgs[$i]; continue } '^--?bundle-url$' { $i++; $options.BundleUrl = $InstallerArgs[$i]; continue } '^--?token$' { $i++; $options.Token = $InstallerArgs[$i]; continue } '^--?api-key$' { $i++; $options.ApiKey = $InstallerArgs[$i]; continue } '^--?activation-attempt-id$' { $i++; $options.ActivationAttemptId = $InstallerArgs[$i]; continue } '^--?demo-challenge-id$' { $i++; $options.DemoChallengeId = $InstallerArgs[$i]; continue } '^--?update$' { $options.Update = $true; continue } default { throw "Unknown Homer installer option: $arg" } } } if (-not $options.Update -and -not ($options.All -or $options.Cursor -or $options.ClaudeCode -or $options.Codex)) { $options.All = $true } if (-not $options.Update -and -not $options.ApiKey -and -not $options.Token) { throw "Homer needs an install token or API key. Reopen the setup page and copy the command again." } $python = Get-Command python -ErrorAction SilentlyContinue if (-not $python) { $python = Get-Command py -ErrorAction SilentlyContinue } if (-not $python) { throw "Python 3 is required for this Homer beta installer. Install Python 3, restart this terminal, then run the Homer command again." } & $python.Source -c "import sys; raise SystemExit(0 if sys.version_info >= (3, 8) else 1)" if ($LASTEXITCODE -ne 0) { throw "Homer requires Python 3.8 or newer. Install a current Python 3 release, then run the Homer command again." } $target = Join-Path $HOME ".homer\client\$($options.Version)" if ($options.DryRun) { Write-Host "Homer client path: $target" Write-Host "Dry run only. Homer would download $($options.BundleUrl) and configure selected apps." return } New-Item -ItemType Directory -Force -Path $target | Out-Null $zipPath = Join-Path ([System.IO.Path]::GetTempPath()) "homer-client-$($options.Version).zip" Invoke-WebRequest -Uri $options.BundleUrl -OutFile $zipPath -UseBasicParsing Expand-Archive -Path $zipPath -DestinationPath $target -Force $helper = Join-Path $target "homer_install.py" $helperArgs = @("--api-url", $options.ApiUrl) if ($options.ApiKey) { $helperArgs += @("--api-key", $options.ApiKey) } if ($options.Token) { $helperArgs += @("--token", $options.Token) } if ($options.ActivationAttemptId) { $helperArgs += @("--activation-attempt-id", $options.ActivationAttemptId) } if ($options.DemoChallengeId) { $helperArgs += @("--demo-challenge-id", $options.DemoChallengeId) } if ($options.Update) { $helperArgs += "--update" } if ($options.All) { $helperArgs += "--all" } if ($options.Cursor) { $helperArgs += "--cursor" } if ($options.ClaudeCode) { $helperArgs += "--claude-code" } if ($options.Codex) { $helperArgs += "--codex" } & $python.Source $helper @helperArgs if ($LASTEXITCODE -ne 0) { throw "Homer installer failed." } } if ($script:HomerAutoRun) { $embedded = $script:HomerEmbeddedArgs Install-Homer @embedded } else { Write-Host "Homer installer loaded. Run: Install-Homer --all --token " }