Skip to content

feat: save the clipboard image's original bytes with desktop_clipboard_read save_path - #96

Merged
iamnbutler merged 1 commit into
mainfrom
feat/clipboard-image-save
Oct 17, 2026
Merged

iamnbutler merged 1 commit into
mainfrom
feat/clipboard-image-save

Conversation

@iamnbutler

Copy link
Copy Markdown
Contributor

Image export for #3. Temporary image and file paste are out of scope; that needs the reservation design.

How

  • New patch peekaboo-clipboard-image-export.patch, last in the stack. It adds a read-only clipboardImageExport Bridge op.
    • It runs the same readImage as the existing read: the same silent-read gate, one-item and generation checks, and PNG/JPEG/TIFF validation within 10 MiB.
    • It also returns the validated source bytes in an optional ClipboardImageContents.original, which stays nil for an ordinary read.
    • The Bridge client refuses an export whose byte count doesn't match the source.
    • It shares the response, descriptor and semantics with the read. The operation inventory tests now count 130.
    • The runtime allowlist adds .clipboardImageExport. The original bytes stay behind the host gate; the client never reads the pasteboard itself.
  • The native client gets an export_path on image reads. It writes the original bytes to that new file (without overwriting) and drops them from the reply. The reply stays well under the 2 MB stdout limit, which 10 MiB of base64 wouldn't.
  • On the TS side, desktop_clipboard_read takes save_path and overwrite with format: "image", following feat: save a screen or window capture as a full-resolution PNG, optionally one region #81's rules:
    • The path is absolute and normalized, in an existing folder.
    • An existing file is refused unless overwrite is true, and a symlink or folder is never replaced.
    • The copy is exclusive unless overwrite is set.
    • The extension must name the image's type: .png, .jpg/.jpeg, .tif/.tiff. On a mismatch nothing is written, and the refusal names the type to use.
    • The bytes are copied unchanged after a size check from a private temp folder.
    • saved returns path, UTI, MIME type, bytes, width and height.
    • With no image on the clipboard, it returns saved: null and writes nothing.
    • region is refused. save_path and overwrite on text or files reads are refused.

Tests

  • Peekaboo, under isolation: PeekabooBridgeRequestPlanTests|PeekabooBridgeOperationSemanticPlanTests|PeekabooBridgeOperationResultSemanticsTests, 72 passed.
    • No upstream test covers readImage itself, since it needs the real pasteboard. I didn't add one that would touch the user's clipboard.
  • npm test: 39 pass. A new test covers the extension rules per type, byte-for-byte copy, refusal of an existing file without overwrite, overwrite, and an incomplete export.
  • npm run check is clean, and the native build with the full stack passes.

Live check: pending, screen locked. Copy a PNG and a JPEG (for example from Preview), save each with a matching path, cmp against the source, then try a mismatched extension. I'll add this to #42.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant