Skip to content

Latest commit

 

History

History
206 lines (121 loc) · 17.7 KB

File metadata and controls

206 lines (121 loc) · 17.7 KB

Changelog

All notable changes to FlashPaste are listed here. The format follows Keep a Changelog 1.1.0 and the project follows Semantic Versioning.

Release-tag policy: every vX.Y commit on main must be tagged and have a matching GitHub release before the turn ends — see AGENTS.md for the full rule.

Fixed

  • Double-paste under XWayland kitty, round two. The kitty ctrl+v interception is retired: under XWayland, kitten @ ls reports is_focused=false for every OS window and empty foreground_processes, so kitty-paste-router.sh's tmux detection could never succeed. Every paste took the slow fallthrough (a background launch that lands seconds late under load), and the late second fire fell outside the daemon's 2.5 s dedup window — observed as identical 162-byte pastes 4 s apart. config/keybindings.canonical now requires kitty ctrl+v to be UNBOUND (new canonical keyword, enforced by flashpaste-keybindings-check.sh); tmux's bind -n C-v is the single Ctrl+V handler (~5 ms, pane id always from the pressing client). In non-tmux kitty windows the raw 0x16 reaches Claude Code, which reads the clipboard itself via the wl-paste shim; plain shells use kitty's native ctrl+shift+v.

Added

  • flashpaste-keybindings-check.sh: UNBOUND keyword in keybindings.canonical asserts a key must NOT be bound on a surface (previously only positive "must contain" rules existed).
  • kitty-paste-router.sh now traces to the shared clipboard-pipeline log (paste-router tag: invoked / suppressed / fallthrough / pane-resolved / done / image-fallback), closing the observability gap that made this regression invisible — the router was the only paste path that wrote no logs.

1.34 - 2026-05-21

Fixed

  • CI hygiene rolled into a tagged release so the v1.34 tag and the Lint workflow on the same commit agree. v1.33's release workflow shipped the .deb successfully, but the Lint workflow on that exact tag failed on pre-existing issues: docs/overlay-references.md MD032 (17 lists missing surrounding blank lines), openspec/changes/flashpaste-overlayd-phase1-2026-05-20/CHANGE.md MD022 / MD025 / MD012 / MD058 (proposal H1 nested inside an H2, doubled blank line, three tables without surrounding blanks), openspec/plans/flashpaste-overlayd-phase1-2026-05-20/tasks.md MD055 (table rows without leading / trailing pipes), README.md:7 MD001 (h3 directly under h1, skipping h2 — promoted to h2), tests/click-through.md:14 MD032 (list directly under a colon-terminated paragraph), and two dead links in CHANGELOG.md pointing at the never-tagged v1.32 (now pointing at the existing v1.33 / v1.27 references). No behaviour change vs v1.33.

1.33 - 2026-05-21

Added

  • bin/flashpaste-capture-clip — new helper that reads an image from the system clipboard and writes it to ~/Pictures/Screenshots/flashpaste-clip-latest.png so the daemon's inotify watcher can stage it. Bridges the long-standing "browser Copy Image" gap (ROADMAP.md:32, now ticked) where Firefox / Chrome put image bytes on the Wayland clipboard without writing a file, so the daemon's fast path never saw them and Claude Code's wl-paste -t image/png came back with 0 bytes (mutter blocks surfaceless reads, and Firefox under Wayland often doesn't mirror images to the X11 selection either). Stable filename — the file is overwritten on every capture, no clutter accumulates in the screenshots dir.

Changed

  • bin/paste_image.sh image branch now calls flashpaste-capture-clip before sending \026 to kitty, then waits 60 ms for the daemon to claim the staged bytes. Cost is one extra wl-paste + xclip probe per image paste (~30–80 ms); the helper validates the PNG / JPEG / WebP magic so a malformed read can't clobber the daemon's stage with text bytes (the same xclip-lies-about-MIME trap the wl-paste shim already defends against at bin/wl-paste:99-104).
  • rs/flashpaste-common/src/compress.rs tightens the attachment defaults: DEFAULT_MAX_BYTES 4 MB → 3.5 MB and DEFAULT_MAX_DIM 2400 px → 1568 px. Claude's API caps single attachments at 5 MB base64 (~3.75 MB raw) and multi-image conversations at 2000×2000 px; the new defaults sit under both with headroom for HTTP framing and the JSON-RPC wrapper. Browser-copied images that come in larger now downscale cleanly before they hit the agent surface.

[1.32] - 2026-05-20

Added

  • flashpaste-overlayd, a Wayland screen-annotation daemon for agent-driven highlights, pointers, labels, and fade-out TTLs.
  • Three MCP overlay tools in flashpaste-mcp: highlight_region, point_at, and clear_annotations.
  • GNOME-compatible overlay fallback path for environments without layer-shell support.
  • Multi-monitor overlay support so annotations map to the visible output geometry instead of assuming a single screen.

Changed

  • flashpaste-doctor now runs 17 core checks, up from the previous 13, including overlay daemon, socket, compositor, and draw-path probes.

Notes

  • Compositor support matrix: wlroots compositors with layer-shell get the native layer-surface path; GNOME/Mutter uses the fallback path; other compositors should run flashpaste-overlayd --probe before relying on MCP annotations.
  • GNOME fallback caveat: annotations are still programmatic and click-through by design, but Mutter does not expose the same layer-shell semantics as wlroots, so placement and stacking should be treated as best-effort until the probe and quickstart workflow pass on the target desktop.

[1.26] - 2026-05-19

Fixed

  • CI hygiene rolled into a tagged release so the v1.X tag and the Lint workflow on the same commit agree. v1.25's release workflow shipped the .deb successfully, but the Lint workflow on that exact tag failed on three pre-existing issues fixed in commit 8d280ef on main but never re-tagged: bin/flashpaste-logs.sh:118 SC1007 (GRN= RED= WHT= rewritten as GRN='' RED='' WHT=''), bin/flashpaste-logs.sh:206/236/238 SC2178/SC2128 (the local prev="" in kitty_poller shadowed declare -A prev=() in claude_state_poller — renamed the local to last), and CHANGELOG.md:92 MD049 (_…_ italics on the v1.22 revert note converted to *…*). No behaviour change vs v1.25.

[1.25] - 2026-05-19

Added

  • rs/flashpasted/src/ipc.rs text-vs-image intent decision in handle_paste. The single latest_selection slot still holds at most one variant (mirrors how real clipboards work), but the dispatcher now consults live X11 TARGETS too: if the daemon has a fresh staged image AND the X11 CLIPBOARD has been taken over by an external app advertising text-only targets (browser, terminal selection, IDE copy, …), the user's text is scraped, staged, and dispatched as text instead of forcing the image through. The staged image stays in memory so a subsequent paste with no text-overlay still serves it.
  • rs/flashpasted/src/paste.rs dispatch_text_paste: tmux load-buffer + paste-buffer -t <pane> text path. No clipboard claim, no kitty IPC, no unbind/rebind dance — pure tmux pty injection so the text lands in any pane regardless of which terminal hosts the tmux client. Replaces the "punt to bash" path for the text case.
  • rs/flashpasted/src/tmux.rs send_ctrl_v_to_pane(pane): tmux send-keys -t pane -l \x16 injects the literal Ctrl-V byte directly into the named pane's pty, bypassing kitty's "active window only" filter. Fixes the user-reported "I could paste image only into one Claude Code chat — the rest doesn't get my img."

Fixed

  • bin/wl-paste shim now refuses to lie. xclip -selection clipboard -t image/png -o on a text-only clipboard silently returns the text bytes instead of failing (xclip falls back to whatever's in the selection when the requested MIME isn't advertised). The shim was forwarding that text-as-image lie up to Claude Code, which would report "no image found" while pasting raw text into the chat. New behaviour: when a MIME-typed target is requested, the shim probes TARGETS first; if the requested mime isn't on offer, exit 1 with no stdout — matching what a healthy wl-paste -t image/png does on a missing MIME.
  • rs/flashpasted/src/ipc.rs removed the clipboard_holds_user_text punt-to-bash short-circuit at the top of handle_paste. It was firing on every tmux highlight (which auto-copies via @clip to xclip), forcing Claude pastes to deliver highlighted log junk instead of the user's screenshot. The new intent decision (above) handles the same case more precisely — it only honours external text when X11 is actually owned by another app, not when xclip is briefly text-typed by our own pipe.

Changed

  • bin/clipboard-set.sh, bin/flashpaste-logs.sh, bin/flashpaste-screenshot-preload.sh, rs/flashpasted/src/{inotify_watch,wayland}.rs: in-flight tweaks bundled with the release. Notable: clipboard-set.sh gates wl-copy behind FLASHPASTE_USE_WL_COPY=1 and reaps stale wl-broken flags; flashpaste-logs.sh adds --clip / --kitty poller streams with the wl-paste call gated behind --clip-wayland to keep the dock quiet on Mutter.

[1.24] - 2026-05-19

Removed

  • wait_for_pane_idle in rs/flashpasted/src/tmux.rs (and the claude_is_busy / line_has_token_counter helpers + the FLASHPASTE_PANE_IDLE_TIMEOUT_MS env knob in paste.rs). The v1.23 idea was to detect Claude generating via the live ↓ N tokens indicator and hold the dispatch until idle; empirically the detector matched any scrollback line containing <digit> tokens (chat history, release notes, "Saved 200 tokens", etc.), so it timed out on every press into a Claude pane and added the full timeout (5 s default after the v1.23 30 s → 5 s tweak) as pure latency. Confirmed in journalctl: ms_idle_wait=5097, ms_idle_wait=5145 back-to-back on pane=%41. Dispatches now fire immediately; if the TUI drops the byte the user retries, which is far cheaper than 5 s of guaranteed hang.

Kept

  • The paste_in_flight + pending_paste dedup in state.rs / ipc.rs stays. With the wait gone its window shrinks from "up to 30 s" to "~10–20 ms" (just the dispatch itself) but it's still useful for absorbing a rapid double-click on the right-click → Paste menu so Claude sees one \026 instead of two.

Changed

  • The in-flight dedup is now pane-aware. state.rs adds a pending_pane: Mutex<Option<String>> that records the most recent absorbed pane id; the replay dispatch reads it and targets the saved pane instead of always replaying to the pane the initial dispatch was running on. Watcher had caught the cross-pane bug as "absorbed-press pane=%38 → replay pane=%41 (wrong pane)."
  • ipc.rs demotes Broken pipe (os error 32) on the IPC accept path from WARN to DEBUG. That's the trigger's 150 ms read timeout closing the socket before we finish writing the queued-paste reply — expected behaviour, not a bug, but it was polluting the WARN stream.

[1.23] - 2026-05-19

Added

  • bin/flashpaste-logs — unified live viewer across the three streams the pipeline writes to (daemon journal, trigger log, clipboard-pipeline log). Colorized, prefixed, grep / since / -n / no-follow flags. install.sh symlinks it without the .sh suffix to match the muscle memory of flashpaste-trigger / flashpaste-doctor.

Changed

  • rs/flashpasted/main.rs bounds the tokio runtime drop with shutdown_timeout(500ms). Without it, the blocking selection-owner threads kept the runtime alive forever, leaving systemd in deactivating (stop-sigterm) until the 90 s TimeoutStopSec SIGKILL — during which the socket file existed but the listener was already torn down, so flashpaste-trigger got ECONNREFUSED and the user saw paste as "broken after every restart."
  • rs/flashpasted paste pipeline now cancels copy-mode before sending \026 (a wheel-scrolled pane silently swallowed the byte) and waits up to 30 s for the Claude Code TUI to finish generating (detected by the live ↓ N tokens indicator) so pastes during generation no longer drop on the floor.
  • rs/flashpasted/ipc.rs adds an in-flight dispatch guard. While one dispatch is waiting for Claude to become idle, additional paste presses are deduped instead of queueing — previously 4 queued presses fired four \026 bytes back-to-back the instant Claude unblocked.
  • rs/flashpasted kitty dispatch matches state:active instead of state:focused — survives the focus steal from screenshot tools, right-click menu rendering, and other transient focus changes.
  • rs/flashpasted latches WAYLAND_WEDGED once the compositor proves it speaks no ext-data-control / wlr-data-control (Mutter on GNOME 46): subsequent re-asserts skip the doomed copy_multi task entirely instead of spawn-blocking on every paste.
  • rs/flashpasted staged-image TTL bumped 2 min → 30 min so the AFK-then-paste case (screenshot, switch away, come back) doesn't silently demote Tier 3 → bash.
  • rs/flashpasted Ctrl-V rebind now matches the documented flashpaste-trigger || tmux-paste-dispatch.sh fallback. Previously the daemon rebound to bash-only after the first paste, silently demoting the rest of the tmux session to Tier 1.
  • bin/clipboard-set.sh gates the wl-copy path behind FLASHPASTE_USE_WL_COPY=1. On Mutter the wl-copy fork costs ~4–5 extra execs per paste AND surfaces phantom "Unknown" dock icons, all without acting as a durable selection owner (no data-control protocol available). xclip remains the durable owner.

Fixed

  • shellcheck SC2163 in bin/clipboard-set.sh:40 and bin/get-clipboard-text.sh:50 (export "$kv"export "${kv?}").
  • shellcheck SC2209 in bin/flashpaste-trace.sh:162 (AWK_BIN=awkAWK_BIN='awk').
  • markdownlint: bulk MD022 / MD031 / MD032 blank-line fixes via markdownlint-cli2 --fix across AGENTS.md, CHANGELOG.md, CONTRIBUTING.md, docs/adr/*, docs/*. MD040 fence-language tags added to 12 plain-text fences. docs/glossary.md entries promoted h3 → h2 (flat list, no intermediate h2). README "TL;DR for AI assistants" blockquote heading converted to bold (was h3 skipping h2). .markdownlint.json sets MD025.front_matter_title="" so YAML frontmatter title: no longer clashes with the body h1, and disables MD060 (table-pipe spacing) which the CI action's bundled markdownlint version does not enforce.

Reverted

  • examples/tmux.conf.snippet: v1.22 dropped the -O flag from the right-click menu binding on the theory that -O froze the TUI pane until Escape. That repro was on tmux <3.4 and does not hold on 3.6a; removing -O instead caused the menu to auto-dismiss the instant the user moved the mouse toward an entry. v1.23 restores -O so the menu stays open until item-click, click-outside, or Escape.

[1.22] - 2026-05-19

Fixed

  • examples/tmux.conf.snippet: dropped the -O flag from the right-click menu binding so the menu auto-dismisses on click-outside / mouse-release-outside. With -O the menu held the pane in modal-grab until Escape, which read as the pane being "frozen" after a right-click — most visible in TUIs that grab keystrokes (Claude Code chat input). Reverted in v1.23 — the freeze repro was on tmux <3.4 and the removal made the menu unusable on 3.6a.

1.19 - 2026-05-19

Fixed

  • Killed the "wl-clipboard" dock flicker on copy (replaces the v1.13 NoDisplay workaround with the root-cause fix in the daemon path)

1.18 - 2026-05-19

Added

  • flashpaste-mcp server exposing clipboard / screenshot / paste-into-pane tools to LLM agents over MCP stdio
  • flashpaste agent skill for Claude Code
  • AGENTS.md release-policy enforcement
  • AGENTS-release-check.sh audit script

1.17 - 2026-05-19

Changed

  • Tier 3 path enabled by default in the example snippets — Ctrl+V now uses flashpaste-trigger with automatic fallback to tmux-paste-dispatch.sh when the daemon socket is absent

1.16 - 2026-05-19

Added

  • Rust daemon (flashpasted) — long-lived clipboard owner with inotify-driven screenshot pre-stage
  • Sub-15 ms Tier 3 paste path via flashpaste-trigger (1-byte unix-socket ping to the daemon)
  • Trigger falls back to the bash dispatcher when the daemon is absent

1.15 - 2026-05-19

Added

  • Debian packaging — make deb produces dist/flashpaste_*_all.deb
  • GitHub Actions release workflow (.github/workflows/release.yml) auto-builds the .deb and publishes a GitHub release on every v* tag push

[1.14] - earlier

Fixed

  • Aggressively kill phantom dock icons (refines v1.13)

The v1.10–v1.14 tags predate the .github/workflows/release.yml workflow. Per AGENTS.md, we do not retroactively tag them by default — their build environment may not reproduce.

[1.13] - earlier

Added

  • NoDisplay=true .desktop files for wl-paste / wl-copy to suppress Ubuntu Dock phantom-icon flashes

[1.12] - earlier

Added

  • Kitty Ctrl+V auto-routes between text and image paste

[1.11] - earlier

Added

  • Parallel flashpaste-doctor probes (13 checks)
  • Upstream credits surfaced in README

[1.10] - earlier

Added

  • One-line bootstrap.sh installer
  • Optional structured logging
  • Screenshot watcher (flashpaste-screenshot-watcher.path + .service)

[1.0] - initial

Initial commit: sub-120 ms bash hot path for image-paste into GNOME Wayland TUIs.