# CogNEXUS - run it in your boundary. https://cognexuslabs.ai/install # # Thin bootstrap, on purpose: everything real lives in the artzain CLI # (PyPI), which this script installs and hands off to. Read it before you # run it - it is short because there is nothing to hide. # # irm https://cognexuslabs.ai/install.ps1 | iex # # Needs: Python 3.10+ and Docker Desktop (the CLI's own preflight checks # Docker and prints a one-line fix for anything missing). WSL2 users can use # install.sh inside the distro instead - both paths are supported equally. # # Everything runs inside one script block and fails with `throw`, never # `exit`. Under `irm ... | iex` this text runs in your own session: `exit` # would close your PowerShell window, output and all, and top-level # variables, functions and $ErrorActionPreference would outlive the install. & { $ErrorActionPreference = 'Stop' function Fail([string]$Message) { throw "install.ps1: $Message" } function IsStoreAlias($cmd) { # App execution aliases live in WindowsApps. Running the stub when # Python is not installed opens the Microsoft Store and hangs here; # treat them as missing and keep looking. $src = $cmd.Source return (-not $src -or $src -like '*\WindowsApps\*') } # py -3 so a 2.x default launcher cannot win; skip Store aliases. # Discovery is Continue so a missing `py -3` does not abort the loop # under Stop (stderr from the launcher becomes error records). $pyExe = $null $pyOpt = @() $foundVer = $null $savedEap = $ErrorActionPreference $ErrorActionPreference = 'Continue' foreach ($c in @( @{ Exe = 'py'; Opt = @('-3') }, @{ Exe = 'python3'; Opt = @() }, @{ Exe = 'python'; Opt = @() } )) { $cmd = Get-Command $c.Exe -ErrorAction SilentlyContinue if (-not $cmd -or (IsStoreAlias $cmd)) { continue } & $c.Exe @($c.Opt) -c 'import sys; raise SystemExit(0 if sys.version_info >= (3, 10) else 1)' 2>$null if ($LASTEXITCODE -eq 0) { $pyExe = $c.Exe $pyOpt = @($c.Opt) break } $foundVer = (& $c.Exe @($c.Opt) -V 2>&1 | Out-String).Trim() } $ErrorActionPreference = $savedEap if (-not $pyExe) { if ($foundVer) { Fail "Python 3.10+ is required (found: $foundVer)." } Fail 'Python 3.10+ is required. Install it from python.org (check "Add to PATH"), then re-run.' } # The CLI this run installed, when we know where it is. Preferred over # whatever `artzain` PATH finds first, which may be an older install. $bin = $null $pipxBin = $null # artzain>=0.6.0 is the first release that carries `artzain local`. Pinning # the floor makes an out-of-date index fail loudly instead of installing a # CLI without the installer in it. if (Get-Command pipx -ErrorAction SilentlyContinue) { Write-Host 'Installing the artzain CLI (pipx)...' pipx install --force 'artzain>=0.6.0' if ($LASTEXITCODE -ne 0) { Fail 'pipx install failed - see the output above.' } # pipx links the CLI into its bin dir, which stays off PATH until # `pipx ensurepath` has run AND a new terminal has opened. The module # fallback below cannot help, because pipx installs into a private # venv. Ask pipx for the bin dir (Continue: a pipx too old for # `environment --value` writes to stderr) and fall back to its default. $ErrorActionPreference = 'Continue' $pipxBin = (& pipx environment --value PIPX_BIN_DIR 2>$null | Out-String).Trim() $ErrorActionPreference = $savedEap if (-not $pipxBin) { $pipxBin = $env:PIPX_BIN_DIR } if (-not $pipxBin) { $pipxBin = Join-Path (Join-Path $HOME '.local') 'bin' } $bin = Join-Path $pipxBin 'artzain.exe' } else { Write-Host 'pipx not found - installing artzain for this user with pip...' & $pyExe @pyOpt -m pip install --user --upgrade --quiet 'artzain>=0.6.0' if ($LASTEXITCODE -ne 0) { Fail 'pip install failed - see the output above.' } } Write-Host '' Write-Host 'Starting CogNEXUS (docker compose, images pinned by digest)...' $onPath = Get-Command artzain -ErrorAction SilentlyContinue if ($bin -and (Test-Path -LiteralPath $bin)) { if (-not $onPath -or $onPath.Source -ne $bin) { Write-Host "Note: artzain is in $pipxBin, which is not on PATH in this terminal." Write-Host " Run 'pipx ensurepath' and open a new terminal to use 'artzain' directly." } & $bin local up @args } elseif ($onPath) { artzain local up @args } elseif ($pipxBin) { Fail "pipx installed artzain, but it is not in $pipxBin or on PATH. Run 'pipx ensurepath', open a new terminal, then run: artzain local up" } else { # pip --user installs sometimes land off PATH; the module entry point # is the same code either way. & $pyExe @pyOpt -c 'import sys; from artzain.cli import main; sys.argv = ["artzain", "local", "up"] + sys.argv[1:]; main()' @args } if ($LASTEXITCODE -ne 0) { Fail "artzain local up exited with code $LASTEXITCODE - see the output above." } } @args