# How to build ori-desktop This guide shows how to build the [ori-desktop](./README.md) Wails shell on each platform, and what to watch out for. See [README.md](./README.md) for what the app does and [README.fr.md](./README.fr.md) for the French version of that overview. ## Prerequisites (every platform) - **Go 1.25 or newer** — `go.mod` requires `go 1.25.0`. - **The Wails v2 CLI**, matching the module's Wails version: ```bash go install github.com/wailsapp/wails/v2/cmd/wails@v2.16.0 export PATH="$PATH:$(go env GOPATH)/bin" wails version # → v2.16.0 ``` - **No Node or npm.** The frontend is plain HTML/CSS/JS embedded as-is; `wails.json` leaves `frontend:install` and `frontend:build` empty on purpose. Everything below is run from the `ori-desktop/` directory, which is a **separate Go module** (`rickub.com/bots-garden/ori-desktop`). The repository root's `make build` and `go test ./...` never touch it. ## What can be built from where Wails compiles the native window through cgo against the platform's webview, so the host decides what is reachable: | Target | From macOS | From Linux | From Windows | | --- | --- | --- | --- | | `darwin/*` (`.app`) | ✅ | ❌ needs the macOS SDK | ❌ | | `linux/*` | ❌ | ✅ | ❌ | | `windows/*` (`.exe`) | ✅ | ✅ | ✅ | Windows is the only free cross-build: WebView2 is loaded at runtime, so no C toolchain is involved. macOS needs Cocoa and WKWebView from Xcode, and Linux needs WebKitGTK — neither is cross-compilable in practice. All outputs land in `build/bin/` and can coexist there, since each target has a distinct name: `ori-desktop` (Linux), `ori-desktop.app` (macOS), `ori-desktop.exe` (Windows). ## macOS 1. Install the Xcode command line tools, if they are not already there: ```bash xcode-select --install ``` 2. Build and launch: ```bash cd ori-desktop wails build xattr -cr build/bin/ori-desktop.app # clear the quarantine attribute open build/bin/ori-desktop.app ``` No build tag is needed: `-tags webkit2_41` is a Linux-only concern (see below). 3. The app opens on its connection screen and needs an ori server to reach. From the repository root: `make run` (Claude Code) or `make run-mock` (demo agent, no network). The `scripts/launch-ori.applescript` launcher does the whole sequence — start the sandbox, wait for `/healthz`, open the `.app`. ### Choosing the architecture `wails build` alone targets the architecture of the machine you build on. To be explicit: ```bash wails build -platform darwin/universal # one .app running on Apple Silicon and Intel wails build -platform darwin/arm64 # Apple Silicon only wails build -platform darwin/amd64 # Intel only ``` A `universal` build runs the Go compiler twice and merges the results with `lipo`, so it takes about twice as long and produces a noticeably larger bundle. ### Bundle details `build/darwin/Info.plist` is a Go template filled from the `info` block of `wails.json` (product name `ori`, version `0.1.0`, company `bots-garden`). It sets `NSAppTransportSecurity/NSAllowsLocalNetworking` so App Transport Security allows the app to load ori over plain HTTP on the loopback interface — without it the iframe stays blank. `build/darwin/Info.dev.plist` is the variant `wails dev` uses. ## Linux 1. Install the GUI toolchain. On Ubuntu 26.04 (and any distribution that has moved past WebKitGTK 4.0): ```bash sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev ``` 2. Build with the matching build tag: ```bash cd ori-desktop wails build -tags webkit2_41 ``` **The build tag is mandatory on any system without WebKitGTK 4.0.** Wails' default cgo `pkg-config` line asks for `webkit2gtk-4.0`; where only 4.1 is packaged, a bare `wails build` stops with: ``` # [pkg-config --cflags -- gtk+-3.0 gio-unix-2.0 webkit2gtk-4.0 …] Package 'webkit2gtk-4.0' not found ``` `-tags webkit2_41` switches Wails to the `webkit2gtk-4.1` pkg-config name. On an older distribution that still ships `libwebkit2gtk-4.0-dev`, drop the tag. Two traps: - **`wails doctor` reports a false negative.** It probes `webkit2gtk-4.0` only, so even with 4.1 correctly installed it prints `libwebkit | Unknown | Not Found` and `Fatal: Required dependencies missing: libwebkit`. Ignore it and check the real thing: ```bash pkg-config --modversion gtk+-3.0 webkit2gtk-4.1 ``` - **`make desktop` runs a bare `wails build`**, so it fails on those distributions. Build from `ori-desktop/` with the tag instead. The target is correct on macOS, where it is normally used. ## Windows Cross-build from anywhere, no C toolchain required: ```bash cd ori-desktop wails build -platform windows/amd64 # → build/bin/ori-desktop.exe wails build -platform windows/arm64 ``` The resulting binary needs the WebView2 runtime, which is preinstalled on Windows 10 and 11. The `-webview2` flag picks the strategy for machines without it (`download`, the default, `embed`, `browser` or `error`), and `-nsis` produces an installer — that one needs NSIS on the build machine (`sudo apt-get install nsis` on Debian-family systems). `build/windows/` holds the manifest, icon and NSIS assets. ## Useful flags `wails build -help` lists them all; these are the ones that matter here. | Flag | Use | | --- | --- | | `-clean` | Empties `build/bin/` first. **It removes the other platforms' outputs too** — the `.app`, the `.exe` and the Linux binary all live in that one directory. | | `-platform os/arch` | Target something other than the host; comma-separate several. Defaults to the host. | | `-tags "…"` | Go build tags — this is how `webkit2_41` is passed. | | `-dryrun` | Prints the `go build` command Wails would run, without running it. Handy for diagnosing a cgo or pkg-config failure. | | `-debug` / `-devtools` | Keep the webview devtools available in a production build. | | `-race`, `-trimpath`, `-ldflags`, `-o` | Passed through to the Go compiler / output name. | | `-s` | Skip the frontend step — a no-op here, since there is no frontend build. | `wails build` also regenerates `frontend/wailsjs/` (the typed JS wrappers for the bound Go methods). Nothing imports them and they are gitignored; the frontend calls `window.go.main.App.()` directly. ## Development mode ```bash cd ori-desktop wails dev # add -tags webkit2_41 on Linux, as for build ``` This opens the window and reloads it whenever a file under `frontend/src/` changes (`assetdir` in `wails.json`). It also serves the app on http://localhost:34115, so it can be opened in a normal browser with devtools while still calling the Go methods. ## Tests The connection logic is pure Go and needs no GUI dependency at all — it can be run on a machine where the build itself is impossible: ```bash cd ori-desktop && go test ./internal/... # or, from the repository root: make desktop-test ``` ## Troubleshooting **`Package 'webkit2gtk-4.0' not found` (Linux)** — add `-tags webkit2_41`; see above. **`wails: command not found`** — `$(go env GOPATH)/bin` is not on `PATH`. **macOS refuses to open the `.app`** — two distinct causes: - *"cannot be opened"* / nothing happens: the executable inside the bundle lost its execute bit. This happens when `build/bin/` sits in a cloud-synced folder (iCloud Drive, kDrive, Dropbox), which does not always preserve POSIX modes. Restore it with: ```bash chmod +x build/bin/ori-desktop.app/Contents/MacOS/ori-desktop ``` That invalidates the bundle's signature, so if macOS then calls the app damaged, rebuild with `wails build -clean`. - *"cannot be opened because it is from an unidentified developer"* / *"damaged"*: Gatekeeper. `xattr -cr build/bin/ori-desktop.app` clears the quarantine flag on the machine that built it. Wails only signs the bundle ad hoc, so distributing it to other Macs requires a Developer ID certificate, `codesign` and notarisation with `notarytool`. **The window opens but stays empty** — that is the connection screen failing to reach ori, not a build problem. Check that an ori server answers on the URL shown (`curl http://localhost:8888/healthz`) and use the "Open in browser" button to confirm. ## See also - What the app is and how it talks to ori: [README.md](./README.md) / [README.fr.md](./README.fr.md) - Running the ori server itself: the repository's [quickstart](../quickstart.md) - Running the test suites: [docs/en/how-to/run-the-tests.md](../docs/en/how-to/run-the-tests.md)