| 1 | |
| 2 | set -euo pipefail |
| 3 | |
| 4 | OUTPUT_PATH="${DARWIN_CLIPBOARD_OUTPUT:-$HOME/darwin-clipboard-history.jsonl}" |
| 5 | POLL_INTERVAL="${DARWIN_CLIPBOARD_POLL:-0.5}" |
| 6 | MAX_BYTES=65536 |
| 7 | |
| 8 | if command -v wl-paste &>/dev/null && [ -n "${WAYLAND_DISPLAY:-}" ]; then |
| 9 | CLIP_CMD="wl-paste --no-newline 2>/dev/null" |
| 10 | elif command -v xclip &>/dev/null && [ -n "${DISPLAY:-}" ]; then |
| 11 | CLIP_CMD="xclip -o -selection clipboard 2>/dev/null" |
| 12 | elif command -v xsel &>/dev/null && [ -n "${DISPLAY:-}" ]; then |
| 13 | CLIP_CMD="xsel --clipboard --output 2>/dev/null" |
| 14 | else |
| 15 | echo "[clipboard-daemon] No display or clipboard tool found. Headless CT? Exiting." >&2 |
| 16 | exit 1 |
| 17 | fi |
| 18 | |
| 19 | last="" |
| 20 | echo "[clipboard-daemon] Started. Writing to $OUTPUT_PATH" |
| 21 | |
| 22 | while true; do |
| 23 | current=$(eval "$CLIP_CMD" || echo "") |
| 24 | if [ -n "$current" ] && [ "$current" != "$last" ]; then |
| 25 | ts=$(date -u +"%Y-%m-%dT%H:%M:%SZ") |
| 26 | byte_len=${ |
| 27 | if [ "$byte_len" -gt "$MAX_BYTES" ]; then |
| 28 | current="${current:0:$MAX_BYTES}...[TRUNCATED]" |
| 29 | fi |
| 30 | escaped=$(printf '%s' "$current" | python3 -c "import json,sys; print(json.dumps(sys.stdin.read()))" 2>/dev/null || echo '""') |
| 31 | printf '{"ts":"%s","content":%s,"len":%d}\n' "$ts" "$escaped" "$byte_len" >> "$OUTPUT_PATH" |
| 32 | last="$current" |
| 33 | fi |
| 34 | sleep "$POLL_INTERVAL" |
| 35 | done |