Skip to content

Reconstruct deleted oss-feed skill (daily GitHub activity collector) #3

Description

@ryota-murakami

Goal

Reconstruct the deleted oss-feed skill — a daily GitHub activity digest tool that tracks key OSS engineers in the React / TanStack / Next.js ecosystem and produces a JSON summary suitable for blog/article generation.

Background

The previous version of this skill was accidentally deleted via a bug in skills-desktop. We have ~85–90% of the structure recoverable from prior usage and conversation logs. This issue captures everything we know so we can rebuild it cleanly.

Skill structure

oss-feed/
├── SKILL.md
└── scripts/
    └── collect.sh

SKILL.md (intent)

  • What it is: Daily OSS activity collector for a curated list of engineers.
  • Manual run: bash ~/.agents/skills/oss-feed/scripts/collect.sh [hours]
  • Automatic mode: Daily isolated cron job that runs the script and produces a digest article.
  • Configuration: The tracked engineers live in the USERS array inside scripts/collect.sh. Edit the array to add/remove people.
  • Output: Writes JSON to /tmp/oss-feed-latest.json.

Summarization guidelines (carry over from previous SKILL.md)

  1. Group by engineer; show most interesting activity first.
  2. Include direct links to Issues / PRs.
  3. Highlight anything related to React, Next.js, or the TanStack ecosystem.
  4. Note any RFCs, breaking changes, or architectural discussions.
  5. Skip bot/automated activity (dependabot, etc.).
  6. If an engineer had no activity, render 静かな一日 instead of an empty section.

scripts/collect.sh

Interface

bash collect.sh [hours]   # default: 24
# Writes: /tmp/oss-feed-latest.json

Tracked engineers (canonical list)

USERS=(
  "acdlite"        # Andrew Clark - React core
  "gaearon"        # Dan Abramov - React / Bluesky
  "sebmarkbage"    # Sebastian Markbåge - React architecture
  "bluebill1049"   # Bill Luo - React Hook Form
  "leerob"         # Lee Robinson - Vercel/Next.js
  "timneutkens"    # Tim Neutkens - Next.js
  "bvaughn"        # Brian Vaughn - ex-React core, React DevTools
  "t3dotgg"        # Theo Browne - T3 Stack, Ping.gg
  "TkDodo"         # Dominik Dorfmeister - TanStack Query maintainer
  "phryneas"       # Lenz Weber-Tronic - Redux Toolkit / Apollo
  "markerikson"    # Mark Erikson - Redux maintainer
  "kettanaito"     # Artem Zakharchenko - MSW (Mock Service Worker)
  "dinwwwh"        # Định Lê - oRPC
  "yyx990803"      # Evan You - Vue.js / Vite / Rolldown
)

Output JSON shape

{
  "collected_at": "<ISO timestamp, when the script ran>",
  "period": "24h",
  "since": "<ISO timestamp, lookback start>",
  "engineers": {
    "<github_username>": {
      "issues_opened": [...],
      "prs_opened": [...],
      "issue_comments": [...],
      "pr_reviews": [...]
    }
  }
}

Required behaviors

  • Use gh api (GitHub CLI) to query each user's recent activity within the lookback window.
  • For each user, collect: issues opened, PRs opened, issue comments, PR reviews. Filter by created_at > SINCE.
  • Skip bot/automated activity (e.g. dependabot, renovate-bot).

Rate-limit hardening (must-have)

This was added previously after we hit secondary rate limits during runs. Re-implement:

gh_api_safe() {
  local query="$1"
  local jq_filter="$2"
  local attempt=0
  local result
  while [ $attempt -lt 3 ]; do
    result=$(gh api "$query" --jq "$jq_filter" 2>&1)
    if echo "$result" | grep -q "secondary rate limit\|API rate limit exceeded"; then
      attempt=$((attempt + 1))
      local wait_time=$((attempt * 30))   # 30s, 60s, 90s backoff
      echo "  ⚠️  Rate limited, waiting ${wait_time}s (attempt ${attempt}/3)..." >&2
      sleep $wait_time
      continue
    fi
    if echo "$result" | head -c 1 | grep -q '\['; then
      echo "$result"
      return 0
    fi
    echo "[]"
    return 0
  done
  echo "[]"
}

Additionally:

  • sleep 2 between API calls inside the same user (4 endpoints).
  • sleep 8 between users (longer to avoid secondary rate limits across the loop).
  • Validate JSON output before writing (must start with [ for arrays, fall back to [] on parse failure).

Header / setup

#!/usr/bin/env bash
set -euo pipefail

HOURS="${1:-24}"
SINCE=$(date -u -v-${HOURS}H +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null \
       || date -u -d "${HOURS} hours ago" +"%Y-%m-%dT%H:%M:%SZ")
OUTPUT="/tmp/oss-feed-latest.json"

(Compatible with both BSD date on macOS and GNU date on Linux.)

Cron integration (current state)

A cron job exists in OpenClaw with id 067ef093-d4e2-435c-a2c3-89f3fc54d687 named "OSS Feed Daily Digest". It is currently disabled until the skill is rebuilt. The cron's prompt expects:

  1. bash ~/.agents/skills/oss-feed/scripts/collect.sh 24
  2. Read /tmp/oss-feed-latest.json
  3. Build a Japanese digest grouped by engineer (link-rich).
  4. Send a terminal-notifier macOS notification.
  5. Generate an English MDX article in ~/laststance/laststance.io/src/app/articles/OSS-Feed-YYYY-MM-DD/ (page.tsx + content.mdx).
  6. Run pnpm lint:fix, then git add / commit / push (added on 2026-04-24 to prevent CI failures).

The skill itself only needs to produce /tmp/oss-feed-latest.json reliably — everything else (translation, article generation, commit) lives in the cron prompt.

Failure mode to avoid

When the previous skill went missing, the cron still ran but produced a hallucinated article that fabricated @vercel, @shadcn, and @cloudflare entries (none of which were in the USERS list). The article was reverted in laststance/laststance.io. The cron is disabled until the skill is back.

To prevent this from recurring, the cron prompt should fail loudly if /tmp/oss-feed-latest.json does not exist or is empty / malformed, instead of improvising content.

Uncertain pieces (need verification during rebuild)

These details are not confidently recovered and should be re-derived against the GitHub API docs:

  • Exact gh api query strings for each of: issues opened, PRs opened, issue comments, PR reviews.
  • Exact field shape per activity (title, url, created_at, repo, etc.).
  • Bot filtering rules (likely a username allow/deny list).

Acceptance criteria

  • oss-feed/SKILL.md is restored with the intent, manual usage, configuration, output schema, and summarization guidelines above.
  • oss-feed/scripts/collect.sh is restored with the canonical USERS list, the lookback window logic, the rate-limit-hardened gh_api_safe, inter-call and inter-user sleeps, and JSON validation.
  • Manual run produces a well-formed /tmp/oss-feed-latest.json matching the documented shape.
  • The disabled cron 067ef093-d4e2-435c-a2c3-89f3fc54d687 can be re-enabled without code changes on the cron side.
  • One end-to-end dry run (collector → cron prompt → article generation) succeeds before re-enabling on the schedule.

Estimated effort

~30 minutes once we sit down with it: skeleton (~10m), API plumbing + dry run (~15m), skill registration / verification (~5m).

Related

  • The cron prompt itself is stored in ~/.openclaw/cron/jobs.json (id 067ef093-d4e2-435c-a2c3-89f3fc54d687); restoring the skill does not require editing the cron.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions