Client Apps
Sonny has four clients beyond the terminal. They are not four runtimes. The desktop app, the VS Code extension, and the remote controller are three surfaces onto one shared local service and one shared React session UI, and they reconnect to sessions the terminal is already running.
| Client | What it is | Where it lives |
|---|---|---|
| Desktop | Wails v2 native shell around the shared React UI | ui/apps/desktop |
| VS Code | Extension plus webview reusing that same UI and client | ui/apps/vscode |
| Remote controller | Thin mobile/web surface for supervising sessions | ui/apps/controller |
| Neovim | Inline AI completion plugin with its own daemon | sonny-neovim |
One service, several windows
The client apps do not run sessions themselves. They connect to one
user-scoped local service, sonny supervisor serve, which the desktop starts on
first launch and which the other clients attach to.
That single ownership model produces behaviour worth knowing before you use the GUIs:
- Closing a window does not stop your work. Closing the desktop window, or choosing Quit Sonny (sessions keep running) from the tray, stops only that window’s connection. The service keeps running, so sessions and scheduled work carry on and the next launch reconnects in seconds.
- Relaunching does not restart the service. When you need a fresh service —
after changing a setting or credential the service reads at startup, or after
an upgrade — stop it explicitly with Quit Sonny and stop daemon… in the
tray menu, or run
sonny supervisor stop. Reopen the client and it starts a new one. - The executable is never found on
PATH. The host resolves and authenticates the shared supervisor before it starts the window-scopededitor-rpcchild. Executable selection is updater activation, then a protected sibling binary — never ambientPATH. A developmentSONNY_BINoverride must be paired withSONNY_BIN_SHA256. - Parallel native clients serialize startup, and window shutdown stops only the proxy and deliberately leaves the user-scoped supervisor alive.
The desktop and VS Code clients each start their own sonny editor-rpc child
and bridge its NDJSON frames to the UI. sonny supervisor ensure is the command
that starts or attaches to the local shared service and returns its exact
endpoint, executable, and tenant.
Remote controller
ui/apps/controller is a thin mobile and web surface for supervising sessions.
It deliberately reuses SonnyClient, ClientSessionsSource,
ClientTranscriptSource, and ClientAttentionSource; it does not define a
second session or approval protocol.
The built page connects to the same-origin path named by the
sonny-controller-endpoint meta element. A deployment must:
- terminate HTTPS;
- authenticate the browser with a Secure, HttpOnly, SameSite cookie;
- bridge the WebSocket’s
sonny.client-protocol.v1text frames to an authorized Sonny client-protocol endpoint.
The browser rejects cross-origin endpoints, URL credentials, query strings, fragments, and non-TLS remote origins. Loopback HTTP stays available for local development.
The controller never asks for provider credentials, never exposes a file or
terminal API, never renders workspace paths, and persists neither session data
nor attention state. Authorization and capability negotiation remain daemon
decisions made during the normal sonny/initialize handshake.
Headless verification without a display
The shipping desktop binary has a supported automation mode that does not initialize Wails or need a display server. On a server, fresh VM, or CI runner:
sonny-desktop --bootstrap-check
The command reads the same desktop.yaml, trusted companion binary, and local
daemon-bootstrap profile as a graphical launch, ensures the supervisor, performs
an authenticated readiness read-back, and exits without initializing Wails. A
successful check exits 0 and writes one sonny.desktop.bootstrap-check.v1
JSON document to stdout; progress and diagnostics go to stderr. The JSON
includes the shared bootstrap state, effective configuration digest, source
tiers, and client/daemon versions. It is bounded to two minutes and exits 1 on
failure.
Managed workstations
Preseed a partial Desktop policy using the same desktop.yaml schema at:
| Platform | Path |
|---|---|
| Linux | /etc/sonny/desktop.yaml |
| macOS | /Library/Application Support/sonny/desktop.yaml |
| Windows | %ProgramData%\sonny\desktop.yaml |
Values present there override both the user’s file and SONNY_DESKTOP_* launch
variables, and appear read-only in the graphical settings. The file must be a
regular, non-symlink system policy that is not group- or other-writable; a
present-but-unsafe, malformed, or invalid policy makes both graphical
startup and --bootstrap-check fail closed. The bootstrap JSON names the
selected file in desktop_settings.managed_policy_path and reports each locked
field with managed_by: "system".
Source of truth
ui/apps/desktop/README.md,ui/apps/desktop/main.godocs/config/supervisor-daemon-lifecycle.mdui/apps/vscode/README.md,ui/apps/vscode/package.jsonui/apps/controller/README.mdsonny-neovim/README.md