Skip to main content

What you get

One per-user .exe. The person you send it to double-clicks, then runs gaia-tui — no Python, no Go, no clone, no admin rights. It installs two binaries and a sentinel file, and nothing else. Lemonade and the models are deliberately not bundled. They are gigabytes, and gaia init already owns downloading them on first run.
This is a developer build, not what users install — they use Install GAIA. It puts its own gaia-tui on your PATH under its own GAIA entry in Installed apps, so the GAIA installer refuses to run while it is installed (exit code 4) rather than leave two of each. Uninstall it from Installed apps → GAIA first.

Build it

The packaging script packages binaries — it does not build them. Build both first:
The result lands in dist/installer/gaia-setup-<version>.exe. You need NSIS 3.x (winget install NSIS.NSIS). Every other input is checked before makensis runs, so a missing binary fails with the exact command that produces it rather than a link error deep in the NSIS log.
The frozen agent ignores PYTHONPATH. Whatever is in your working tree when you run freeze.py is what ships — so build the agent after your last source change, not before. A binary frozen from an older tree looks identical and behaves like the old code.

Where it installs

Verify before you share it

Run the binary the way your recipient will — with no repo on PATH and no PYTHONPATH — and confirm it reaches the model server:
lemonade_reachable must be true and lemonade_base_url must name the server you expect. A frozen binary that resolves the wrong address reports a connection refusal and tells the user to run gaia init — on a machine where the server is already running and healthy.
If you run GAIA’s own embedded server (gaia lemonade embedded), it binds a port chosen at start time and records it in ~/.gaia/lemonade/state.json. Clients find it through resolve_lemonade_base_url(); anything that hardcodes the packaged default port cannot see it.