Your always-on AI agent, in your pocket.
A native-feeling iOS client for the Nous Research Hermes Agent —
streaming chat, tool-call traces, session history, scheduled jobs, and usage analytics,
all over a private Tailscale connection to the gateway on your Mac.
The Hermes Agent runs on your Mac — reading your notes, running skills, executing scheduled jobs. But when you step away from the desk, it keeps working and you stop seeing it. Hermes iOS closes that gap: a polished, first-class phone client that talks directly to your own gateway over your tailnet. No cloud middleman, no third-party relay, no accounts. Your agent, your Mac, your phone.
Every endpoint is verified live against a real gateway (v0.17.0), and every screenshot in this README is a real capture from the iOS Simulator against a live instance.
| 💬 Streaming chat | Real-time SSE streaming with rendered Markdown, collapsible reasoning blocks, and tool-call trace cards showing status, arguments, and duration. Start fresh or continue any existing session. |
| 🗂 Sessions | Every conversation across every source — TUI, Slack, webhook, API. Search, source filters, token/cost metadata, swipe-to-delete, rename, fork, and full transcripts. |
| ☀️ Today | One-tap agent briefings ("today's tasks", "what needs me?", "recap", "standup") rendered inline, plus your scheduled jobs with run / pause / resume controls. |
| ⚡ Skills | Browse the agent's installed skills by category and inspect its resolved toolsets. |
| 📊 Insights | Gateway health, connected platforms, and usage analytics — cost & tokens over 14 days, by model, by source, cache-hit ratio — computed client-side from session metadata. |
| 🔐 Private by design | The bearer token lives in the iOS Keychain (SecureStore). Traffic never leaves your tailnet. The gateway stays bound to loopback, exactly as shipped. |
The look comes straight from the Hermes Agent brand: electric ultramarine, a high-contrast Didone serif (Playfair Display) for display, monospace (Courier Prime) for labels and data, sharp 0–6px edges, square status indicators, and a radiating-engraving motif at hero moments. Three themes ship: Hermes (electric blue, default), Ink (near-black), and Nous (light).
| Hermes (default) | Ink | Nous |
|---|---|---|
![]() |
![]() |
![]() |
See PRODUCT.md and DESIGN.md for the full design system.
You'll need: a Mac running the Hermes Agent gateway, Tailscale on both the Mac and your iPhone (free for personal use), and Node 20+.
On the Mac running Hermes:
git clone https://github.com/glisom/hermes-ios.git && cd hermes-ios
./scripts/setup-tailscale-serve.shThis runs tailscale serve --bg --https=8443 → 127.0.0.1:8642: TLS with a valid Let's Encrypt
certificate, reachable only from your tailnet — never the public internet — and it leaves the
gateway itself untouched. The script prints your exact gateway URL when it finishes.
npm install
npx expo start # press i for the iOS Simulator, or scan the QR with Expo GoIn the app, open Settings and enter:
- Gateway URL →
https://<your-mac>.<your-tailnet>.ts.net:8443(printed by the script in step 1) - Token → the value of
API_SERVER_KEYfrom~/.hermes/.envon the Mac
Tap Test connection, then start chatting.
Local: npx expo run:ios (requires Xcode). Cloud: eas build -p ios — see eas.json.
To install on your own device via TestFlight, point app.json's bundleIdentifier, owner, and
EAS projectId at your own accounts.
iPhone (Expo app)
│ HTTPS + Bearer token token stored in the iOS Keychain via SecureStore
▼
https://<your-mac>.<tailnet>.ts.net:8443 Tailscale Serve — valid TLS, tailnet-only
│ proxy → 127.0.0.1:8642
▼
Hermes gateway API server (aiohttp) ── ~/.hermes/state.db
- Transport: REST + Server-Sent Events. The native event stream
(
/api/sessions/{id}/chat/stream) drives the chat UI withassistant.delta,tool.*, and reasoning events. Streaming usesexpo/fetch— a realReadableStreamin React Native. - Auth: a single bearer key (
API_SERVER_KEY), stored only in SecureStore — never in git, never bundled into the app. - Connectivity: the gateway binds loopback by design; Tailscale Serve fronts it with a valid certificate on a tailnet-only HTTPS port. No App Transport Security exceptions needed.
Expo SDK 57 · React Native 0.86 · React 19 · expo-router (typed routes) · TypeScript ·
@tanstack/react-query · zustand · expo-secure-store · react-native-svg · marked ·
Playfair Display + Courier Prime (@expo-google-fonts)
src/
api/ HermesClient (REST), SSE stream reader, types, React Query hooks
store/ connection (URL + token), settings (theme), chat (live conversation + SSE reducer)
theme/ light/dark tokens, accent, source colors
components/ ui primitives, chat (markdown / reasoning / tool cards), per-feature components
app/ expo-router routes — (tabs)/ + session/[id] + settings
docs/specs/ design spec
scripts/ Tailscale Serve setup
npm run typecheck # tsc --noEmit
npm run lint # eslint (expo config)
npm run web # run in a browser (the gateway's SSE endpoint needs CORS for web;
# native iOS has no such restriction)Optional env overrides live in .env.example. CI runs typecheck + lint on every push.
MIT — do whatever you like, attribution appreciated.








