Forward Android devices from a remote host to your local machine via P2P network traversal. Use adb shell, scrcpy screen mirroring, and large file transfers as if the device were plugged in locally.
macOS users: If you see "damaged" or "developer cannot be verified" on first launch, run
sudo xattr -dr com.apple.quarantine /Applications/radb.app. DetailsWindows users: The standalone
.exeis UPX-compressed and may trigger antivirus false positives. Use the.zipversion instead if this happens. Details
- P2P NAT/Firewall Traversal -- no VPN or port forwarding required
- Three Connection Modes: P2P direct / LAN TCP direct / Relay Server
- Multi-device, Multi-user -- each device gets its own port, supports multiple developers
- DTLS Encryption with token-based authentication
- Single Binary Deployment -- no dependencies to install
- CLI + GUI -- one-key device selection with automatic port allocation
- Supports adb shell, scrcpy, large file transfers (100MB+ stable)
graph LR
subgraph Developer Machine
CLI[radb CLI]
Daemon[radb daemon]
end
subgraph Cloud / Intranet
Signal[radb relay server]
end
subgraph Remote Host
Agent[radb agent]
Phone1[📱 Device 1]
Phone2[📱 Device 2]
end
CLI -->|IPC| Daemon
Daemon <-->|WebRTC P2P| Agent
Daemon <-->|WebSocket Signaling| Signal
Agent <-->|WebSocket Signaling| Signal
Agent -->|ADB Protocol| Phone1
Agent -->|ADB Protocol| Phone2
See Architecture Docs for details.
| Requirement | Description |
|---|---|
| Go | >= 1.22 (build only) |
| ADB | Android Platform Tools on the Agent host |
| Network | Controller and Agent must be able to connect (via Server relay, LAN direct, or manual SDP pairing) |
| OS | Windows / Linux / macOS |
git clone https://github.com/chris1004tw/remote-adb.git
cd remote-adb
go build -trimpath -o radb ./cmd/radbOn Windows with Go 1.26+, prefer the bundled build script:
powershell -ExecutionPolicy Bypass -File .\scripts\build-windows.ps1go install github.com/chris1004tw/remote-adb/cmd/radb@latestDownload from GitHub Releases.
| Platform | Format | Description |
|---|---|---|
| macOS | .dmg (Universal Binary) |
Supports both Intel and Apple Silicon. Drag radb.app to Applications |
| Linux | .tar.gz |
Extract to get the radb binary |
| Windows | .zip |
Extract to get radb.exe (uncompressed, clean PE structure) |
| Windows | .exe |
Standalone executable (UPX-compressed, smaller size) |
Antivirus Note: The standalone
.exeis compressed with UPX to reduce file size. Some antivirus software may flag it due to heuristic detection. If this happens, use the.zipversion instead -- the binary inside is not UPX-compressed and will not trigger false positives.
Since the binary is not signed by Apple, macOS will block the first launch. You may see one of the following messages:
- "can't be opened because the developer cannot be verified" (Gatekeeper block)
- "is damaged and can't be opened. You should move it to the Trash" (quarantine attribute)
Use either method below:
Option 1: Remove quarantine attribute (recommended, also fixes the "damaged" error)
sudo xattr -dr com.apple.quarantine /Applications/radb.appOption 2: Local code signing
# Install Command Line Tools for Xcode (skip if already installed)
xcode-select --install
# Sign locally
sudo codesign --force --deep --sign - /Applications/radb.appradb offers three connection modes, all supported in both CLI and GUI:
| Mode | Use Case | Server Required |
|---|---|---|
| P2P | Cross-NAT, one-to-one quick pairing | No (uses free Cloudflare TURN by default) |
| Direct | Same LAN / VPN | No |
| Relay | Multi-user, multi-device, long-term deployment | Yes (self-hosted Relay Server) |
Establish a P2P connection via WebRTC by exchanging offer/answer tokens:
# Client: generate offer
radb p2p connect
# → Copy the offer token to the Agent, then wait for the answer token
# → Retry on invalid input (offer is one-time-use, won't be wasted by accidental Enter)
# Agent: process offer and return answer
radb p2p agent <offer-token>
# → Copy the answer token back to the Client
# Client pastes answer → P2P connection established
# → Each device gets its own port (starting from 5555), auto adb connect
# Uses Cloudflare free TURN by default, switch with --conn-mode / --turn-mode:
radb p2p connect --conn-mode direct-only # STUN only, no TURN relay
radb p2p connect --conn-mode relay-only # TURN relay only
radb p2p connect --turn-mode custom # Use custom TURN serverFor same LAN or VPN scenarios:
# Agent: start listening on LAN
radb direct agent --port 9000 --token mysecret
# Client: auto-discover Agents on LAN (mDNS)
radb direct discover
# List devices
radb direct connect 192.168.1.100:9000 --list --token mysecret
# TCP direct connection (per-device proxy ports, supports adb shell / scrcpy / forward)
radb direct connect 192.168.1.100:9000 --token mysecret
# → Each device gets its own port (starting from 5555), auto adb connectFor multi-user, multi-device team environments:
Step 1: Start the Relay Server
RADB_TOKEN=your-secret radb relay server --port 8080Step 2: Start the Agent on the remote host
RADB_TOKEN=your-secret radb relay agent --server ws://your-server:8080 --host-id lab-pc-01Step 3: Start the local Daemon
RADB_TOKEN=your-secret radb relay daemon --server ws://your-server:8080Step 4: Bind a device interactively
radb relay bind
# Select host → Select device → Auto-assigned port
# Output: Bound DEVICE_SERIAL → localhost:15555Step 5: Use it like a local device
adb -s localhost:15555 shell
scrcpy -s localhost:15555
adb -s localhost:15555 push large_file.apk /sdcard/See Configuration Guide for all options.
Run radb without arguments to open the graphical interface.
radb| Tab | Function | CLI Equivalent |
|---|---|---|
| Easy Connect | Cross-NAT manual SDP exchange (Client / Agent dual mode) | radb p2p |
| LAN Direct | Start Agent server or scan LAN for auto-discovery | radb direct |
| Relay Server | Connect via a central Relay Server | radb relay |
- Per-device Proxy Port: Each remote device gets its own port (starting from 5555), so
scrcpy/ UIAutomator can target a specific device viaadb -s 127.0.0.1:<port> - Device Model Display: Device list shows model names (e.g., "Pixel 10 Pro XL (SN123) → 127.0.0.1:5555") for easy identification
- Re-add Remote ADB Devices: One-click
adb connectbutton on the P2P client page -- no need to rebuild the P2P connection when tools like Scrcpy GUI accidentally disconnect ADB - Refresh Remote Devices: Request the agent to rescan ADB devices without rebuilding the connection
- Quick Offer: "Generate offer now" button for faster ICE gathering (may lack some candidates)
- Offer Pre-generation: Automatically pre-generates offer in the background when entering client mode, ready instantly on click
- Connection Progress: Multi-stage progress display (Preparing TURN → Creating components → Gathering candidates → Encoding)
- Bilingual UI: Traditional Chinese / English, auto-detected from system locale, switchable instantly (no restart)
- Auto Update: Checks for new versions on startup, shows notification banner
Click the gear icon (bottom-right) to manage:
- ADB Port, Proxy Port, Direct Port
- Connection mode (Direct-first / Direct-only / Relay-only)
- NAT discovery server (STUN)
- Relay server mode (Cloudflare free / custom URL + credentials)
- Language switch, manual update check
TURN defaults to free Cloudflare credentials (auto-fetched, works out of the box). Settings are persisted in TOML at radb.toml in the same directory as the executable.
| Environment Variable | Default | Description |
|---|---|---|
RADB_TOKEN |
(required) | PSK authentication token |
RADB_SERVER_URL |
ws://localhost:8080 |
Server URL |
RADB_STUN_URLS |
stun:stun.l.google.com:19302 |
STUN Server |
RADB_CONN_MODE |
direct-first |
Connection mode (direct-first / direct-only / relay-only) |
RADB_TURN_MODE |
cloudflare |
TURN mode (cloudflare / custom) |
RADB_TURN_URL |
(empty) | Custom TURN Server URL (used with --turn-mode custom) |
RADB_DIRECT_PORT |
(empty) | Agent Direct TCP listen port |
RADB_DIRECT_TOKEN |
(empty) | Direct connection token |
RADB_PORT_START |
5555 |
Client starting port |
See Configuration Guide for the full reference.
remote-adb/
├── cmd/
│ └── radb/ # Unified entry point (p2p/direct/relay modules + update/version + GUI + auto-relocation/migration)
├── internal/
│ ├── adb/ # ADB protocol, device management, auto-download platform-tools (exe-relative)
│ ├── agent/ # Remote agent core logic
│ ├── buildinfo/ # Build-time version info (Version/Commit/Date) + hostname cache
│ ├── cli/ # bubbletea interactive bind menu
│ ├── daemon/ # Background service, port allocation, binding table, IPC
│ ├── bridge/ # Shared GUI/CLI logic (SDP codec, ADB transport, forward management)
│ ├── directsrv/ # TCP direct connection service + mDNS broadcast + client connection
│ ├── gui/ # Gio GUI (Easy Connect/LAN Direct/Relay tabs + settings + i18n + Cloudflare TURN + TURN prefetch cache)
│ ├── ioutil/ # Shared I/O utilities (ChunkedCopy: chunked copy + short write protection + sync.Pool buffer reuse, BiCopy: bidirectional copy + dual Close + ctx cancel)
│ ├── proxy/ # TCP proxy (16KB chunking, single-connection replacement)
│ ├── signal/ # WebSocket signaling hub, PSK auth, shared ConnectAndAuth
│ ├── updater/ # Auto-update (GitHub Releases download + cross-platform binary replacement)
│ └── webrtc/ # PeerConnection and DataChannel management (detach mode + relay detection + Cloudflare TURN)
├── pkg/protocol/ # Shared signaling JSON format (Envelope + Payload types)
├── assets/ # Cross-platform resources (app SVG icon)
├── macos/ # macOS .app bundle metadata (Info.plist)
├── configs/ # Configuration examples
├── docs/ # Design documents
├── scripts/ # Platform helper scripts (build-dmg.sh, build-windows.ps1: Windows local build)
├── test/e2e/ # End-to-end integration tests
├── go.mod
└── README.md
# Build
go build -trimpath -o radb ./cmd/radb
# Test
go test ./...
# Lint
golangci-lint runFor local Windows builds on Go 1.26+, use scripts/build-windows.ps1 so GOEXPERIMENT=nogreenteagc is applied automatically.
See Development Guide for details.
| Document | Description |
|---|---|
| Architecture | System architecture, signaling protocol, tech stack |
| Agent Design | Remote agent device management and forwarding |
| Client Design | Local daemon, CLI, TCP proxy design |
| Configuration | Full environment variable and CLI flag reference |
| Development | Build, test, code conventions |
| coturn Setup | TURN Server installation, configuration, and integration |
Q: Can't connect to the remote device? A: Check that the Server is reachable, tokens match, and firewalls aren't blocking WebRTC traffic. If behind symmetric NAT, configure a TURN Server (GUI defaults to Cloudflare free TURN, usually no extra setup needed).
Q: Device shows as offline?
A: Ensure the ADB server is running on the remote host (adb start-server) and the device has authorized USB debugging.
Q: Port already in use?
A: Use --port-start to specify a different starting port, or run radb relay list to see occupied ports.
Q: Large file transfer interrupted? A: If using TURN relay, check the TURN server's bandwidth limits. Use STUN direct connection (P2P) when possible.
MIT License -- see LICENSE