Skip to content
waynehacking8Public

About

Daily email digest of trending GitHub tools — GitHub Trending + Hacker News + new-repo search, no X API. Runs on GitHub Actions.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

gh-radar

A sparse alert for GitHub repos important enough to deserve your attention — without touching the X API.

You saw mempalace on X and thought "how did I not know about this?". gh-radar is the cron job that makes sure you find the next one. Every morning it pulls the tools that are trending and being discussed, dedupes them, and applies a strict, tiered importance gate. Must-see items can expand the alert beyond five; notable items only fill empty slots in the normal five-item target. A ten-item safety cap prevents runaway alerts, and on an ordinary day it sends nothing.

It reads the places tools surface, across several current-signal angles. Five of the six sources need no API key at all; only Reddit is opt-in. A Claude subscription (CLI or token) adds the Chinese summaries and resolves Chinese-prose tweets — without it the digest still ships in English.

Source Signal How Key
GitHub Trending today's global rank + star velocity + per-language public HTML —
Hacker News what devs are discussing now Algolia API —
GitHub Search brand-new repos gaining stars official API —
Lobsters curated programming community hottest.json —
X / Twitter tools shared by curated accounts Firecrawl scrape (free, keyless) —
Reddit r/commandline, r/selfhosted, … OAuth API REDDIT_CLIENT_ID + REDDIT_CLIENT_SECRET

The X layer is the one that catches an already-popular tool being re-shared (the "I saw it on X" case). Chinese tool accounts rarely link GitHub directly — they describe the tool in prose — so the LLM extracts the tool name and a GitHub search, disambiguated by the star count mentioned in the post, resolves the real repo (e.g. "记忆宫殿 55K star" → MemPalace/mempalace). A free FIRECRAWL_API_KEY raises rate limits if the keyless tier starts returning 429s.

Discovery remains broad but fresh: stale weekly Trending entries and undated web listicles are excluded, and X/Lobsters items must be no more than 48 hours old. A repo is delivered only when it reaches one of two explicit tiers:

  • Tier A / must-see: global Trending top 3; at least 500 stars/day; HN 200, X 300, Reddit 750, or Lobsters 100 engagement; a new repo already at 2,000 stars; or moderate activity from at least two independently active source families. Every Tier A item is sent, up to the ten-item safety cap.
  • Tier B / notable: at least 250 stars/day; HN 100, X 100, Reddit 300, or Lobsters 50 engagement; or a new repo already at 1,000 stars. Tier B only fills the alert to the normal target of five—it never displaces Tier A or extends an alert that already contains five Tier A items.

A 90-day memory stops old projects recycling into the alert. Any single source can fail or be disabled without affecting the rest.

Run it on GitHub Actions (recommended — laptop can be off)

The included workflow (.github/workflows/radar.yml) runs daily at 08:00 Taipei on GitHub's servers, emails you the digest, commits a browsable copy to digests/, and persists the de-dup memory in state/.

Setup — Repo → Settings → Secrets and variables → Actions, add:

Secret Value
GMAIL_USER your gmail address
GMAIL_APP_PASSWORD a Gmail App Password (needs 2FA)

GITHUB_TOKEN is injected automatically (lifts the API limit to 5000/hr). Trigger a run any time from the Actions tab → gh-radar → Run workflow.

Run it locally instead

cd gh-radar
cp config.example.env config.env   # then fill in SMTP_PASS (Gmail App Password)
./run.sh                           # run once; missing SMTP prints the digest and exits failed
./install.sh 8                     # schedule daily at 08:00 via cron

The run reports one fixed status: sent, no_new, already_completed, or failure. GitHub Actions also appends that status to GITHUB_STEP_SUMMARY without addresses, secrets, or exception details. Missing SMTP configuration prints the digest; failed delivery raises an error. Neither updates the de-dup state, so a later run can retry it.

Zero pip dependencies — Python 3.9+ standard library only.

Sample output

gh-radar: collecting…
  trending: 120 repos
  hn: 91 repos
  new: 30 repos
  lobsters: 1 repos
  x: 3 repos
  ✓ X: 3 repo(s) resolved from prose tweets
  important: 6 Tier A + 4 Tier B qualified; selected 6 Tier A + 0 Tier B from 147 repos
  ✓ Chinese summaries: 6/6
  ✓ emailed digest to [email protected]
### 1. [MemPalace/mempalace](https://github.com/MemPalace/mempalace)
⭐ 55,992 · 𝕏 @axichuhai

> 將 AI 長期記憶從摘要快取改造成可翻閱的檔案空間,本地運行、近乎零成本。
> _A memory palace for AI agents — a browsable archive replacing summary caches._

📍 出處 / via: Firecrawl → X @axichuhai

[X post](https://x.com/axichuhai/status/...)

Config

All via env (see config.example.env):

  • GITHUB_TOKEN — recommended: lifts API limit 60→5000/hr. Without it, enrich rate-limits and only the Trending source survives.
  • FIRECRAWL_API_KEY — optional: lifts Firecrawl's keyless 429 cap for X.
  • CLAUDE_CODE_OAUTH_TOKEN — optional: enables Chinese summaries + X-prose resolution.
  • SMTP_* / EMAIL_TO — Gmail App Password delivery (EMAIL_TO falls back to SMTP_USER).
  • MIN_STARS (30), SEEN_TTL_DAYS (90), GH_RADAR_TARGET_ITEMS (5), GH_RADAR_SAFETY_CAP (10), GH_RADAR_EVERGREEN_STARS (50000) — tuning.
  • GH_RADAR_TOP_TRENDING_RANK (3), GH_RADAR_MOMENTUM_STARS_PER_DAY (250), GH_RADAR_STRONG_HN_POINTS (100), and the other GH_RADAR_STRONG_* knobs — Tier B thresholds.
  • GH_RADAR_MUST_SEND_STARS_PER_DAY (500), GH_RADAR_MUST_SEND_HN_POINTS (200), and the other GH_RADAR_MUST_SEND_* knobs — Tier A thresholds. A quiet run sends no email.
  • A selected digest is marked complete only after SMTP delivery succeeds. A missing or failed SMTP configuration is a failed run and does not update state/seen.json or state/last-run.
  • GH_RADAR_SOURCE_MAX_AGE_HOURS (48), GH_RADAR_NEW_REPO_MAX_AGE_DAYS (7) — explicit source freshness windows.
  • GH_RADAR_TIMEZONE (Asia/Taipei) — calendar date used by the daily sentinel and digest filename, independent of the GitHub runner's UTC clock.
  • GH_RADAR_X_ACCOUNTS, GH_RADAR_SUBREDDITS, GH_RADAR_TREND_LANGS — what each source watches.
  • GH_RADAR_VAULT / GH_RADAR_DIGEST_DIR — also save each digest as Markdown.

Project layout

A single radar.py shim (keeps python radar.py working) over the gh_radar/ package:

gh_radar/
  config.py     constants, scoring weights (config.W), env helpers
  models.py     the Repo dataclass — typed core model (merge() rejects unknown keys)
  clients.py    github / firecrawl / claude / http — every call degrades to None
  sources.py    one src_*() per signal; SOURCES table; enrich()
  scoring.py    Tier A/B classification + ranking + evergreen-noise filter
  state.py      de-dup memory (seen.json), atomic writes
  render.py     zh summaries, Markdown digest, HTML
  email_out.py  SMTP delivery
  cli.py        collect → select → render → email → remember

Standard library only — zero pip dependencies.

Honest limitations

  • GitHub Trending has no official API, so that source is an HTML scrape that can break on a redesign. The other five keep the digest alive if it does.
  • No GITHUB_TOKEN = trending-only. Without a token the GitHub API rate-limits and every non-trending repo is dropped at the enrich step. CI injects one.
  • X prose resolution needs Claude. Without the CLI/token, X keeps only tweets that link a repo directly; Chinese-prose tools are skipped (graceful).
  • Precision wins over recall. Weekly Trending and generic "best tools" listicles are intentionally excluded because neither proves that a repo matters now. X posts without a verifiably recent status ID are also dropped.

How scoring works (config.W)

score = stars_today                       # trending velocity
      + 2 × hn_points                     # discussion = strong "people care" signal
      + 120 if shared on a curated X acct # a human you follow chose it — strongest
      + 15 × min(x_mentions, 5)
      + 0.02 × min(reddit_points, 1000)
      + 0.3 × min(lobsters_score, 200)
      + 40 if brand-new repo              # novelty
      + 0.01 × min(stars, 5000)           # mild popularity tiebreak
      + 15 × (number of sources)          # multi-source = stronger signal
      + 100–300 for global Trending #3–#1

Qualification and delivery size are separate: Tier A expands from 1–10 items; Tier B fills only up to the five-item target. A 90-day memory stops repeats.

About

Daily email digest of trending GitHub tools — GitHub Trending + Hacker News + new-repo search, no X API. Runs on GitHub Actions.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages