An astonishingly awful Hermes iOS client
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-08-14 11:53:42 +01:00
.pi add pretty names for tool calls 2026-08-09 18:18:47 +01:00
Assets.xcassets add initial cron job reading functionality 2026-08-08 16:14:24 +01:00
docs initial commit 2026-08-07 22:54:01 +01:00
Talaria clarify tool support 2026-08-14 11:53:42 +01:00
Talaria.xcodeproj clarify tool support 2026-08-14 11:53:42 +01:00
TalariaTests clarify tool support 2026-08-14 11:53:42 +01:00
.gitignore clone hermes-agent to a local directory for reference 2026-08-09 17:14:58 +01:00
AGENTS.md add pretty names for tool calls 2026-08-09 18:18:47 +01:00
README.md clarify tool support 2026-08-14 11:53:42 +01:00

Talaria

Talaria is a SwiftUI iOS client scaffold for Hermes Agent. It connects directly to a running, authenticated Hermes Dashboard.

Included

  • Dashboard URL onboarding and GET /api/status capability discovery
  • Provider discovery through GET /api/auth/providers
  • Hermes username/password-provider login through POST /auth/password-login
  • Nous OAuth and self-hosted OIDC login through the dashboard's existing cookie flow
  • Authenticated REST client and single-use WebSocket tickets
  • Native chat over /api/ws using Hermes' JSON-RPC protocol
    • Per-chat model selection before a new session is created and while an existing chat is open
    • session.create
    • session.resume
    • prompt.submit
    • streaming message.delta / message.complete events
    • session.interrupt
    • native inline clarification prompts via clarify.request / clarify.respond
  • Foreground reconnect and session reattachment after app backgrounding
  • Native Markdown rendering for assistant responses with Textual
  • Recent session list and persisted transcript loading
  • Dashboard-wide default model selection in Settings
  • Saved single-dashboard connection and sign-out
  • Basic unit tests for URL normalization and protocol decoding

This is an MVP scaffold. Approval prompts, attachments, profiles, additional session mutations, and native bearer-token OAuth are follow-up work.

Requirements

  • Xcode 26 or newer
  • iOS 26+
  • A current Hermes Agent dashboard reachable from the device
  • A non-loopback dashboard bind with one of Hermes' dashboard auth providers configured

Talaria intentionally targets iOS 26 rather than maintaining compatibility with older iOS releases. This lets the app use current SwiftUI APIs and dependencies without fallback implementations or availability branches.

Hermes' username/password provider is intended only for a trusted LAN or VPN. Use Nous OAuth or self-hosted OIDC for an internet-facing dashboard.

Run

  1. Open Talaria.xcodeproj.
  2. Change the app and test bundle identifiers from com.example.* and select your development team.
  3. Choose an iPhone simulator or device and run the Talaria scheme.
  4. Enter the dashboard's externally reachable base URL, including a reverse-proxy path prefix when applicable, for example:
    • https://hermes.example.com
    • https://example.com/hermes
    • http://192.168.1.20:9119 for trusted-network development

Command-line build:

xcodebuild \
  -project Talaria.xcodeproj \
  -scheme Talaria \
  -sdk iphonesimulator \
  -destination 'generic/platform=iOS Simulator' \
  CODE_SIGNING_ALLOWED=NO build

Authentication note

The current OAuth/OIDC implementation uses a private WKWebView sign-in sheet, then transfers the dashboard's HttpOnly session cookies into the app's URLSession cookie store. This interoperates with the current Hermes cookie contract but is a compatibility implementation, not the desired final native-app OAuth design.

Hermes now advertises native_pkce, but its native callback currently accepts only a desktop-style HTTP loopback redirect. iOS cannot reliably keep a loopback listener alive while the user authenticates. The proposed production design is a small Hermes contract extension for an allowlisted app callback, followed by ASWebAuthenticationSession, PKCE, bearer tokens in Keychain, and /auth/native/refresh. See docs/AUTHENTICATION.md.

Security defaults

  • Passwords are submitted once and are never persisted.
  • WebSockets use Hermes' 30-second, single-use ticket from POST /api/auth/ws-ticket.
  • The app does not disable TLS validation.
  • Info.plist permits local networking but does not globally opt out of App Transport Security.
  • The current scaffold supports one dashboard connection, avoiding cross-host cookie ambiguity.