You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
It would be so lovely if this would just work (on macos):
llm -m gemma3:27b "Transcribe to markdown" -a <(pngpaste -)
but unfortunately it doesn't (see below for the error output).
Background: pngpaste outputs what is currently on the clipboard, so pressing shift-cmd-4 and outlining an area (shortcut for "copy part of screen to clipboard as an image") and running the above command would be a pretty neat hack.
The reason for the exception is that the process substitution input file "<()" is not seekable. My proposal: if the input file for -a is not seekable, read it into a buffer for up to 1GB, then use that buffer with bytesio.
I can make a PR if this sounds ok.
Another alternative: read and save the first bytes, use those to do the magic check, and then stream all the rest of the bytes in. If that works for all filetypes, that could even just be the default.
Traceback (most recent call last):
File "/Users/tjl/.local/pipx/venvs/llm/lib/python3.13/site-packages/puremagic/main.py", line 214, in _file_details
fin.seek(-max_foot, os.SEEK_END)
~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
io.UnsupportedOperation: File or stream is not seekable.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/tjl/.local/bin/llm", line 8, in <module>
sys.exit(cli())
~~~^^
File "/Users/tjl/.local/pipx/venvs/llm/lib/python3.13/site-packages/click/core.py", line 1161, in __call__
return self.main(*args, **kwargs)
~~~~~~~~~^^^^^^^^^^^^^^^^^
File "/Users/tjl/.local/pipx/venvs/llm/lib/python3.13/site-packages/click/core.py", line 1082, in main
rv = self.invoke(ctx)
File "/Users/tjl/.local/pipx/venvs/llm/lib/python3.13/site-packages/click/core.py", line 1695, in invoke
sub_ctx = cmd.make_context(cmd_name, args, parent=ctx)
File "/Users/tjl/.local/pipx/venvs/llm/lib/python3.13/site-packages/click/core.py", line 949, in make_context
self.parse_args(ctx, args)
~~~~~~~~~~~~~~~^^^^^^^^^^^
File "/Users/tjl/.local/pipx/venvs/llm/lib/python3.13/site-packages/click/core.py", line 1417, in parse_args
value, args = param.handle_parse_result(ctx, opts, args)
~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
File "/Users/tjl/.local/pipx/venvs/llm/lib/python3.13/site-packages/click/core.py", line 2403, in handle_parse_result
value = self.process_value(ctx, value)
File "/Users/tjl/.local/pipx/venvs/llm/lib/python3.13/site-packages/click/core.py", line 2359, in process_value
value = self.type_cast_value(ctx, value)
File "/Users/tjl/.local/pipx/venvs/llm/lib/python3.13/site-packages/click/core.py", line 2345, in type_cast_value
return tuple(convert(x) for x in check_iter(value))
File "/Users/tjl/.local/pipx/venvs/llm/lib/python3.13/site-packages/click/core.py", line 2345, in <genexpr>
return tuple(convert(x) for x in check_iter(value))
~~~~~~~^^^
File "/Users/tjl/.local/pipx/venvs/llm/lib/python3.13/site-packages/click/core.py", line 2319, in convert
return self.type(value, param=self, ctx=ctx)
~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/tjl/.local/pipx/venvs/llm/lib/python3.13/site-packages/click/types.py", line 84, in __call__
return self.convert(value, param, ctx)
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^
File "/Users/tjl/.local/pipx/venvs/llm/lib/python3.13/site-packages/llm/cli.py", line 207, in convert
return resolve_attachment(value)
File "/Users/tjl/.local/pipx/venvs/llm/lib/python3.13/site-packages/llm/cli.py", line 195, in resolve_attachment
mimetype = mimetype_from_path(str(path))
File "/Users/tjl/.local/pipx/venvs/llm/lib/python3.13/site-packages/llm/utils.py", line 40, in mimetype_from_path
type_ = puremagic.from_file(path, mime=True)
File "/Users/tjl/.local/pipx/venvs/llm/lib/python3.13/site-packages/puremagic/main.py", line 270, in from_file
head, foot = _file_details(filename)
~~~~~~~~~~~~~^^^^^^^^^^
File "/Users/tjl/.local/pipx/venvs/llm/lib/python3.13/site-packages/puremagic/main.py", line 216, in _file_details
fin.seek(0)
~~~~~~~~^^^
io.UnsupportedOperation: File or stream is not seekable.
The text was updated successfully, but these errors were encountered:
tjltjl
changed the title
Support unseekable attachments
Enable mac clipboard via pngpaste (Support unseekable attachments)
May 5, 2025
It would be so lovely if this would just work (on macos):
but unfortunately it doesn't (see below for the error output).
Background: pngpaste outputs what is currently on the clipboard, so pressing shift-cmd-4 and outlining an area (shortcut for "copy part of screen to clipboard as an image") and running the above command would be a pretty neat hack.
The reason for the exception is that the process substitution input file "<()" is not seekable. My proposal: if the input file for -a is not seekable, read it into a buffer for up to 1GB, then use that buffer with bytesio.
I can make a PR if this sounds ok.
Another alternative: read and save the first bytes, use those to do the magic check, and then stream all the rest of the bytes in. If that works for all filetypes, that could even just be the default.
The text was updated successfully, but these errors were encountered: