A personal X11 clipboard manager I built to solve one specific annoyance: I wanted clipboard history and PRIMARY/CLIPBOARD sync without a loud, colorful tray icon.
I do not recommend this project for general use. It exists because it fits my workflow, my X11 setup, and my preference for a quiet tray icon. If it helps you, great; if not, there are more polished clipboard managers with broader goals.
BCM is intentionally boring. YAML configuration, XDG paths, systemd integration, explicit privacy warnings, and local release gates are enough. Simple and boring work.
- Bidirectional X11 sync — keeps PRIMARY and CLIPBOARD aligned by default.
- Persistent local history — stores text and image history under XDG data paths, with explicit cache-like semantics.
- Image capture with thumbnails — captures common image MIME types and displays tray thumbnails.
- System tray controls — AppIndicator/GTK menu with history entries, Clear History, Show Logs, and Quit.
- First-run configuration — creates
${XDG_CONFIG_HOME:-~/.config}/bcm/config.yamlwhen no config exists; existing files are never overwritten. - Privacy hardening — private file permissions, path validation, decompression-bomb checks, sensitive log masking, and side-effect-free dry runs.
- systemd user service — install, start, inspect logs, uninstall, and optionally purge user data.
- Release-grade checks — format, lint, source/test type checks, unit/integration/E2E tests, warning policy, and coverage gate through
make check.
BCM uses GTK 3, GObject introspection, AppIndicator/Ayatana AppIndicator, Cairo, and xclip. Install the distro libraries before running make install.
Ubuntu/Debian:
sudo apt install -y \
python3-dev pkg-config libcairo2-dev libgirepository-2.0-dev \
gir1.2-gtk-3.0 gir1.2-gdkpixbuf-2.0 gir1.2-ayatanaappindicator3-0.1 \
xclipFedora:
sudo dnf install -y \
python3-devel pkgconf-pkg-config cairo-devel gobject-introspection-devel \
gtk3 libappindicator-gtk3 \
xclipArch Linux:
sudo pacman -S --needed \
base-devel pkgconf python cairo gobject-introspection gtk3 libayatana-appindicator \
xclipBCM requires an X11 session. DISPLAY must point to a running X server. Wayland-only and headless sessions are not supported unless you provide X11 compatibility, such as Xvfb for automation.
Run this from an X11 desktop session to install the published x86_64 binary, install the user service, start it, and show its status:
sh -c 'set -eu; case "$(uname -m)" in x86_64|amd64) ;; *) echo "The v1.0.0 prebuilt binary is only published for x86_64. Build from source on this architecture." >&2; exit 1 ;; esac; bin_dir="$HOME/.local/bin"; service_dir="${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user"; mkdir -p "$bin_dir" "$service_dir"; curl -fL "https://github.com/francis-io/better-clipboard-manager/releases/download/v1.0.0/bcm-linux-x86_64" -o "$bin_dir/bcm"; chmod 0755 "$bin_dir/bcm"; curl -fL "https://raw.githubusercontent.com/francis-io/better-clipboard-manager/master/systemd/bcm.service" -o "$service_dir/bcm.service"; systemctl --user daemon-reload; systemctl --user enable --now bcm.service; systemctl --user --no-pager status bcm.service'Install uv if it is not already available:
curl -LsSf https://astral.sh/uv/install.sh | shgit clone https://github.com/francis-io/better-clipboard-manager.git
cd better-clipboard-manager
make install
make build
make install-servicemake install-service installs the package, writes the systemd user unit to ${XDG_CONFIG_HOME:-~/.config}/systemd/user/bcm.service, enables it, and starts it.
make runOn first run, BCM creates a starter config at ${XDG_CONFIG_HOME:-~/.config}/bcm/config.yaml.
Useful service commands:
systemctl --user status bcm
journalctl --user -u bcm -f
systemctl --user restart bcm
systemctl --user stop bcmbcm --help
bcm --version
bcm --config /path/to/config.yaml
bcm --debug
bcm --dry-run--dry-run logs intended actions without clipboard writes, history mutation, image/thumbnail writes, cleanup deletion, or persistence writes.
Clipboard history can contain passwords, tokens, customer data, screenshots, and other sensitive material. BCM keeps history local and uses private file permissions, but persistence is enabled by default. Treat ${XDG_DATA_HOME:-~/.local/share}/bcm as sensitive local cache data.
Use Clear History from the tray to clear in-memory history, immediately persist an empty history file when persistence is enabled, and remove unreferenced image/thumbnail files.
- Installation and service management
- Configuration and privacy model
- Development, testing, and CI gates
- Building binaries
- Architecture notes and known limitations
BCM supports the bcm command, make targets, systemd service, and YAML configuration documented here. Python modules under bcm are internal implementation details; they are not a stable Python API or plugin interface.
MIT