DEEIX Chat for macOS, Windows, and Linux. It runs the same web interface as a browser, and it can also start a server bundled inside the app so everything stays on your computer.
Where to find it#
Install the desktop client from the project's GitHub Releases page. It is not served by your DEEIX Chat deployment.
Use the download page to pick the right file for your platform automatically.
- Open
https://github.com/DEEIX-AI/DEEIX-Chat/releases. - Download the package for your platform.
- Install it and launch DEEIX Chat.
- On first launch, choose a server on the setup screen.
| Platform | Package | Requirement |
|---|---|---|
| macOS | .dmg | macOS 10.15 or later |
| Windows | .exe (NSIS) or .msi | WebView2 runtime |
| Linux | .deb or .AppImage | WebKitGTK |
Releases built with signing secrets are signed. Unsigned installers still run, but macOS asks you to allow the app under System Settings → Privacy & Security, and Windows shows a SmartScreen prompt.
Choose a server on first launch#
On first launch the window shows a setup screen with two buttons:
| Button | What it does |
|---|---|
| Use on this computer | Starts the server bundled with the app and signs you in locally. |
| Connect to a server | Connects this tab to a DEEIX Chat deployment you or your team runs. |
To connect to a remote server:
- Click Connect to a server.
- Enter the full address in Server address, for example
https://chat.example.com. - Click Connect. The button shows Checking… while the client probes the server.
- The address is saved only after the server answers. The client requests
/healthzfirst, so a typo cannot survive a restart. - Click Back to return to the two choices.
If the server is already open in another tab, the client switches to that tab instead of creating a duplicate.
If the configured server cannot be started on a later launch — for example when the local sidecar fails — the tab shows Could not connect to the configured server and returns to the setup screen so you can point it somewhere else.
Use local mode#
Use on this computer runs a complete DEEIX Chat from the app itself, with no server to deploy.
- The Go server bundled with the app starts as a sidecar process on a random
127.0.0.1port. Nothing is exposed to your network. - Data lives in SQLite and local files under the app's data directory. Secrets are generated for that installation.
- You are signed in as the only user, a passwordless owner. The shell reads a one-time grant printed once to the sidecar's standard output; the grant is single-use, expires after two minutes, and is consumed before the web page sees it.
- The refresh token is stored in the OS keychain under
refresh-token:local. - There is no login page, so Sign out means leaving the server: the tab drops its credential and returns to the setup screen.
- The sidecar stops when the last local tab closes.
Local mode uses the same server code and security policy as a deployment. It is meant for personal use and evaluation. For a team or a long-running instance, connect to a PostgreSQL + Redis deployment instead.
Work with several servers in tabs#
Each tab is bound to exactly one server and runs its own copy of the web app. Sessions, caches, and streaming connections are not shared between tabs, so you can keep a local instance and one or more remote deployments open at the same time.
| Action | What happens |
|---|---|
| New tab | Opens the setup screen in a new tab. |
| Open a server that is already in a tab | Activates the existing tab. Binding it twice shows That server is already open in another tab. |
| Close a tab | Forgets that server. Its refresh token is deleted, and the sidecar stops when the last local tab closes. |
| Drag a tab | Reorders the strip. The order is saved and restored on the next launch. |
| Leave a tab in the background | After 30 minutes the tab's webview is released to save memory. It reloads and signs back in from the keychain when you activate it again. |
| Middle-click a tab | Closes it. |
Bound tabs are restored on the next launch. A tab's label is This computer for local mode, the server host for a remote server, and New tab while unbound.
Interface preferences such as theme and font size are stored once and shared across tabs, because they belong to you, not to a server.
Sign in and credentials#
Remote servers accept the same sign-in methods as the browser: password, two-factor authentication, and OAuth/OIDC providers.
The desktop client keeps the long-lived refresh token in the OS keychain instead of an HttpOnly cookie. The web page never gets a way to read it back.
| Item | Browser | Desktop |
|---|---|---|
| Access token | Page memory | Page memory |
| Refresh token at rest | HttpOnly cookie | OS keychain |
| Keychain entry | — | Service com.deeix.chat.desktop, account refresh-token:<origin> |
| Who sends the refresh token | Browser, to the cookie's origin | The shell, to the bound origin only |
| Readable by page script | No | No; the shell has no read command |
| Server address | Page origin | Bound per tab and persisted by the shell |
The page hands the refresh token to the shell once, at sign-in. After that it can only ask the shell to refresh the session, sign in locally, or clear it. Closing a tab drops that session, and switching servers deletes the previous keychain entry.
Sign in with a third-party provider#
The webview cannot receive a provider redirect, so the desktop client uses the RFC 8252 loopback flow:
- The shell binds an ephemeral port on
127.0.0.1and gives the web apphttp://127.0.0.1:<port>/oauth/callbackas the redirect URI. - The web app starts the provider bridge with the client ID
com.deeix.chat.desktop. - The provider's authorization page opens in your system browser, so any existing provider session is reused.
- The provider redirects to the server callback. The server issues a one-time DEEIX grant and redirects the browser to the loopback URI.
- The shell answers with a "you can close this tab" page and passes the callback to the web app, which exchanges the grant with its PKCE verifier.
The listener waits up to 10 minutes for the redirect.
The server must have PUBLIC_API_BASE_URL set and the instance callback registered with each provider. The desktop client needs no custom URL scheme and no provider allowlist entry. See Configuration for the callback format.
Tray#
The app keeps running in the system tray so notifications and the updater can reach you while the window is closed.
- Left-click the tray icon to show and focus the window.
- The tray menu has Show DEEIX Chat and Quit. Quit exits the app, including the local sidecar.
Updates and release channels#
The app checks for updates on launch and every four hours. Nothing is downloaded until you accept.
- When a newer version exists, a toast reads Version {version} is available with an Update button.
- Click Update. The toast changes to Downloading update….
- When the download finishes, the toast reads Version {version} is installed with a Relaunch button.
- Click Relaunch to restart into the new version.
If the download or install fails, the toast reads Update failed: {message}. Every update is verified against the public key in tauri.conf.json before it is installed.
| Release tag | Channel | Update source |
|---|---|---|
vX.Y.Z | Stable | releases/latest/download/latest.json |
vX.Y.Z-beta.N | Beta | releases/download/desktop-beta/latest.json |
A stable install never receives a prerelease. A beta install keeps receiving betas; install a stable build to move back to the stable channel. Both channels use the same signing key.
Build from source#
The desktop shell lives in apps/desktop and loads the same static build the server serves (apps/web/out), so there is no desktop-specific build of the product UI.
Prerequisites: a Rust toolchain, the Tauri 2 platform dependencies (WebKitGTK on Linux, WebView2 on Windows, Xcode command line tools on macOS), and pnpm install from the repository root.
terminal
make dev starts the API and the web app together but not the desktop shell; use make desktop for the shell. Artifacts land in apps/desktop/src-tauri/target/release/bundle/.
Building is not enough to ship. macOS packages must be notarized and Windows packages code-signed. Signing keys live only in CI secrets.
Common problems#
| What you see | What to check |
|---|---|
| The local server could not start | The bundled server failed to launch. Quit and reopen the app, or check that the app's data directory is writable. |
| Enter a full address including https:// or http:// | The value in Server address is not an absolute http:// or https:// URL. |
| Could not reach the server | The address is valid but nothing answered. Check that the server is running and reachable from this network. |
| The server answered with status {status} | The address points at something that is not a healthy DEEIX Chat server. Check /healthz in a browser. |
| That server is already open in another tab | The server is already bound to a tab. Switch to that tab instead of adding it again. |
| A remote tab cannot connect after a working setup | Confirm the address still includes https:// and that the server's /healthz responds. |
| The window is closed but the app still runs | That is the tray. Use Quit in the tray menu to exit fully. |