atproto libraries implementation in ocaml

Feed Generator#

AT Protocol firehose client with filtering and feed skeleton generation.

This example demonstrates how to:

  • Subscribe to the Bluesky network firehose using atproto-sync
  • Filter events by type (posts, likes, follows, etc.)
  • Filter posts by keyword content
  • Parse and decode CAR files and DAG-CBOR records
  • Generate feed skeleton output for custom feed generators

Building#

dune build examples/feed_generator/feed_generator.exe

Usage#

dune exec examples/feed_generator/feed_generator.exe -- [OPTIONS]

Options#

Option Description
--cursor <INT64> Resume from a specific sequence number
--limit <INT> Stop after N matched events
--filter <TYPES> Filter by event type (comma-separated)
-k, --keyword <STRING> Filter posts containing keyword (case-insensitive)
--json Output events as JSON
--content Include decoded record content in output
-s, --skeleton Output feed skeleton at end (for custom feeds)

Event Types#

Available filter types:

  • posts - app.bsky.feed.post records
  • likes - app.bsky.feed.like records
  • follows - app.bsky.graph.follow records
  • reposts - app.bsky.feed.repost records
  • blocks - app.bsky.graph.block records
  • lists - app.bsky.graph.list records
  • profiles - app.bsky.actor.profile records
  • feeds - app.bsky.feed.generator records
  • commits - all commit events
  • identities - identity change events
  • accounts - account status events
  • handles - handle change events
  • tombstones - account deletion events

Examples#

Watch all posts#

feed_generator --filter posts

Filter posts by keyword#

feed_generator --filter posts --keyword "ocaml" --limit 10

Generate a feed skeleton#

Collect posts matching a keyword and output a feed skeleton suitable for serving via app.bsky.feed.getFeedSkeleton:

feed_generator --filter posts --keyword "rust" --limit 50 --skeleton

Output includes:

{
  "feed": [
    {"post": "at://did:plc:xxx/app.bsky.feed.post/abc123"},
    {"post": "at://did:plc:yyy/app.bsky.feed.post/def456"}
  ]
}

JSON output with full record content#

feed_generator --filter posts --json --content --limit 5

Watch multiple event types#

feed_generator --filter posts,likes,follows --limit 100

Resume from a cursor#

feed_generator --cursor 1234567890 --limit 50

Watch all activity with decoded content#

feed_generator --content

Architecture#

The tool uses several AT Protocol libraries:

  • atproto-sync: Firehose subscription and event parsing
  • atproto-ipld: CAR file parsing, DAG-CBOR decoding, CID handling

Key components:

  1. WebSocket client: TLS-enabled WebSocket connection to the relay
  2. Event handler: Processes commit, identity, account, and other events
  3. Type filter: Matches operations against Lexicon record types
  4. Keyword filter: Case-insensitive text search in post records
  5. Feed skeleton: Collects AT URIs for matched posts

Building a Custom Feed#

To build a complete custom feed generator:

  1. Use this tool to prototype your filtering logic
  2. Run with --skeleton to verify the output format
  3. Implement a persistent service that:
    • Subscribes to the firehose continuously
    • Stores matched post URIs in a database
    • Serves the feed via XRPC endpoint app.bsky.feed.getFeedSkeleton
    • Publishes a feed generator record to your repository

See the AT Protocol Feed Generator documentation for more details.