Skip to content

Install

Everything here runs on the Herdr host — the machine your agents already live on. One Go binary, gothalo, is both the daemon and the CLI.

Install Herdr’s agent integration for every agent you run. This is required, or the transcript view shows one agent’s conversation under another:

Terminal window
herdr integration install claude # likewise: hermes, codex, opencode, …

Why, and where each agent keeps its transcript: Agent integration.

macOS or Linux, from the latest release:

Terminal window
curl -fsSL https://raw.githubusercontent.com/dipeshdulal/gothalo/main/install.sh | sh

The script detects your OS and architecture, downloads the matching release archive, and verifies its SHA-256 against the release’s checksums.txt before installing — best effort: it needs shasum or sha256sum on the host and a checksums.txt on the release.

Or build from source:

Terminal window
go install github.com/dipeshdulal/gothalo/cmd/gothalo@latest
Terminal window
go install github.com/dipeshdulal/gothalo/cmd/gothalo@latest
gothalo serve # first run writes ~/.gothalo/config.json + an admin token
gothalo-service install # supervise it via launchd (macOS) / systemd (Linux)
gothalo pair # QR-pair a phone

It defaults to 127.0.0.1:8787. Point it at the tailnet so the phone can reach it:

Terminal window
GOTHALO_ADDR=$(tailscale ip -4):8787 \
GOTHALO_PUBLIC_URL=https://<host>.<tailnet>.ts.net:8787 \
gothalo serve

Config lives in ~/.gothalo/config.json; env wins. The main overrides are GOTHALO_DIR, GOTHALO_ADDR, GOTHALO_PUBLIC_URL, GOTHALO_ADMIN_TOKEN, GOTHALO_SERVICE_ACCOUNT and GOTHALO_FCM_PROJECT. Runtime state lives outside the repo in ~/.gothalo ($GOTHALO_DIR): config.json, devices.json, the FCM key.

Terminal window
./gothalo pair # prints a QR: {"url":…,"code":…}, one-time, ~5 min TTL
./gothalo devices list
./gothalo devices revoke <id>

The app POSTs {code, device_name, fcm_token} to /pair and gets back a per-device bearer it sends as Authorization: Bearer … from then on. Revoking one device turns away one phone without touching the others.

Android, no packaged APK yet. Point it at your own Firebase project first (Push), then build it:

Terminal window
./scripts/setup-firebase.sh --project <firebase-project-id>
cd app && flutter pub get && flutter build apk --release

Or skip the build entirely and open the hosted web app, published beside this site at /gothalo/app/. It is the same client, with no Firebase project of its own — it takes the bridge’s at pair time — so it works against any install. Add it to the home screen and it runs as a PWA.

Two things it needs that the Android build does not: the bridge must have an https URL (tailscale serve, not a bare http://100.x.x.x:8787 — an https page cannot call a plain-http one), and its origin must be on the bridge’s allowlist. https://dipeshdulal.github.io is permitted out of the box; a fork’s own Pages site goes in transport.allowed_origins (GOTHALO_ALLOWED_ORIGINS). See Browser origins.

A bridge built with ./scripts/build.sh also bakes the app in and serves it from its own URL (GOTHALO_PUBLIC_URL, the same address the app pairs to): same origin as the API, so nothing to allow. The install.sh binary does not include the web UI yet.

Without credentials the bridge logs instead of notifying. Two steps — credentials for the bridge, a Firebase project for the app:

Terminal window
gothalo push login --project <firebase-project-id>
./scripts/setup-firebase.sh --project <firebase-project-id>

Full walkthrough, including why every fork needs its own project: Push.