You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Toss is a cross-platform application that synchronizes clipboard content between devices with end-to-end encryption. It prioritizes privacy, security, and seamless user experience.
Establish: X25519 key exchange, derive session key via HKDF
Store: Save device with encrypted session key
7.3 mDNS Pairing Properties
code: Pairing code
pk: Base64 public key (43 chars)
name: Device name
8. Platform-Specific Implementation
Platform
Clipboard
Permissions
Notes
macOS
NSPasteboard via arboard
Accessibility
AXIsProcessTrusted() check
Windows
Win32 API
None
CF_UNICODETEXT, CF_HDROP, CF_DIB formats
Linux
X11/Wayland via arboard
None
Dual protocol support
iOS
UIPasteboard (Flutter)
Local Network
Limited background access, iOS 14+ restrictions
Android
ClipboardManager (Flutter)
None
Android 10+ restrictions, Keystore for storage
8.1 Windows Clipboard Formats
CF_UNICODETEXT: Unicode text
CF_HDROP: File list (drag & drop)
CF_DIB: Device-independent bitmap
8.2 iOS Background Service Implementation
iOS has significant restrictions on background clipboard access starting with iOS 14. The following strategies are implemented to provide the best possible user experience:
8.2.1 iOS Clipboard Restrictions
iOS Version
Restriction
iOS 14+
Clipboard read shows user notification ("App pasted from...")
iOS 14+
Background clipboard reading is blocked
iOS 16+
App must be in foreground to read clipboard
8.2.2 Background Sync Strategies
Foreground Sync: Clipboard sync triggers automatically when app returns to foreground
Siri Shortcuts Integration: Users can create shortcuts for quick sync:
"Sync Clipboard" - Sends current clipboard to paired devices
"Send Clipboard" - Same as sync
"Get Latest Clipboard" - Receives clipboard from devices
Background Fetch: Limited background processing for receiving (not reading) clipboard
App Extensions: Share extension for sending content without opening main app
Widgets: WidgetKit widget for quick status view and sync trigger
8.2.3 Implementation Details
iOS Background Service Flow:
┌─────────────────────────────────────────────────────────┐
│ App in Foreground │
│ ├── Full clipboard access │
│ ├── Monitor clipboard changes (250ms polling) │
│ └── Auto-sync on change (rate limited) │
├─────────────────────────────────────────────────────────┤
│ App Becomes Active (from background) │
│ ├── syncOnForeground() called │
│ ├── Check for local clipboard changes │
│ └── Receive pending content from network │
├─────────────────────────────────────────────────────────┤
│ App Goes to Background │
│ ├── Update widget with current status │
│ ├── Schedule background refresh task │
│ └── Cannot read clipboard (iOS restriction) │
├─────────────────────────────────────────────────────────┤
│ Background Fetch Triggered │
│ ├── Receive content from paired devices │
│ ├── Update widget │
│ └── Cannot access local clipboard │
├─────────────────────────────────────────────────────────┤
│ Siri Shortcut Invoked │
│ ├── handleShortcutAction() processes request │
│ ├── Can read clipboard (user interaction) │
│ └── Sync content to/from devices │
└─────────────────────────────────────────────────────────┘
8.2.4 User Recommendations for iOS
Enable Background App Refresh in iOS Settings for best sync experience
Use Siri Shortcuts for quick clipboard sync without opening the app
Add Home Screen Widget for at-a-glance status and quick sync
Note: iOS will show a notification when the app reads the clipboard (this is expected)
9. Performance Requirements
Metric
Target
Text sync latency (local)
< 100ms
Text sync latency (relay)
< 500ms
Image sync (1MB, local)
< 1s
Memory usage (idle)
< 50MB
Battery impact (mobile)
< 2%/day
Max clipboard size
50 MB
Max preview size
256 KB
10. Protocol Flows
10.1 Clipboard Sync
A: Clipboard change detected
A: Create ClipboardUpdate (content + SHA-256 hash)
A: Encrypt with session key (AES-256-GCM, header as AAD)
A: Send via QUIC/relay
B: Decrypt and verify hash
B: Send ClipboardAck
B: Update local clipboard
10.2 Key Rotation
Trigger: 1000 messages OR 24 hours
A: Generate new ephemeral X25519 keypair
A: Sign new public key with Ed25519 identity key
A: Send KeyRotation message
B: Verify signature with A's identity key
B: Derive new session key via HKDF
Both: Reset message counters
10.3 Device Pairing
A: Generate pairing code
A: Advertise on mDNS + register on relay (300s expiry)
B: Enter code, search mDNS (3s timeout)
B: Fallback to relay if not found
B: Initiate QUIC connection
Both: Exchange DeviceInfo messages
Both: X25519 key exchange
Both: Derive session key via HKDF
Both: Store paired device
11. CI/CD Pipeline
11.1 Quality Gates (Required Before Commit)
cargo fmt --check - Code formatting
cargo clippy -- -D warnings - Linting
cargo test - All tests passing (100%)
cargo audit - No security vulnerabilities
flutter analyze - Static analysis
flutter test - Widget and unit tests
11.2 Commands
make ci # Run all CI checks
make test# Run all tests
make build # Build everything
11.3 Release Artifacts
Platform
Artifacts
Windows
.zip (portable), .msi installer
macOS
.dmg (Universal)
Linux
.AppImage, .deb, .tar.gz
iOS
.ipa (TestFlight)
Android
.apk, .aab
12. Chunked Transfer Protocol
12.1 Overview
Large clipboard content (> 1 MB by default) uses a chunked transfer protocol for efficient streaming. This provides:
Memory-efficient transfers (content is not loaded entirely into memory)
Progress tracking for large transfers
Resume capability for interrupted transfers
Configurable chunk sizes
12.2 Configuration
Parameter
Default
Min
Max
Description
streaming_chunk_size
1 MB
64 KB
4 MB
Size of each chunk
chunked_threshold
1 MB
-
-
Content size threshold for chunked transfer
streaming_enabled
true
-
-
Enable/disable chunked transfers
12.3 Message Types
Type
Code
Description
ChunkedTransferInit
0x13
Initiate chunked transfer with metadata
ChunkedTransferData
0x14
Individual chunk with sequence number
ChunkedTransferAck
0x15
Acknowledge receipt of chunk
ChunkedTransferComplete
0x16
Signal transfer completion/cancellation
12.4 Message Structures
structChunkedTransferInit{transfer_id:u64,// Unique transfer identifiertotal_chunks:u32,// Total number of chunkstotal_size:u64,// Total size in byteschunk_size:u32,// Chunk size in bytescontent_type:ContentType,// Clipboard content typemetadata:ContentMetadata,// Preview, dimensions, etc.content_hash:[u8;32],// SHA-256 of full content}structChunkedTransferData{transfer_id:u64,// Transfer identifierchunk_index:u32,// Chunk sequence number (0-indexed)data:Vec<u8>,// Chunk datachunk_hash:[u8;32],// SHA-256 of this chunk}structChunkedTransferAck{transfer_id:u64,// Transfer identifierchunk_index:u32,// Acknowledged chunk indexsuccess:bool,// Whether chunk was received successfullyerror:Option<String>,// Error message if failed}structChunkedTransferComplete{transfer_id:u64,// Transfer identifierstate:TransferState,// Completed, Failed, or Cancellederror:Option<String>,// Error message if failed}enumTransferState{Initiated,InProgress,Completed,Failed,Cancelled,}
Chunk Hash Mismatch: Receiver requests retransmission via ChunkedTransferAck
Transfer Timeout: Transfers expire after 300 seconds (5 minutes)
Missing Chunks: Receiver can request specific chunks via ChunkedTransferAck
Cancellation: Either party can send ChunkedTransferComplete with state=Cancelled
12.7 Limits
Limit
Value
Max concurrent transfers
4 per connection
Transfer timeout
300 seconds
Max transfer ID
u64::MAX
13. Team/Organization Support
13.1 Overview
Teams allow groups of devices to share clipboards collaboratively. Teams support role-based access control, invitation-based onboarding, and full audit logging.
The relay server admin dashboard provides team management:
View all teams with member counts
Team details with members, invitations, and audit logs
Delete teams and remove members
All POST actions protected by CSRF tokens
14. Compression
14.1 Overview
Clipboard content is compressed before encryption to reduce transfer sizes. Uses zstd compression with configurable thresholds.
14.2 Configuration
Parameter
Default
Description
compression_enabled
true
Enable/disable compression
compression_threshold
1 KB
Minimum size to compress
compression_level
3
zstd compression level (1-22)
14.3 Behavior
Content below the threshold is sent uncompressed
Incompressible data (already compressed images, encrypted data) is detected and sent raw
A compression flag in the frame header indicates whether the payload is compressed
Decompression is transparent to the receiver
15. Browser Extension
15.1 Overview
Browser extension for Chrome/Firefox that integrates with the Toss relay server for clipboard sync directly from the browser.
15.2 Features
Copy text from browser to all paired devices
Receive clipboard content from devices into browser
Secure communication via relay server WebSocket
Works across Chrome and Firefox
16. Future Considerations
Selective sync (choose devices)
Conflict resolution
Browser extension dependency validation
Browser extension pull requests run ESLint, generate icons with Sharp, and build
both Chrome and Firefox packages. These checks cover the extension independently
of the Rust and Flutter application workflows.
Documentation dependency validation
Documentation pull requests build the Astro site before merge. Astro 7 uses an
explicit Starlight content loader and the astro-mermaid integration; the older
client Mermaid plugin is incompatible with its configuration API.
Flutter bridge version alignment
The Dart dependency, Rust workspace dependency, Rust lockfile, generated Rust
bindings and code-generator commands use flutter_rust_bridge 2.13.0 together.
The Bridge Version Check rejects inconsistent pins before the platform builds.