Skip to content

ForageA declarative DSL for data gathering

Write a recipe to gather structured records, enrich them against other sources, then share it on the hub.

Forage

How it works

1
Gather
A recipe pulls typed records from any site or API. No bespoke code per source.
2
Enrich
Compose recipes to combine sources, and align fields to shared vocabularies like schema.org and Wikidata.
3
Share
Publish recipes and their types to the hub, where anyone can run, fork, or version them.

Example

Top 30 Hacker News front-page stories from the Algolia API. One step, no auth, no pagination.

forage
recipe "hacker-news"

type Story {
    title:    String
    url:      String?
    points:   Int
    author:   String
    comments: Int
}

step front {
    method "GET"
    url    "https://hn.algolia.com/api/v1/search?tags=front_page&hitsPerPage=30"
}

for $story in $front.hits[*] {
    emit Story {
        title     $story.title
        url $story.url
        points    $story.points
        author    $story.author
        comments  $story.num_comments
    }
}
sh
forage run hacker-news
json
{
  "observedAt": "2026-05-11T15:11:11Z",
  "records": [
    {
      "_typeName": "Story",
      "fields": {
        "title": "Hardware Attestation as Monopoly Enabler",
        "url": "https://grapheneos.social/@GrapheneOS/116550899908879585",
        "points": 1879,
        "author": "ChuckMcM",
        "comments": 617
      }
    },
    {
      "_typeName": "Story",
      "fields": {
        "title": "Local AI needs to be the norm",
        "url": "https://unix.foo/posts/local-ai-needs-to-be-norm/",
        "points": 1498,
        "author": "cylo",
        "comments": 580
      }
    }
  ]
}

Features