Open Source

Hermes Telegram Mini App

A terminal-style web interface for your Hermes agent. Chat, manage cron jobs, and monitor system health — all inside Telegram.

Everything in one file

A single 75KB HTML file. No build step, no framework, no npm. Copy it and go.

💬

Streaming Chat

Real-time SSE streaming with typing indicator, haptic feedback, and abort-on-cancel.

📊

Context Bar

Live model name, token usage progress bar, and session duration — just like the Hermes CLI.

Cron Management

View, create, pause, and trigger scheduled jobs from a dedicated tab.

🖥

System Monitor

CPU, memory, disk gauges plus process list and quick actions.

🔐

Ed25519 Auth

Validates Telegram initData using their published public key. No bot token needed for verification.

Smooth UX

CSS containment, visualViewport handling, GPU-composited scrolls. No jank on keyboard open.

Get running in 10 minutes

Seven steps. No build tools, no frameworks, no surprises.

  1. Install Hermes Agent

    You need Hermes v0.8.0 or later.

    pip install hermes-agent
  2. Create a Telegram bot

    Open @BotFather, send /newbot, pick a name and username. Save the bot token — it looks like 123456789:ABCdefGHIjklMNOpqrsTUVwxyz.

  3. Get your Telegram user ID

    Open @userinfobot, send /start. It replies with your numeric ID. This is a number like 9876543210 — not your username.

  4. Install the mini app

    One file. That's it.

    mkdir -p ~/.hermes/miniapp
    cp index.html ~/.hermes/miniapp/index.html
  5. Configure environment variables

    Add these to ~/.hermes/.env:

    TELEGRAM_BOT_TOKEN=your_bot_token_here
    TELEGRAM_OWNER_ID=your_numeric_user_id
    TELEGRAM_ALLOWED_USERS=your_numeric_user_id
    API_SERVER_KEY=$(python3 -c "import secrets; print(secrets.token_urlsafe(32))")
    TELEGRAM_OWNER_ID is a number, not your username. This is the most common setup mistake. Get it from @userinfobot.
  6. Expose the gateway

    The Hermes gateway runs on port 8642. Telegram needs HTTPS to reach it.

    # Quick test (URL changes on restart):
    cloudflared tunnel --url http://localhost:8642
    
    # Production (stable URL):
    cloudflared tunnel create hermes
    cloudflared tunnel route dns hermes miniapp.yourdomain.com
    cloudflared tunnel run hermes
  7. Set the bot's menu button

    In @BotFather, send /setmenubutton, pick your bot, then send your URL: https://your-domain/miniapp/index.html

    Users tap the menu button in the chat to launch the mini app.

How authentication works

Ed25519 signature validation — Telegram's official method. No bot token needed for verification.

1
You open the mini app in Telegram. Telegram generates a signed initData payload using their Ed25519 private key.
2
The mini app sends initData to your server via the X-Telegram-Init-Data header on every API request.
3
Your server verifies the Ed25519 signature using Telegram's published public key. No bot token needed — just their public key.
4
The server checks that the user ID matches your TELEGRAM_OWNER_ID. Only you can access the API.
Authenticated. The request goes through. If initData is missing (e.g. browser testing), Bearer token auth is used instead.
💡
Why not HMAC? The HMAC-SHA256 method (using the bot token) has encoding edge cases that cause validation failures in practice. Ed25519 uses Telegram's published public key — no encoding ambiguities, no bot token needed, and it just works.

Endpoints used

The mini app talks to the Hermes gateway API.

EndpointAuthPurpose
GET /healthNoneSystem health (CPU, memory, uptime)
GET /api/model-infoYesActive model, provider, context length
GET /api/session-usageYesCumulative token usage
GET /api/jobsYesList cron jobs
POST /api/commandYesExecute a slash command
POST /v1/chat/completionsYesStreaming chat (SSE)

Common issues

❌ Error 401 when sending a message

initData validation is failing. Check:

  • Is TELEGRAM_BOT_TOKEN set? It's needed to extract the bot ID for validation.
  • Verify your token: curl https://api.telegram.org/bot<TOKEN>/getMe
  • Are you opening the app from inside Telegram? initData only exists in Telegram's browser.
  • Is TELEGRAM_OWNER_ID your numeric ID? Not your username.

❌ "Invalid API key" on cron/status tab

The cron tab uses Bearer token fallback. Check that API_SERVER_KEY is set in your environment and matches what the mini app has stored. Try clearing the mini app's storage: Telegram → tap and hold the mini app → Clear storage.

❌ initData keeps expiring

initData is valid for 24 hours. If the app stays open overnight, close and reopen it to get fresh data.

❌ Cloudflare tunnel URL changed

Free cloudflared tunnel --url tunnels get random URLs each restart. Set up a named tunnel with your own domain for stability.

⚠️ Missing cryptography package

Ed25519 validation requires the cryptography Python package. Install it with:

pip install cryptography

How it fits together

Telegram Client
├─ Mini App (index.html — single file, 75KB)
├─ Sends Ed25519-signed initData
└─ Falls back to Bearer token for browser testing


HTTPS Reverse Proxy (Cloudflare Tunnel, nginx, Caddy...)


Hermes Gateway (port 8642)
├─ Ed25519 signature validation
├─ Owner-only access control
├─ Serves mini app from ~/.hermes/miniapp/
└─ SSE streaming for chat responses

Contributing

Found a bug? Have an idea? PRs are welcome on GitHub.

📜
MIT License. Use it, fork it, ship it. The gateway-side auth changes live in the Hermes Agent repo.