bridge library

The desktop half of beacon: receives selections from a running app over the Dart VM Service, writes them to .ref/, and copies a paste-ready reference to the clipboard.

This library is deliberately not exported from beacon_widget.dart. It runs on your development machine, not on the device — it reaches for dart:io and package:vm_service, neither of which belongs in the widget tree. Importing it from app code would be a mistake; the usual entry point is the executable:

dart run beacon_widget:bridge --vmservice-out-file=.ref/vm.json

It's exposed as a library so the pieces stay testable, and so anyone wanting to build a different front end (an IDE plugin, a daemon) can reuse the transport rather than reimplement it.

Classes

Clipboard
Shells out to the platform clipboard tool — pbcopy/pbpaste on macOS, clip/PowerShell's Get-Clipboard on Windows, xclip on Linux. No clipboard package — those need Accessibility grants, TCC prompts, or notarization; a pipe to a system binary needs none of that (PLAN.md §5).
VmClient
Watches vmServiceOutFile for the websocket address flutter run --vmservice-out-file=PATH writes there, connects, and forwards every beacon.* extension event to onSelectedbeacon.selected for a single tap, beacon.selectedMany for a broadcast selection stack (PLAN.md §6). The event kind itself is passed through so the caller decides what to do with each; new kinds don't need a change here.
WrittenSelection
What got written to disk for one beacon.selected event.

Functions

checkGitignore(Directory projectRoot) String?
Warns, at startup, if projectRoot's .gitignore doesn't mention .ref — these are throwaway dev-tool scratch files, not something meant to land in commits (PLAN.md §5.3). Returns null if all's well.
copyToClipboard(String text, {required void onStatus(String message), Clipboard clipboard = const Clipboard()}) Future<bool>
Writes text to the clipboard and reports what happened via onStatus.
formatMultiSelection(List<({String jsonPath, Map<String, Object?> payload})> items) String
Builds the combined paste string for a broadcast selection stack (PLAN.md §6: "the paste string for a multi-selection lists all three refs"). One compact ref per line — always multiline regardless of the --format flag, since several distinct references don't have a sensible single-line form the way one reference's optional detail lines do.
formatSelection(Map<String, Object?> payload, {required String jsonPath, bool multiline = false}) String
Builds the string that goes on the clipboard for one written selection.
pruneOldSelections(Directory refDir, {Duration maxAge = const Duration(hours: 1)}) → void
Deletes sel-* files older than maxAge from refDir — each tap leaves a .json+.png pair behind, and nobody's going back to reference a selection from an hour ago.
schedulePeriodicPruning(Directory refDir, {Duration interval = const Duration(minutes: 10), Duration maxAge = const Duration(hours: 1)}) Timer
Re-runs pruneOldSelections every interval for as long as the returned Timer is alive.
writeSelection(Map<String, Object?> payload, {required Directory refDir}) WrittenSelection
Writes sel-<id>.json and sel-<id>.png into refDir for payload (a decoded beacon.selected event) and returns what was written.

Typedefs

BeaconEventHandler = void Function(String kind, Map<String, Object?> payload)
StatusHandler = void Function(String message)