npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

deso-ag

v1.0.6

Published

CLI tool for aggregating posts from decentralized social protocols (Farcaster, Lens, Nostr, Bluesky)

Readme

deso-ag

Decentralized Social Aggregator - A CLI tool and library for aggregating posts from decentralized social protocols.

Search and view content across Farcaster, Lens, Nostr, and Bluesky from your terminal or programmatically from your agent.

Installation

npm install deso-ag

Or to use as a CLI globally:

npm install -g deso-ag

From Source

git clone https://github.com/mtple/deso-ag
cd deso-ag
pnpm install

Environment Variables

| Variable | Required | Default | Description | |----------|----------|---------|-------------| | NEYNAR_API_KEY | For Farcaster | None — Farcaster is skipped | Neynar API key. Get one free at neynar.com | | BLUESKY_IDENTIFIER | For Bluesky search | None — Bluesky search is skipped, trending still works | Your Bluesky handle (e.g. user.bsky.social) | | BLUESKY_APP_PASSWORD | For Bluesky search | None — Bluesky search is skipped, trending still works | App password from bsky.app/settings/app-passwords |

Lens, Nostr, and Bluesky trending work without any keys. Bluesky search requires authentication.

Add keys to your shell profile so they persist across sessions:

# Add to ~/.zshrc or ~/.bashrc
export NEYNAR_API_KEY=your-key-here
export BLUESKY_IDENTIFIER=your-handle.bsky.social
export BLUESKY_APP_PASSWORD=your-app-password

Without a key, the respective source/feature is skipped and everything else still works normally.

Commands

search [query]

Search for posts across networks.

deso-ag search "ethereum"
deso-ag search "AI" --sources nostr
deso-ag search --channel dev --sources farcaster

Multi-word queries use AND semantics (all terms must match):

deso-ag search "AI crypto"       # posts must contain both "AI" and "crypto"
deso-ag search "ethereum layer2"

trending

Get trending posts from all networks.

deso-ag trending
deso-ag trending --sources farcaster,lens
deso-ag trending --format json --limit 50

terms

Extract top discussion terms from posts via engagement-weighted frequency analysis.

deso-ag terms                              # top 3 terms per platform, last 24h
deso-ag terms -n 5 -s farcaster -t week    # top 5, Farcaster only, last week
deso-ag terms -f json                      # machine-readable output

channels

Browse popular Farcaster channels.

deso-ag channels
deso-ag channels --limit 50

Options

All commands accept the following options (except where noted):

| Option | Description | Values | Default | |--------|-------------|--------|---------| | -s, --sources | Networks to query | farcaster, lens, nostr, bluesky (comma-separated) | farcaster,lens,nostr,bluesky (all) | | -t, --timeframe | Time range for posts | 24h, 48h, week | 24h | | -c, --channel | Filter by channel | Any channel ID (Farcaster only) | none | | -f, --format | Output format | json, markdown, summary, compact | markdown (search), summary (trending) | | -l, --limit | Max posts per source | Any positive integer | 25 | | -o, --sort | Sort order | engagement, recent, relevance | relevance (search), engagement (trending) | | -n, --top | Top terms per source | Any positive integer (terms command only) | 3 |

Output Formats

  • markdown - Human-readable with headers, author info, and engagement stats. Default for search.
  • summary - Condensed overview with post counts and top content. Default for trending.
  • json - Raw JSON array of post objects. Good for piping to other tools.
  • compact - Single JSON object with metadata envelope, engagement scores, and full content. Designed for AI agents.

Sort Orders

  • engagement - By score (likes + reposts*2 + replies). Best for discovering high-signal content. Default for trending.
  • recent - By timestamp descending. Best for monitoring.
  • relevance - Query-matching posts first, then by engagement. Default for search.

Agent Usage

deso-ag is designed for consumption by AI agents doing research across decentralized social networks.

Compact Output Format

The compact format returns a single JSON object with a metadata envelope, pre-computed engagement scores, full untruncated content, and source health info:

deso-ag trending -f compact -l 10
deso-ag search "AI agents" -f compact -l 10

Output shape:

{
  "meta": {
    "query": "AI agents",
    "totalPosts": 42,
    "sources": [
      {"name": "farcaster", "count": 15},
      {"name": "lens", "count": 12},
      {"name": "nostr", "count": 15}
    ],
    "timeframe": "24h",
    "fetchedAt": "2025-01-01T00:00:00.000Z"
  },
  "posts": [
    {
      "id": "...",
      "source": "farcaster",
      "author": "dwr",
      "content": "full untruncated content...",
      "timestamp": "2025-01-01T00:00:00.000Z",
      "url": "https://...",
      "score": 523,
      "engagement": {"likes": 400, "reposts": 50, "replies": 23},
      "tags": []
    }
  ]
}

Library Import

For agents that run in Node.js, import aggregate() directly instead of shelling out:

import { aggregate } from 'deso-ag';

const result = await aggregate({
  sources: ['farcaster', 'lens', 'nostr', 'bluesky'],
  timeframe: '24h',
  query: 'AI agents',
  limit: 20,
  sort: 'relevance',
});

console.log(result.meta.totalPosts);
for (const post of result.posts) {
  console.log(`[${post.source}] @${post.author.username}: ${post.content.slice(0, 100)}`);
}

The terms() function extracts top discussion terms:

import { terms } from 'deso-ag';

const result = await terms({
  sources: ['farcaster', 'nostr'],
  timeframe: '24h',
  limit: 20,
}, 5); // top 5 terms

for (const st of result.bySource) {
  console.log(`${st.source}: ${st.terms.map(t => t.token).join(', ')}`);
}

Individual fetchers and utilities are also exported:

import { fetchFarcaster, fetchLens, fetchNostr, fetchBluesky, computeEngagementScore, matchesQuery, extractTerms } from 'deso-ag';

Examples

# Get a quick summary of trending content
deso-ag trending -f summary -l 20

# Agent-optimized compact output sorted by engagement
deso-ag trending -f compact -o engagement -l 10

# Search for AI discussions on Lens only
deso-ag search "AI" -s lens -f json

# Multi-word search with compact output
deso-ag search "AI crypto" -f compact -l 10

# Browse the /dev channel on Farcaster
deso-ag search --channel dev -s farcaster

# Export trending Nostr posts as JSON
deso-ag trending -s nostr -f json > nostr-trending.json

# Search Bluesky for discussions
deso-ag search "ethereum" -s bluesky -l 5

# Trending on Bluesky
deso-ag trending -s bluesky -f summary

# Sort search results by recency
deso-ag search "ethereum" -o recent -f json -l 5

# Top 5 terms across all networks this week
deso-ag terms -n 5 -t week

# Terms from Farcaster and Nostr as JSON
deso-ag terms -f json -s farcaster,nostr -l 10

Supported Networks

| Network | API | Auth | |---------|-----|------| | Farcaster | Neynar API - trending feed and full-text search | NEYNAR_API_KEY required | | Lens | Lens V3 GraphQL API - server-side search, recent posts | None | | Nostr | nostr.wine trending API + public relays (relay.damus.io, nos.lol, relay.snort.social) | None | | Bluesky | AT Protocol API - public "What's Hot" feed for trending, authenticated search via app.bsky.feed.searchPosts | None (trending), BLUESKY_IDENTIFIER + BLUESKY_APP_PASSWORD (search) |

All networks return engagement stats (likes, reposts, replies) and support timeframe filtering.

Limitations

  • Farcaster: Requires NEYNAR_API_KEY. Without it, Farcaster is skipped.
  • Nostr: Relay responses can be slow or inconsistent depending on network conditions.
  • Rate limits: All APIs have rate limits. For heavy usage, consider running your own infrastructure.

Development

pnpm build    # Build for production
pnpm test     # Run tests

Tech Stack

  • TypeScript
  • Commander.js for CLI
  • nostr-tools for Nostr protocol
  • Native fetch for HTTP requests

License

MIT

Author

Matt Lee