Skip to content

florianbeisel/esper-relay

Repository files navigation

esper-relay logo

esper-relay

Secure remote Codex control from your phone

crates.io version Rust 1.85+ Tailscale secured access Mobile-first web UI MIT license


esper-relay keeps codex app-server running on a machine you trust and gives you a mobile-friendly remote control surface over Tailscale. You get your Codex sessions on your phone, without exposing the host directly to the public internet.

πŸ“± See It First

Mobile thread view in esper-relay Mobile prompt composer in esper-relay Mobile session controls in esper-relay

Thread view, prompt composer, and session controls on a phone-sized screen.

✨ Why It Exists

  • Remote Codex access: resume threads, send prompts, and handle approvals from your phone.
  • Private by default: keep remote access inside your tailnet instead of opening public ports.
  • Host-side supervision: let esper-relay keep codex app-server running instead of managing it manually.
  • Mobile-first UI: use a touch-friendly web interface instead of remoting into a full desktop.
  • Better file links: referenced host files open through the relay instead of dead local filesystem URLs.

πŸ“¦ Install

crates.io

cargo install esper-relay

If you want a prebuilt archive instead, use GitHub Releases.

πŸš€ Quick Start

What You Need

  • Codex CLI installed and authenticated so codex app-server works on the host machine.
  • Tailscale installed on the host if you want remote access from your phone.
  • Tailscale installed on your phone if you want to use the tailnet URL there.
  • Rust and Cargo available for cargo install.

Local-only setup

esper-relay --daemon

Then open http://127.0.0.1:3000.

Remote setup over Tailscale

Create ~/.config/esper-relay/config.toml:

bind_addr = "127.0.0.1:3500"
ready_timeout_ms = 60000

[tailnet]
enabled = true
hostname = "esper-relay"
listener_mode = "https"
listen_addr = ":443"
advertise_tags = ["tag:esper-relay"]
oauth_client_secret = "tskey-client-REPLACE_ME"

Then start the relay:

esper-relay --daemon

This gives you:

  • local access on your configured bind_addr
  • tailnet-only https://<hostname>.<tailnet>.ts.net/ access once MagicDNS and tailnet HTTPS are enabled

Stop cleanly

esper-relay --stop

When tailnet.oauth_ephemeral = true, a clean stop logs the ephemeral node out immediately instead of waiting for delayed tailnet cleanup.

🧭 How People Use It

  1. Run esper-relay on the machine where Codex lives.
  2. Open the web UI locally or through your tailnet.
  3. Resume a thread or start a new one from your phone.
  4. Send prompts, approve actions, and keep the session moving without sitting at the host machine.

βš™οΈ Configuration

Essentials

  • ~/.config/esper-relay/config.toml is loaded automatically when it exists.
  • bind_addr controls the local web UI address.
  • app_server_cmd defaults to codex app-server.
  • tailnet.listener_mode = "https" replaces the raw tailnet listener with tailnet-only HTTPS on :443.
  • tailnet.advertise_tags is required when you use tailnet.oauth_client_secret.
  • tailnet.oauth_ephemeral defaults to true; set it to false if you want persistent OAuth-derived authkeys instead.

Environment Variables

Full environment variable reference
  • ESPER_RELAY_BIND (default: 127.0.0.1:3000)
  • ESPER_RELAY_APP_SERVER_CMD (default: codex app-server)
  • ESPER_RELAY_READY_TIMEOUT_MS (default: 8000)
  • ESPER_RELAY_RESTART_BASE_DELAY_MS (default: 500)
  • ESPER_RELAY_RESTART_MAX_DELAY_MS (default: 8000)
  • ESPER_RELAY_EVENT_BUFFER (default: 256)
  • ESPER_RELAY_TRUSTED_LAN (default: true)
  • ESPER_RELAY_TAILNET_LISTENER_MODE (default: tcp, valid values: tcp, https)
  • ESPER_RELAY_TAILNET_OAUTH_EPHEMERAL (default: true, only applies to tailnet.oauth_client_secret)

πŸ› οΈ Build Options

GitHub Releases

Stable and prerelease archives are published on GitHub Releases for:

  • x86_64-unknown-linux-gnu
  • aarch64-unknown-linux-gnu
  • x86_64-pc-windows-gnu
  • aarch64-apple-darwin

Build from source

git clone https://github.com/beisel-it/esper-relay.git
cd esper-relay
make run

πŸ”Œ Technical Reference

Core Commands

  • make run
  • make fmt
  • make fmt-check
  • make clippy
  • make test
  • make ci-local
  • make fetch-codex-sources
  • make fetch-themes

API Surface

  • POST /api/sessions
  • GET /api/themes
  • GET /api/files/content?path=/absolute/path[&line=n][&column=n]
  • GET /api/sessions/latest
  • GET /api/sessions/{session_id}
  • GET /api/sessions/{session_id}/timeline
  • GET /api/sessions/{session_id}/events (WebSocket)
  • POST /api/sessions/{session_id}/turns
  • POST /api/sessions/{session_id}/interrupt
  • POST /api/sessions/{session_id}/approvals/{approval_id}
  • POST /api/sessions/{session_id}/server-requests/{request_id}/respond
  • GET /api/threads?limit=50
  • POST /api/threads/{thread_id}/resume

Approval and tool-input prompts surface the related turn/item context from the app-server payload, and explicit Codex file-reference links are rewritten through the relay so remote users can request host files safely through GET /api/files/content.

Operational Endpoints

  • GET /health
  • GET /ready
  • GET /metrics

Repository Layout

.
β”œβ”€β”€ .github/workflows/
β”œβ”€β”€ crates/esper-relay/
β”œβ”€β”€ docs/
β”œβ”€β”€ scripts/
└── vendor/

Codex Source References

  • Canonical captures: docs/sources/codex/
  • Latest snapshot metadata: docs/sources/codex/manifest.json
  • Primary protocol reference: docs/sources/codex/snapshots/.../remote/app-server.md

πŸ” Maintainers

  • Release and publishing details: docs/releasing.md
  • release-plz manages release PRs, tagging, and crates.io publish.
  • Stable binaries are published from v* tags, and prerelease binaries are published from pushes to main.

About

Remote control service for codex app-server with a mobile-first web interface

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors