The previous F-Droid build run produced a 'BUILD SUCCESSFUL' but the universal APK was missing from apps/mobile/android/app/build/outputs/apk/release/. The cause: the first gradle assembleRelease (for the GitHub Release) had already produced per-ABI + universal APKs. The F-Droid build's gradle re-evaluated the signing config (now null because -Phermes.fdroid=true leaves it unset), and the resulting packageRelease task overwrote the per-ABI APKs but skipped the universal APK packaging task (UP-TO-DATE). `gradle clean assembleRelease` forces a from-scratch build that produces all 4 APKs (per-ABI + universal). The clean takes ~10s; the from-scratch release build is ~3min on CI. F-Droid's own rebuild will be similarly slow. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
hermes-mobile
An Android port of hermes-desktop that runs
hermes-agent on the device. The UI is a
native Jetpack Compose port — no WebView, no Capacitor, no vendored React renderer. The
Hermes Kotlin sources live in android-runner/; the live apps/mobile/android/ tree is
regenerated by apps/mobile/scripts/setup-android.sh on every build. See
docs/architecture.md for the full layout and design rationale.
The parity roadmap at ~/.claude/plans/groovy-fluttering-island.md has landed
all 8 phases. v0.1.0 is the first public release — see
CHANGELOG.md for the per-phase summary. The next iteration
(v0.2.0) is in [Unreleased]; the v2 deferred items in the plan (iOS, Play Store,
bundled uv, i18n, gateway auto-restart, Claw3D on mobile) are tracked there.
Layout
hermes-mobile/
├── android-runner/ # canonical Kotlin sources
│ ├── README.md # edit conventions
│ └── app/src/main/
│ ├── kotlin/com/nousresearch/hermes/ # 33 .kt files: HermesApi, MainActivity,
│ │ # GatewayClient, HermesInstaller, services,
│ │ # Compose UI (chat, sessions, memory, ...)
│ ├── AndroidManifest.xml
│ └── res/values/strings.xml
├── apps/mobile/
│ ├── android/ # generated Android project; Kotlin sources
│ │ # synced from android-runner/ on every build
│ ├── package.json # minimal stub with android:assemble:* scripts
│ └── scripts/
│ └── setup-android.sh # rsync --delete runner → live; merge strings
│ # and permissions
├── script/
│ ├── check-kotlin-drift.sh # CI: fail if android-runner/ and live/ diverge
│ ├── sign-and-zipalign.sh
│ ├── write-update-manifest.sh
│ └── audit-a11y.sh
├── f-droid/ # F-Droid metadata + build script
├── keystore/ # release.jks (RSA 4096, 25-year)
├── review/
│ ├── hermes-desktop/ # upstream fathah/hermes-desktop (visual spec)
│ └── hermes-agent/ # upstream NousResearch/hermes-agent (HTTP API)
├── docs/
│ └── architecture.md
└── .github/workflows/mobile-build.yml # CI: sync, drift check, build, sign, release
Build
# One-time setup
pnpm install
bash apps/mobile/scripts/setup-android.sh # rsync runner → live
bash script/check-kotlin-drift.sh # verify in sync
# Build
cd apps/mobile/android
./gradlew :app:assembleDebug # debug APK
./gradlew :app:assembleRelease # release APK (needs keystore)
./gradlew test # unit tests
./gradlew connectedAndroidTest # instrumented tests
Editing
Edit Kotlin sources in android-runner/, not in apps/mobile/android/. The live
tree is regenerated by setup-android.sh on every build. CI's
script/check-kotlin-drift.sh fails the build on any divergence.
See android-runner/README.md for the layout, edit
conventions, and "how to add a new Hermes source" walkthrough.
Distribution
| Channel | Build | Update mechanism |
|---|---|---|
| Sideload (GitHub Releases) | assembleRelease (signed) |
In-app updater reads latest.json from the release |
| F-Droid | f-droid/build.sh |
F-Droid client auto-update |
| Manual APK | assembleDebug |
None |
Parity status (v0.1.0)
| Desktop | Mobile (this repo) | |
|---|---|---|
| Screens | 20+ | 13 implemented; 1 stub (Dashboard) |
| IPC methods | ~188 | 152 implemented |
| Connection modes | Local + remote + SSH | All three implemented |
| Install | Curl install.sh | Termux + bundled Python (8 stages) |
| Gateway | Python subprocess | Python subprocess (same) |
| OAuth | All providers | All providers (deep-link via hermes://oauth-callback) |
| Updates | electron-updater | GitHub Releases (F-Droid: in-app disabled) |
| Crash reporting | Optional Sentry | Optional Sentry (8.43.1, opt-in via Settings) |
See ~/.claude/plans/groovy-fluttering-island.md for the full roadmap and
CHANGELOG.md for the per-phase delivery log.