__ __ __
/ /_ ___ _________ _/ /___/ /
/ __ \/ _ \/ ___/ __ `/ / __ /
/ / / / __/ / / /_/ / / /_/ /
/_/ /_/\___/_/ \__,_/_/\__,_/
Local-first news intelligence for AI agents.
Collect, cluster, and rank news from RSS and Hacker News — all locally, no API keys, no cloud.
Herald collects articles from RSS feeds and Hacker News, deduplicates by URL, clusters related articles into stories using title similarity, scores them by source weight and recency, and generates a ranked Markdown digest — all locally, no API keys, no cloud.
The pipeline: collect → ingest → cluster → project.
RSS/Atom feeds ─┐
├─→ articles ─→ stories (clustered) ─→ scored brief
HN Algolia API ─┘
claude plugin marketplace add heurema/emporium
claude plugin install herald@emporiumManual install from source
git clone https://github.com/heurema/herald
cd herald
pip install httpx fastfeedparser pyyamlThen symlink or copy the plugin directory into Claude Code's plugin path and run /news-init.
/news-init # creates ~/.herald/ with config and database
/news-add <url> # add an RSS feed
/news-run # collect, ingest, cluster, generate brief
/news-digest # read the latest brief
| Command | What it does |
|---|---|
/news-init |
Create data directory, config template, and database |
/news-add <url> |
Add an RSS/Atom feed — auto-discovers feed URL |
/news-sources |
View all sources grouped by category |
/news-sources remove <name> |
Remove a source from config |
/news-run |
Run the full pipeline manually |
/news-digest |
Read the latest brief with 5-section analysis |
/news-status |
Show article/story counts and last run time |
/news-stop |
Show cleanup options |
Herald v2 uses a 4-stage pipeline with SQLite storage:
- Collect — fetches RSS/Atom feeds and HN front-page stories via public APIs. Optional Tavily adapter for web search.
- Ingest — UPSERT articles with URL canonicalization, deduplication, topic assignment, and cross-source mention tracking.
- Cluster — groups related articles into stories using
SequenceMatchertitle similarity with 4 merge guards (threshold, time gap, title length, version/number conflict). Canonical article re-election with hysteresis. - Project — generates a Markdown brief with YAML frontmatter, stories grouped by type (release, research, tutorial, opinion, news), scored and ranked.
sources → articles → mentions (cross-source)
→ article_topics
→ story_articles → stories → story_topics
- Article score:
source_weight + min(points/500, 3.0) + keyword_density * 0.2 + release_boost - Story score:
max(article_scores) + log(source_count) * 0.3 + momentum
Config: ~/.herald/config.yaml
sources:
- id: hn
name: Hacker News
type: hn # hn | rss | tavily
weight: 0.3
category: community
- id: simonw
name: Simon Willison
type: rss
url: https://simonwillison.net/atom/everything/
weight: 0.25
category: community
topics:
ai_agents:
keywords: [agent, agents, agentic, tool use, mcp]
ai_models:
keywords: [claude, gpt, gemini, llama, llm]
clustering:
threshold: 0.65 # title similarity threshold
max_time_gap_days: 7 # max days between clustered articles
schedule:
interval_hours: 4~/.herald/
├── config.yaml
├── herald.db # SQLite database
└── briefs/
└── {run_id}.md # generated briefs
- Python 3.12+
httpx,fastfeedparser,pyyaml- macOS or Linux
- Claude Code
Herald fetches only public RSS feeds and the HN Algolia API. All data stays on your machine under ~/.herald/. No telemetry, no cloud sync. Optional Tavily adapter requires a free API key but is not needed for core functionality.
Found a bug? All heurema plugins ship with Reporter - file issues without leaving Claude Code:
claude plugin install reporter@emporium
/report bug- Herald v2: Local-First News Intelligence for AI Agents - blog post with architecture deep-dive
- emporium - plugin marketplace
- signum - contract-first AI dev pipeline
- reporter - issue filing from Claude Code