-
released this
2026-08-31 21:44:41 +00:00 | 2 commits to master since this releaseIris Release Notes — v0.1.3
Covers the last 5 commits (
b065d17→8657e6a).Bug Fixes
HTTP fallback transport
- Port-conflict pre-check now actually fires (
8657e6a)
acquire_scoped_lockreturns(acquired, existing_record), but the old
if not acquire_scoped_lock(...)tested the tuple — which is always
truthy — so the "port in use by another profile" pre-check never ran and a
conflict surfaced as a generic bind failure. The code now unpacks and tests
the first element, matching the canonical usage in
gateway/platforms/base.py.
Gateway version reporting
- Gateway no longer advertises
unknownversion in production installs
(0f5b5a1)
hermes plugins install <repo>#gateway-pluginships only the
gateway-plugin/subdirectory into~/.hermes/plugins/iris, so the
repo-rootVERSIONfile is absent there andplugin_version()fell back
tounknown— causing the app to show a false "App and gateway versions
differ" warning.version.py: resolution chain is now repo-rootVERSION(dev/symlink
install) →plugin.yamlversion field (production install) →unknown;
stdlib-only parse, with abase=param for tests.plugin.yaml: bumped stale0.1.0→0.1.2to matchVERSION.- Added regression test simulating the production layout.
App notifications
- Fixed double notification + double unread count for cron deliveries
(ea375fd)
A cron delivery emits two frames (high-priority notification banner +
message). When backgrounded, each posted its own system notification
(Cron: <job_id>and the channel name), and the message frame's
redelivery (live SSE + sync replay after the push-triggered reconnect)
incremented the unread badge twice.- Records when a high-priority banner (cron/approval/clarify) was posted
per lane; suppresses the message frame's system notification within a
5 s window (mirrors the gateway's push-coalesce window). - Dedupes unread counting per lane by message id so a redelivered frame
only counts once (recorded only when the message actually counts as
unread).
- Records when a high-priority banner (cron/approval/clarify) was posted
Documentation
-
Clarified ntfy privacy (
b065d17)
The docs claimed ntfy keeps push metadata on your own infrastructure, but
the defaultNTFY_SERVER_URLis the publichttps://ntfy.shcloud
service.README.md,docs/08-push.md,docs/install.md, and
docs/playstore-listing.mdnow make explicit that push metadata (topic,
notification title) passes through ntfy.sh unless you self-host ntfy. -
Refreshed
AGENTS.mdto match the current codebase (5b78e15)- Removed hardcoded ADB serial (differs per developer/machine).
- Added the second pre-commit hook (
check_version_sync) to hard rules. - Documented
tests/,scripts/,backdrops/, andCI-SETUP.mdin the
layout. - Noted the committed
tests/test_android.pycopy and
test_android_http.py.
Tooling / Internal
- New pre-commit hook: version sync guard (
0f5b5a1)
scripts/check_version_sync.sh(wired into.pre-commit-config.yaml)
fails any commit wheregateway-plugin/plugin.yamlversion drifts from the
repo-rootVERSIONfile.
Version
- Bumped
VERSION/plugin.yamlto 0.1.3 (8657e6a).
Downloads
- Port-conflict pre-check now actually fires (
-
released this
2026-08-25 13:15:38 +00:00 | 7 commits to master since this releasev0.1.2
✨ Features
- Release version management — single
VERSIONfile at the repo root is now the source of truth; the release workflow reads it automatically (no manual input, with an empty-file guard). - App & gateway version reporting — the app shows its version in Settings (generated
AppVersion.ktfromVERSION) and sends it to the gateway via theX-Iris-App-Versionheader on SSE open; the gateway reports its own version inhello.ack(server_caps.app_version) and stores the app version in the device registry (merge, not overwrite). - Update hint in Settings — app + gateway version rows with a mismatch hint, plus a best-effort Gitea latest-release check with an "update available" badge.
- Smooth streaming markdown — incremental parser (no full re-parse per snapshot) with a client-side typewriter reveal: steady reveal rate with rate-relative catch-up (jumps when backlog exceeds 2s), cursor drawn via annotator, and the streaming renderer stays alive until the reveal catches up.
- New "Streaming speed" setting (0.2–0.8s) in Settings, persisted per device via SecureStore and live-updatable.
- Thread topic chips ordered newest-first — the gateway now sends a
createdtimestamp per channel/thread over the wire; the topic switcher sorts threads newest-first right beneath General (name as tie-break).
🐛 Fixes
- Pairing was impossible after
iris setup—interactive_setup()generated a freshIRIS_TOKENand saved it to.env, but the localtokenvariable was never updated, so the pairing URL/QR were built with an empty token. The generated value is now embedded in the pairing URL/QR. Regression test added. - Plugin install blocked by security scanner — the install-time scanner flagged test/dev fixtures in
gateway-plugin/(hardcoded tokens,/tmppaths,~/.hermes/.envliteral) as DANGEROUS ("19 findings"). Tests moved to top-leveltests/, the.envpath is now built at runtime, and the scanner verdict ongateway-plugin/is SAFE (0 findings); fresh installs with scan enabled succeed.
📚 Docs & Protocol
frames.schema.jsonanddocs/04-wire-protocol.mdupdated forapp_versionand the threadcreatedfield.docs/05-streaming.mddocuments the new rate mapping, catch-up, and wait-for-reveal semantics.- CI-SETUP.md, README, and docs updated for the new
tests/location and VERSION-based releases.
Downloads
- Release version management — single
-
released this
2026-08-24 21:13:30 +00:00 | 12 commits to master since this releaseChangelog
New features
- Per-device tokens with revocation (#11) — Each paired device now receives its own token (delivered in
hello.ack) instead of sharing the globalIRIS_TOKEN. A leaked or compromised device can be isolated without rotating the shared token.- New operator CLI:
tools/iris_devices.py(list / revoke / unrevoke / reissue) hermes gateway setupnow offers a "Remove a paired device?" menu- App stores the device token in the secure store and presents it from then on
- New operator CLI:
- TLS fingerprint-confirm flow for self-signed gateway certs (#14) — SSH-host-key-style flow: on first pairing against a self-signed cert, the app shows the SHA-256 fingerprint; "Confirm & pin" stores it (EncryptedSharedPreferences / desktop keyring) and allows the connection. Anything else is rejected. Pin is cleared on "forget device".
- Self-signed TLS cert generation in
hermes gateway setup— WhenIRIS_HTTP_CERTis not set, setup now offers to generate a 10-year RSA-2048 self-signed cert (with proper SANs) using hermes' existingcryptographydependency — noopensslneeded. Prints the fingerprint in the format the app's confirm dialog expects; pairing URL/QR advertisehttps://automatically. - Push backend defaults to ntfy (#10) —
IRIS_PUSH_BACKENDnow defaults tontfy, keeping push metadata on your own infrastructure. FCM is opt-in (IRIS_PUSH_BACKEND=fcm) with a privacy warning during setup (metadata routed via Google's servers).
Changes
- HTTP-only transport cleanup — Renamed
IRIS_WS_HOST→IRIS_HTTP_HOST(clean rename, no compat fallback); dropped deadDEFAULT_PORT=8790.ws_probe.py/e2e.pydefault tohttp://127.0.0.1:8791and honorIRIS_HTTP_URL. - Refactor: split
adapter.pymonolith (#12) — The 3,493-lineadapter.pyis now ~857 lines plus focused modules (hooks, classify, pickers, commands, setup, secrets, and 7 frame-handler mixins). Ruff complexity ceilings restored to built-in defaults; genuinely complex functions carry explicit# noqaas frozen, reviewed exceptions.
Fixes
- README limit claims corrected to match reality (#13): uploads are 100 MB default (configurable via
max_upload_bytes), and there is a 1 MiB hard frame-body cap (no 4,096-character limit like Telegram). Limits are set on the gateway side.
Documentation
- New end-to-end install guide (
docs/install.md) for non-technical users: gateway install, app install, LAN/TLS/remote connection, push, options, troubleshooting. - README gained an "Install the gateway" section; pairing section updated for HTTP transport (port 8791, QR scan on Android).
- Replaced stale "android" name mentions with "iris" across docs; fixed stale WS-era references in docs 03/09/12/19.
- New
docs/playstore-listing.mdwith the FCM/ntfy privacy note.
Tests
- 5 new Python tests for cert generation (incl. openssl fingerprint cross-check)
- 8 new Python tests for per-device token issuance/revocation/isolation
- New Kotlin
TlsPinningTest+TlsPinningIntegrationTest(real TLS handshake: unpinned → confirm data, pinned → 200) - Live E2E verified on the phone: self-signed cert pairing, pinning, chat, auto-reconnect after gateway restart⏎
Downloads
- Per-device tokens with revocation (#11) — Each paired device now receives its own token (delivered in
-
released this
2026-08-23 18:20:48 +00:00 | 21 commits to master since this releaseRelease Notes — Iris × Hermes 0.1.0
First public release. Iris is a native Android + desktop chat app for
hermes-agent, built with Compose
Multiplatform and paired with your ownhermes gatewayover a private WebSocket.
Everything stays on your own infrastructure.Highlights
- One codebase, two apps — native Android app and desktop app (Linux, macOS,
Windows) sharing a single Kotlin/Compose codebase. - Telegram-quality chat experience — streaming replies, markdown rendering
(tables, syntax-highlighted code, tap-to-copy), reasoning and tool activity
shown in the bubble, media in both directions, search from everywhere. - Channels & threads — organize reports, cron jobs, and webhook output into
channels; create threads manually or let the agent auto-thread topics. - Push notifications — FCM (primary) or ntfy (fallback), with offline
catch-up and deduplication. - HTML artifact preview — agent-sent HTML/CSS/JS rendered in an in-app
WebView (Android WebView / desktop JCEF). - Fully in-app settings — appearance, font size, streaming, tool/reasoning
verbosity, and more; no hermesconfig.ymlediting required.
Gateway plugin (
gateway-plugin/)- New hermes platform plugin (
iris) with zero new Python dependencies and
zero hermes-core changes; the app is a first-class hermes messaging platform
(slash commands, cron delivery,send_messagerouting all work). - http SSE server with token pairing, outbox sync, and full channel/thread
management (create/rename/favorite/icon/delete, hard deletes). - Push backends: FCM and ntfy;
hello.ackreports the active backend so the
app only runs its ntfy listener when needed. - Push dedupe: gateway tracks the highest outbox cursor delivered per device
via push (devices.last_pushed_cursor); replayed frames at/below the
watermark are not re-notified. 5s per-chat push coalescing. - Channel automation:
channel.set_automationmarks a channel read-only for
cron/webhook output (composer hidden,message.sendrejected, flag synced
to all devices). - Official hermes-gateway status messages as a dedicated comment category.
MAX_MESSAGE_LENGTHraised to 1 MB so long replies and complete HTML
artifacts are no longer chunked.- History frames omit null media (schema-conformant).
Android app
- Pairing flow (manual URL + token or QR Code), connection status bubble in the header.
- Chat: streaming with toggle, markdown bubbles, single-newline preservation,
timestamps + delivery checkmarks, back-to-bottom FAB, history pagination,
long-press message selection and delete (synced to all devices). - Media upload/download/playback in both directions.
- HTML artifact cards with full-screen WebView preview (DOM storage enabled).
- Push: FCM handler + ntfy foreground listener (started/stopped based on the
gateway's backend), background notifications. - Local message cache (SQLDelight) for instant start and offline reading.
- Settings: appearance (bubble colors, background color/image), app-wide font
scale (0.8x–1.5x), streaming and tool/reasoning display options. - Winged-bubble adaptive app icon.
Desktop app
- Two-pane layout, system tray, keyboard shortcuts, inspector, window icon.
- Packaged via
jpackage(app-image, or.debwith-PjpackageType=deb).
Channels, threads & search
- Channels: create, rename, favorite, change color/icon, delete (default
channel is rename-only); flat Material star/heart badges; context menu on
long-press/right-click; favorites and icons synced across devices. - Threading: topic switcher, Ctrl+T, auto-threading (default channel only).
- Global message search.
- Cron delivery to channels, including automation (read-only) channels with a
tappablechat_idpill for delivery targeting.
Quality, tooling & docs
- Lint/LSP cleanup across gateway, Android, and desktop (alpha → stable).
- Gitea CI + release workflows (builds APK and AAB; keystore guidance in
CI-SETUP.md). - E2E test driver (
gateway-plugin/tests/e2e.py) and WS probe; Python test
suite for the gateway plugin; Kotlin host-side tests. - Numbered reference library in
docs/(start with00-overview.md),
frames.schema.jsonas the frame source of truth, security and setup docs. - User-facing README rewrite + Apache-2.0 LICENSE.
Requirements
hermes-agentwith the gateway (hermes gateway setup→hermes gateway).- Android: Android device +
adbfor development; JDK 17 for builds. - Desktop: Linux, macOS, or Windows.
- Push: FCM requires
google-services.json(optional — without it, ntfy is
the push path; self-hosting ntfy is recommended).
Downloads
- One codebase, two apps — native Android app and desktop app (Linux, macOS,