{"id":50719880,"url":"https://github.com/davidboulay/clippy","last_synced_at":"2026-06-09T23:00:25.247Z","repository":{"id":360765191,"uuid":"1251536267","full_name":"davidboulay/Clippy","owner":"davidboulay","description":"A Paste-style clipboard history panel for Linux/Wayland (COSMIC, wlroots). Bottom-screen tiles of recent copies, toggled by a global shortcut.","archived":false,"fork":false,"pushed_at":"2026-06-07T13:59:59.000Z","size":987,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-07T14:05:37.830Z","etag":null,"topics":["clipboard","clipboard-manager","cosmic","gtk","layer-shell","linux","paste","pop-os","python","wayland"],"latest_commit_sha":null,"homepage":"https://github.com/davidboulay/clippy/releases/latest","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/davidboulay.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"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-05-27T17:14:12.000Z","updated_at":"2026-06-04T16:20:56.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/davidboulay/Clippy","commit_stats":null,"previous_names":["davidboulay/clippy"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/davidboulay/Clippy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidboulay%2FClippy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidboulay%2FClippy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidboulay%2FClippy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidboulay%2FClippy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/davidboulay","download_url":"https://codeload.github.com/davidboulay/Clippy/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidboulay%2FClippy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34129072,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-09T02:00:06.510Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["clipboard","clipboard-manager","cosmic","gtk","layer-shell","linux","paste","pop-os","python","wayland"],"created_at":"2026-06-09T23:00:19.431Z","updated_at":"2026-06-09T23:00:25.220Z","avatar_url":"https://github.com/davidboulay.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Clippy\n\nA clipboard-history panel for Linux, inspired by [Paste for macOS](https://pasteapp.io/).\nPress a global shortcut and a strip of tiles slides up from the bottom of the\nscreen showing everything you've recently copied — text and images. Click a\ntile (or press \u003ckbd\u003eEnter\u003c/kbd\u003e) to load it back onto the clipboard.\n\nLives in the **system tray** (a paperclip), never in the dock. Built for\n**Wayland** (developed on **Pop!_OS 24.04 + COSMIC**; also works on Sway,\nHyprland, and other wlroots compositors).\n\nNow with **encrypted LAN clipboard sync** across your machines — copy on one\ndevice, paste on another — including images and files, plus a **macOS menubar\ncompanion app**. See [Cross-device sync](#cross-device-clipboard-sync).\n\n![Clippy's clipboard panel at the bottom of the screen](docs/screenshot.png)\n\n## Features\n\n- **Bottom panel of tiles** for recent clipboard text and images.\n- **Click-away to dismiss** — the panel is a dimmed full-screen overlay; click\n  anywhere outside it (or press \u003ckbd\u003eEsc\u003c/kbd\u003e) to close.\n- **Tray icon + Settings** (paperclip in the COSMIC panel). Not shown in the dock.\n- **Follows the COSMIC light/dark theme** automatically.\n- **Settings**:\n  - **Open at login** toggle.\n  - **Sound on copy** — a short synthesized tone when you copy.\n  - **Always paste as plain text** — strip formatting on paste; when off, rich\n    formatting is preserved if the original had it.\n  - **History retention** — keep for *1 day / 1 week / 1 month / 1 year /\n    forever*, with automatic deletion past the threshold.\n  - **Shortcut picker** — press a key combo and Clippy registers it in COSMIC\n    for you (with a backup of your existing shortcuts).\n- **Right-click a tile** → Paste, **Copy as plain text**, Copy with formatting,\n  Pin/Unpin, Delete.\n- **Pin** items so they survive pruning and sort first.\n- **Search** by typing.\n- **Encrypted LAN sync** (opt-in) — share the clipboard across paired devices on\n  your network: text, images, and **any file** (videos, PDFs…), with previews in\n  the panel and a size cap you control. macOS is supported via a menubar app.\n\n## Why these technologies?\n\nmacOS lets an app float a window over everything and grab a global hotkey.\nWayland — by design — does not. Clippy uses the native Wayland mechanisms:\n\n| Need | macOS | Clippy (Wayland) |\n|------|-------|------------------|\n| Panel pinned to the screen edge | borderless window | **wlr-layer-shell** (`gtk-layer-shell`) |\n| Watch the clipboard | `NSPasteboard` | **`wl-paste --watch`** (`ext-data-control`) |\n| Global hotkey | `CGEventTap` | a **COSMIC custom shortcut** running `clippy toggle` |\n| Tray icon | `NSStatusItem` | **StatusNotifierItem** via Ayatana **AppIndicator** |\n| Theme | system | reads COSMIC's `is_dark` and matches |\n| UI | AppKit | **GTK 3** (PyGObject) |\n| Storage | — | **SQLite** + image files under `~/.local/share/clippy` |\n\nOne binary, several roles:\n\n```\nclippy daemon    # tray + overlay panel + IPC server + clipboard watcher\nclippy toggle    # tiny client → tells the daemon to open/close (your shortcut runs this)\nclippy settings  # open the settings window\nclippy _store    # internal: wl-paste runs this on every clipboard change\n```\n\nThe shortcut → `toggle` → Unix socket → daemon path is what lets a global key\nopen the panel without any forbidden hotkey grab.\n\n## Cross-device clipboard sync\n\nOpt-in, **end-to-end-encrypted** clipboard sync over your LAN — no cloud, no\naccount. Copy on one machine, paste on another. Works across **Wayland-Linux and\nmacOS** peers.\n\n- **What syncs:** text, images, and **any file** (video, PDF, …). Files arrive\n  as the real file (right name + type), images/videos show a preview tile.\n- **Size cap:** default **512 MiB**, raise up to **2 GiB** in *Settings → Sync*\n  (enforced on both ends). Transfers over ~5 MiB show a progress bar on the sender.\n- **Discovery:** automatic via mDNS (zeroconf); falls back to a manual IP if your\n  network blocks multicast (`clippy pair \u003ccode\u003e \u003cip\u003e`).\n- **Security:** each device has a long-term X25519 identity; **pairing is\n  confirmed with a 6-digit code** (so a man-in-the-middle can't slip in a key);\n  every payload is encrypted + authenticated with NaCl. Only paired devices are\n  accepted; LAN-only.\n\n**Enable + pair:**\n1. *Settings → Sync* → turn on **Sync clipboard over LAN**, restart Clippy.\n2. On one device: **Show pairing code** (CLI: `clippy pair`).\n3. On the other: **Enter code** (CLI: `clippy pair \u003ccode\u003e`). Done — `clippy peers`\n   lists paired devices.\n\n**macOS:** ships as a **menubar app** (no history panel — it's a sync peer for\nyour Linux machines, with a native Settings window for updates, pairing, and\nstart-at-login). Build it on a Mac:\n```bash\ngit clone https://github.com/davidboulay/clippy.git \u0026\u0026 cd clippy\n./packaging/macos/build-app.sh --dmg      # → dist/Clippy.app and dist/Clippy-\u003cver\u003e.dmg\n```\nSee [`packaging/macos/README.md`](packaging/macos/README.md). (Unsigned build —\nright-click → Open the first time; Developer-ID signing/notarization is optional.)\n\nSync needs `python3-nacl` + `python3-zeroconf` (pulled in by the `.deb`); video\npreview thumbnails use `ffmpeg` if present.\n\n## Install\n\n### Ubuntu / Pop!_OS / Debian — recommended\n\nDownload the latest `clippy_*.deb` from the\n**[Releases page](https://github.com/davidboulay/clippy/releases/latest)**, then:\n\n```bash\nsudo apt install ./clippy_1.3.2_all.deb\n```\n\n…or fetch it from the terminal with the GitHub CLI:\n\n```bash\ngh release download --repo davidboulay/clippy --pattern '*.deb'\nsudo apt install ./clippy_*.deb\n```\n\n`apt` pulls in the dependencies automatically. Then launch **Clippy** from your\napp list and open **Settings** to bind a shortcut (see below).\n\n### Other distributions\n\n- **Arch / Manjaro:** `cd packaging/arch \u0026\u0026 makepkg -si`\n- **AppImage** (experimental, any distro): `make appimage`, then run `dist/Clippy-*.AppImage`\n- **Flatpak / COSMIC Store:** ❌ not viable — COSMIC withholds the privileged\n  `layer-shell` and `data-control` Wayland protocols from Flatpak-sandboxed\n  apps, which Clippy's panel and clipboard watching require. Details in\n  [`FLATHUB.md`](FLATHUB.md).\n\n### From source\n\n```bash\ngit clone https://github.com/davidboulay/clippy.git\ncd clippy\n./scripts/install.sh\n```\n\n`install.sh` (asks for `sudo` once) installs the dependencies, a\n`~/.local/bin/clippy` launcher and icon, enables autostart, and starts the\ndaemon — a paperclip should appear in your COSMIC panel. To build a `.deb`\nyourself instead: `make deb`, then `sudo apt install ./dist/clippy_*.deb` (see\n[`packaging/README.md`](packaging/README.md)).\n\nDependencies: `wl-clipboard`, `python3-gi`, `gir1.2-gtk-3.0`,\n`gir1.2-gtklayershell-0.1`, `libgtk-layer-shell0`,\n`gir1.2-ayatanaappindicator3-0.1`, `libayatana-appindicator3-1`, `pipewire-bin`,\nplus `python3-nacl` + `python3-zeroconf` for sync (`ffmpeg` optional, for video\npreview thumbnails).\n\n### Set the shortcut\n\nOpen the tray icon → **Settings** (or the ⚙ in the panel), click the shortcut\nbutton, and press your combo (e.g. \u003ckbd\u003eSuper\u003c/kbd\u003e+\u003ckbd\u003eV\u003c/kbd\u003e). Clippy writes\nthe COSMIC binding for you. To do it manually, run `clippy setup-shortcut`.\n\n\u003e Tray not showing? Ensure COSMIC's **Status Area / applet** is on your panel.\n\u003e Either way, the panel's ⚙ opens Settings and the shortcut still works.\n\n## Usage\n\n| Key / action | Effect |\n|---|---|\n| type | search history |\n| \u003ckbd\u003e←\u003c/kbd\u003e/\u003ckbd\u003e→\u003c/kbd\u003e or \u003ckbd\u003e↑\u003c/kbd\u003e/\u003ckbd\u003e↓\u003c/kbd\u003e | move between tiles |\n| \u003ckbd\u003eEnter\u003c/kbd\u003e | copy selected tile \u0026 close |\n| \u003ckbd\u003eCtrl\u003c/kbd\u003e+\u003ckbd\u003e1…9\u003c/kbd\u003e | copy the Nth tile \u0026 close |\n| \u003ckbd\u003eCtrl\u003c/kbd\u003e+\u003ckbd\u003eP\u003c/kbd\u003e | pin/unpin selected |\n| \u003ckbd\u003eDelete\u003c/kbd\u003e | remove selected |\n| \u003ckbd\u003eEsc\u003c/kbd\u003e / click away | close |\n| left-click tile | copy \u0026 close (respects the plain-text setting) |\n| right-click tile | menu: paste / copy-as-plain / pin / delete |\n| middle-click tile | delete |\n\nAfter selecting a tile, paste with \u003ckbd\u003eCtrl\u003c/kbd\u003e+\u003ckbd\u003eV\u003c/kbd\u003e as usual.\n\n### Other commands\n\n```bash\nclippy status            # is the daemon up? how many items?\nclippy settings          # open settings\nclippy clear [--all]     # wipe history (--all includes pinned)\nclippy quit              # stop the daemon\n```\n\n## Configuration \u0026 data\n\nPreferences: `~/.config/clippy/settings.json` (edited via the Settings window).\nFixed limits/geometry: `clippy/config.py`. Colors: `clippy/theme.py`.\n\nEverything stays local:\n\n- `~/.local/share/clippy/history.db` — SQLite history (text + rich html inline)\n- `~/.local/share/clippy/images/`, `files/`, `received/`, `thumbs/` — copied\n  images, file payloads, files received from peers, and cached previews\n- `~/.local/share/clippy/identity.key` + `peers.json` — sync identity key (0600)\n  and trusted paired devices\n- `~/.local/share/clippy/copy.wav` — synthesized copy sound\n- `$XDG_RUNTIME_DIR/clippy.sock` — control socket (mode 0600)\n\nNothing leaves your machine. `./scripts/uninstall.sh --purge` removes it all.\nA backup of your COSMIC shortcuts is kept at\n`…/CosmicSettings.Shortcuts/v1/custom.clippy.bak` the first time Clippy edits it.\n\n## Limitations\n\n- **No auto-paste.** Selecting a tile sets the clipboard; you press\n  \u003ckbd\u003eCtrl\u003c/kbd\u003e+\u003ckbd\u003eV\u003c/kbd\u003e yourself (synthetic keystrokes on Wayland need\n  `ydotool`).\n- **Plain/rich** uses `text/html` for the rich case (wl-copy offers one type at\n  a time); plain-only apps still get plain text via the plain-text path.\n- **Multi-monitor:** the panel appears on the compositor's active output.\n- Needs a compositor with `wlr-layer-shell` **and** `ext-/wlr-data-control`\n  (COSMIC, Sway, Hyprland). A plain GNOME Wayland session lacks layer-shell.\n\n## Project layout\n\n```\nclippy/\n  cli.py             subcommand dispatch\n  daemon.py          AppController: tray + panel + settings + IPC + retention\n  panel.py           overlay panel, tiles, context menu, plain/rich paste\n  settings_window.py settings UI + shortcut capture\n  tray.py            AppIndicator tray icon\n  capture.py         read clipboard → storage (+ sound, retention)\n  clipboard.py       backend dispatch (text/image/file read + write)\n  backends/          per-OS clipboard: wayland.py (wl-*) + mac.py (NSPasteboard)\n  sync.py            encrypted LAN sync engine (mDNS, pairing, streamed media)\n  progress.py        sender transfer-progress window (large media)\n  mac_app.py         macOS menubar app  ·  mac_settings.py  macOS settings window\n  storage.py         SQLite history (+ html column, files, time retention)\n  settings.py        JSON preferences\n  theme.py           COSMIC light/dark → generated GTK CSS\n  sound.py           synthesize + play the copy sound\n  setup.py           autostart + COSMIC shortcut editing\n  ipc.py             Unix-socket control channel\n  config.py          paths \u0026 limits\nscripts/install.sh · scripts/uninstall.sh · data/icons/clippy.png\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidboulay%2Fclippy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavidboulay%2Fclippy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidboulay%2Fclippy/lists"}