Control Claude Code from your phone — E2E encrypted, self-hosted, open source
Termopus is an open-source mobile remote for Claude Code. Approve file edits, review diffs, and chat with Claude — all from your phone. Everything is end-to-end encrypted, self-hosted on your own Cloudflare account, and secured with mutual TLS.
Claude Code stops and waits every time it needs permission to edit a file or run a command. If you step away from your desk, work stops too. Termopus lets you approve, deny, or respond from your phone — so Claude keeps working while you're on the couch, in a meeting, or grabbing coffee.
You can also resume any Claude Code session across all your projects, start new ones, and even preview what Claude builds through localhost — all from your phone.
- Chat interface — WhatsApp-style conversation showing Claude's output in real time
- One-tap approvals — Allow / Deny / Edit buttons for file changes
- Code diffs — Syntax-highlighted previews of proposed edits
- Push notifications — Get notified when Claude is waiting (optional, requires Firebase)
- Multi-session — Control multiple Claude Code instances from one phone
- E2E encrypted — AES-256-GCM encryption with hardware-backed keys
- Self-hosted — Runs entirely on your own Cloudflare account
COMPUTER CLOUDFLARE PHONE
──────── ────────── ─────
Claude Code Flutter App
↓ ↓
Bridge (Rust) ←── WebSocket ──→ Relay DO ←── WebSocket ──→ Native WS
↓ (opaque) ↓
Encrypt(msg) Decrypt(msg)
The bridge runs alongside Claude Code on your computer. It connects to a Cloudflare Durable Object relay via WebSocket. Your phone connects to the same relay. All messages are end-to-end encrypted — the relay only forwards opaque blobs.
| Component | Tech | Description |
|---|---|---|
| Phone App | Flutter (iOS / Android) | Chat UI, biometric auth, hardware-backed keys |
| Bridge | Rust (macOS / Linux / Windows) | Runs alongside Claude Code, encrypts all traffic |
| Relay | Cloudflare Durable Objects | Stateful WebSocket relay, opaque message forwarding |
| Provisioning API | Cloudflare Workers | Device certificate issuance, challenge-response auth |
Termopus uses your own Cloudflare account to host the relay and provisioning API. This keeps your data under your control — no third-party servers. You'll need a free Cloudflare account before starting.
| Tool | Version | Install |
|---|---|---|
| Cloudflare account | Free tier | Sign up |
| Claude Code | Latest | Install |
| Node.js | 18+ | nodejs.org |
| Flutter | 3.11+ | flutter.dev |
| Rust | Latest stable | rustup.rs (only if building from source) |
| wrangler | Latest | npm install -g wrangler |
| OpenSSL | Any | Pre-installed on macOS/Linux |
git clone https://github.com/Termopus/termopus.git
cd termopus
wrangler login # opens browser to authenticate with your Cloudflare accountmacOS / Linux:
./scripts/setup.shWindows (PowerShell):
.\scripts\setup.ps1The setup script will:
- Create KV namespaces (
FCM_TOKENS,PROVISIONED_DEVICES,SUBSCRIPTIONS) - Update worker configs with namespace IDs
- Install dependencies and deploy both Cloudflare Workers
- Generate a CA certificate for mTLS device authentication
- Set CA secrets on both workers
- Print your relay and provisioning API URLs
# Connect your phone via USB, then:
cd app
flutter pub get
flutter runOption A: Pre-built binary
Download the latest release for your platform from the Releases page:
| Platform | Download |
|---|---|
| macOS (Apple Silicon) | Termopus-vX.Y.Z-macos-arm64.dmg |
| Windows (x86_64) | Termopus-vX.Y.Z-windows-x86_64.msi |
| Linux (x86_64) | Termopus-vX.Y.Z-linux-x86_64.tar.gz |
For macOS, open the DMG and drag Termopus to Applications. For Windows, run the MSI installer and launch from the Start Menu. On first launch, you'll be prompted to enter your relay WebSocket URL (the wss:// URL printed by setup.sh). The URL is saved automatically for future launches.
For Linux, extract and run:
tar -xzf Termopus-*.tar.gz
./Termopus-*/termopus --relay wss://YOUR_RELAY_WORKER_URLOption B: Build from source
cd bridge
cargo build --release
./target/release/termopus --relay wss://YOUR_RELAY_WORKER_URLReplace
YOUR_RELAY_WORKER_URLwith the URL printed by setup.sh
Scan the QR code displayed by the bridge with the Termopus app on your phone. That's it.
After running setup.sh, most configuration is automatic. If you need to configure manually:
| Placeholder | File | Description |
|---|---|---|
YOUR_FCM_TOKENS_KV_ID |
*/wrangler.toml |
KV namespace ID for FCM tokens |
YOUR_PROVISIONED_DEVICES_KV_ID |
*/wrangler.toml |
KV namespace ID for device certificates |
YOUR_SUBSCRIPTIONS_KV_ID |
*/wrangler.toml |
KV namespace ID for subscriptions |
YOUR_PROVISIONING_API_URL |
app/lib/shared/constants.dart |
Deployed provisioning worker URL |
YOUR_RELAY_URL |
bridge/src/main.rs |
Deployed relay worker URL (wss://) |
| Placeholder | File | Description |
|---|---|---|
YOUR_RELAY_DOMAIN |
relay_worker/wrangler.toml |
Custom domain for relay |
YOUR_API_DOMAIN |
provisioning_api/wrangler.toml |
Custom domain for API |
The app ships with a placeholder google-services.json that allows building without Firebase. To enable push notifications:
- Create a Firebase project at console.firebase.google.com
- Replace
app/android/app/google-services.jsonwith your config - For iOS: add
GoogleService-Info.plisttoapp/ios/Runner/ - Set FCM secrets on the relay worker:
cd relay_worker wrangler secret put FCM_PROJECT_ID --env dev wrangler secret put FCM_SERVICE_ACCOUNT_EMAIL --env dev wrangler secret put FCM_SERVICE_ACCOUNT_KEY --env dev
Termopus uses a 7-layer security model. Every connection is end-to-end encrypted and authenticated with mutual TLS.
| Layer | Protection | Always On | Description |
|---|---|---|---|
| 1 | Hardware-backed keys | Yes | Secure Enclave (iOS) / StrongBox (Android) |
| 2 | Session binding | Yes | Sessions locked to hardware device ID |
| 3 | E2E encryption | Yes | AES-256-GCM with ephemeral ECDH key exchange |
| 4 | Cloudflare Tunnel | Optional | Zero-trust network access, no open ports |
| 5 | mTLS certificates | Yes | Mutual TLS client certificate authentication |
| 6 | Device attestation | Optional | App Attest (iOS) / Play Integrity (Android) |
| 7 | Biometric gate | Yes | Face ID / Fingerprint required to open the app |
See docs/MTLS.md for details on the mTLS implementation.
termopus/
├── app/ # Flutter mobile app (iOS / Android)
│ ├── lib/ # Dart source code
│ ├── android/ # Android-specific (Kotlin bridge, signing)
│ └── ios/ # iOS-specific (Swift bridge, entitlements)
├── bridge/ # Rust desktop bridge agent
│ └── src/ # Relay connection, encryption, QR pairing
├── relay_worker/ # Cloudflare Worker — WebSocket relay
│ └── src/ # Durable Object, auth, push notifications
├── provisioning_api/ # Cloudflare Worker — device provisioning
│ └── src/ # CSR signing, challenge-response, KV storage
├── scripts/
│ ├── setup.sh # One-command setup (includes mTLS)
│ └── setup-mtls.sh # Standalone mTLS re-setup
├── assets/ # Logo, icons, screenshots
└── docs/ # Documentation
- App store releases — iOS and Android app store listings
Contributions are welcome! Here's how to get started:
- Open an issue to discuss your idea or report a bug
- Fork the repo and create a feature branch
- Submit a pull request with a clear description of changes
Please make sure your code follows the existing patterns in the codebase.
This project is licensed under the AGPL-3.0 License.
Built with Flutter, Rust, and Cloudflare Workers




