Omniscio documentation
Browse all documentation
  1. Getting Started14
  2. Sessions & Agents126
  3. Inbox & Notifications65
  4. Projects & Tasks96
  5. Automation & Scheduling73
  6. Knowledge & Memory27
  7. AI Features66
  8. Integrations104
  9. Plugins & Marketplace34
  10. Cloud & Teams58
  11. Settings & Customization63
  12. Account & Billing28
  13. Troubleshooting77
  14. CLI & API Reference26
  15. Legal & Policies5
  16. Uncategorised17

Chat links and link previews (how a reply's links are recognised and shown)

A link or email address written in a reply is turned into the right affordance automatically: a web address becomes a clickable link with a Copy URL button, an email address becomes one copyable unit that is deliberately not a link, and a tweet link becomes a picture card. Hovering an external link shows that page's real title — fetched once and remembered — and a file path or other in-app link is left with no preview.

What it is

When an AI writes a link into a chat reply — a web address, an email address, a tweet, or a file path — Omniscio recognises it and gives it the right shape instead of leaving it as dead text. This page is the single overview of that behaviour: what becomes a link, what becomes a card, where the preview comes from, and how to tell a real web link from an email address at a glance.

Text an AI writes as markdown ([label](https://…)) is already a link and renders as one. Plain, non-markdown text — operator and system message bubbles, and the structured question widget — is scanned for bare web addresses and email addresses, and each match gets its own affordance. What a recognised link then gets depends on what it points at:

  • A normal external web link (http/https): a clickable link, plus a web-title preview on hover (desktop only).
  • A tweet / X status link: a tweet screenshot card below the message, on every surface.
  • A plain URL inside Team Chat: a full Open Graph preview card.
  • An in-app link (a file path, an attachment, an omniscio:// deep link, a saved prompt): no web preview at all — it keeps its own click behaviour.

Where to find it

Everywhere Omniscio renders a message: the session transcript (agent replies and your own messages), the structured question widget, Team Chat, and the inbox alert / drip body viewers. Nothing to turn on — it is automatic the moment the text appears. The hover title preview is desktop-only: a phone or tablet has no hover, so it never appears there and makes no web request.

How it behaves

What becomes a link, and what stays plain

  • A web address — either http:// / https://… or a bare domain with a known ending such as example.com — becomes a clickable, underlined link that opens in your browser, with a small Copy URL button.
  • An email address (name@host.com) becomes the whole address in accent colour with a single Copy email address button — and is deliberately not a link. Omniscio's window-open guard only allows http/https, so a mailto: link would be a dead click; copying the address is the reliable action instead.
  • The email is matched before the address's own domain, so owner@mailhost.dev is never mistaken for the website mailhost.dev. That ordering is the whole point: it is what stops an address turning into a wrong website link, a stray copy icon mid-sentence, and a broken mid-word wrap.

Telling a link from an address at a glance

A real web link is underlined, opens your browser, and has a Copy URL button. An email address shows the full address in accent text with a Copy email address button, and clicking the address itself does nothing — it is not a navigation.

Which links get a preview

  • Hover any external web link and a tooltip shows that page's real title — the article headline, the repo name, the video title — instead of the bare URL. The title is fetched the first time your pointer settles on the link, then remembered, so each link is looked up at most once. While it loads, and if the page has no title, the tooltip shows the link's domain. In-app links never show a title.
  • A tweet / X status link becomes a screenshot card of the tweet right below the message — wherever the link appears, and no matter who wrote it. Click it to open the tweet on X.
  • In Team Chat, an ordinary URL unfurls into a card — title, description, thumbnail image and site name, from the page's Open Graph metadata, laid out compactly (a small thumbnail beside the text) so it stays dense.

Where the preview comes from, and whether it is live or cached

  • Previews are built by fetching the linked page once, never by an AI call — so they cost nothing in AI spend.
  • The hover title and the Team Chat card are fetched in Main (Omniscio's trusted process), because a link in chat is untrusted content and the on-screen app may not reach the internet on its own. Every fetch runs through the shared network-safety guard: it refuses links that point at your own machine or private network, allows only http/https, gives up after a few seconds, and reads only the first part of the page.
  • Everything is cached — a good result for hours, a failure for a few minutes — so re-hovering is instant and a dead link is not re-fetched on every hover. Nothing is written to disk except the tweet screenshot, kept so a given tweet is never rendered (and never paid for) twice.
  • Failures are silent. An unreachable or titleless page shows just the domain; a tweet that cannot be rendered leaves the ordinary link standing — no broken image, no error message.

For agents

  • Detection / rendering — LinkifiedText (src/renderer/src/components/ui/LinkifiedText.tsx) scans plain (non-markdown) text with one URL_RE whose alternatives are email first, then protocol URL, then a bare allow-listed-TLD domain. A match containing @ that is not a protocol URL renders CopyableEmail; everything else renders CopyableLink (src/renderer/src/components/ui/agent-markdown-helpers.tsx). Consumers: MessageBubble (operator bubbles), SmsViewer, QuestionWidget. CopyableLink gates the fetch on isExternalWebLink && supportsHover() and arms a 200 ms dwell (LINK_TITLE_DWELL_MS; keyboard focus arms immediately) into useLinkTitlePreview.
  • IPC domain link-preview — channels src/shared/ipc-channels/link-preview.ts (link-preview:fetch-title / :unfurl / :tweet-shot), schemas src/shared/ipc-schemas/link-preview.ts, handlers src/main/ipc/link-preview-handlers.ts. Per-window rate limits: fetch-title 60 / 10 s, unfurl and tweet-shot 30 / 10 s; a throttled call degrades to a null / empty result, never an error.
  • Main services — src/main/services/link-preview/link-title-fetcher.ts (title: og:title → <title>, 8 s timeout, 100 KB capped read, 6 h positive / 5 min negative TTL, 500-entry cache) and link-unfurl.ts (full Open Graph metadata, 512 KB cap, 500-char fields, og:image only when it is a non-private https URL). Both fetch through redirectAwareFetch (the SSRF-safe guard).
  • Renderer hooks — useLinkTitlePreview.ts and useChatLinkUnfurl.ts (30 min TTL, cap 500, in-flight dedup, max 3 URLs per message via src/shared/team-chat/extract-urls.ts).
  • Cards — LinkPreviewCard.tsx (hero / compact layouts) and TweetShots.tsx backed by src/main/services/tweet-shot/tweet-shot-cache.ts.
  • Contracts — linkified-text-contract.md and link-title-preview-contract.md are both anchored to cat-chat-link-rendering; the Team Chat unfurl is the subject of team-chat-link-unfurl-contract.md.

Related

Last verified 2026-10-07