Cross-device file sharing and clipboard synchronization for Linux and Android. Think AirDrop, but for Linux.
- Auto-Discovery — mDNS zero-configuration device discovery on your local network
- File Transfer — Unlimited size, chunked transmission with resume support and BLAKE3 integrity verification
- Clipboard Sync — Real-time clipboard mirroring (text, images, rich text, file references) with echo prevention
- Secure by Default — SPAKE2 PIN-based pairing, Ed25519 device identities, TLS 1.3 transport encryption
- LAN Only — All traffic stays on your local network, no cloud or internet required
┌─────────────────────────────────────────────┐
│ syncs-core (Rust) │
│ discovery · pairing · transfer · clipboard │
│ protocol · crypto · config · store │
├──────────────────┬──────────────────────────┤
│ Linux │ Android │
│ syncs-daemon │ syncs-android (JNI) │
│ syncs-cli │ Kotlin + Jetpack Compose│
│ syncs-tray │ │
└──────────────────┴──────────────────────────┘
All core logic lives in syncs-core. Platform frontends are thin wrappers:
| Crate | Description |
|---|---|
syncs-core |
Shared library — discovery, pairing, transfer, clipboard, crypto, protocol |
syncs-daemon |
Linux background service — mDNS, connections, clipboard monitoring |
syncs-cli |
Linux CLI — devices, pair, send, clipboard, config commands |
syncs-tray |
Optional Linux system tray icon (via ksni/D-Bus) |
syncs-android |
JNI bridge exposing syncs-core to the Android app |
- Rust 1.75+ (2021 edition)
- Linux: D-Bus (for tray), SQLite
- Android: NDK 27+, JDK 21, Gradle
# Build everything
cargo build --release
# Start the daemon
cargo run --bin syncs-daemon
# Discover devices
cargo run --bin syncs-cli -- devices
# Pair with a device (shows a 6-digit PIN)
cargo run --bin syncs-cli -- pair <device-id>
# Send a file
cargo run --bin syncs-cli -- send <device-id> path/to/file
# Watch clipboard sync
cargo run --bin syncs-cli -- clipboard watch# Install Rust Android targets
rustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android
# Build the APK
cd android
./gradlew assembleDebug- Discovery — Devices broadcast
_syncs._tcp.local.via mDNS on the LAN - Pairing — SPAKE2 password-authenticated key exchange with a 6-digit PIN displayed on both devices
- Connection — TLS 1.3 with self-signed certificates tied to Ed25519 device identities
- Transfer — Files are split into 1MB chunks, each verified with BLAKE3 hashes, resumable on disconnect
- Clipboard — Polled at 200ms intervals, synced over the encrypted channel with timestamp-based echo prevention
Stored at ~/.config/syncs/config.toml:
[general]
device_name = "my-laptop"
receive_dir = "~/Syncs"
auto_accept = false
[clipboard]
enabled = true
sync_images = true
[transfer]
chunk_size = 1048576
max_concurrent = 3Communication uses length-prefixed protobuf messages (see proto/syncs.proto):
- Pairing:
PairRequest→PairResponse→PairConfirm - Transfer:
TransferRequest→TransferAccept→TransferChunk* →TransferComplete - Clipboard:
ClipboardUpdate→ClipboardAck - Status:
Ping/Pong,DeviceInfo
| Layer | Mechanism |
|---|---|
| Identity | Ed25519 keypair per device, persisted locally |
| Pairing | SPAKE2 with 6-digit PIN — no trust-on-first-use |
| Transport | TLS 1.3 (rustls), mutual authentication |
| Integrity | BLAKE3 hashes on every file chunk |
MIT