Appearance
The desktop app
The web app in a native window for Windows, macOS and Linux, built with Tauri 2 around the same SPA the server ships. It adds what a browser tab cannot: a sign-in that survives restarts without a cookie jar and matterwave:// links. The shell lives at clients/desktop; building it is in its README (clients/desktop/README.md).
The SPA is bundled into the app, not loaded from the server, and talks to the deployment named at build time (MW_DESKTOP_BASE_URL) over HTTPS.
Sign in
The app's own sign-in page offers one button, "Sign in with your browser". It opens your system browser, never a login page inside the app, so your password manager and passkeys work. The app runs the OAuth authorization-code flow with PKCE against MatterWave's native client (matterwave-desktop, provisioned in Zitadel by the gateway play beside the web client, and advertised by the API as native_client_id on /api/auth-config) and receives the result on matterwave://auth/callback, or on a loopback address (http://127.0.0.1:<port>/callback) where the deep link is not registered. A deployment that has not provisioned the native client (MW_OIDC_NATIVE_CLIENT_ID empty) says so when sign-in is attempted; it does not fall back to the web client.
The access and refresh tokens go in the OS keychain: Keychain on macOS, Credential Manager on Windows, Secret Service on Linux. Nothing is written to a file. The web page inside the window never holds the refresh token; it asks the native side for the current access token and sends it as Authorization: Bearer. The app refreshes ahead of expiry and retries once on a 401.
Sign-out, from the user menu or Settings, revokes the tokens at the identity provider (best effort), clears the keychain either way and returns the app to its sign-in page; it never sends the window to the identity provider's own sign-out page, which is the browser's path. A refresh the provider refuses, for example after the session was revoked, also clears the keychain and signs the app out. The desktop app signs in only this way; API keys are for the terminal and editor clients.
Offline
There is no send queue. A message is never sent later on your behalf: a prompt sent minutes after you wrote it lands in a thread that has moved on and is billed while you are not watching. Offline, Send is disabled and the draft is kept; a turn that was streaming when the connection dropped resumes once you are back online.
Reporting a problem
Quote the app version (the app_info command; it is the API's MW_RELEASE when that is semver) and the request id shown with the error. Never paste the keychain entries (dev.matterwave.desktop, access / refresh): they are credentials.
Updates
Off unless the build turned them on. A build made without MW_DESKTOP_UPDATER=1 has no updater at all: it names no update server and never asks one. A build made with it checks once at launch and tells the page when a newer version exists; it downloads and installs nothing on its own. The release job is what sets the flag, together with the per-channel endpoint and the signing key (one channel per environment, so a dev build never updates to production).
Not built yet
- Updates, the rest. The six-hourly re-check, the install step and the rollback test.
- Installers and signing. Signed MSI for Windows, notarised universal DMG for macOS, and AppImage /
.debfor Linux are designed; CI does not produce them yet, and macOS builds need a macOS runner.clients.ymlrunscargo checkandcargo testonly. - Native touches. Notifications when an answer finishes (the plugin is loaded, nothing calls it), a tray menu,
Ctrl/Cmd+N/Ctrl/Cmd+K, and opening a conversation frommatterwave://conversation/<id>(the native side forwards the link; the SPA does not route it yet). - An offline cache. Without a network the app has no conversations to show.
- Device sessions. A desktop sign-in is meant to appear in Settings → Sessions and be revocable there.