nandi/oripublic Fork 0
main
Commits
Clone
git clone https://git.rickub.com/nandi/ori.git
git clone ssh://git@rickub.com/nandi/ori.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

forked from bots-garden/ori

🛟 Updated. b6cd929Unverified · on main · k33g · 11h ago
README.md · 138 lines · 6.3 KBmarkdown
Blame HistoryOpen raw

ori-desktop — a Wails desktop shell for ori

ori-desktop wraps the ori web client in a native window built with
Wails v2 (Go + the platform's webview). It does not reimplement ori:
the ori server keeps serving the React SPA and the /ws, /api/files, /ws/terminal
endpoints. The desktop app only

  1. shows a small connection screen with the ori server URL (default http://localhost:8888),
    remembered between runs in a JSON settings file;
  2. checks the server with GET /healthz through a Go-bound method;
  3. then displays the ori webapp itself inside the window.

It is a separate Go module (rickub.com/bots-garden/ori-desktop), so the parent
repository's go test ./... and make build are unaffected.

Prerequisites

  • Go 1.25+ (the module follows Wails v2.16's requirement).
  • The Wails v2 CLI: go install github.com/wailsapp/wails/v2/cmd/wails@v2.16.0
    (then make sure $(go env GOPATH)/bin is on your PATH).
  • The platform GUI toolchain Wails needs — run wails doctor to see what is missing:
    • Linux: gcc, pkg-config, libgtk-3-dev, libwebkit2gtk-4.0-dev (or -4.1-dev
      with -tags webkit2_41);
    • macOS: Xcode command line tools;
    • Windows: WebView2 runtime (preinstalled on Windows 10/11); NSIS only for the installer.
  • A running ori server. From the repository root: make run or make run-mock.

No Node/npm is needed: the frontend is plain HTML/CSS/JS embedded as-is (no bundler).

Run in development mode

cd ori-desktop
wails dev

wails dev builds the Go side, opens the window, and reloads the frontend when a file under
frontend/src/ changes (assetdir in wails.json). It also serves the app at
http://localhost:34115 so you can open it in a normal browser with devtools and still call the
Go methods.

Build a redistributable binary

cd ori-desktop
wails build            # → build/bin/ori-desktop (or .app / .exe)
# or, from the repository root:
make desktop

Cross-compiling for Windows from Linux/macOS works without any C toolchain:
wails build -platform windows/amd64build/bin/ori-desktop.exe.

Tests

The connection logic is pure Go and tested without any GUI dependency:

cd ori-desktop && go test ./internal/...
# or, from the repository root:
make desktop-test

internal/settings covers load/save round trips, defaults on a first run, invalid files and URL
normalisation; internal/health covers /healthz against an httptest server (healthy,
non-ori, unreachable, cancelled).

How it connects to ori

┌──────────────── ori-desktop (Wails window) ─────────────────┐
│ frontend/src (embedded, wails:// origin)                    │
│   connection screen ──► window.go.main.App.Connect(url)     │
│                             │ Go: NormalizeURL → GET /healthz → Save settings
│                             ▼                               │
│   <iframe src="http://localhost:8888/">  ◄── ori server serves the SPA,
│        SPA opens ws://localhost:8888/ws, /ws/terminal, /api/files as usual
└─────────────────────────────────────────────────────────────┘

Why an iframe? Wails v2 gives no runtime call to navigate the main webview to an external
URL; the window always shows the embedded frontend (runtime.BrowserOpenURL opens the system
browser instead, which is offered as the "Open in browser" fallback). Loading ori in an
<iframe> keeps a thin native bar (URL, Reload, Open in browser, Disconnect) around the
untouched ori SPA. This works because ori sends no X-Frame-Options/CSP frame-ancestors
header, and because the SPA derives its WebSocket URLs from window.location — inside the
iframe that is the ori origin itself, so ori's localhost:* WebSocket origin check passes.

On macOS, build/darwin/Info.plist sets NSAppTransportSecurity/NSAllowsLocalNetworking so
App Transport Security allows the plain-HTTP loopback load.

Go methods bound to the frontend (app.go)

Method Purpose
GetConfig() → settings.Settings Remembered settings (defaults on a first run).
SaveConfig(settings.Settings) Normalise the URL and persist.
CheckHealth(url) → health.Report GET <url>/healthz; never rejects — ok, statusCode, detail.
Connect(url) → string Normalise, check health, remember the URL, return the base URL to load.
OpenInBrowser(url) runtime.BrowserOpenURL fallback.
SettingsPath() → string Where the settings file lives (displayed on the screen).

The frontend calls them as window.go.main.App.<Method>() (Promises). The typed wrappers that
wails dev/wails build generate under frontend/wailsjs/ are gitignored because nothing
imports them; regenerate them with wails generate module if you want the .d.ts files.

Settings file

<user config dir>/ori-desktop/settings.json, i.e. ~/.config/ori-desktop/settings.json on
Linux, ~/Library/Application Support/ori-desktop/settings.json on macOS,
%AppData%\ori-desktop\settings.json on Windows:

{
  "serverUrl": "http://localhost:8888"
}

Layout

ori-desktop/
├── main.go              Wails bootstrap (window options, embedded assets, bindings)
├── app.go               Go methods bound to the frontend
├── wails.json           Wails project configuration
├── internal/settings/   settings file (load/save/normalise) + tests
├── internal/health/     GET /healthz probe + tests
├── frontend/src/        index.html, main.css, main.js (embedded ES module, no bundler)
└── build/               Wails build assets (icon, Info.plist, Windows manifest); build/bin is the output

Status / known limitations

  • Verified so far: unit tests, go vet, and a Windows cross-build (wails build -platform windows/amd64) from a Linux sandbox without GUI libraries. The window itself has not yet been
    launched (no WebKitGTK in that sandbox) — see the repository's .memory/ notes.
  • ori is loaded over plain HTTP; use it against local or trusted servers only.
  • Ori's --addr other than :8888 simply means typing the matching URL on the connection screen.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# ori-desktop — a Wails desktop shell for ori

`ori-desktop` wraps the [ori](../README.md) web client in a native window built with
[Wails v2](https://wails.io) (Go + the platform's webview). It does **not** reimplement ori:
the ori server keeps serving the React SPA and the `/ws`, `/api/files`, `/ws/terminal`
endpoints. The desktop app only

1. shows a small **connection screen** with the ori server URL (default `http://localhost:8888`),
   remembered between runs in a JSON settings file;
2. checks the server with **`GET /healthz`** through a Go-bound method;
3. then displays the **ori webapp itself** inside the window.

It is a separate Go module (`rickub.com/bots-garden/ori-desktop`), so the parent
repository's `go test ./...` and `make build` are unaffected.

## Prerequisites

- Go 1.25+ (the module follows Wails v2.16's requirement).
- The Wails v2 CLI: `go install github.com/wailsapp/wails/v2/cmd/wails@v2.16.0`
  (then make sure `$(go env GOPATH)/bin` is on your `PATH`).
- The platform GUI toolchain Wails needs — run `wails doctor` to see what is missing:
  - **Linux**: `gcc`, `pkg-config`, `libgtk-3-dev`, `libwebkit2gtk-4.0-dev` (or `-4.1-dev`
    with `-tags webkit2_41`);
  - **macOS**: Xcode command line tools;
  - **Windows**: WebView2 runtime (preinstalled on Windows 10/11); NSIS only for the installer.
- A running ori server. From the repository root: `make run` or `make run-mock`.

No Node/npm is needed: the frontend is plain HTML/CSS/JS embedded as-is (no bundler).

## Run in development mode

```bash
cd ori-desktop
wails dev
```

`wails dev` builds the Go side, opens the window, and reloads the frontend when a file under
`frontend/src/` changes (`assetdir` in `wails.json`). It also serves the app at
http://localhost:34115 so you can open it in a normal browser with devtools and still call the
Go methods.

## Build a redistributable binary

```bash
cd ori-desktop
wails build            # → build/bin/ori-desktop (or .app / .exe)
# or, from the repository root:
make desktop
```

Cross-compiling for Windows from Linux/macOS works without any C toolchain:
`wails build -platform windows/amd64``build/bin/ori-desktop.exe`.

## Tests

The connection logic is pure Go and tested without any GUI dependency:

```bash
cd ori-desktop && go test ./internal/...
# or, from the repository root:
make desktop-test
```

`internal/settings` covers load/save round trips, defaults on a first run, invalid files and URL
normalisation; `internal/health` covers `/healthz` against an `httptest` server (healthy,
non-ori, unreachable, cancelled).

## How it connects to ori

```
┌──────────────── ori-desktop (Wails window) ─────────────────┐
│ frontend/src (embedded, wails:// origin)                    │
│   connection screen ──► window.go.main.App.Connect(url)     │
│                             │ Go: NormalizeURL → GET /healthz → Save settings
│                             ▼                               │
│   <iframe src="http://localhost:8888/">  ◄── ori server serves the SPA,
│        SPA opens ws://localhost:8888/ws, /ws/terminal, /api/files as usual
└─────────────────────────────────────────────────────────────┘
```

**Why an iframe?** Wails v2 gives no runtime call to navigate the main webview to an external
URL; the window always shows the embedded frontend (`runtime.BrowserOpenURL` opens the system
browser instead, which is offered as the "Open in browser" fallback). Loading ori in an
`<iframe>` keeps a thin native bar (URL, Reload, Open in browser, Disconnect) around the
untouched ori SPA. This works because ori sends no `X-Frame-Options`/CSP `frame-ancestors`
header, and because the SPA derives its WebSocket URLs from `window.location` — inside the
iframe that is the ori origin itself, so ori's `localhost:*` WebSocket origin check passes.

On macOS, `build/darwin/Info.plist` sets `NSAppTransportSecurity/NSAllowsLocalNetworking` so
App Transport Security allows the plain-HTTP loopback load.

### Go methods bound to the frontend (`app.go`)

| Method | Purpose |
| --- | --- |
| `GetConfig() → settings.Settings` | Remembered settings (defaults on a first run). |
| `SaveConfig(settings.Settings)` | Normalise the URL and persist. |
| `CheckHealth(url) → health.Report` | `GET <url>/healthz`; never rejects — `ok`, `statusCode`, `detail`. |
| `Connect(url) → string` | Normalise, check health, remember the URL, return the base URL to load. |
| `OpenInBrowser(url)` | `runtime.BrowserOpenURL` fallback. |
| `SettingsPath() → string` | Where the settings file lives (displayed on the screen). |

The frontend calls them as `window.go.main.App.<Method>()` (Promises). The typed wrappers that
`wails dev`/`wails build` generate under `frontend/wailsjs/` are gitignored because nothing
imports them; regenerate them with `wails generate module` if you want the `.d.ts` files.

### Settings file

`<user config dir>/ori-desktop/settings.json`, i.e. `~/.config/ori-desktop/settings.json` on
Linux, `~/Library/Application Support/ori-desktop/settings.json` on macOS,
`%AppData%\ori-desktop\settings.json` on Windows:

```json
{
  "serverUrl": "http://localhost:8888"
}
```

## Layout

```
ori-desktop/
├── main.go              Wails bootstrap (window options, embedded assets, bindings)
├── app.go               Go methods bound to the frontend
├── wails.json           Wails project configuration
├── internal/settings/   settings file (load/save/normalise) + tests
├── internal/health/     GET /healthz probe + tests
├── frontend/src/        index.html, main.css, main.js (embedded ES module, no bundler)
└── build/               Wails build assets (icon, Info.plist, Windows manifest); build/bin is the output
```

## Status / known limitations

- Verified so far: unit tests, `go vet`, and a Windows cross-build (`wails build -platform
  windows/amd64`) from a Linux sandbox without GUI libraries. The window itself has not yet been
  launched (no WebKitGTK in that sandbox) — see the repository's `.memory/` notes.
- ori is loaded over plain HTTP; use it against local or trusted servers only.
- Ori's `--addr` other than `:8888` simply means typing the matching URL on the connection screen.