Skip to content

About

Text clipboard synchronization for Omarchy with SyncClipboard.

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Omaclipsync

English · 简体中文

Omaclipsync icon

Omaclipsync is a lightweight text clipboard client plugin for Omarchy Quattro, using the dedicated RustClipSync server protocol. Its synchronization core is written in Rust and its interface lives in the Omarchy bar.

Use the platform clients below to synchronize with Windows, Linux and Android devices.

Desktop resource usage for the current implementation still needs separate measurement.

Omaclipsync main panel

Screenshots were captured from the real Omarchy plugin in English. Server details and last-sync values are hidden; revealed text below is a harmless test fixture.

Sensitive inbox — masked
Sensitive inbox with its body hidden

Explicit reveal — test text only
Sensitive inbox revealing a harmless test item

Receive mode settings
Sensitive sync allowed and automatic clipboard writing disabled

Only the current RustClipSync protocol is supported; there is no protocol selector or SyncClipboard compatibility transport. HTTP endpoints use /api/...; update the server and clients together.

This release requires wire protocol 3 and RustClipSync Server 3.0.0; matching standalone Desktop is 0.5.0 and shared core is 0.4.0. Mobile apps and Fcitx input methods are released separately; check their protocol support before upgrading a shared server. Older clients need server 2.0.0.

Clients for other platforms

These clients synchronize UTF-8 text through the same self-hosted RustClipSync server. The following released versions support Server 3.0.0 / protocol 3:

Platform Client and download Notes
Omarchy Quattro, x86_64 Omaclipsync 0.4.1 Bar plugin; requires Wayland data-control support.
Windows 11, x64 RustClipSync Desktop 0.5.0 WinUI 3 interface; Windows installer is currently unsigned.
Linux, x86_64 RustClipSync Desktop 0.5.0 Packages for Debian 12, Ubuntu 24.04, Fedora 43 and Arch. Supports X11 and Wayland with data-control; GNOME Wayland without that protocol is unsupported.
Android 12+, ARM64 / x86_64 RustClipSync Mobile 0.2.0 Standalone app; no keyboard replacement required.
Android, ARM64 Fcitx5 RustClipSync Keyboard 0.1.5 Synchronization built into this input-method fork. Upstream Fcitx5 builds do not include this module.
iPhone / iPad RustClipSync Mobile project Swift/SwiftUI client in development; no iOS release is available yet.

Configure each device with the same HTTPS server base URL and account. Enter the base URL without appending /api; the clients construct API paths themselves. These projects do not currently provide a macOS client release.

On an Omarchy machine, choose either this plugin or the standalone desktop client for clipboard synchronization. On Android, enable either the standalone app or the keyboard's sync module to avoid competing clipboard writers.

The standalone Android app sends manually in the foreground. Automatic receiving requires its background-operation setting; capturing new copies in the background additionally requires Shizuku 13+ running in wireless-debugging / ADB shell mode. Receiving does not require Shizuku. Android/OEM background limits still apply; see the mobile setup guide.

Features

  • Real-time receive and event-driven push: local copies use Wayland data-control events. HTTPS long polling signals remote changes, after which the client retrieves the latest value.
  • Automatic recovery: when the real-time connection is unavailable, the client falls back to polling every 60 seconds by default, configurable from 30 to 300 seconds. Reconnection uses backoff and checks the latest state immediately after reconnecting.
  • Desktop integration: bar status and controls for push, receive, and pause, with live English and Chinese translations.
  • Sync direction: choose push only, receive only, or two-way automatic sync (the default) in the main panel. Manual actions obey the chosen direction; pause blocks both sending and receiving.
  • Optional local history: off by default; browse, copy, paste, and favorite up to five entries. Favorites stay at the top and survive clearing ordinary history. Enabled history is stored as plaintext; system clipboard history can be used instead.
  • Sync notifications: enabled by default and configurable in Settings. Successful pushes and receives show a notification without revealing clipboard text; unchanged and failed operations do not.
  • Sensitive clipboard policy and inbox: marked sensitive content is blocked in both directions by default. When allowed, choose an encrypted inbox or automatic clipboard writing. The inbox keeps only its latest item, masks the preview, and offers reveal, receipt time, copy and delete. Ordinary history does not record marked sensitive text.
  • Filtering and deduplication: regex blacklist or whitelist and optional filtering on receive. Message IDs and a persistent per-device cursor suppress retries and repeated notifications while allowing distinct copies of identical text.

If notifications do not appear, check Omarchy's Do Not Disturb mode with omarchy shell notifications isDnd. On Omarchy 4.5.0 RC, notifications received while it is on are kept in notification history without a pop-up. Turn it off in Omarchy or run omarchy shell notifications setDnd off to allow pop-ups again.

Requirements and limitations

  • Deploy a RustClipSync server. This plugin does not include a server. Choose companion clients from the platform table.
  • UTF-8 text only: image and file synchronization are not supported. LocalSend, included in standard Omarchy installations, can already transfer images and files manually between devices.
  • Multiple accounts and WebDAV are not currently supported; configure one server account at a time.
  • This plugin requires Linux, Omarchy Quattro / Quickshell, and a Wayland compositor with data-control support. The bundled binaries target x86_64 only. X11/XWayland, Windows, and macOS are not supported.
  • Multi-monitor behavior, long-term stability, and all desktop environments have not been fully validated. See acceptance notes.

Install

Dependencies: an available Secret Service keyring and secret-tool; Omarchy's notification service and omarchy notification send for notifications; native Wayland data-control watching for synchronization; wtype for automatic pasting from history. Git installation also requires Git and a trusted HTTPS server.

For the Omaclipsync icon to remain visible in notification history, install the bundled icon into the user icon theme after installing the plugin:

install -Dm644 "$HOME/.config/omarchy/plugins/io.github.infinifar.omaclipsync/assets/omaclipsync-icon.svg" "$HOME/.local/share/icons/hicolor/scalable/apps/io.github.infinifar.omaclipsync.svg"
gtk-update-icon-cache -ft "$HOME/.local/share/icons/hicolor"

Live notifications also supply the bundled icon directly. Remove the installed icon file when uninstalling if it is no longer needed. gtk-update-icon-cache is provided by GTK; a desktop session may need to reload its icon theme after installation.

Plugins run as unsandboxed code with your user's permissions inside Omarchy shell. Review the source and bundled x86_64 binaries before installing and enabling.

Build a package from source and back up, deploy, and enable it yourself:

./scripts/package.sh

The packaging command overwrites outputs of the same version in dist/; back up any packages you want to keep first. Git installation is also available:

omarchy plugin add https://github.com/Infinifar/omaclipsync.git --enable

Manually deploying the plugin package

Run these commands yourself only once the server and other clients are ready. They disable the current plugin, move its directory into a backup under your user data directory, and load the package. The manually installed plugin will not be Git-managed. Configuration, history, and keyring entries are outside the plugin directory and need their own backups. Replace package with the absolute path to the verified plugin package:

(
  set -eu
  plugin_id='io.github.infinifar.omaclipsync'
  load_root="${XDG_CONFIG_HOME:-$HOME/.config}/omarchy/plugins"
  backup_root="${XDG_DATA_HOME:-$HOME/.local/share}/omaclipsync-backups"
  package='/absolute/path/to/omaclipsync-plugin.tar.gz'
  test -f "$package" && test -d "$load_root/$plugin_id"
  mkdir -p "$backup_root"
  backup=$(mktemp -d "$backup_root/$plugin_id.XXXXXXXX")
  printf 'Previous plugin will be backed up to: %s/previous\n' "$backup"
  omarchy plugin disable "$plugin_id"
  mv "$load_root/$plugin_id" "$backup/previous"
  mkdir -p "$load_root/$plugin_id"
  tar -xzf "$package" -C "$load_root/$plugin_id"
  omarchy plugin validate "$load_root/$plugin_id"
  omarchy-shell shell rescanPlugins
  omarchy plugin enable "$plugin_id"
)

Keep the printed backup path. If validation or enabling fails, retain the backup and inspect the error; do not move it again blindly.

The plugin ID is io.github.infinifar.omaclipsync. The repository includes bin/syncclipd and bin/syncclipctl. Enabling it runs the bundled daemon; installation does not download a separate binary or start a second Quickshell.

Recovering a saved policy after a storage error

If a pause or direction change is saved but encrypted-state cleanup fails, the saved selection remains visible and synchronization stays blocked. The old session cannot upload or restart its listener. The plugin re-reads the saved configuration every 30 seconds and retries cleanup; a resume cannot replace that saved restriction until cleanup succeeds. Resolve the local storage/permission error and let the retry complete, or save Settings again to retry. Failed operations show an explicit message instead of claiming a successful switch. Pairing, history and inbox data are not reset.

Setup and use

  1. Open Omaclipsync in the bar, choose Settings, and save the server HTTPS URL, username, and password. Include the deployment's URL path prefix if one is configured.
  2. The password is stored in the user's Secret Service keyring, not in the configuration file. Leaving the password blank keeps the existing password for that account; unlock the keyring if needed.
  3. Initial pairing starts at the current server revision without overwriting the local clipboard; the selection present at startup is not uploaded. Offline synchronization catches up to the latest value. Conflicting pending local text is preserved; explicitly use Push to choose the current local clipboard. Receive and Pause are also available.
  4. Enable local history and filters if desired. Selecting a history entry changes the system clipboard and may push it to the server when synchronization is enabled. Paste sends Shift+Insert to the application active before opening history; if that window is unavailable, the item is copied and a notification is shown.

Sensitive inbox

Enable Allow sensitive content in Settings, then choose how to receive it with Automatically copy sensitive receives:

  • Off: keep the latest sensitive text in the encrypted local inbox without changing the system clipboard. This is the default. A new sensitive item replaces the previous one; ordinary text does not clear it, and local history can remain disabled.
  • On: write new sensitive text directly to the system clipboard with its sensitivity marker, without retaining it in the inbox or ordinary history. Switching modes does not apply or delete an existing inbox item, reset device identity or move the receive cursor backwards.

The inbox appears below sync direction on the main panel, with History and Settings still in the last row. Text is masked until you click Show. Closing the panel, entering another view, losing the background connection or receiving a replacement hides it again. The preview retains at most the first 64 KiB and shows up to four lines; Copy to clipboard copies the complete original through Rust with its sensitive marker and suppresses automatic re-upload. Receipt time follows the active locale and local time zone.

Delete removes only the current local inbox item. It does not delete server content or clear a copy already placed on the system clipboard, and the consumed item is not received again. Read, copy and delete validate the message ID, rejecting stale commands after replacement.

Open the main panel or history from the bar, or run these commands; the plugin does not automatically change keybindings. In the history panel, select Back to return to the main panel:

omarchy shell io.github.infinifar.omaclipsync open
omarchy shell io.github.infinifar.omaclipsync openHistory

For example, after checking for shortcut conflicts, add this history shortcut to a compatible Omarchy Hyprland Lua binding configuration:

o.bind("SUPER + ALT + H", "Omaclipsync history", "omarchy shell io.github.infinifar.omaclipsync openHistory")

To cycle the automatic sync direction with Super + Alt + C, first check for conflicts and add this binding yourself:

o.bind("SUPER + ALT + C", "Cycle Omaclipsync direction", "omarchy shell io.github.infinifar.omaclipsync cycleDirection")

The shortcut cycles push only → receive only → two-way and shows the saved direction in Omarchy's bottom-center OSD. If automatic sync is paused, the OSD also says so. The plugin does not install or change keybindings.

Show bar icon is enabled by default in Settings. Turning it off hides the icon while the service continues to run. Configure a history shortcut before hiding the icon so you can open history and return to Settings to show it again. Keep the Omaclipsync widget in the bar layout: removing it or disabling the plugin is different from hiding its icon and may make the panel unavailable.

You can also open the main panel directly and re-enable Show bar icon in Settings:

omarchy shell io.github.infinifar.omaclipsync open
# Alternatively:
omarchy shell shell summon io.github.infinifar.omaclipsync '{}'

To request that the icon be shown or hidden without opening the panel:

omarchy shell io.github.infinifar.omaclipsync showIcon
omarchy shell io.github.infinifar.omaclipsync hideIcon

These commands return queued when the request is sent, not when the change has completed. They can be queued even if the daemon is offline, so showIcon can be used to attempt recovery; the widget must still be present in the bar layout for either request to take effect.

The hidden-icon mode is implemented but has not yet been verified on a running desktop.

Other commands:

omarchy shell io.github.infinifar.omaclipsync status
omarchy shell io.github.infinifar.omaclipsync push
omarchy shell io.github.infinifar.omaclipsync pull
omarchy shell io.github.infinifar.omaclipsync toggle

queued means that a command was queued, not that synchronization succeeded. The bundled bin/syncclipctl connects to the existing shell and supports status, push, pull, toggle, watch, and config. The plugin does not force replay of processed messages.

Permissions, network, and data

The plugin runs with the current user's permissions, reads and writes the regular Wayland clipboard, and exchanges text with the user-configured HTTPS server. TLS certificate validation is on by default and can only be disabled by explicitly enabling insecure. Requests do not follow redirects. HTTPS long polling waits up to 25 seconds and reconnects with backoff.

Text is limited to 10 MiB and metadata to 16 KiB. Automatic and manual pushes and receives skip marked sensitive content by default. If allowed, receives use the encrypted inbox or system clipboard according to Settings. Ordinary history excludes new marked sensitive uploads and receives. Protection relies on source applications marking clipboard offers; unmarked secrets cannot be identified. Changing the sensitive synchronization permission discards queued clipboard events and restarts the listener. The plugin pauses if native listening is unavailable so its own writes cannot create a loop.

The inbox body and receive cursor are committed together in the existing AES-GCM encrypted state, with its key held in Secret Service. Status and notifications contain no body. Reveal, copy and delete are local operations and add no server polling. Automatic writes and explicit copies carry the password-manager sensitivity marker; compatible history managers may omit them, but other applications can still read the current clipboard. HTTPS protects transport; the server can still read the text.

Data Default location Behavior
Configuration ~/.config/omaclipsync/config.json Mode 0600; contains no password
Password User's Secret Service keyring Stored per server username
Device token, pending text and current sensitive inbox item ~/.local/state/omaclipsync/v1-*.state AES-GCM encrypted; the key is in Secret Service, without the administrator password
Local history ~/.local/share/omaclipsync/history.json Off by default; plaintext when enabled, mode 0600, default 50 entries, maximum 1000, file limit 16 MiB
Logs ~/.local/state/omaclipsync/ JSONL, mode 0600; fixed events only, no password or clipboard text, retained for 7 UTC dates

The corresponding XDG_CONFIG_HOME, XDG_DATA_HOME, and XDG_STATE_HOME override these paths. Disabling history stops reading and writing it but does not delete existing data. Favorites do not count toward the ordinary entry limit; the 16 MiB file limit still applies to all entries.

Uninstall

omarchy plugin disable io.github.infinifar.omaclipsync
omarchy plugin remove io.github.infinifar.omaclipsync

Uninstalling the plugin does not automatically delete configuration, history, logs, or keyring entries; remove those separately if desired. Some Omarchy versions move a manually copied plugin directory to a hidden backup; check the command output.

Build from source

The RustClipSync engine is maintained in the sibling rustclipsync-core project. This checkout contains an automatically exported source snapshot in core/vendor/rustclipsync-core, with file hashes in UPSTREAM.json, so standalone builds do not require a sibling checkout. To update it from the shared project, run bash scripts/sync-core.sh; use --check to verify an exact match. Do not edit the generated copy.

Requires Rust, Cargo, Clippy, jq, and GNU tar; integration tests also require Python 3 and OpenSSL. From the repository root:

For QML static checks on an Omarchy machine with qmllint installed, run ./scripts/qmllint.sh. It resolves the installed shell modules through a temporary directory, fails on warnings, and does not modify the installed shell or the plugin directory. Set OMARCHY_PATH for a nonstandard Omarchy installation or QMLLINT to select the executable. A clean static check does not replace desktop testing.

cargo test --manifest-path core/Cargo.toml --locked
gjs tests/inbox.test.js Inbox.js
cargo clippy --manifest-path core/Cargo.toml --locked --all-targets -- -D warnings
cargo build --manifest-path core/Cargo.toml --locked --bin syncclipd
# With an isolated Wayland compositor and RCS_TEST_DISPOSABLE_WAYLAND=1:
python3 core/tests/sync_e2e.py "$PWD/core/target/debug/syncclipd" /path/to/rustclipsync-server
./scripts/package.sh
omarchy plugin validate "$PWD"

Artifacts are written to dist/; the integration tests use isolated local services. See acceptance notes for further validation and limitations.

License

MIT. Rust dependency licenses and notices: THIRD_PARTY_NOTICES.md. Native clipboard watching uses wl-clipboard-rs.

Direction reporting and compatibility

This client requires protocol 3 (X-RCS-Protocol: 3) and matching server/client versions. Older clients must stay on their older server. Protocol mismatch stops sync with an upgrade message.

Connection/reconnection first reports the latest direction and waits for ACK. Changes report immediately through the core WebSocket control channel, with authenticated HTTP fallback; local direction and sensitive filters remain in force. Unknown or unconfirmed direction never permits receiving. Pause retains the chosen direction and pairing, but blocks sending and receiving. Manual actions obey the same policy.

A normal daemon/socket close is offline and retains eligibility for server backfill. Explicit re-pairing or changing the account/server first revokes the previous direction session; failure is shown as unconfirmed and retains the old identity. The server expires idle direction state after 30 days. On reconnect, it delivers at most the latest eligible per-device message after direction ACK. The reconnect window and its disable setting belong to the server administration page; no client backfill window is hardcoded. See the direction protocol.

Migration from an older server

Switch server and client versions together. When the old server cannot revoke a direction session, use its administrator or older client to revoke the old device token first. Only then explicitly discard this local pairing:

syncclipctl forget-pairing --confirm-remote-revocation-unconfirmed

This requires the running plugin and queues an explicitly confirmed local-only operation. Check status afterwards. It removes the local device token, pending outbox and sensitive inbox; history and key-store entries remain. It never claims the remote token was revoked; remote access may remain until the old administrator removes that token. Configure the new server and pair afterwards. A protocol mismatch is never accepted as successful revocation.

HTTP fallback has a 30-second online lease, distinct from the admin activity badge. A zero server backfill window disables offline storage/replay but does not disable eligible online real-time delivery.

Automatic upload conflicts

In version 0.4.0, a rejected automatic upload no longer freezes synchronization until restart. The engine durably cancels the conflicting outbox and already queued copies, skips the then-current remote delivery, and keeps the system clipboard unchanged. It does not rebase/re-upload rejected text. Clipboard events observed during recovery are discarded; a fresh copy after recovery synchronizes normally. Network failures or restarts resume the same cancellation/skip decision. Fixed conflict_skipped logs contain no text or credentials. Storage, epoch and credential failures still stop safely.

About

Text clipboard synchronization for Omarchy with SyncClipboard.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages