# 00 — Overview ## Vision A **native, Telegram-quality chat experience** for a personal hermes-agent: install an app on your phone (and a desktop app on your PC), pair it to your running `hermes gateway`, and talk to your agent with streaming replies, visible reasoning, structured tool activity, channels/threads, media, search, and push notifications — with cron jobs able to post into any channel you create. ## Goals - **Native feel.** Real native app (Iris on Android, Kotlin/Compose), not a WebView. Desktop app that is the same app, resized for a big screen. - **First-class gateway citizen.** The app is a hermes *messaging platform*, so everything the gateway already does "just works": slash commands, cron delivery, `send_message` routing, coexistence with Telegram/Discord/etc. - **Full agent transparency.** Streaming text, reasoning shown *before* the answer, structured tool events (the app chooses how much to show), and intermediate assistant beats. - **Organized by default.** A default chat with optional threads, plus user-created channels that cron jobs can target. - **Reachable anywhere.** Live over a WebSocket; background push via FCM (primary) or ntfy (fallback). ## In scope (v1) Everything in the feature checklist below. ## Out of scope / stretch (v1) - **Standalone-cron delivery while the gateway process is fully down** — best-effort FCM/ntfy only (the outbox is served by the running gateway). - **Multi-user / group chat** — this is a *personal* 1-user agent. - **End-to-end encryption** — transport security (WSS) only. - **iOS** — Android + Desktop only (the protocol is transport-agnostic, so an iOS client is a future port, not a v1 goal). ## Feature checklist → where it's handled | Requirement | Gateway plugin | App | | --- | --- | --- | | Input box, auto-grow (max height) | — | Compose `TextField` + bounded `heightIn` | | Menu button → all slash commands | Dispatches `/…`; serves command catalog | Bottom-sheet menu + `/` autocomplete | | Tool output (app decides how much) | Emits **structured** tool events | App setting: everything / truncated / nothing | | Reasoning shown before message | Captures + splits reasoning | Collapsible "Reasoning" block above message | | Intermediate messages | Forwards `Commentary` events | Distinct dimmed bubble | | Threading + channels; default chat; user channels for cron | `chat_id`/`thread_id` model; cron `deliver=iris:[:]` | Channel list, thread toggle, "new channel" | | Search ("everywhere" / "this chat/channel") | FTS5 session search bridge | Search UI + scope toggle | | Attach media (music/video/images/docs) | Inbound cache; outbound `send_*` | Pickers + chunked upload + preview | | Push notifications | FCM (primary) / ntfy (fallback) | FCM token / ntfy topic + notification service | | Live playback of AI-sent music/video | Serves media bytes over WS | ExoPlayer inline player | ## Locked decisions (from planning) | Decision | Choice | | --- | --- | | Desktop app tech | **Compose Multiplatform** (shares Android code; "tweaked" for big screen) | | Push backend | **Both** — ntfy default, FCM optional (`IRIS_PUSH_BACKEND`) | | Media transport | **Over the WebSocket** (chunked binary frames; no extra Python deps) | | Phone default layout | **User-toggleable, single-pane default** (auto two-pane on large screens) | ## Disclaimers (hard rules) 1. **`hermes-agent/` is a read-only research reference.** It lives next to this folder for study only. It is **git-ignored** and must **never** be committed, pushed, or included in any artifact. Our plugin is *installed* into a live hermes home (`~/.hermes/plugins/iris`); we never edit hermes core files. 2. **ADB is available and a device is connected** (`a5ca2a4b`, Xiaomi MIX 2S, Android 10 / API 29). Use `adb install` / `adb logcat` / `adb shell am start` to install, launch, and debug the app on-device throughout the build. ## Verified environment state (2026-08-19) | Item | State | | --- | --- | | OS | CachyOS (Arch-based), `pacman` present | | JDK | **Not installed** → Milestone M0 (`pacman -S jdk17-openjdk`) | | Android SDK | **Not installed** → M0 (cmdline-tools + sdkmanager) | | Gradle | Via project wrapper (`gradlew`), no system install | | ADB | Installed; device `a5ca2a4b` (MIX 2S, API 29) connected | | Python | 3.14.7; `uv` 0.12.3 present | | hermes venv | **Not created** → M0 (`cd hermes-agent && uv sync`) | | hermes core deps | `websockets==15.0.1` and `httpx` are **core** deps → plugin needs **zero new Python deps** | | Disk / RAM | 522 GB free / 62 GB RAM — ample | ## Naming - Product/effort name: **Iris × Hermes** (folder `iris_x_hermes`). - hermes platform name: **`iris`** (the plugin registers `Platform("iris")`). - WS default port: **8790** (configurable). - Default chat id: **`default`** (the home channel).