Files
iris_x_hermes/README.md
T
ARIA f90e40a3fc
CI / Gateway plugin tests (push) Failing after 1m4s
CI / Kotlin tests (android host + desktop) (push) Successful in 8m3s
Fix README limit claims to match reality (issue #13)
- 'No file limit' -> 100 MB default, configurable via max_upload_bytes
- 'No character limit' -> 'No 4,096-character limit like Telegram'
  (hard frame-body cap: 1 MiB)
- Note that limits are set on the gateway side (hermes), not in the app
- Sync docs/playstore-listing.md (same overclaim)
2026-08-24 21:05:13 +02:00

159 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Iris × Hermes
A chat app for [hermes-agent](https://github.com/NousResearch/hermes-agent): a **native Android app** and a **desktop app** (Linux, macOS, Windows) — both built from one shared Kotlin codebase (Compose Multiplatform).
Iris pairs with your running `hermes gateway` over a private WebSocket and gives you a Telegram-quality chat experience with your personal agent: streaming replies, visible reasoning, structured tool activity, channels, threads, media, search, and push notifications.
## Features
- **Native Hermes-Gateway integration** — your hermes → gateway → Iris app
- **Absolute Privacy!** — everything stays on your own infrastructure
(push: ntfy by default; FCM is opt-in and routes push metadata via Google —
see [Push notifications](#push-notifications))
- **100 MB file uploads by default** — configurable on the gateway via
`max_upload_bytes` (see [Media](docs/07-media.md) §7.7); all limits are set
on the gateway side (hermes), not in the app
- **No 4,096-character message limit like Telegram** — messages travel over
your own gateway (hard frame-body cap: 1 MiB)
- **Full markdown support** — tables, checkmarks, bold, inline code, code blocks + syntax highlighting…
- **HTML Artifact Preview** — agent-sent HTML/CSS/JS rendered in an in-app WebView
- **All settings live in the app**, not in hermes `config.yml`! Change everything on the fly.
- **Channels** — create channels to keep track of your reports, cronjobs, webhook calls
- **Pin channels, rename them, change the color/icon**
- **Customize how your chat should look like** — color? Check! Images? Check!
- **Reasoning collapse/expandable** in the chat bubble
- **Change the default behavior** of tool & reasoning verbosity
- **Threads** — create your own, or let the AI create them with a title
- **Search messages from everywhere**
## How it works
```
hermes-agent ──> hermes gateway ──(WebSocket :8790)──> Iris app (Android / Desktop)
```
- `gateway-plugin/` is a hermes **platform plugin** (`android`). It runs inside the
`hermes gateway` process and opens a WebSocket server the apps connect to.
Zero new Python dependencies, zero hermes-core changes.
- `app/` is one Compose Multiplatform Gradle project: `:shared` (KMP, most of the
code), `:androidApp` (native Kotlin + Jetpack Compose client), `:desktopApp`
(the same app, tweaked for a big screen).
- The app is a first-class hermes *messaging platform*, so everything the gateway
already does just works: slash commands, cron delivery, `send_message` routing,
coexistence with Telegram/Discord/etc.
- Push notifications: ntfy (default) or FCM (opt-in).
## Push notifications
Push wakes a backgrounded/offline device; on reconnect the app syncs the
outbox, so nothing is lost.
- **ntfy (default)** — push metadata stays on your own infrastructure
(self-hosted ntfy recommended). This is the backend for truly private
communication.
- **FCM (opt-in, `IRIS_PUSH_BACKEND=fcm`)** — standard/reliable, but FCM push
metadata (notification title, device token) is routed through **Google's
servers**. If you want truly private communication, use ntfy instead.
Setup: [`docs/setup.md`](docs/setup.md) §4; details:
[`docs/08-push.md`](docs/08-push.md).
## Build from source
### Prerequisites
| Where | You need |
| --- | --- |
| Gateway host | [hermes-agent](https://github.com/NousResearch/hermes-agent) with its venv (`uv sync`) |
| Android build machine | JDK 17, Android SDK (`sdk.dir` in `app/local.properties` or `ANDROID_HOME`), ADB with a connected device |
| Desktop build machine | JDK 17 only |
No system Gradle needed — both apps use the project wrapper (`./gradlew`).
### 1. Gateway (on the gateway host)
```bash
# hermes-agent is a separate project (not part of this repo)
cd hermes-agent && uv sync
# install the Iris plugin into the live hermes home
mkdir -p ~/.hermes/plugins
ln -s "$PWD/gateway-plugin" ~/.hermes/plugins/android
hermes gateway status # should list "android"
hermes gateway setup # generates ANDROID_TOKEN, prints the server URL
hermes gateway # run the gateway
```
### 2. Android app
```bash
cd app
./gradlew :androidApp:installDebug # build + install on the connected ADB device
# or just build the APK:
./gradlew :androidApp:assembleDebug # → app/androidApp/build/outputs/apk/debug/
```
### 3. Desktop app
```bash
cd app
./gradlew :desktopApp:run # dev run
./gradlew :desktopApp:jpackage # native app-image (bundles the JRE)
```
### 4. Pair
On the app's **Connect** screen:
1. **Server URL** — `ws://<gateway-ip>:8790/ws` (printed by `hermes gateway setup`).
2. **Pairing token** — from the setup output, or `ANDROID_TOKEN` in `~/.hermes/.env`
on the gateway host.
3. **Test & Connect.**
Notes:
- The app has **no QR scanner** — pairing is manual URL + token entry.
- The default bind is `127.0.0.1` (desktop on the same machine only). For a phone
on the LAN, set `ANDROID_WS_HOST` to the gateway's LAN IP.
- Remote access: Tailscale/WireGuard, or a reverse proxy with CA-signed WSS
(`ANDROID_WS_CERT` / `ANDROID_WS_KEY`).
Full walkthrough, push setup (ntfy/FCM), and troubleshooting:
[`docs/setup.md`](docs/setup.md).
## Contributing
Contributions are welcome! Before you start:
1. **Read the docs.** The full reference library is in [`docs/`](docs/README.md) —
start with [`docs/00-overview.md`](docs/00-overview.md), then follow the
numbered docs (architecture, wire protocol, plugin design, testing, …).
2. **Know the layout.**
| Path | What |
| --- | --- |
| `gateway-plugin/` | Python hermes platform plugin (`android`); `protocol.py` is the frame source of truth |
| `app/shared` | KMP module with most of the client code (shared by Android + Desktop) |
| `app/androidApp` | Thin Android shell (package `dev.iris.app`) |
| `app/desktopApp` | Thin desktop shell |
| `docs/` | Numbered reference library |
3. **Run the tests.**
- Python (gateway plugin): `cd hermes-agent && scripts/run_tests.sh tests/gateway/test_android.py`
(never bare `pytest` — hermes's runner sandboxes `HERMES_HOME`).
- Kotlin: `cd app && ./gradlew :shared:testDebugUnitTest`
- Live check (gateway must be running): `gateway-plugin/tests/ws_probe.py` and
`gateway-plugin/tests/e2e.py` — see [`gateway-plugin/tests/README.md`](gateway-plugin/tests/README.md).
4. **Keep the protocol in sync.** `gateway-plugin/protocol.py`,
`app/shared/.../protocol/Protocol.kt`, and `docs/protocol/frames.schema.json`
must always agree.
5. **Pre-commit hooks** are configured (`.pre-commit-config.yaml`); run
`pre-commit install` once after cloning.
Open an issue first for anything big, then send a pull request.
## License
Apache License 2.0 — see [LICENSE](LICENSE).