# Ork Meter installer for Windows (PowerShell 5.1 or later). # # irm https://orkmeter.com/install.ps1 | iex # # Installs the Ork Meter plugin for each agent it finds on your PATH: # Claude Code (2.1.280 or later) via `claude plugin ...` # Codex (the Codex CLI) via `codex plugin ...`, then setup, # which needs Python 3.11, 3.12 or 3.13 # # This script downloads nothing itself. Claude Code and Codex fetch the # plugins, and every release they fetch is pinned by SHA-256: the Claude # marketplace file names the plugin zip's digest, and the Codex installer's # release.json names the wheel's. Run it again at any time to update in place. # It needs no administrator rights and writes only through the agents' own # plugin commands. Source and support: https://orkmeter.com/install & { $ClaudeMin = [version]'2.1.280' $ClaudeMarketplace = 'https://orkmeter.com/releases/claude/marketplace.json' $ClaudePlugin = 'ork-meter@edos' $CodexMarketplace = 'EDOS-Engineering/ork-meter-codex' $CodexPlugin = 'ork-meter-codex@edos-codex' # What to do after the Claude Code install. Becomes "Open Claude Code; Ork # Meter connects on first start" once the plugin connects by itself. $ClaudeNextStep = 'Claude Code: open Claude Code and run /ork-meter:connect, then restart Claude Code once.' # The executable for a command on PATH (claude.exe, codex.cmd), or $null. # Applications only, so a .ps1 shim never trips the execution policy. function Find-Tool($name) { $found = Get-Command $name -CommandType Application -ErrorAction SilentlyContinue | Select-Object -First 1 if ($found) { $found.Source } else { $null } } # What the run found: the next step per agent, and whether any install failed. # The install functions are called without capturing their output, so the # agents' own commands (and Codex setup's prompts) talk to your console. $state = @{ Next = @(); Failed = $false } # --- Claude Code ----------------------------------------------------------- function Install-Claude($claude) { Write-Host 'Claude Code: installing Ork Meter' $text = (& $claude --version 2>$null | Select-Object -First 1) $version = $null if ($text -match '^(\d+\.\d+\.\d+)') { $version = [version]$Matches[1] } if (-not $version -or $version -lt $ClaudeMin) { Write-Host " Claude Code $text is older than $ClaudeMin. Update it with: claude update" return } # Adding is a no-op when the marketplace is already there; update refreshes # it so a re-run picks up the newest release, then install and update. & $claude plugin marketplace add $ClaudeMarketplace; if ($LASTEXITCODE -ne 0) { return } & $claude plugin marketplace update edos; if ($LASTEXITCODE -ne 0) { return } & $claude plugin install $ClaudePlugin; if ($LASTEXITCODE -ne 0) { return } & $claude plugin update $ClaudePlugin; if ($LASTEXITCODE -ne 0) { return } $state.Next += $ClaudeNextStep } # --- Codex ----------------------------------------------------------------- # A Python the Codex plugin's pinned dependencies support (3.11-3.13), as the # command words to start it, or $null. function Find-CodexPython { $py = Find-Tool 'py' foreach ($v in '3.13', '3.12', '3.11') { if ($py) { & $py "-$v" -c 'import sys' 2>$null if ($LASTEXITCODE -eq 0) { return @($py, "-$v") } } } $python = Find-Tool 'python' if ($python) { $v = & $python -c 'import sys; print("%d.%d" % sys.version_info[:2])' 2>$null if ($v -in '3.11', '3.12', '3.13') { return @($python) } } $uv = Find-Tool 'uv' if ($uv) { foreach ($v in '3.13', '3.12', '3.11') { $found = & $uv python find --no-project $v 2>$null | Select-Object -Last 1 if ($LASTEXITCODE -eq 0 -and $found) { return @($found) } } } $null } # The whole Codex install is this one function: add the marketplace, add the # plugin, then run the plugin's setup, which pairs in the browser. function Install-Codex($codex) { Write-Host 'Codex: installing Ork Meter' $python = Find-CodexPython if (-not $python) { Write-Host ' Codex needs Python 3.11, 3.12 or 3.13. Install one (for example: winget install Python.Python.3.13), then run this again.' return } & $codex plugin marketplace add $CodexMarketplace; if ($LASTEXITCODE -ne 0) { return } & $codex plugin marketplace upgrade edos-codex; if ($LASTEXITCODE -ne 0) { return } $added = (& $codex plugin add $CodexPlugin --json) -join "`n" if ($LASTEXITCODE -ne 0) { return } $setup = Join-Path ($added | ConvertFrom-Json).installedPath 'scripts\ork_codex.py' if (-not (Test-Path $setup)) { Write-Host " The Codex plugin installed, but its setup script was not found at $setup." return } # Setup asks you to approve in the browser and to type the claim code here. # Start-Process gives it this console directly, so its prompts show as typed. $exe, $rest = $python $arguments = @() if ($rest) { $arguments += $rest } $arguments += '-I', '-B', "`"$setup`"", 'setup' $run = Start-Process -FilePath $exe -ArgumentList $arguments -NoNewWindow -Wait -PassThru if ($run.ExitCode -ne 0) { return } $state.Next += 'Codex: setup finished.' } $claude = Find-Tool 'claude' $codex = Find-Tool 'codex' if (-not $claude -and -not $codex) { Write-Host 'ork-meter: neither claude (Claude Code) nor codex (Codex CLI) is on your PATH. Install one, then run this again. Help: https://orkmeter.com/install' -ForegroundColor Red return } if ($claude) { $before = $state.Next.Count Install-Claude $claude if ($state.Next.Count -eq $before) { $state.Failed = $true; Write-Host 'Claude Code: install did not finish (see above).' -ForegroundColor Red } } if ($codex) { $before = $state.Next.Count Install-Codex $codex if ($state.Next.Count -eq $before) { $state.Failed = $true; Write-Host 'Codex: install did not finish (see above).' -ForegroundColor Red } } Write-Host '' $state.Next | ForEach-Object { Write-Host $_ } if (-not $state.Failed) { Write-Host 'Your dashboard: https://orkmeter.com/' } # No `exit`: under `irm | iex` it would close your PowerShell window. }