Red Queen
“You may all be staying here indefinitely.”Self-hosted end to end: a native SwiftUI Matrix client on iOS talking to @hermes — an agent with the Red Queen persona — on my own closed, self-hosted homeserver. Text, voice messages, live calls and push notifications. No public signup, no federation, no third-party chat cloud.
The stack
Six pieces, one job: give one agent a private home with chat, voice and push — reachable only from my own client.
Red Queen (iOS)
Native SwiftUI Matrix client with a ChatGPT-style UX: centered composer, auto-titled conversations, markdown, typing indicators, MSC3245 voice messages with live waveform, and Element Call embedded for two-way audio. Built with XcodeGen on the Matrix Rust SDK.
Hermes — the Red Queen
The agent behind the avatar: Hermes, dual-connected to Discord and Matrix as a normal
user @hermes, speaking Claude Sonnet 4.6
through Nous Portal's API — but the brain is swappable: it's an OpenAI-compatible
endpoint, so any hosted or local model plugs in. Its persona lives in
SOUL.md:
the Umbrella Corp AI — clinical, dry, protective under the surface.
Synapse + Postgres
Dockerized Synapse behind nginx at matrix.roesrath-kleineichen.de. Closed by design: registration disabled and an empty federation whitelist — a Matrix server for exactly two users. Serves the simplified sliding sync (MSC4186) the app requires.
LiveKit + Element Call
A LiveKit SFU relays call media; lk-jwt-service bridges Matrix identity to LiveKit room tokens, advertised via .well-known RTC foci. The app embeds Element Call in a WKWebView — Hermes joins the MatrixRTC session from its side so calls work both ways.
Sygnal → APNs
Matrix push gateway routed at /_matrix/push/, with two APNs apps: production and a sandbox twin for debug builds. Rooms are unencrypted for now, so full event content arrives in the notification — no service extension needed yet.
nginx + Let's Encrypt
One vhost per subdomain, certbot-managed TLS, matching IPv4 and IPv6 listeners. Also serves the three static files the app depends on: apple-app-site-association for password AutoFill, plus the Matrix client and server well-known documents.
Inside the app
Red Queen is a personal, AI-first Matrix client for iOS — a native SwiftUI app deliberately styled to look and feel like the agent apps (Gemini, ChatGPT) rather than a general messenger. It talks to the self-hosted homeserver above, where Hermes (branded "Red Queen" after Resident Evil) participates as the chat partner.
Matrix Rust SDK
matrix-rust-components-swift, pinned to exact date-tags, instead of writing a Matrix stack — with Element X iOS as the architecture reference, not a fork. Simplified sliding sync (MSC4186) comes natively with the SDK.
One room per conversation
A ChatGPT-style history drawer over Matrix rooms: auto-titled from the first message, swipe-to-delete = leave + forget. New agent rooms are unencrypted by default (agent E2EE unconfirmed) — a choice that later paid off for push notifications.
XcodeGen, iOS 17, pure SwiftUI
A checked-in project.yml as source of
truth — no hand-maintained pbxproj. iOS 17 minimum for
@Observable, NavigationSplitView, and no UIKit imports outside
#if os(iOS) — so a native macOS target stays cheap as Phase 2.
How it flows
Three paths through the same front door.
Build your own
The real point of this project: standing up a personal AI agent, end to end, is easier than it looks — and everything here is a template for your own custom agent, not just mine.
Bring any brain
Nothing here is bound to Claude. Point the agent at any frontier model — Gemini, ChatGPT, Meta AI — or at increasingly powerful open models running on your own hardware (Llama, Qwen, Mistral via Ollama or vLLM): anything with an OpenAI-compatible endpoint plugs in. Rent the brain or run it yourself — everything wrapped around it, you own either way.
Own the look & feel
The client rebrands by swapping a handful of values: homeserver URL and agent name
in AppConfig.swift, colors in Theme.swift, icon and avatar
assets. Ship your own persona instead of the Red Queen — the UX is yours to shape.
Own auth & storage
Accounts, credentials, message history, media — all on your homeserver, in your Postgres, on your disk. Login is plain Matrix auth against a server nobody else can even register on. No third-party identity, no chat cloud.




