Close
01Desktop AI workspaceActive · 2026

Relay

A local-first desktop workspace for chatting with and comparing OpenAI-compatible models.

Relay chat workspace showing a conversation with a configured model

Relay is a local-first desktop workspace for chatting with and comparing OpenAI-compatible language models. It uses a React/Vite renderer inside Tauri, a Rust backend that owns provider traffic, SQLite for durable history and metrics, and the operating system credential vault for API keys.

Problem

Browser-based chat clients scatter conversation data, credentials, provider traffic, and usage metrics across separate services. Relay needed to bring them together without routing secrets through the web interface.

Solution

Relay keeps the interface thin and moves model communication, storage, and secret handling into a native Rust backend. The WebView renders state and never receives an API key or makes a provider request directly.

Key Features

Real SSE streaming from the Rust backend, with stop-generation support.

Concurrent side-by-side model comparison where one column cannot abort another.

Local conversations, messages, generation attempts, and usage telemetry in SQLite.

Configurable per-million-token pricing with estimated cost reporting.

API keys stored in the OS credential vault rather than SQLite or browser storage.

Import and export through native file dialogs, with backups that exclude credentials.

HTTPS-only provider endpoints with redirect denial and private-address blocking.

Technical Decisions

SQLite was chosen for a single-user desktop app: it removes an external service, gives atomic local transactions, works offline, and is easy to back up.

Generation attempts are stored separately from assistant messages so that interruption and retry do not corrupt the logical transcript.

Writes before and after a stream use short transactions, so no database lock is held across provider network time.

Credentials live in the platform vault because encrypting a key beside its own encryption key offers little protection.

Provider networking is confined to Rust; typed wrappers in the renderer are the only backend contract.

Challenges

DNS rebinding protection is best-effort because hostname resolution and connection are separate operations with the current HTTP client. A hardened release would pin the validated address for the request.

What I Learned

Content to be added.

Architecture

React / Vite rendererPresentation only — no keys, no direct provider access
Typed IPC boundaryinvoke commands and generation:<request-id> events
Tauri / Rust backendcommands · network · database · credentials
OpenAI-compatible APIsHTTPS only, redirects disabled
How a message moves through Relay.Persistence: SQLite holds conversations, messages, generations, and usage. API keys stay in the OS credential vault.