Herdr Mobile is a native iOS and Android control surface for durable Herdr sessions. It connects to the separately deployed Herdr Mobile Relay, displays live terminal panes, and lets an authorized user navigate and operate Herdr from a phone or tablet.
Companion repository: Herdr Mobile Relay.
The application never owns agent processes. Herdr and the relay run on the host; the mobile client can disconnect, suspend, or be closed without terminating work.
- Spaces and linked worktrees grouped in a native navigator.
- Agent-focused view sorted by attention state.
- Live ANSI terminal rendering and interactive terminal input.
- Workspace file browser with bounded text and image previews.
- Read-only Git branch, ahead/behind, changed-file, and unified-diff inspection.
- Device-sized terminal takeover, resize, and scroll commands.
- Space, worktree, and shell-tab creation.
- Tab renaming and worktree removal.
- Multi-session selection.
- Optional read-only device authorization enforced by the relay.
- Secure persistence of relay connection settings.
- Responsive split layout for tablets and compact navigation for phones.
- iOS and Android native modules for terminal rendering and platform controls.
| Codex CLI | Grok CLI |
|---|---|
![]() |
![]() |
Herdr Mobile
|
| HTTPS REST + WebSocket
v
Herdr Mobile Relay on the private tailnet
|
| Unix-socket RPC
v
Herdr server and durable terminal sessions
The companion relay is published separately as Herdr Mobile Relay. Install and configure that repository on the machine running Herdr before connecting this app.
- Node.js 24.18.0, matching .node-version.
- pnpm.
- Xcode and CocoaPods for iOS development.
- Android Studio, Android SDK, JDK, and
adbfor Android development. - macOS for iOS builds.
This project uses native modules and therefore does not run in Expo Go. Use an Expo development client or a native release build.
- A running Herdr server.
- The Herdr Mobile Relay plugin.
- A private network path from the device to the relay, normally Tailscale.
pnpm installOptional formatting and native lint tools are listed in Brewfile:
brew bundleCopy the example environment file for build-time defaults:
cp .env.example .env.localSet the relay URL printed by the host plugin’s url action:
EXPO_PUBLIC_HERDR_URL=https://your-machine.your-tailnet.ts.net:8787
EXPO_PUBLIC_HERDR_DEMO=0The URL is only a default. Users can enter or replace it from the connection sheet, and the app stores the resulting connection in platform secure storage. A named Herdr session may also be selected.
The workspace browser requires a current Herdr Mobile Relay build. File and Git reads are resolved from the selected Herdr workspace on the host; the mobile client never supplies an arbitrary root.
Remote relay URLs must use HTTPS. Plain HTTP is accepted only for loopback development.
Start Metro for a native development client:
pnpm dev:clientGenerate and run the Android native project:
pnpm androidGenerate and run the iOS native project:
pnpm iosThe generated /android and /ios directories are disposable and ignored by Git. Native behavior
is defined by app.config.ts, config plugins, and the checked-in modules.
Use deterministic local data when a Herdr host is unavailable:
EXPO_PUBLIC_HERDR_DEMO=1 pnpm dev:clientFor repeatable screenshots without development overlays:
pnpm showcasePreview mode simulates mutations in memory and never contacts or changes a real Herdr session.
Build a standalone ARM64 release APK with its JavaScript bundle embedded:
EXPO_PUBLIC_HERDR_URL=https://your-machine.your-tailnet.ts.net:8787 \
pnpm android:releaseOmit EXPO_PUBLIC_HERDR_URL to produce a generic build that opens connection setup on first launch.
The APK is written to:
android/app/build/outputs/apk/release/app-release.apk
The first release build creates a private signing identity in:
${XDG_CONFIG_HOME:-$HOME/.config}/herdr-mobile/android-signing
Back up both files in that directory together. Android will reject upgrades signed with a different
identity. Set HERDR_ANDROID_SIGNING_DIR to use another protected location.
Enable USB or wireless debugging, then provide an explicit adb serial or host:port:
HERDR_ANDROID_ADB_SERIAL=adb-serial-or-host:port pnpm android:installThe installer uses agent-device to install and relaunch dev.herdr.mobile. It never selects an
arbitrary attached device. Customize the reusable automation session name when desired:
HERDR_ANDROID_ADB_SERIAL=adb-serial \
HERDR_ANDROID_DEVICE_SESSION=my-device \
pnpm android:installGenerate and run a release configuration locally:
pnpm ios:releaseThe checked-in app configuration uses bundle identifier dev.herdr.mobile and an iOS deployment
target of 18.0. Forks that distribute their own signed build must change the bundle identifier and
configure an appropriate Apple development team, App Store record, and provisioning setup.
No App Store Connect or EAS project identifiers are committed.
Run the complete standalone mobile verification suite:
pnpm verifyThis runs:
pnpm typecheck
pnpm testResolve the public Expo configuration without generating native projects:
pnpm config -- --type publicFor a release-level Android check, run pnpm android:release after the test suite.
assets/ App icons, brand assets, and widget assets
modules/ Native terminal, markdown, review, and platform-control modules
packages/ Shared contracts, client runtime, and utilities
patches/ Pinned dependency compatibility patches
plugins/ Expo config plugins
scripts/ Release, install, configuration, and asset tooling
src/features/herdr/ Herdr-native application UI
src/hooks/ Relay connection and live terminal state
src/lib/ Relay transport, domain model, storage, and helpers
app.config.ts Expo application and platform configuration
pnpm-workspace.yaml Workspace catalog and dependency policy
The project began from the open-source T3 Code mobile foundation and retains supporting modules used by the Herdr-native screen. See THIRD_PARTY_NOTICES.md for provenance.
The mobile transport consumes the relay’s bounded REST/WebSocket contract:
- Snapshot reads provide spaces, tabs, panes, sessions, and authorization state.
- REST mutations create and update structural Herdr resources.
- A session-scoped WebSocket announces structural changes.
- The selected pane receives full or incremental terminal frames.
- Resize and scroll messages are sent back through the live terminal controller.
- Bounded REST pane reads recover startup and reconnect state.
The UI treats the relay snapshot as authoritative. Optimistic state makes newly created spaces and tabs immediately navigable while a subsequent refresh reconciles with Herdr.
- Use a tailnet-only relay; never expose write access through a public Funnel.
- Keep trusted-user validation enabled on the relay.
- Treat relay write authorization as remote shell authorization.
- Connection settings are stored with the platform secure-storage implementation.
- Release signing credentials live outside this repository.
- No personal hostname, tailnet name, IP address, user directory, token, or signing credential is required or committed.
- Demo mode is explicit and does not silently replace a failed live connection.
The default application name is Herdr, with Android package and iOS bundle identifier
dev.herdr.mobile. Brand source assets live under assets/prod.
If publishing an independent fork, review at least:
name,slug,scheme, and platform identifiers inapp.config.ts;- application icons and splash assets;
- Android signing identity location;
- Apple signing and store metadata;
- default relay configuration and privacy disclosures.
Enter the HTTPS URL printed by:
herdr plugin action invoke url --plugin herdr.controlVerify the device is connected to the same tailnet.
The relay’s optional device-authorization policy does not allow this device to write. Update the relay allowlist or continue in read-only mode.
The client automatically reconnects its WebSocket and falls back to bounded snapshot/pane reads. Check relay status and confirm the Herdr server is still running.
Run adb devices, reconnect wireless debugging if needed, and pass the exact listed serial through
HERDR_ANDROID_ADB_SERIAL.
Expo Go is unsupported. Build an Expo development client with pnpm android or pnpm ios.
The signing identity differs from the one used for the installed build. Restore the original signing directory or uninstall the existing application before installing a differently signed fork.
MIT. The root LICENSE covers the T3 Code-derived mobile foundation. Vendored and adapted components retain their own notices and licenses; see THIRD_PARTY_NOTICES.md.

