Skip to content

Instantly share code, notes, and snippets.

@simonw
Created April 4, 2024 23:49
Show Gist options
  • Save simonw/736bcc9bcfaef40a55deaa959fd57ca8 to your computer and use it in GitHub Desktop.
Save simonw/736bcc9bcfaef40a55deaa959fd57ca8 to your computer and use it in GitHub Desktop.

2024-04-04T23:44:10 conversation: 01htnqznbdrxcrbdryacec17g0

Model: claude-3-opus-20240229

Prompt:

osascript -e 'set theImage to the clipboard as «class PNGf»' \
  -e 'set theFile to open for access POSIX file "/tmp/clipboard.png" with write permission' \
  -e 'write theImage to theFile' \
  -e 'close access theFile' \
  && cat /tmp/clipboard.png && rm /tmp/clipboard.png

--

Take that script and turn it into a zsh script - but instead of /tmp/clipboard.png have it generate a unique temporary filename

I want it to read that temporary file into a variable in memory, then delete the temporary file, then output the contents to stdout and terminate

Response:

Here's the script converted to a zsh script with the modifications you requested:

#!/bin/zsh

# Generate a unique temporary filename
tempfile=$(mktemp -t clipboard.XXXXXXXXXX.png)

# Save the clipboard image to the temporary file
osascript -e 'set theImage to the clipboard as «class PNGf»' \
  -e "set theFile to open for access POSIX file \"$tempfile\" with write permission" \
  -e 'write theImage to theFile' \
  -e 'close access theFile'

# Read the temporary file into a variable
image_data=$(cat "$tempfile")

# Delete the temporary file
rm "$tempfile"

# Output the image data to stdout
echo "$image_data"

This script does the following:

  1. It generates a unique temporary filename using mktemp and stores it in the tempfile variable. The filename will be in the format clipboard.XXXXXXXXXX.png, where XXXXXXXXXX is a unique string of characters.

  2. It uses osascript to save the clipboard image to the temporary file specified by $tempfile.

  3. It reads the contents of the temporary file into the image_data variable using cat.

  4. It deletes the temporary file using rm.

  5. Finally, it outputs the contents of image_data to stdout using echo and terminates.

Make sure to save the script with a .zsh extension (e.g., clipboard_to_stdout.zsh) and make it executable using chmod +x clipboard_to_stdout.zsh. Then you can run the script to retrieve the clipboard image, store it in memory, delete the temporary file, and output the image data to stdout.

2024-04-04T23:46:12

Prompt:

that seems to corrupt the image, maybe a newline was added?

Response:

I apologize for the confusion. You're correct that using echo might add a newline character at the end, which can corrupt the image data. To avoid this issue, we can use cat to output the image data directly to stdout without any additional characters. Here's the updated script:

#!/bin/zsh

# Generate a unique temporary filename
tempfile=$(mktemp -t clipboard.XXXXXXXXXX.png)

# Save the clipboard image to the temporary file
osascript -e 'set theImage to the clipboard as «class PNGf»' \
  -e "set theFile to open for access POSIX file \"$tempfile\" with write permission" \
  -e 'write theImage to theFile' \
  -e 'close access theFile'

# Read the temporary file into a variable
image_data=$(cat "$tempfile")

# Delete the temporary file
rm "$tempfile"

# Output the image data to stdout
echo -n "$image_data"

The main change in this script is the use of echo -n "$image_data" instead of echo "$image_data". The -n flag prevents echo from adding a newline character at the end of the output.

Alternatively, you can use printf to output the image data without any additional characters:

# Output the image data to stdout
printf "%s" "$image_data"

Using either echo -n or printf should ensure that the image data is output to stdout without any corruption.

2024-04-04T23:47:49

Prompt:

still seems to corrupt the image in some way

Response:

I apologize for the confusion. In order to properly output the binary image data without corruption, we should use cat directly without assigning the data to a variable. Here's the updated script:

#!/bin/zsh

# Generate a unique temporary filename
tempfile=$(mktemp -t clipboard.XXXXXXXXXX.png)

# Save the clipboard image to the temporary file
osascript -e 'set theImage to the clipboard as «class PNGf»' \
  -e "set theFile to open for access POSIX file \"$tempfile\" with write permission" \
  -e 'write theImage to theFile' \
  -e 'close access theFile'

# Output the image data to stdout
cat "$tempfile"

# Delete the temporary file
rm "$tempfile"

In this updated version:

  1. We generate a unique temporary filename using mktemp and store it in the tempfile variable.

  2. We use osascript to save the clipboard image to the temporary file specified by $tempfile.

  3. Instead of reading the file into a variable, we directly use cat "$tempfile" to output the binary image data to stdout. This ensures that the data is written to stdout without any modifications or additions.

  4. Finally, we delete the temporary file using rm "$tempfile".

This script should output the clipboard image data to stdout without any corruption. The image data can be piped or redirected as needed.

@deric4
Copy link

deric4 commented Jul 20, 2024

Thoroughly enjoying getting nerd sniped while reading through your TIL posts 😄 and came across an alternative implementation:

Leveraging the Shortcuts.app along with a very minimal shortcut definition you can paste images from the cli:

definition

impaste

usage

# ... assuming image already in clipboard

# output to a specified file
$ shortcuts run impaste --output ~/my-image.png

# this also works since it will send the result to stdout if the '--output' param isn't provided
$ shortcuts run impaste > ~/my-image.png


# when output to a file, the following commands work as expected
# open in a quicklook window
$ qlmanage -p ~/my-image.png             
Testing Quick Look preview with files:
	/Users/deric4/my-image.png

$ sips -g all ~/my-image.png 
/Users/deric4/my-image.png
  pixelWidth: 400
  pixelHeight: 400
  typeIdentifier: public.png
  format: png
  formatOptions: default
  dpiWidth: 72.000
  dpiHeight: 72.000
  samplesPerPixel: 3
  bitsPerSample: 8
  hasAlpha: no
  space: RGB

# previous examples don't work when reading from stdin but works with commands that do
$ shortcuts run impaste | md5
...

# process substitution does as well
$ md5 <(shortcuts run impaste)
...

Pros

  • It should handle most other types of image formats (i.e. jpg)
  • seems fairly trivial to add other resource media types like audio or video without needing to maintain them explicitly in the nested applescript def.
  • no need to create a tmp file

Cons

  • There doesn't seem to be any way to export the source code/definition so it can be added to the project repository
  • Very little Shortcuts.app documentation

I don't think this provides anything to help resolve the challenges discussed in simonw/llm#331 (comment) but thought it was worth mentioning nonetheless 🤓

Thanks for all the great content!

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