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.

ClientWhat it isWhere it lives
DesktopWails v2 native shell around the shared React UIui/apps/desktop
VS CodeExtension plus webview reusing that same UI and clientui/apps/vscode
Remote controllerThin mobile/web surface for supervising sessionsui/apps/controller
NeovimInline AI completion plugin with its own daemonsonny-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-scoped editor-rpc child. Executable selection is updater activation, then a protected sibling binary — never ambient PATH. A development SONNY_BIN override must be paired with SONNY_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.v1 text 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:

PlatformPath
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.go
  • docs/config/supervisor-daemon-lifecycle.md
  • ui/apps/vscode/README.md, ui/apps/vscode/package.json
  • ui/apps/controller/README.md
  • sonny-neovim/README.md

pages