diff --git a/docs/cli.md b/docs/cli.md index 17b97bc04..1bd714132 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -316,7 +316,7 @@ intact, including any existing signature or Name Tag. Use a body flag to replace it when needed. `draft show` includes the selected From address in both styled and JSON output. No command here persists a default sender. -`--attach` is repeatable on `hey compose`, `hey reply`, and `hey bulk-reply send`, and attachment-only messages are supported. The CLI validates and uploads every file before sending the email. `hey attachment list ` returns every named downloadable file, including named inline images. Direct files keep stable message-and-position IDs such as `456:1`; files inside embedded HTML receive opaque IDs scoped to their message. Pass either returned ID to `hey attachment save`. Saving uses the original filename by default, accepts `--output` for a file or directory, and preserves existing files unless `--force` is set. +`--attach` is repeatable on `hey compose`, `hey reply`, and `hey bulk-reply send`, and attachment-only messages are supported. The CLI validates and uploads every file before sending the email. `hey attachment list ` returns every named downloadable file, including named inline images. Direct files keep stable message-and-position IDs such as `456:1`; files inside embedded HTML receive opaque IDs scoped to their message. Pass either returned ID to `hey attachment save`. Saving uses the original filename by default, accepts `--output` for a file or directory, and preserves existing files unless `--force` is set. On macOS and Windows a saved file is marked as downloaded from the internet, so the system warns before running it: the `com.apple.quarantine` attribute on macOS, where a save that cannot be marked fails rather than leaving an unmarked file, and, as a best effort, a `Zone.Identifier` stream on Windows wherever the drive can hold one. Other systems keep no such mark, so files saved there are not marked. Organization actions take the `id` values returned by `hey box view --json`, `hey label view --json`, or `hey search --json`. Reading, replying to, and forwarding a thread take its `topic_id` instead, which `hey box view --json`, `hey label view --json`, `hey collection view --json` and `hey search --json` all carry alongside `id`. `hey box view` also returns `next_page` and accepts `--page ` to continue a box listing; it keeps `next_history_url` for the sync clients that read it, and `--page` accepts that URL as readily as the cursor inside it. Label IDs come from `hey label list`; `hey label view` returns `next_page` and `total_count`, accepts `--page ` for continuation, and supports `--all` for complete traversal. `hey label create` files at least one thread as it creates the label, so it needs one or more of your box item IDs; a name you already use (in any case) is refused. diff --git a/docs/tui.md b/docs/tui.md index ae67ccf7b..0a5685f31 100644 --- a/docs/tui.md +++ b/docs/tui.md @@ -202,7 +202,7 @@ the iOS and Android apps each keep their own local choice too, and this is the s ## Attachments -Thread attachments always appear with their filename, media type, and size. Use `[` and `]` to select an attachment, `s` to save it without replacing an existing file, and Enter to download and open it in an external application — once Tab has selected a link, Enter opens the link instead, and Escape clears it. Enter only opens documents, images, audio and video (on Linux, only when the file's contents are one too, since the system picks the application from them); anything that could run a program, such as a script, a shortcut or a Terminal profile, has to be saved with `s` and opened by hand. Attachments never open automatically, and on macOS and Windows every saved attachment is marked as downloaded from the internet, so the system warns before running one. Kitty and Ghostty can show inline images. In the message itself, a file is marked by its kind: 📷 an image, 🎬 a video, 🎵 audio, 📄 a PDF or document, 📎 anything else. An image shows by name rather than by its URL, unless its name looks like a URL, when the real destination is shown beside it; an image on the web is a link you can select with Tab, and the row above the shortcut bar shows its whole destination. +Thread attachments always appear with their filename, media type, and size. Use `[` and `]` to select an attachment, `s` to save it without replacing an existing file, and Enter to download and open it in an external application — once Tab has selected a link, Enter opens the link instead, and Escape clears it. Enter only opens documents, images, audio and video (on Linux, only when the file's contents are one too, since the system picks the application from them; a zip-based document the system cannot tell from an archive still opens, in an archive manager at worst); anything that could run a program, such as a script, a shortcut or a Terminal profile, has to be saved with `s` and opened by hand. Attachments never open automatically. On macOS and Windows every saved attachment is marked as downloaded from the internet, so the system warns before running one: always on macOS, and on Windows wherever the drive can hold the mark (a FAT drive cannot). Linux keeps no such mark. Kitty and Ghostty can show inline images. In the message itself, a file is marked by its kind: 📷 an image, 🎬 a video, 🎵 audio, 📄 a PDF or document, 📎 anything else. An image shows by name rather than by its URL, unless its name looks like a URL, when the real destination is shown beside it; an image on the web is a link you can select with Tab, and the row above the shortcut bar shows its whole destination. ## Contacts diff --git a/internal/cmd/attachments_save.go b/internal/cmd/attachments_save.go index aea7e2f7d..a40d165bc 100644 --- a/internal/cmd/attachments_save.go +++ b/internal/cmd/attachments_save.go @@ -33,8 +33,12 @@ func newAttachmentsSaveCommand() *attachmentsSaveCommand { attachmentsSaveCommand.cmd = &cobra.Command{ Use: "save ", Short: "Save an attachment to disk", + Long: "Save an attachment to disk under its original filename, or at --output. Existing files are preserved unless --force is set. " + + "On macOS and Windows the saved file is marked as downloaded from the internet, so the system warns before running it: " + + "on macOS a save that cannot be marked fails, and on Windows the mark is a best effort, written wherever the drive can hold it. " + + "Other systems keep no such mark.", Annotations: map[string]string{ - "agent_notes": "Saves the attachment identified by an ID from `hey attachment list `. Existing files are preserved unless --force is set.", + "agent_notes": "Saves the attachment identified by an ID from `hey attachment list `. Existing files are preserved unless --force is set. On macOS the saved file gets the quarantine attribute, and a save that cannot be marked fails; on Windows a Zone.Identifier mark is written as a best effort, and may be missing on drives that cannot hold it; other platforms add no mark.", }, Example: ` hey attachment save 67890:1 hey attachment save 67890:1 --output ./quarterly-report.pdf