Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ on:

jobs:
lint-and-test:
name: ${{ matrix.os }} / Python 3.12
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- uses: actions/checkout@v4

Expand Down
34 changes: 31 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# ClipSync

Peer-to-peer clipboard sync for Windows, macOS, and Linux. Copy on one machine,
paste on another. No account, no cloud, no central server. The data never
leaves your devices.
paste on another. No account and no ClipSync-operated server. Syncthing may use
its encrypted public relays when devices cannot connect directly; relays cannot
read the TLS-encrypted traffic.

Verified working across Windows, macOS, and Linux, across different networks.

Expand Down Expand Up @@ -51,6 +52,9 @@ ciphertext.

## Install

Download the current Windows and Linux builds from the
[GitHub Releases page](https://github.com/offbyonebit/clipsync/releases), or install with Python:

```bash
pip install offbyonebit-clipsync
clipsync
Expand Down Expand Up @@ -102,21 +106,45 @@ for the icon to actually show up.
1. Tray icon -> **Add Device**.
2. On the second machine, do the same.
3. Scan the QR code with the webcam, or paste the device ID shown below it.
4. Both sides auto-accept and start syncing.
4. Approve the incoming request on the other device. Auto-accept is available
in Settings for trusted private networks, and is off by default.
5. Copy a short phrase on either device, then paste it on the other. The tray
distinguishes a local publish from Syncthing replication; it does not call
a clipboard delivered until a receiver has confirmed it.

## Settings

- Start on login (HKCU Run on Windows, LaunchAgent on macOS, XDG autostart on
Linux).
- Show notifications.
- Pause sync.
- Pause for 15 minutes, or use manual-send mode from the tray.
- Configurable text and image size limits.
- Sync folder path.
- Encryption passphrase.
- View Syncthing logs.
- Reset / unpair all devices.
- Check for updates (compares against the latest GitHub release and opens the
download page, no auto-install, no phone-home on startup).

Clipboard history opens from the tray or with `Ctrl+Alt+V` when the platform
supports global shortcuts. It supports search, arrow-key navigation, pinned
snippets, and bounded image thumbnails. Pinned items still follow the selected
auto-clear window. File transfers use unique IDs, retry failed receives after a
restart, and show "delivered" only after a receiver writes an acknowledgement.

The tray status shows the latest local send and incoming paste separately. If
an incoming paste is waiting on the desktop clipboard, use **Retry Incoming
Clipboard Now** from the tray; ClipSync also retries automatically with a
capped backoff. The Connected Devices view shows each peer's connection and
folder replication status. **Settings → View Syncthing logs** opens transport
diagnostics.

Settings can block text that matches common private-key, API-token, or
password-assignment patterns. This heuristic is off by default, can miss
secrets or flag examples, and does not inspect images. Clipboard history can
be disabled locally or set to auto-clear after a short interval.

Settings changes from the UI take effect immediately; hand-editing
`settings.json` is also picked up, the file is watched for changes.

Expand Down
5 changes: 5 additions & 0 deletions clipsync/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ def _common_args(name: str) -> list[str]:
# customtkinter ships TTF files that don't auto-detect.
"--collect-data",
"customtkinter",
# The OS keychain package is imported lazily by config.py. Collect its
# backends explicitly so Windows Credential Manager is present in the
# frozen app as well as in a source checkout.
"--collect-all",
"keyring",
str(ENTRY_POINT),
]

Expand Down
Loading
Loading