Feed Subscriptions & Resource Monitoring
- Status: shipped
- Date: 2026-02-24
- Updated: 2026-02-27
- Related: ADR-0087 (observability pipeline), ADR-0112 (caching layer)
Context
Joel wants to “subscribe” to external resources — blogs, repos, guides — and get periodic summaries of changes. The first concrete case: Simon Willison’s agentic engineering patterns guide and his blog in general.
Currently joelclaw has no mechanism to monitor external content for changes and surface updates. Discovery captures are one-shot — fire and forget.
Decision
Build a feed subscription system as an Inngest cron that:
- Checks subscribed resources on a schedule (hourly for RSS, daily for scraped pages)
- Detects changes via content hash diff or feed entry timestamps
- Summarizes updates via LLM when changes are detected
- Publishes to
/coolon joelclaw.com (discovery pipeline) - Notifies Joel with a brief review summary via gateway
Feed Types (efficiency-first)
| Type | Method | Frequency | Example |
|---|---|---|---|
| Atom/RSS | Standard feed parse | Hourly | Simon Willison’s blog |
| GitHub repo | GitHub API releases/commits | Hourly | frontman-ai/frontman |
| Living page | Content hash diff (defuddle) | Daily | Simon’s agentic patterns guide |
| Substack | RSS feed | Hourly | simonw.substack.com |
| Bluesky | AT Protocol firehose/feed | Hourly | simonwillison.net on bsky |
Subscription Schema
interface Subscription {
id: string
name: string // "Simon Willison"
feedUrl: string // Atom/RSS URL or GitHub API URL
type: "atom" | "rss" | "github" | "page" | "bluesky"
checkInterval: "hourly" | "daily" | "weekly"
lastChecked: number
lastContentHash: string // For page-type change detection
lastEntryId: string // For feed-type dedup
filters?: string[] // Tag/topic filters (e.g., ["ai", "agents", "llm"])
publishToCool: false // Default OFF — /cool is curated, not a firehose
notify: boolean // Send gateway notification with approve/dismiss
summarize: boolean // LLM summarize changes
active: boolean
}Storage
Redis sorted set subscriptions:feeds with subscription metadata as JSON values. Content hashes and last-seen entry IDs for dedup.
Inngest Functions
subscription/check-feeds— Cron (hourly). Fans out per subscription.subscription/check-single— Per-subscription: fetch, diff, detect changes.subscription/summarize— LLM summarize new entries/changes.subscription/publish— Firediscovery/notedfor new items, notify gateway.
CLI
joelclaw subscribe add <url> [--name "Simon Willison"] [--filter ai,agents] [--interval hourly]
joelclaw subscribe list
joelclaw subscribe remove <id>
joelclaw subscribe check [--id <id>] # Manual trigger
joelclaw subscribe summary # What's new across all subscriptionsInitial Subscriptions
| Name | URL | Type | Filter |
|---|---|---|---|
| Simon Willison (all) | https://simonwillison.net/atom/everything/ | atom | — |
| Simon Willison (agentic guide) | https://simonwillison.net/guides/agentic-engineering-patterns/ | page | — |
| Frontman AI | https://github.com/frontman-ai/frontman | github | releases |
| Kimaki | https://github.com/remorses/kimaki | github | releases |
| OpenClaw | https://github.com/openclaw/openclaw | github | releases |
Consequences
- External content monitoring becomes a first-class capability
- RSS/Atom preferred over scraping (efficient, polite, stable)
- GitHub API for repos (rate-limited but reliable)
- Page hash diff as fallback for non-feed content
- LLM summarization costs per update (~$0.01-0.05 per summary)
/coolstays curated — nothing auto-publishes. Joel approves via gateway notification button.- Joel gets brief notification summaries with [Publish to /cool] [Dismiss] buttons
- Only items Joel explicitly approves reach
/cool— quality over quantity
Publishing Flow
Feed update detected
→ LLM summarizes (brief, relevant-to-joelclaw filter)
→ Gateway notification with summary + [Publish to /cool] [Dismiss]
→ Joel taps Publish → fires discovery/noted → appears on /cool
→ Joel taps Dismiss → logged, not publishedThe LLM summary step should also assess relevance to joelclaw (agents, personal infra, BEAM/Elixir, developer tools, agentic patterns). Low-relevance items get a shorter notification without the publish button — just “FYI: Simon posted about Django migrations” vs a full card for “Simon published new agentic engineering patterns.”
Implementation Status (2026-02-27)
✅ Completed
- Redis storage:
joelclaw:subscriptionshash (packages/system-bus/src/lib/subscriptions.ts) - Feed checker: Atom/RSS parse, GitHub API, page hash diff (
packages/system-bus/src/lib/feed-checker.ts) - Inngest functions:
subscription/check-feeds(cron hourly) +subscription/check-single(packages/system-bus/src/inngest/functions/subscriptions.ts) - CLI commands:
joelclaw subscribe {list|add|remove|check|summary}(packages/cli/src/commands/subscribe.ts) - Skill:
monitorskill for agent-driven subscription management (skills/monitor/SKILL.md) - Discovery integration: Discovery skill updated with Step 2 “Assess for Monitoring” — agent recommends monitoring for relevant resources
- Live subscriptions: Simon Willison (atom + page), Frontman AI (github), json-render (github)
Active Subscriptions (as of 2026-02-27)
| ID | Name | Type | Interval |
|---|---|---|---|
| simon-willison-all | Simon Willison (all) | atom | hourly |
| simon-willison-agentic | Simon Willison (agentic guide) | page | daily |
| frontman-ai | Frontman AI | github | daily |
| json-render | json-render | github | daily |
Non-Goals (v1)
- No auto-publishing to /cool — ever. Joel curates.
- No full-text indexing of subscribed content (just summaries)
- No social media monitoring beyond Bluesky (Twitter API too expensive)
- No comment/reply tracking
- No real-time (webhook) — polling only