{"id":49557934,"url":"https://github.com/kai3316/clipsync","last_synced_at":"2026-05-03T06:14:41.552Z","repository":{"id":354895216,"uuid":"1225819442","full_name":"kai3316/clipsync","owner":"kai3316","description":"Instant cross-device clipboard sync over LAN. Copy on one device, paste on another. TLS 1.3 + AES-256-GCM encryption, mDNS auto-discovery, zero configuration. Supports text, HTML, images, RTF, and file transfer. Windows / macOS / Linux.","archived":false,"fork":false,"pushed_at":"2026-05-03T05:06:43.000Z","size":578,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-05-03T05:28:19.218Z","etag":null,"topics":["aes-256-gcm","clipboard","clipboard-sync","clipsync","cross-platform","ed25519","encrypted","file-transfer","lan","linux","macos","mdns","python","realtime","secure","sync","tls","windows","zeroconf"],"latest_commit_sha":null,"homepage":"https://kai3316.github.io/clipsync/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kai3316.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-30T17:13:20.000Z","updated_at":"2026-05-03T05:06:46.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/kai3316/clipsync","commit_stats":null,"previous_names":["kai3316/copyboard","kai3316/clipsync"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/kai3316/clipsync","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kai3316%2Fclipsync","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kai3316%2Fclipsync/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kai3316%2Fclipsync/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kai3316%2Fclipsync/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kai3316","download_url":"https://codeload.github.com/kai3316/clipsync/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kai3316%2Fclipsync/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32559757,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T03:21:47.309Z","status":"ssl_error","status_checked_at":"2026-05-03T03:21:43.884Z","response_time":103,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aes-256-gcm","clipboard","clipboard-sync","clipsync","cross-platform","ed25519","encrypted","file-transfer","lan","linux","macos","mdns","python","realtime","secure","sync","tls","windows","zeroconf"],"created_at":"2026-05-03T06:14:40.965Z","updated_at":"2026-05-03T06:14:41.543Z","avatar_url":"https://github.com/kai3316.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"README.md\"\u003eEnglish\u003c/a\u003e \u0026nbsp;|\u0026nbsp;\n  \u003ca href=\"README_zh.md\"\u003e中文\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/kai3316/clipsync/master/assets/icon.svg\" alt=\"ClipSync\" width=\"96\" height=\"96\"\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eClipSync\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eCopy on one device. Paste on another. Instantly.\u003c/strong\u003e\n  \u003cbr\u003e\n  Cross-platform \u0026middot; LAN \u0026middot; TLS 1.3 + AES-256-GCM \u0026middot; Zero config\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/kai3316/clipsync/releases\"\u003e\u003cimg src=\"https://img.shields.io/github/v/release/kai3316/clipsync?color=3498DB\" alt=\"Release\"\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-MIT-green\" alt=\"License\"\u003e\u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/badge/python-3.12+-blue\" alt=\"Python\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/platform-Windows%20%7C%20macOS%20%7C%20Linux-lightgrey\" alt=\"Platforms\"\u003e\n\u003c/p\u003e\n\n---\n\n## Quick Start\n\n1. [Download](https://github.com/kai3316/clipsync/releases/latest) the app for your platform\n2. Run it — no install needed\n3. Run it on another device on the **same network**\n4. Confirm the 8-digit pairing code on both devices\n5. Copy on one, paste on the other!\n\n\u003e **macOS users:** If Gatekeeper blocks the app, run `xattr -cr clipsync.app` then right-click → Open.\n\n---\n\n## Contents\n\n- [Overview](#overview)\n- [Why ClipSync?](#why-clipsync)\n- [Features](#features)\n- [Download](#download)\n- [Install from Source](#install-from-source)\n- [Build from Source](#build-from-source)\n- [How It Works](#how-it-works)\n- [Configuration](#configuration)\n- [Troubleshooting](#troubleshooting)\n- [Project Structure](#project-structure)\n- [Contributing](#contributing)\n- [License](#license)\n\n---\n\n## Overview\n\nClipSync syncs your clipboard across devices on the same local network. Copy text, images, HTML, or rich text on your Windows PC — paste it seconds later on your MacBook. No cloud, no accounts, no setup.\n\n### Why ClipSync?\n\n- **No cloud dependency** — all data stays on your LAN; nothing ever leaves your network\n- **Instant** — sub-second sync after paste detection, with smart debouncing to prevent echo\n- **Full fidelity** — preserves text encoding, HTML structure, RTF formatting, and image data byte-for-byte\n- **Secure by default** — dual-layer encryption: TLS 1.3 transport + AES-256-GCM per frame, at-rest encryption for stored data\n- **Zero config** — devices discover each other automatically via mDNS; pair once, trusted forever\n\n---\n\n## Comparison\n\nMost clipboard sync tools fall into two camps: **cloud-based services** (convenient but your data leaves your network) and **OS built-in solutions** (limited to one ecosystem, plain text only). ClipSync takes a third path.\n\n| Capability | ClipSync | Cloud Clipboard Tools | OS Built-in (Universal Clipboard, etc.) |\n|---|---|---|---|\n| **Plain Text** | ✅ UTF-8, full Unicode | ✅ | ✅ |\n| **Rich Text / HTML** | ✅ Links, tables, formatting preserved | ❌ Plain text only | ❌ Plain text only |\n| **Images (PNG)** | ✅ Full resolution, any size | ❌ Not supported | ❌ Not supported |\n| **File Transfer** | ✅ Encrypted, any file type | ❌ Not supported | ❌ |\n| **Data Location** | ✅ Pure LAN — never leaves | ❌ Uploaded to cloud servers | ✅ Local only |\n| **Account Required** | ✅ None — just run it | ❌ Account + sign-in | Varies |\n| **Cross-Platform** | ✅ Windows / macOS / Linux | Varies by tool | ❌ Single ecosystem |\n| **Encryption** | ✅ TLS 1.3 + AES-256-GCM | ⚠️ TLS only (if at all) | ❌ None or basic |\n| **Zero Config** | ✅ mDNS auto-discovery | ❌ Manual setup | ✅ |\n| **Open Source** | ✅ MIT License | ❌ Proprietary | ❌ |\n| **Price** | ✅ Free forever | ❌ Freemium / Paid | ✅ Free |\n\n**Bottom line:** If you only copy plain text within one ecosystem, built-in tools work fine. If you need rich text, images, files, cross-platform sync, and privacy — ClipSync is purpose-built for that.\n\n---\n\n## Features\n\n### Clipboard Sync\n| Format | Type | Notes |\n|---|---|---|\n| Plain Text | `TEXT` | UTF-8, full Unicode support |\n| Rich Text | `HTML` | Preserves links, tables, formatting |\n| Rich Text | `RTF` | Microsoft Office compatible |\n| Images | `IMAGE_PNG` | PNG format, any resolution |\n\n### Device Management\n- **Auto-discovery** — mDNS/Zeroconf finds peers on the LAN without any IP configuration\n- **Trust-on-first-use (TOFU)** — each device has a unique Ed25519 identity; pinned on first pairing\n- **Certificate pinning** — if a device's certificate changes, you're alerted immediately\n- **Pairing codes** — 8-digit verification codes prevent MITM attacks during initial handshake\n\n### Security Architecture\n\n| Layer | Technology | Detail |\n|---|---|---|\n| **Application** | AES-256-GCM per frame | Per-peer encryption keys derived via HKDF from Ed25519 certificates; optional pre-shared password for extra entropy (PBKDF2, 600K iterations) |\n| **Transport** | TLS 1.3 | Self-signed Ed25519 X.509 certificates with certificate pinning (TOFU); MITM detection on identity change |\n| **At-Rest** | AES-256-GCM on disk | Private keys, clipboard history, and sensitive config fields encrypted at rest; password stored as PBKDF2 verification token (never persisted) |\n\n- **Dual-layer encryption** — TLS 1.3 secures the transport; AES-256-GCM encrypts each frame at the application layer. Different keys per peer-pair, automatically derived\n- **Storage encryption** — private keys, clipboard history, and sensitive config fields are AES-256-GCM encrypted at rest\n- **Optional pre-shared password** — add an out-of-band password for additional entropy; verified via PBKDF2 hash on startup\n\n### Additional Features\n- **File transfer** — send files between paired devices over the encrypted channel\n- **Content filtering** — optional regex-based filters for credit cards, SSNs, API keys, passwords\n- **System tray** — runs quietly in the background; right-click for settings\n- **Notifications** — optional desktop notifications on connect, disconnect, and sync events\n- **Dark mode** — follows system theme or manual toggle\n- **Auto-start** — optionally launch on login\n\n---\n\n## Download\n\nGet the latest release from the [Releases page](https://github.com/kai3316/clipsync/releases):\n\n| Platform | File | Notes |\n|---|---|---|\n| Windows 10/11 | `clipsync.exe` | Portable — no install needed |\n| macOS 12+ | `clipsync.app` (zip) | Universal binary (Apple Silicon + Intel) |\n| Linux (X11/Wayland) | `clipsync` (tar.gz) | Requires `xclip` or `wl-clipboard` |\n\nNo Python installation required. Download, run, done.\n\n\u003e **macOS users:** The app is not notarized. If Gatekeeper blocks it:\n\u003e ```bash\n\u003e xattr -cr clipsync.app\n\u003e ```\n\u003e Then right-click the app and select **Open**. If issues persist, run the binary directly for diagnostics:\n\u003e ```bash\n\u003e ./clipsync.app/Contents/MacOS/clipsync\n\u003e ```\n\n---\n\n## Install from Source\n\nRequires **Python 3.12+**.\n\n```bash\n# Clone the repository\ngit clone https://github.com/kai3316/clipsync.git\ncd clipsync\n\n# Create and activate a virtual environment\npython -m venv .venv\nsource .venv/bin/activate      # macOS / Linux\n# .venv\\Scripts\\activate       # Windows\n\n# Install dependencies\npip install -r requirements.txt\n\n# Run\npython src/main.py\n```\n\n**Linux prerequisites:**\n```bash\n# Debian/Ubuntu\nsudo apt install xclip\n# Fedora\nsudo dnf install xclip\n# Arch\nsudo pacman -S xclip\n# Wayland users: install wl-clipboard instead\n```\n\n---\n\n## Build from Source\n\nBuild a standalone executable with PyInstaller:\n\n```bash\npip install pyinstaller\npyinstaller clipsync.spec\n```\n\nOutput in `dist/`:\n- Windows: `dist/clipsync.exe`\n- macOS: `dist/clipsync.app`\n- Linux: `dist/clipsync`\n\nThe `.spec` file auto-collects all internal modules and required dependencies (`zeroconf`, `cryptography`, `PIL`, `pystray`, `customtkinter`).\n\n---\n\n## How It Works\n\n```\nDevice A                              Device B\n   │                                     │\n   ├─ 1. mDNS broadcast ────────────────►│  \"I'm here: clipsync._tcp.local\"\n   │                                     │\n   ├─ 2. TCP connection ◄───────────────►│  TLS 1.3 handshake\n   │                                     │\n   ├─ 3. Identity exchange ─────────────►│  Ed25519 cert fingerprints\n   │                                     │\n   ├─ 4. Pairing (first time) ◄─────────►│  8-digit code confirmation\n   │     Certificate pinned              │  Certificate pinned\n   │                                     │\n   ├─ 5. Clipboard change detected──────►│  Hash → dedup → encrypt → send\n   │     AES-256-GCM encrypted frame     │  Decrypt → write to clipboard\n   │                                     │\n   ├─ 6. Trusted on reconnect ──────────►│  Pinned cert verified, auto-connect\n```\n\n1. **Discovery** — mDNS/Zeroconf broadcasts device presence on the LAN. The service type `_clipsync._tcp.local` enables automatic peer detection without IP configuration.\n\n2. **Connection** — TCP connection established, TLS 1.3 handshake with self-signed Ed25519 certificates. Certificate fingerprints are exchanged at the application layer for identity verification.\n\n3. **Pairing** — On first contact, both devices display the same 8-digit code (derived from cert fingerprints). Confirming the code pins the peer's certificate — all future connections are trust-on-first-use.\n\n4. **Sync** — The clipboard monitor detects content changes. Before sending, the content is hashed for deduplication (prevents echo loops). The frame is encrypted with AES-256-GCM (peer-specific key), then sent over TLS 1.3.\n\n5. **Reconnect** — Paired devices reconnect automatically. If a peer's certificate has changed since pairing, the user is alerted (potential MITM).\n\n---\n\n## Configuration\n\n| Setting | Location | Description |\n|---|---|---|\n| Device Name | Dashboard → Overview | Custom name shown to other devices |\n| Sync Toggle | Dashboard → Overview | Pause/resume clipboard sharing |\n| Auto-start | Settings | Launch on system login |\n| Theme | Settings | Light / Dark / System |\n| Port | Settings → Network | Default: 19990 |\n| Relay URL | Settings → Network | Optional relay server for cross-subnet sync |\n| Content Filter | Settings → Filter | Regex categories: credit card, SSN, API key, etc. |\n| Encryption | Settings → Security | Toggle at-rest + frame encryption |\n| Pre-shared Password | Settings → Security | Optional shared secret for extra key entropy |\n| History | Settings → Advanced | Max entries (default: 50) |\n| File Receive Dir | Settings → Advanced | Where received files are saved |\n| Poll Interval | Settings → Advanced | Clipboard check frequency (default: 0.4s) |\n| Sync Debounce | Settings → Advanced | Minimum interval between syncs (default: 0.3s) |\n\n### Data Storage\n\nAll application data is stored locally:\n\n| OS | Config \u0026 History | Logs |\n|---|---|---|\n| Windows | `%APPDATA%\\ClipSync\\` | `%APPDATA%\\ClipSync\\clipsync.log` |\n| macOS | `~/Library/Application Support/ClipSync/` | `~/Library/Logs/ClipSync/clipsync.log` |\n| Linux | `~/.config/clipsync/` | `~/.local/share/clipsync/clipsync.log` |\n\n- `config.json` — device identity, peer list, settings (private key encrypted)\n- `clipboard_history.json` — last N clipboard entries (all content encrypted at rest)\n\n---\n\n## Troubleshooting\n\n### Devices not discovering each other\n1. Verify both devices are on the **same subnet** (same WiFi network)\n2. Corporate networks may have **client isolation** blocking mDNS — try a personal hotspot\n3. Check that your firewall allows **UDP port 5353** (mDNS) and **TCP port 19990** (ClipSync)\n4. Try the **Relay URL** setting if crossing subnets\n\n### Sync not working\n1. Confirm **Sync is enabled** on both devices (Dashboard → Overview toggle)\n2. Check the **Devices panel** — the peer should show \"Connected\" with a lock icon\n3. If \"Paired\" but not connected, click the **Reconnect** button\n4. Check the **Settings → Security** panel — if encryption is enabled on one device, both must have matching passwords if set\n\n### Connection issues\n- Look at the **Devices panel** status indicators:\n  - Green dot + lock = Connected and encrypted\n  - Orange dot + \"Paired\" = Trusted but offline\n  - Blue dot + \"Discovered\" = Found but not yet paired\n- If a device shows as \"Discovered\" but won't connect, try **Forget** and re-discover\n- Restarting ClipSync on both devices often resolves transient mDNS issues\n\n### Getting logs\n- Right-click the system tray icon → **Export Logs**\n- Or open the log file directly (see [Data Storage](#data-storage) paths above)\n- Log level can be set in Settings → Advanced (DEBUG, INFO, WARNING, ERROR)\n\n---\n\n## Project Structure\n\n```\nclipsync/\n├── src/\n│   └── main.py                      # Application entry point\n├── internal/\n│   ├── clipboard/                   # Clipboard I/O per platform\n│   │   ├── clipboard.py             # Factory + common logic\n│   │   ├── clipboard_windows.py     # Windows via win32clipboard\n│   │   ├── clipboard_darwin.py      # macOS via AppKit\n│   │   ├── clipboard_linux.py       # Linux via xclip/wl-paste\n│   │   ├── filter.py                # Content filtering (regex)\n│   │   ├── format.py                # Content type + sync message\n│   │   └── history.py               # Encrypted local history\n│   ├── config/\n│   │   └── config.py                # JSON config load/save\n│   ├── platform/\n│   │   ├── autostart.py             # OS-specific auto-launch\n│   │   └── notify.py                # Desktop notifications\n│   ├── protocol/\n│   │   └── codec.py                 # Frame encoding/decoding\n│   ├── security/\n│   │   ├── encryption.py            # AES-256-GCM + HKDF + PBKDF2\n│   │   └── pairing.py               # Ed25519 identity, TOFU, pairing codes\n│   ├── sync/\n│   │   ├── manager.py               # Sync orchestration + dedup\n│   │   └── file_transfer.py         # File transfer protocol\n│   ├── transport/\n│   │   ├── connection.py            # TLS 1.3 TCP connections\n│   │   └── discovery.py             # mDNS/Zeroconf discovery\n│   └── ui/\n│       ├── dashboard.py             # Main window with 4 panels\n│       ├── settings_window.py       # Settings with sidebar nav\n│       ├── dialogs.py               # Themed CTk dialog replacements\n│       └── systray.py               # System tray icon + menu\n├── tests/                           # 204 tests covering all modules\n├── assets/\n│   └── icon.svg                     # Application icon\n├── clipsync.spec                   # PyInstaller build spec\n├── requirements.txt                 # Python dependencies\n├── README.md\n├── README_zh.md\n└── LICENSE\n```\n\n---\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch: `git checkout -b feat/my-feature`\n3. Make your changes and ensure all tests pass: `python -m pytest tests/ -v`\n4. Submit a pull request\n\nPlease keep changes focused — one PR, one purpose.\n\n---\n\n## License\n\nMIT — see [LICENSE](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkai3316%2Fclipsync","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkai3316%2Fclipsync","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkai3316%2Fclipsync/lists"}