Architecture

Architecture

Clipboard Manager is built with clean architecture principles: a clear separation between the API surface, the business logic, and the infrastructure, with components communicating through interfaces so each layer can be tested on its own.

A learning project too

Beyond being a useful tool, this codebase is a deliberate exercise in Go project structure and software design patterns.

Layout

  • cmd
    • clipd
    • clipctl
  • internal
    • api
    • service
    • storage
    • daemon
    • monitor
    • analyzer
    • client
    • cli
    • config
    • logger
    • domain
  • Makefile

What each package owns:

PackageResponsibility
apiHTTP handlers and routes (chi)
serviceBusiness logic
storageSQLite and in-memory stores
daemonOrchestration, PID file, signals, retention
monitorClipboard polling
analyzerSensitive-content detection
clientHTTP client used by clipctl
cliCommand dispatch for clipctl
configFlags and defaults
loggerStructured logging with rotation
domainThe core entry model

How a clipboard change flows

  1. monitor polls the system clipboard on the configured interval and reports changes.
  2. analyzer inspects the new content. If it matches a sensitive pattern (passwords, bearer tokens, API keys), the entry is dropped with a reason and never stored.
  3. service applies the business rules and hands the entry to storage.
  4. storage persists it to SQLite.
  5. api exposes the history over the Unix socket; clipctl consumes that same API through the client package.

Design choices

  • Interfaces at the boundaries. The service layer depends on a storage interface, not on SQLite. An in-memory store implements the same interface, which is what the table-driven service tests run against.
  • Unix socket, not TCP. The API is unreachable from the network by construction, and filesystem permissions (0600) are the access control.
  • The daemon owns lifecycle concerns. PID file management, signal handling, graceful shutdown with a deadline, and the retention loop all live in the daemon package, away from the business logic.

Sensitive-content detection

The analyzer keeps history safe with three regex families, matched case-insensitively:

PatternMatches
Passwordspassword:, passwd=, pwd: followed by a value
Tokenstoken or bearer followed by a 20+ char value
API keysapi_key, api-key, secret_key with a value

Matched content is skipped before it ever reaches the database.