Skip to main content
T2 fan-out · personal / research: for_each fans one nika:fetch with mode: metadata per URL — the page’s OG/meta head as typed data, not a scrape — with retry: for transient blips and on_error: recover: so a dead link degrades to a { dead: true } row instead of failing the batch. nika:jq renders the triage table; nika:write persists it.

The job

Every bookmark pile has the same two questions: what is this, and is it even alive? Answering them by hand means opening every tab. This workflow answers both in one run — title/description/site from each page’s own metadata, dead links marked as dead — and leaves a table you can sort, grep, and prune from.

The shape

The file

bookmark-triage.nika.yaml

The resilience ladder, in order

  1. retry: { max_attempts: 2, backoff_ms: 500 } — a transient blip gets a second chance BEFORE any verdict.
  2. on_error: recover: — a link that still fails becomes { dead: true } and the batch keeps walking. recover: takes a YAML value, not a JSON string: quote it and jq downstream sees an unindexable string instead of an object.
  3. The table renders both worlds — the jq step escapes pipes and newlines from page-controlled metadata (a | in someone’s OG title must not break your markdown table), and dead rows print as DEAD instead of vanishing.
The quiet lesson: mode: metadata fetches the page’s head, typed — when all you need is identity, don’t ask for the body.

Run it

Replace inputs.bookmarks with your own export (most browsers dump bookmarks to HTML — one jq pass turns that into the URL list this file expects).