# fluxClipboard

A context-aware X11 clipboard manager. Three binaries ship as a single
package:

| Binary           | Role                                                          |
|------------------|---------------------------------------------------------------|
| `fluxClip`       | Long-running daemon. Owns CLIPBOARD; stores per-context history. |
| `fluxClipCtrl`   | Thin CLI client (used by WM keybinds, dmenu, scripts).        |
| `fluxClipDock`   | Fluxbox-slit dockapp that subscribes to the daemon.           |

The motivation and full design are in
[`fluxClipboard-blueprint.md`](./fluxClipboard-blueprint.md). The
short version: instead of one flat clipboard history, fluxClipboard
gives you multiple **contexts** — independent clipboard namespaces,
each with its own history, retention, and (optionally) persistence.
Switch contexts and `CLIPBOARD` follows along; everyday Ctrl-V keeps
working in any app.

## Status

This is **Phase 1 of the blueprint + dockapp + Phase-4 TTL eviction +
multi-MIME capture + auto-wipe**. Enough to use day-to-day in place of
parcellite / clipmenu. Still deferred:

* Default set: `scratch` (memory, 50 items), `regular` (disk, 200 items),
  and `secret` (memory, 5 items, 60-second TTL, wipes on switch).
  Per-context `ttl` and `auto_wipe = on_switch_away` are honored.
* No tray-icon binary yet — `fluxClipDock` is the only GUI.
* The dockapp preview still uses the text variant — image and
  rich-text history shows up as `[image image/png]` / `[binary …]`
  placeholders.

### Secret context

`fluxClipCtrl switch secret`, then copy a password. The item expires
after 60 seconds; if you switch away to another context, the secret
context's whole history is wiped immediately (and `CLIPBOARD` is
released if the head was still loaded). Either way, the password
doesn't outlive the moment of attention.

### Multi-MIME capture

Each capture asks the source app for every clipboard target it
advertises (text variants, `text/html`, `image/png`, `text/uri-list`,
`x-special/gnome-copied-files`, …) and stores them all. A paste
later — even after switching contexts and back — hands out the same
payload, so file-manager paste from Thunar / Nautilus, image copies
from Firefox, and rich-text round-trips through LibreOffice all
survive. Payloads whose bytes are valid UTF-8 are persisted as text
in the JSONL log; the rest are base64-encoded. JSONL files written
by older versions migrate transparently on first read.

The dockapp's history popup auto-sizes to fit the active context's
entire history (clamped to ~85% of the screen). Drag any edge to
resize; when the history overflows the popup, a scrollbar appears on
the right and the mouse wheel scrolls through.

`fluxClipDock` auto-starts the `fluxClip` daemon if the socket isn't
reachable at launch, the way parcellite or clipmenu do — you only
need to run one thing. Set `auto_start_daemon = false` in the dockapp
config if you prefer to manage the daemon yourself.

## Build

```sh
cargo build --release
```

Three binaries land in `target/release/`: `fluxClip`, `fluxClipCtrl`,
`fluxClipDock`.

## Install

```sh
./install.sh
```

Installs all three binaries to `~/.local/bin`, the three man pages to
`~/.local/share/man/man1`, and sample configs to
`~/.config/fluxClipboard/` and `~/.config/fluxClipDock/`.

## Quick start

1. Stop any other clipboard manager (parcellite, clipmenu, CopyQ…).
   Two daemons fighting over `CLIPBOARD` makes both useless.
2. Start the daemon:

   ```sh
   fluxClip --background
   ```

3. Add `fluxClipDock` to your Fluxbox slit (or run it once to test).
4. Optional: bind some keys in `~/.fluxbox/keys`:

   ```
   Mod4 1 :Exec fluxClipCtrl switch scratch
   Mod4 2 :Exec fluxClipCtrl switch regular
   ```

Now Ctrl-C in any app appends to the active context. The dockapp
shows which context that is and how many items are in it.

## CLI examples

```sh
fluxClipCtrl current               # which context is active?
fluxClipCtrl contexts              # list configured contexts
fluxClipCtrl switch regular        # change active context
fluxClipCtrl list --limit 5        # show 5 most recent items
fluxClipCtrl list scratch --json   # machine-readable
fluxClipCtrl clear scratch         # empty a context
echo "snippet" | fluxClipCtrl push regular   # script-driven push
```

## Architecture

```
┌──────────────┐    Unix socket    ┌──────────────┐
│ fluxClipCtrl │ ◄───────────────► │              │
│   (CLI)      │                   │   fluxClip   │
└──────────────┘                   │   (daemon)   │
                                   │              │     X11
┌──────────────┐    Unix socket    │  owns        │ ◄─────►
│ fluxClipDock │ ◄───────────────► │  CLIPBOARD   │   server
│  (dockapp)   │   subscribe       │              │
└──────────────┘                   └──────────────┘
```

The daemon is the only component that talks to X11. Clients
(`fluxClipCtrl`, `fluxClipDock`, anything else you write) speak
line-delimited JSON over a unix socket at
`$XDG_RUNTIME_DIR/fluxClip.sock`.

The protocol is plain enough that you can drive it from a shell:

```sh
echo '{"op":"current"}' | socat - UNIX-CONNECT:$XDG_RUNTIME_DIR/fluxClip.sock
```

## What's deferred

In rough priority order:

* Image previews inside the dockapp history popup (multi-MIME items
  are captured and pasted correctly today; the popup just shows a
  `[image ...]` placeholder)
* Cross-context search / rofi frontend
* `fluxClipTray` — system-tray sibling of `fluxClipDock`
* `.idx` side files for fast random access into large persistent
  contexts
* D-Bus shim, Wayland backend

See the blueprint for the full picture.

## License

CC0 1.0 Universal (see `LICENSE`). Public-domain dedication, matching
the rest of the flux suite.
