Skip to content

Latest commit

 

History

History
58 lines (46 loc) · 3.9 KB

File metadata and controls

58 lines (46 loc) · 3.9 KB

Project

Better Clipboard Manager (BCM) is a Python 3.12+ Linux/X11 clipboard manager. It provides a GTK/AppIndicator tray menu, PRIMARY/CLIPBOARD sync, local text/image history, first-run YAML config creation, and optional systemd user-service installation.

Supported public surfaces are the bcm CLI, YAML configuration, make targets, and systemd service. Python modules under bcm are internal implementation details, not a stable API or plugin interface.

Architecture

  • main.py parses CLI flags, enforces the single-instance lock, initializes config/logging, and owns shutdown signal handling.
  • app.py is the imperative shell: X11 polling, sync orchestration, history mutation, tray integration, persistence, cleanup, and shutdown behavior.
  • sync.py, most history transforms, and image/path helpers keep side-effect-light logic isolated for unit testing.
  • clipboard.py is the X11 boundary. DisplayProtocol and ClipboardReader allow tests to exercise clipboard behavior without a real display.
  • types.py holds frozen dataclasses for runtime state/history entries plus config TypedDicts.

Design decisions and invariants

  • BCM targets X11. Wayland-only/headless sessions are unsupported unless an X11 compatibility environment, such as Xvfb, provides DISPLAY.
  • Text clipboard writes use external tools (xclip/xsel) instead of long-running selection ownership. Image copy-back uses GTK clipboard APIs because image paste targets need richer metadata.
  • History is local cache-like state, not a stable file format. Persisted history may contain secrets; storage paths and log files use private permissions.
  • Stored images use SHA-256 content-addressed filenames for deduplication. History-loaded image paths must stay under the configured images directory.
  • Logs go to stdout/stderr by default. Log rotation is intentionally delegated to systemd journal or external rotation for configured file output.
  • --dry-run must avoid clipboard writes, history mutation, image/thumbnail writes, cleanup deletion, and persistence writes.

Key files

File Purpose
src/bcm/main.py CLI entry point, instance lock, signal handling
src/bcm/app.py Runtime orchestration and main loop
src/bcm/clipboard.py X11 clipboard reads/writes and test protocols
src/bcm/clipboard_tool.py xclip/xsel subprocess wrappers
src/bcm/sync.py Pure PRIMARY/CLIPBOARD sync decision logic
src/bcm/history.py History transforms, JSON persistence, path validation
src/bcm/images.py Image storage, thumbnails, cleanup helpers
src/bcm/tray.py GTK/AppIndicator tray UI
src/bcm/config.py Defaults, YAML load/merge, validation, path resolution
src/bcm/logger.py Logging, private file setup, status tracking
src/bcm/types.py Dataclasses, enums, config TypedDicts
config/default.yaml User-facing default/starter configuration template

Common commands

make install           # Install dependencies with uv
make run               # Run from source
make test              # All pytest tests under Xvfb with release policy
make coverage          # All pytest tests with coverage threshold under Xvfb
make type-check        # Source MyPy
make type-check-tests  # Test-suite MyPy
make build             # PyInstaller Linux release binary
make check             # Full local release gate: format, lint, mypy, test, coverage

Change checklist

  • Config changes: update get_default_config() in src/bcm/config.py, _CONFIG_SCHEMA, src/bcm/types.py, config/default.yaml, and relevant docs/tests.
  • New history entry types: add frozen dataclass and ClipboardEntry union member in types.py; update serialization/deserialization and path/security validation in history.py; update tray rendering if visible to users.
  • Clipboard behavior changes: cover pure sync decisions in unit tests and X11/tool boundaries with existing mocks or Xvfb tests.