mirror of github.com/Breadway/breadclip
Find a file
Breadway 83630033cd breadclipd: watch-driven capture, flock singleton, ignore rules, pin verb
- Capture now keys off wl-paste's `CLIPBOARD_STATE`: `sensitive`
  (password manager via `wl-copy --sensitive`, covers the old
  x-kde-passwordManagerHint case) and `nil`/`clear` persist nothing;
  `data` reads the content off stdin in the same event, so the
  sensitive check and the read can't straddle a clipboard change.
  A manual `--capture-once` with no CLIPBOARD_STATE falls back to
  querying wl-paste directly, now wrapped in `timeout -k 2 5` so a
  stalled offer can't block a capture process forever.
- Single-instance guard moves to `bread_utils::singleton` (flock) —
  kernel-atomic, auto-released on death, no stale pid file.
- `ignore_rules::is_sensitive`: conservative best-effort heuristics
  that skip copies which look like secrets even when unflagged —
  PEM/OpenSSH private key blocks, `password:`-style lines, labelled
  one-time codes, Luhn-valid card numbers, well-known token prefixes.
  A convenience, not a security boundary.
- `bread.command.clip.pin` verb (payload `{id, pin?}`, pin defaults
  true) → `set_pinned`, emits `bread.clip.pinned` / `.pin.failed`.
- Two independent `wl-paste --watch` loops (regular clipboard always
  on; primary selection when `capture.primary`), each restarting with
  2s→30s capped backoff and state-change-only journal logging.
- Image type is sniffed from magic bytes (PNG/JPEG) on the stdin path
  and requested by actual offered type on the fallback path — a JPEG
  is stored as `.jpg` / `image/jpeg`, not relabelled PNG.
- content_kind: a single line of prose that merely contains a keyword
  ("class is a concept") no longer classifies as code — it must look
  like a statement.
2026-08-31 15:07:22 +08:00
.forgejo/workflows CI: refuse unsigned bakery index on stable tag releases 2026-08-16 00:50:22 +08:00
breadclip Bump version to v0.2.4 2026-08-16 14:09:21 +08:00
breadclip-core breadclip-core: history DB hardening + user config + pin/primary schema 2026-08-31 15:07:04 +08:00
breadclipd breadclipd: watch-driven capture, flock singleton, ignore rules, pin verb 2026-08-31 15:07:22 +08:00
ci ci: build against bread-ecosystem's shared Arch CI image, add check.yml 2026-08-05 14:03:05 +08:00
contrib breadclipd: watch-driven capture, flock singleton, ignore rules, pin verb 2026-08-31 15:07:22 +08:00
.gitignore gitignore: exclude graphify-out local cache 2026-08-15 22:32:33 +08:00
AGENTS.md Pin bread-screenshots to the shared ecosystem rev; track AGENTS.md 2026-08-15 22:03:30 +08:00
bakery.toml Initial commit 2026-07-02 20:59:21 +08:00
Cargo.lock breadclip-core: history DB hardening + user config + pin/primary schema 2026-08-31 15:07:04 +08:00
Cargo.toml Initial commit 2026-07-02 20:59:21 +08:00
CONTRIBUTING.md CONTRIBUTING.md: document single-trunk + RC-tag release model 2026-07-31 11:08:41 +08:00
EVENTS.md Switch to tag-pinned bread-ecosystem deps; bump version to v0.2.0 2026-07-19 03:42:05 +08:00
LICENSE Initial commit 2026-07-02 20:59:21 +08:00
README.md breadclip: privacy hardening + event-driven daemon 2026-07-17 03:17:24 +08:00

breadclip

A Wayland clipboard history manager for Hyprland. It consists of two binaries:

  • breadclipd — a background daemon that watches the clipboard and persists entries to a local SQLite database.
  • breadclip — a GTK4 Layer Shell popup for browsing and recalling clipboard history.

Requirements

  • Rust toolchain (edition 2021)
  • GTK 4.12+
  • gtk4-layer-shell
  • wl-clipboard (wl-paste and wl-copy must be on $PATH)
  • Hyprland (or any Wayland compositor with Layer Shell support, though the panel-positioning logic is Hyprland-specific)

Build

git clone https://git.breadway.dev/breadway/breadclip
cd breadclip
cargo build --release

The compiled binaries are at target/release/breadclip and target/release/breadclipd.

Install

Copy the binaries to somewhere on your $PATH, e.g.:

cp target/release/breadclip target/release/breadclipd ~/.local/bin/

systemd user service

A unit file is provided in contrib/:

cp contrib/breadclipd.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now breadclipd

Hyprland keybind

Add the contents of contrib/hyprland.conf to your hyprland.conf:

layerrule = blur, breadclip
layerrule = ignorezero, breadclip

bind = $mainMod, V, exec, breadclip

The layerrule lines enable the frosted-glass blur effect behind the panel.

Usage

Start the daemon (or let the systemd unit handle it):

breadclipd

Open the clipboard history popup:

breadclip

Running breadclip a second time while it is open closes it (toggle behaviour).

Keyboard shortcuts

Key Action
Up / Down Move selection
Enter Copy selected entry to clipboard and close
Delete Remove selected entry from history
Escape Close without copying

Clicking an entry copies it and closes the popup. Clicking outside the panel closes it.

The popup has three filter chips — All, Text, Images — and a search box. The search box filters text entries by content; image entries only appear under the Images filter.

Data storage

History is stored under $XDG_DATA_HOME/breadclip/ (typically ~/.local/share/breadclip/):

Path Contents
history.db SQLite database of all entries
images/ PNG files for image entries

The daemon keeps at most 200 text entries and 50 image entries, trimming oldest entries automatically.

Privacy

  • history.db and every file under images/ are created with 0600 permissions (owner read/write only), regardless of your umask.
  • breadclipd never persists clipboard content flagged as sensitive by a password manager. If a clipboard offer advertises the x-kde-passwordManagerHint MIME type — the convention used by KeePassXC, Bitwarden, and other password managers to mark content they own — that copy is skipped entirely and never reaches the database.
  • That said, this is still a plaintext SQLite database of everything else you copy. Anything copied by an app that doesn't set the hint (e.g. copying a password from a terminal or a non-integrated app) will be stored like any other text entry. Treat history.db as sensitive, and don't rely on it as your only safeguard.

Theming

breadclip inherits its colour palette from bread-theme. The panel renders with an 80% opaque background so Hyprland's layerrule = blur can show a frosted-glass effect behind it.