Docs/refactor readme (#430)
* docs: improve and shorten README Update app name to Hermes Mobile, correct JDK/dependency versions, and simplify structure. * docs: extract contributing guidelines to CONTRIBUTING.md Move the contributing workflow, code style, and PR checklist to its own file and update README.md to reference it. * docs: link to LICENSE file instead of raw text Simplify the License section in README.md to reference the LICENSE file directly. * docs: remove emojis from features list Clean up visual clutter in README.md by removing emojis from the features section. * docs: add authentication setup guide to README * docs: fix authentication section — matches actual code paths --------- Co-authored-by: M57 <hy4ri@users.noreply.github.com>
This commit is contained in:
1 parent
546dc86a98
commit
8dfc280b94
2 files changed
+125
-239
No files matched your search
@@ -0,0 +1,49 @@
|
||||
# Contributing to Hermes Mobile
|
||||
|
||||
Thank you for your interest in contributing to Hermes Mobile! To maintain high code quality and consistency, we ask all contributors to follow the workflow and guidelines outlined below.
|
||||
|
||||
---
|
||||
|
||||
## PR Workflow
|
||||
|
||||
All code changes must go through a pull request (PR). Directly pushing to `main` is not allowed.
|
||||
|
||||
1. **Pick or open an issue** to discuss the changes you want to make.
|
||||
2. **Create a branch** off `main` using the following naming convention:
|
||||
- Features: `feat/issue-N-description`
|
||||
- Bug fixes: `fix/issue-N-description`
|
||||
3. **Implement your changes** and format them locally.
|
||||
4. **Submit a PR** targeting the `main` branch.
|
||||
5. **Ensure all CI checks pass** (formatting, linting, and unit tests).
|
||||
6. **Maintainers will squash-merge** your PR into `main`.
|
||||
|
||||
---
|
||||
|
||||
## Code Style
|
||||
|
||||
We enforce Kotlin coding conventions and Jetpack Compose best practices.
|
||||
|
||||
### Kotlin Formatting
|
||||
- Code formatting is checked and enforced by **ktlint 1.2.1**.
|
||||
- Run formatting check locally before committing:
|
||||
```bash
|
||||
./ktlint <file> # Check one file
|
||||
./ktlint --format <file> # Auto-fix formatting issues
|
||||
```
|
||||
- Import ordering is strictly ASCII-lexicographic (uppercase before lowercase: e.g., `LaunchedEffect` before `collectAsState`).
|
||||
|
||||
### Compose Guidelines
|
||||
- Standard screen structures must use `HermesScaffold` rather than raw Material3 `Scaffold`.
|
||||
- Composable parameters must follow the standard order: `modifier` first, then event callbacks, and finally children content.
|
||||
|
||||
---
|
||||
|
||||
## PR Checklist
|
||||
|
||||
Before submitting your PR, please verify:
|
||||
|
||||
- [ ] Your branch is up-to-date with `main`.
|
||||
- [ ] Local build and `ktlint` checks pass successfully.
|
||||
- [ ] No unused imports, unused parameters, or dead code.
|
||||
- [ ] Every `Image` and `Icon` element has a descriptive `contentDescription` for accessibility.
|
||||
- [ ] New components match the UI/UX style of similar existing screens.
|
||||
@@ -7,23 +7,12 @@
|
||||
<br><br>
|
||||
</div>
|
||||
|
||||
<h1 align="center">Hermes Control</h1>
|
||||
<p align="center"><strong>Remote control for your Hermes AI agent — from your pocket.</strong></p>
|
||||
|
||||
<p align="center">
|
||||
<a href="#features">Features</a> •
|
||||
<a href="#screenshots">Screenshots</a> •
|
||||
<a href="#quick-start">Quick Start</a> •
|
||||
<a href="#project-structure">Project Structure</a> •
|
||||
<a href="#tech-stack">Tech Stack</a> •
|
||||
<a href="#contributing">Contributing</a> •
|
||||
<a href="#releases">Releases</a>
|
||||
</p>
|
||||
<h1 align="center">Hermes Mobile</h1>
|
||||
<p align="center"><strong>Native Android companion app for your Hermes AI agent.</strong></p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/Hy4ri/hermes-mobile/releases/latest"><img src="https://img.shields.io/github/v/release/Hy4ri/hermes-mobile?color=6750A4&label=Latest%20Release&logo=github" alt="Latest Release"></a>
|
||||
<img src="https://img.shields.io/github/actions/workflow/status/Hy4ri/hermes-mobile/android.yml?branch=main&label=CI&logo=githubactions" alt="CI">
|
||||
<img src="https://img.shields.io/github/last-commit/Hy4ri/hermes-mobile?color=success&label=Last%20Commit" alt="Last Commit">
|
||||
<img src="https://img.shields.io/badge/minSdk-26-brightgreen" alt="minSdk 26">
|
||||
<img src="https://img.shields.io/badge/targetSdk-36-brightgreen" alt="targetSdk 36">
|
||||
</p>
|
||||
@@ -32,274 +21,122 @@
|
||||
|
||||
## Overview
|
||||
|
||||
**Hermes Control** is a native Android companion app for [Hermes Agent](https://hermes-agent.nousresearch.com) — the open-source, multi-platform AI assistant by Nous Research.
|
||||
|
||||
Instead of pulling out a laptop or switching to Telegram/Discord, you can manage your Hermes agent directly from your phone:
|
||||
|
||||
- 💬 Chat with your agent in real time
|
||||
- 🔧 Inspect and reconfigure system settings, profiles, and plugins
|
||||
- 📊 Monitor gateway status, MCP servers, and webhook health
|
||||
- 📋 Manage cron jobs, environment keys, and toolsets
|
||||
- 🗂️ Track kanban boards and agent achievements
|
||||
- 🔄 Pull-to-refresh every data screen
|
||||
|
||||
All this with a **Material You** design that adapts to your device's dynamic color theme.
|
||||
**Hermes Mobile** is the native Android client for [Hermes Agent](https://hermes-agent.nousresearch.com). It connects securely to your local Hermes gateway (REST API and WebSocket TUI Gateway) over LAN, giving you pocket control over your AI assistant.
|
||||
|
||||
---
|
||||
|
||||
## Features
|
||||
|
||||
### 🤖 Agent Chat
|
||||
- Real-time message exchange with your Hermes agent
|
||||
- Session management with profile switching
|
||||
- Message history with persistent storage (Room)
|
||||
|
||||
### ⚙️ System Management
|
||||
- **Profiles** — View and switch between Hermes agent profiles
|
||||
- **Skills** — Browse installed skills with inline descriptions
|
||||
- **Plugins** — Manage active plugins and their configurations
|
||||
- **Toolsets** — See which toolsets are enabled per profile
|
||||
|
||||
### 🛠️ Operations
|
||||
- **Cron Jobs** — View scheduled tasks, their schedules, and last-run status
|
||||
- **Webhooks** — Configure and test webhook endpoints
|
||||
- **Keys & Credentials** — Securely manage environment variables
|
||||
- **Logs** — Stream and filter agent logs
|
||||
|
||||
### 📡 Connectivity
|
||||
- **Gateway Status** — Monitor WebSocket and API gateway health
|
||||
- **MCP Servers** — Manage Model Context Protocol server connections
|
||||
- **Channels** — View connected messaging platform status
|
||||
|
||||
### 📊 Productivity
|
||||
- **Kanban Boards** — Track tasks across boards, columns, and cards
|
||||
- **System Info** — Runtime environment and configuration overview
|
||||
- **Achievements** — Agent milestone tracker
|
||||
|
||||
### 🎨 UX
|
||||
- **Material You** — Dynamic color theming from your wallpaper
|
||||
- **Pull-to-Refresh** — Swipe down on any data screen to reload
|
||||
- **Shared Scaffold** — Consistent navigation and layout across all screens
|
||||
- **Scroll-aware TopBar** — Collapsing top bar on scroll
|
||||
|
||||
---
|
||||
|
||||
## Screenshots
|
||||
|
||||
> 📸 Screenshots coming soon. Build the app and see it in action!
|
||||
|
||||
| Chat | System | Profile | Kanban |
|
||||
|:---:|:---:|:---:|:---:|
|
||||
| 🔲 | 🔲 | 🔲 | 🔲 |
|
||||
- **Real-Time Chat:** Message your agent with Room-backed local database history.
|
||||
- **System Config:** Manage active profiles, installed skills, plugins, and LLM model selections.
|
||||
- **Operations:** Stream and filter live logs, manage cron jobs, edit environment keys, and test webhooks.
|
||||
- **Gateway Status:** Monitor WebSocket connection, MCP servers, and messaging channel status.
|
||||
- **Productivity:** View and manage tasks via integrated Kanban boards and track agent milestones.
|
||||
- **Modern UX:** Native Material You design supporting dynamic color theming, scroll-aware TopBar, and pull-to-refresh.
|
||||
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Prerequisites
|
||||
- **JDK 21+** (required for Kotlin compilation and the Gradle toolchain)
|
||||
- **Android Studio** (Ladybug+) or a **Nix** development environment
|
||||
|
||||
| Tool | Version | Reason |
|
||||
|------|---------|--------|
|
||||
| [JDK](https://adoptium.net/) | 17+ | Kotlin/JVM compilation |
|
||||
| [Android Studio](https://developer.android.com/studio) | Hedgehog+ | IDE + SDK management |
|
||||
| Android SDK | 36 (compile), 26 (min) | Via Android Studio SDK Manager |
|
||||
| Git | any | Clone the repo |
|
||||
### Build & Deploy
|
||||
1. **Clone the repository:**
|
||||
```bash
|
||||
git clone https://github.com/Hy4ri/hermes-mobile.git
|
||||
cd hermes-mobile
|
||||
```
|
||||
2. **Build the debug APK:**
|
||||
```bash
|
||||
./gradlew assembleDebug
|
||||
```
|
||||
3. **Install on your emulator/device:**
|
||||
```bash
|
||||
adb install app/build/outputs/apk/debug/app-debug.apk
|
||||
```
|
||||
|
||||
### Clone & Build
|
||||
*Note: For release builds, ensure keystore environment variables (`KEYSTORE_PATH`, `KEYSTORE_PASSWORD`, `KEY_ALIAS`, `KEY_PASSWORD`) are configured, or let the GitHub Actions release workflow handle it on tag push (`v*`).*
|
||||
|
||||
---
|
||||
|
||||
## Authentication
|
||||
|
||||
Once the app is installed, you need to point it at your Hermes gateway. The app auto-detects which auth mode the dashboard is using — just fill in the fields it shows.
|
||||
|
||||
### 1. Start the dashboard
|
||||
|
||||
On your host machine, start the dashboard:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/Hy4ri/hermes-mobile.git
|
||||
cd hermes-mobile
|
||||
./gradlew assembleDebug
|
||||
hermes dashboard # loopback (127.0.0.1:9119) — no auth needed
|
||||
hermes dashboard --host 0.0.0.0 # LAN — requires auth
|
||||
```
|
||||
|
||||
The debug APK will be at `app/build/outputs/apk/debug/app-debug.apk`.
|
||||
For LAN access, configure credentials in `~/.hermes/config.yaml`:
|
||||
|
||||
### Build with custom version
|
||||
|
||||
```bash
|
||||
./gradlew assembleRelease -PversionName="1.2.0" -PversionCode="120"
|
||||
```yaml
|
||||
dashboard:
|
||||
basic_auth:
|
||||
username: admin # pick your own
|
||||
password: hermes # pick your own
|
||||
```
|
||||
|
||||
> **Note:** Release builds require proper signing configuration. Ensure the environment variables `KEYSTORE_PATH`, `KEYSTORE_PASSWORD`, `KEY_ALIAS`, and `KEY_PASSWORD` are set before building.
|
||||
### 2. Connect the app
|
||||
|
||||
### Install
|
||||
Tap **Sign in** on the landing screen and enter the dashboard host and port. The app probes the dashboard and reveals the fields you need:
|
||||
|
||||
```bash
|
||||
adb install app/build/outputs/apk/debug/app-debug.apk
|
||||
```
|
||||
| Auth mode | When | What you fill |
|
||||
|-----------|------|---------------|
|
||||
| **Token only** | Dashboard on same machine (loopback) | **Token** — grab from `~/.hermes/dashboard-token.txt` or `~/.hermes/.env` (`HERMES_DASHBOARD_SESSION_TOKEN`). The app can also auto-extract it from the dashboard page |
|
||||
| **Basic auth** | Dashboard on LAN with password gate | **Username** + **Password** (default `admin` / `hermes`). The app logs in, gets a session cookie, and mints a WebSocket ticket automatically |
|
||||
|
||||
Or open the project in Android Studio and hit **Run ▶**.
|
||||
> The app communicates over plain HTTP — it's designed for **trusted local networks only**. Do not expose your Hermes gateway to untrusted networks.
|
||||
|
||||
### Connection profiles
|
||||
|
||||
Have multiple gateways? Switch between them in **Settings → Connection profiles**. Each profile stores its own host, port, and token — just tap to swap.
|
||||
|
||||
### Pairing (admin)
|
||||
|
||||
The **Pairing** screen lets you approve or revoke agents and services that are trying to connect to your gateway, such as Telegram or Discord sessions.
|
||||
|
||||
---
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
hermes-mobile/
|
||||
├── app/
|
||||
│ ├── src/
|
||||
│ │ ├── main/
|
||||
│ │ │ ├── java/com/m57/hermescontrol/
|
||||
│ │ │ │ ├── Navigation.kt # Drawer + NavDisplay + entry wiring
|
||||
│ │ │ │ ├── NavigationController.kt # Central navigation guard (dedup)
|
||||
│ │ │ │ ├── NavigationKeys.kt # Screen key definitions
|
||||
│ │ │ │ ├── MainActivity.kt # Single activity entry point
|
||||
│ │ │ │ ├── data/
|
||||
│ │ │ │ │ ├── model/ # API models / DTOs (20+ files)
|
||||
│ │ │ │ │ ├── remote/ # Retrofit + OkHttp API client
|
||||
│ │ │ │ │ ├── local/ # Room DB (Dao, Entity, Mapper)
|
||||
│ │ │ │ │ └── ws/ # WebSocket TUI Gateway (JSON-RPC 2.0)
|
||||
│ │ │ │ ├── notification/
|
||||
│ │ │ │ │ └── ChatNotificationService.kt # Foreground service for reply alerts
|
||||
│ │ │ │ ├── theme/
|
||||
│ │ │ │ │ ├── Theme.kt # Material You dynamic theming
|
||||
│ │ │ │ │ ├── Color.kt # Color palette definitions
|
||||
│ │ │ │ │ ├── HermesStatusColors.kt # Semantic status colours (CompositionLocal)
|
||||
│ │ │ │ │ ├── Type.kt # Typography scale
|
||||
│ │ │ │ │ ├── Motion.kt # Shared transition animations
|
||||
│ │ │ │ │ ├── Spacing.kt # Spacing tokens (CompositionLocal)
|
||||
│ │ │ │ │ └── Shapes.kt # Shape tokens
|
||||
│ │ │ │ ├── ui/
|
||||
│ │ │ │ │ ├── common/ # Shared components
|
||||
│ │ │ │ │ │ ├── HermesScaffold.kt # Standardised screen layout
|
||||
│ │ │ │ │ │ ├── StateViews.kt # Loading, error, empty placeholders
|
||||
│ │ │ │ │ │ └── SharedComponents.kt # SearchBar, FilterChips, ToggleRow, etc.
|
||||
│ │ │ │ │ ├── chat/ # Chat screen + view model
|
||||
│ │ │ │ │ ├── settings/ # Settings screen + view model
|
||||
│ │ │ │ │ ├── connect/ # Connect / pairing screen
|
||||
│ │ │ │ │ ├── profiles/ # Profile management
|
||||
│ │ │ │ │ ├── skills/ # Skills browser
|
||||
│ │ │ │ │ ├── plugins/ # Plugin management
|
||||
│ │ │ │ │ ├── toolsets/ # Toolset viewer
|
||||
│ │ │ │ │ ├── cron/ # Cron job viewer
|
||||
│ │ │ │ │ ├── webhooks/ # Webhook management
|
||||
│ │ │ │ │ ├── logs/ # Log stream viewer
|
||||
│ │ │ │ │ ├── keys/ # Environment variable manager
|
||||
│ │ │ │ │ ├── gateway/ # Gateway health monitor
|
||||
│ │ │ │ │ ├── mcp/ # MCP server manager
|
||||
│ │ │ │ │ ├── model/ # LLM model selector
|
||||
│ │ │ │ │ ├── channels/ # Messaging channels
|
||||
│ │ │ │ │ ├── pairing/ # Device pairing
|
||||
│ │ │ │ │ ├── config/ # Raw config viewer
|
||||
│ │ │ │ │ ├── system/ # System info screen
|
||||
│ │ │ │ │ ├── kanban/ # Kanban board viewer
|
||||
│ │ │ │ │ └── achievements/ # Agent achievements
|
||||
│ │ │ │ └── util/ # Utility classes
|
||||
│ │ │ │ └── CronExpressionFormatter.kt
|
||||
│ │ │ ├── res/
|
||||
│ │ │ │ ├── values/
|
||||
│ │ │ │ │ └── strings.xml # String resources
|
||||
│ │ │ │ ├── drawable/ # Vector icons & drawables
|
||||
│ │ │ │ └── mipmap-*/ # Launcher icons
|
||||
│ │ │ └── AndroidManifest.xml
|
||||
│ │ └── test/ # Unit tests
|
||||
│ │ └── kotlin/com/m57/hermescontrol/
|
||||
│ └── build.gradle.kts # App-level build config
|
||||
├── gradle/
|
||||
│ └── libs.versions.toml # Version catalog
|
||||
├── .github/
|
||||
│ └── workflows/
|
||||
│ ├── android.yml # CI (ktlint + unit tests)
|
||||
│ └── release.yml # Release APK builder
|
||||
├── build.gradle.kts # Root build config
|
||||
├── settings.gradle.kts # Project settings
|
||||
└── gradlew # Gradle wrapper
|
||||
app/src/main/java/com/m57/hermescontrol/
|
||||
├── data/ # Local (Room, EncryptedSharedPreferences) & Remote (Retrofit, OkHttp WS)
|
||||
├── notification/ # Foreground service for message notifications
|
||||
├── theme/ # Material You design system, status colors, spacing, and typography
|
||||
└── ui/ # Compose screens (Chat, Settings, Profiles, Kanban, etc.) + Navigation
|
||||
```
|
||||
\n---
|
||||
|
||||
## Tech Stack
|
||||
|
||||
| Category | Library | Purpose |
|
||||
|----------|---------|---------|
|
||||
| **Language** | [Kotlin 2.3+](https://kotlinlang.org/) | Primary language |
|
||||
| **UI** | [Jetpack Compose](https://developer.android.com/develop/ui/compose) (BOM 2026.03.01) | Declarative UI |
|
||||
| **Design** | [Material3](https://m3.material.io/) (Compose) + Material You | Dynamic theming |
|
||||
| **Navigation** | [Navigation3](https://developer.android.com/develop/ui/compose/navigation) | Screen routing |
|
||||
| **Networking** | [Retrofit 2](https://square.github.io/retrofit/) + [OkHttp 4](https://square.github.io/okhttp/) | REST API calls |
|
||||
| **Persistence** | [Room](https://developer.android.com/training/data-storage/room) (SQLite) | Local message history |
|
||||
| **Encryption** | AndroidX Security Crypto | Secure key storage |
|
||||
| **Background** | Foreground Service | Notification polling (`ChatNotificationService`) |
|
||||
| **Serialization** | [Gson](https://github.com/google/gson) | JSON parsing |
|
||||
| **Testing** | jUnit 5 + [MockK](https://mockk.io/) + [OkHttp MockWebServer](https://github.com/square/okhttp/tree/master/mockwebserver) | Unit testing |
|
||||
| **Linting** | [ktlint](https://ktlint.github.io/) | Kotlin code style |
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
## Tech Stack
|
||||
|
||||
The app follows a **single-activity, Compose-first** architecture with MVVM:
|
||||
|
||||
```
|
||||
View (Composable) → ViewModel → ApiClient (Retrofit) → Hermes Agent (HTTP)
|
||||
```
|
||||
|
||||
- **Screens** are pure Compose functions that observe `StateFlow` from their ViewModel
|
||||
- **ViewModels** manage UI state and call the API client
|
||||
- **ApiClient** is a Retrofit-based HTTP client that talks to the Hermes Agent REST API
|
||||
- **Navigation** uses a custom NavHost with drawer-based routing
|
||||
- **Language:** Kotlin 2.4.0 with KSP compiler plugin
|
||||
- **UI & Layout:** Jetpack Compose (BOM 2026.03.01) & Material 3 / Material You
|
||||
- **Navigation:** Navigation3 (Compose-first Routing)
|
||||
- **Networking:** Retrofit 3.0.0, OkHttp 5.4.0, Gson 2.14.0
|
||||
- **Database:** Room 2.7.1 with SQLCipher encryption
|
||||
- **Security:** `EncryptedSharedPreferences` (AES256-GCM)
|
||||
- **Formatting:** `ktlint` style rules (checked automatically in CI)
|
||||
|
||||
---
|
||||
|
||||
## Contributing
|
||||
|
||||
PRs are welcome! Here's the workflow:
|
||||
Contributions are welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for our branch workflow, code style guidelines, and PR checklist.
|
||||
|
||||
1. **Pick an issue** — or create one first to discuss the change
|
||||
2. **Branch** from `main` — use `feat/issue-N-description` or `fix/issue-N-description`
|
||||
3. **Implement** — one PR per logical change
|
||||
4. **CI must pass** — ktlint + lintDebug + unit tests run on every PR
|
||||
5. **Squash merge** into `main`
|
||||
|
||||
### Code style
|
||||
|
||||
- ktlint enforces consistent formatting (`./gradlew ktlintCheck`)
|
||||
- Use `HermesScaffold` for new screens (never raw Material3 `Scaffold`)
|
||||
- Compose parameters follow the standard order: `modifier`, callbacks, content
|
||||
|
||||
### PR checklist
|
||||
|
||||
- [ ] Branch from `main` and target `main`
|
||||
- [ ] CI is green (ktlint, lint, tests)
|
||||
- [ ] No unused imports or dead code
|
||||
- [ ] `contentDescription` on all `Image`/`Icon` elements (accessibility)
|
||||
- [ ] Follows the existing pattern for similar screens
|
||||
|
||||
---
|
||||
|
||||
## Releases
|
||||
|
||||
Pre-built APKs are available on the [Releases page](https://github.com/Hy4ri/hermes-mobile/releases).
|
||||
|
||||
Each release is built automatically by CI when a maintainer pushes a `v*` tag:
|
||||
|
||||
```bash
|
||||
git tag v1.2.0
|
||||
git push origin v1.2.0
|
||||
```
|
||||
|
||||
The `release.yml` workflow will:
|
||||
1. Run full CI (ktlint, lint, tests)
|
||||
2. Build a release APK with the correct version
|
||||
3. Create a GitHub Release with auto-generated notes
|
||||
4. Attach the APK as a downloadable asset
|
||||
For developer-specific details, code conventions, and project architecture notes, refer to [AGENTS.md](AGENTS.md).
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
|
||||
```
|
||||
Copyright 2026 Hy4ri
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
```
|
||||
This project is licensed under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for details.
|
||||
renamed '/tmp/hermes-snap-800bd6e0cc89.sh.tmp.17855' -> '/tmp/hermes-snap-800bd6e0cc89.sh'
|
||||
Reference in new issue
Block a user