ACP Bridge
A bridge between stdio-based Agent Client Protocol (ACP) agents and mobile applications.
Transport Modes
| Mode | Use Case | Documentation |
|---|---|---|
| Local | Same Wi-Fi network, secure pairing with QR code | docs/transport/local.md |
| Cloudflare | Remote access via Cloudflare Zero Trust (internet-accessible) | docs/transport/cloudflare.md |
| Tailscale Serve | Private overlay network via MagicDNS + HTTPS | docs/transport/tailscale.md |
| Tailscale IP | Direct Tailscale IP with self-signed TLS | docs/transport/tailscale.md |
Multiple transports can run simultaneously β the bridge runs one listener per enabled transport.
Features
- π± QR Code Pairing: Secure one-time code pairing via QR scan
- π TLS + Certificate Pinning: Self-signed certificates with fingerprint validation
- β‘ WebSocket Streaming: Real-time bidirectional communication
- π Multi-Transport: Local, Cloudflare, Tailscale β all at once
- π Stable Agent Identity:
agent_idUUID persisted incommon.tomlfor multi-transport dedup on mobile - π¦ Rust Performance: Low-latency, high-throughput implementation
Quick Start
# Build
# Start with local transport (default β no config needed)
Scan the QR code with the Aptove mobile app to connect.
Configuration β common.toml
All transport settings live in common.toml. The file is created automatically with local transport enabled on first run.
Default location (depends on how you run the bridge):
| Runtime | macOS | Linux |
|---|---|---|
aptove run (embedded) |
~/Library/Application Support/Aptove/common.toml |
~/.config/Aptove/common.toml |
bridge (standalone) |
~/Library/Application Support/com.aptove.bridge/common.toml |
~/.config/bridge/common.toml |
When using aptove run, this config is shared across all workspaces.
Override with --config-dir:
Example common.toml
= "550e8400-e29b-41d4-a716-446655440000" # auto-generated UUID
= "base64urltoken" # auto-generated
[]
= true
= 8765
= true
[]
= true
= "https://agent.example.com"
= "abc123"
= "..."
= "..."
= "client.access"
= "xxxxx"
[]
= true
[]
= true
= 8765
= true
Enable only the transports you need. agent_id and auth_token are generated automatically on first run and stay stable across restarts.
Commands
start β Run the bridge
| Flag | Description | Default |
|---|---|---|
--agent-command <CMD> |
Command to spawn the ACP agent | Required |
--bind <ADDR> |
Address to bind all listeners | 0.0.0.0 |
--qr |
Display QR code(s) for pairing at startup | Off |
--verbose |
Enable info-level logging | Off (warn only) |
Transport selection, ports, TLS, and auth tokens are all read from common.toml.
show-qr β Show QR code for a second device
Displays the connection QR code for the currently active transport. The bridge must already be running. Use this to pair an additional device without restarting the bridge.
To show the QR at initial startup, pass --qr to bridge run instead:
setup β Provision Cloudflare infrastructure
Creates the Cloudflare tunnel, DNS record, Access Application, and Service Token. Saves credentials to common.toml under [transports.cloudflare]. Only needed once.
| Flag | Description | Default |
|---|---|---|
--api-token <TOKEN> |
Cloudflare API token | Required |
--account-id <ID> |
Cloudflare account ID | Required |
--domain <DOMAIN> |
Domain managed by Cloudflare | Required |
--subdomain <SUB> |
Subdomain for the bridge endpoint | agent |
--tunnel-name <NAME> |
Name for the Cloudflare tunnel | aptove-tunnel |
status β Check configuration
Prints the active common.toml path, agent_id, enabled transports, and Tailscale availability.
Architecture
βββββββββββββββ ββββββββββββββββββββββββ ββββββββββββββββ
β Mobile App βββββββββββββββββββββΊβ Bridge (per-transportβββββββββΊβ ACP Agent β
β (iOS/Androidβ WebSocket (TLS) β local / CF / TS) β stdio β (your cmd) β
βββββββββββββββ ββββββββββββββββββββββββ ββββββββββββββββ
Multiple transport listeners share the same agent process.
Troubleshooting
Connection Issues
| Symptom | Cause | Fix |
|---|---|---|
| QR code not scanning | Phone camera can't read terminal QR | Increase terminal font size, or copy the pairing URL and open manually |
| "Unauthorized" on connect | Wrong or missing auth token | Re-scan QR code |
| TLS handshake failure | Certificate mismatch | Delete the config dir and restart to regenerate certs; re-pair the device |
| App cannot reach bridge | Firewall blocking the port | Check OS firewall; ensure the port in common.toml is open |
| All transports fail to start | common.toml has no enabled = true transport |
Run bridge status to see configured transports |
Debugging
# Enable verbose logging
# Check which transports are configured
# Test agent command independently
|
Security
- Auth token: auto-generated 32-byte random value, stored in
common.toml(0600). Transmitted to mobile during QR pairing and stored in the device Keychain. - TLS: self-signed certificate generated on first run. Certificate fingerprint is included in the QR pairing payload and pinned by the mobile app to prevent MITM attacks.
- Pairing codes: 6-digit, single-use, expire after 60 seconds. Rate-limited to 5 attempts per code.
common.toml: contains all secrets. Permissions are set to0600automatically. Keep it secure.
To rotate credentials (invalidates all paired devices):
# Using aptove run (embedded bridge):
# Using standalone bridge binary:
Development
License
Apache 2.0 β see LICENSE