Skip to content

feat(cli): let messages send attach a link-preview snapshot tag #6624

Description

@MattH-ca

Motivation

An agent posts links into a channel on a self-hosted relay. The Buzz desktop client renders those links bare, while the same links posted by a human from the desktop app render as rich cards.

The card comes from a tag the sender embeds, not from anything the recipient does - desktop/src/shared/ui/markdown/useMessageLinkPreviews.ts states the privacy model explicitly ("recipients never contact external sites"), and desktop/src/shared/lib/linkPreviewSnapshot.ts parses it:

["link-preview", "snapshot", "1", <canonical url>, <title>, <site>, <description>,
 <image url>, <image sha256>, <favicon url>, <favicon sha256>]

The desktop app writes it through desktop/src-tauri/src/link_preview_tags.rs, whose validation matches the reader's. An image must be relay-hosted at /media/<sha256>.<jpg|png|gif|webp> with a matching hash, which buzz upload file already produces - so the only missing piece is attaching the tag.

The gap: crates/buzz-cli/src/commands/messages.rs builds an event's tags entirely from SendMessageParams - channel, content, kind, reply-to, broadcast, files, mentions. There is no way to pass an arbitrary tag, so a CLI or SDK client cannot produce a card that the app produces routinely. Non-desktop senders (agents, bots, CI, mobile tooling) are second-class in the timeline as a result.

Proposed solution

--tag '["link-preview","snapshot","1",...]' (repeatable) on messages send, with the relay or CLI applying the same validation the desktop writer applies. This is the most generally useful and the smallest change: every other NIP this project adds later becomes reachable from the CLI at the same time.

Alternatives considered

  1. A purpose-built --link-preview <json> flag, if arbitrary tags are considered too broad a surface to expose. More conservative, but each future tag kind then needs its own flag.
  2. Exposing link_preview_tags::append-equivalent validation from the SDK so a client can build the tag and hand it to build_message.
  3. Workaround in use meanwhile: messages send --file <thumbnail>, which uploads an image and appends ![image](<relay url>) to the body. It shows a picture, but it edits the message body rather than annotating it, and it produces no title, site or description.

Additional context

Relay 0.2.1; CLI built from main as of 2026-08-12; checked again against main on 2026-08-23 (SendMessageParams unchanged).

Duplicates: none found (searched open issues and PRs for link-preview / tag / messages send).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions