| name | GitHub Issues |
| description | Daily digest of new open issues across your repos, ranked by signal (security/bug/feature/other) |
| var | |
| tags | ["dev"] |
${var} — Optional scope. Accepts owner/repo, org:foo, user:bar. Empty = all repos owned by the authenticated user.
Read memory/MEMORY.md for context.
Read the last 2 days of memory/logs/ and extract any GitHub issue URLs already alerted — these are dedup candidates.
Steps
-
Resolve the 24-hour window and the search scope:
YESTERDAY=$(date -u -d "yesterday" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null \
|| date -u -v-1d +%Y-%m-%dT%H:%M:%SZ)
ME=$(gh api user --jq .login)
if [ -z "${var}" ]; then
SCOPE="user:$ME"
else
case "${var}" in
*:*) SCOPE="${var}" ;;
*/*) SCOPE="repo:${var}" ;;
*) SCOPE="user:${var}" ;;
esac
fi
-
Fetch every new open issue in scope with one advanced-search call (much cheaper than per-repo looping):
gh search issues --limit 100 \
--json number,title,url,createdAt,author,labels,repository,commentsCount \
-- "$SCOPE is:issue is:open created:>$YESTERDAY sort:created-desc"
Capture the JSON output directly (do not use shell redirects like > /tmp/gh-issues.json — the sandbox may block them; instead pipe to jq or save via Claude's Write tool if needed). If the call fails (422 / rate-limit / transient), fall back to looping gh issue list -R <repo> over gh repo list "$ME" --limit 100 --json nameWithOwner,hasIssuesEnabled --jq '.[] | select(.hasIssuesEnabled) | .nameWithOwner', applying the same createdAt > $YESTERDAY filter via --jq.
-
Drop URLs already alerted in the previous 2 days of logs.
-
Rank each remaining issue into a priority bucket using its labels and title (case-insensitive regex):
- P0 — security/critical: any label or title matching
security|vuln|cve|exploit|critical|urgent|outage|p0
- P1 — bug/regression: matches
bug|regression|broken|crash|error|p1
- P2 — feature/enhancement: matches
feature|enhancement|feat|p2
- P3 — other: everything else (questions, docs, chores)
-
Sort within each bucket by comment count desc, then createdAt desc (more comments = more attention already drawn).
-
If the post-dedup, post-rank set is empty: send no notification. Skip directly to step 8.
-
Format and send via ./notify. Skip empty buckets. Cap message at ~3500 chars; if over, truncate P3 first, then P2:
*GitHub Issues — ${today}*
<K> new issue(s) across <N> repo(s)
🔴 P0 — security/critical
• <repo> · #N Title (@author) [labels] — <url>
🟠 P1 — bugs
• <repo> · #N Title (@author) [labels] — <url>
🟡 P2 — features
• <repo> · #N Title (@author) — <url>
⚪ P3 — other
• <repo> · #N Title (@author) — <url>
If P3 has more than 5 entries, collapse the tail to +X more low-priority.
-
Log to memory/logs/${today}.md under ### github-issues:
- Scope used
- Counts:
P0=<n> P1=<n> P2=<n> P3=<n>
- URLs (one per line, so the next run can dedup against this log)
If counts are all zero, log a single line GITHUB_ISSUES_OK and end.
Sandbox note
gh CLI handles auth internally — no curl env-var expansion issues. The gh search issues → per-repo gh issue list fallback in step 2 covers transient sandbox or API failures.
Constraints
- Never alert the same issue twice — dedup against the prior 2 days of logs is mandatory.
- Silence on a clean day is a feature — do not send a "0 issues" message.
- Read-only: do not label, comment on, or close issues. This skill reports; it does not act.