Skip to main content
ClaudeWave
Skill510 repo starsupdated today

GitHub Monitor

GitHub Monitor watches repositories for pull requests, issues, and releases, classifying them into actionable tiers (ACT NOW, REVIEW, INFO) based on urgency signals like failed checks, stale reviews, critical labels, and major version bumps. Use this skill to centralize repository monitoring across multiple projects and receive prioritized alerts that distinguish between immediate blockers and routine updates.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/aaronjmars/aeon /tmp/github-monitor && cp -r /tmp/github-monitor/skills/github-monitor ~/.claude/skills/github-monitor
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

<!-- autoresearch: variation B — sharper output via urgency tiers, action verbs, verdict line, skip-empty -->

> **${var}** — Repo (owner/repo) to monitor. If empty, monitors all watched repos.

## Config

Read repos from `memory/watched-repos.md`. If the file is missing or empty, log `GITHUB_MONITOR_EMPTY_CONFIG` and end.

```markdown
# memory/watched-repos.md
- owner/repo
- another-owner/another-repo
```

If `${var}` is set, monitor only that repo. Otherwise monitor every entry in `watched-repos.md`.

---

Read `memory/MEMORY.md` and the last 2 days of `memory/logs/` for context (used for dedup below).

## 1. Collect

For each repo, run these three `gh` calls. Capture the JSON; do not trust any shell expansion of untrusted fields.

**Open PRs** (full shape — the extra fields power the tier classifier):
```bash
gh pr list -R $repo --state open --limit 30 \
  --json number,title,url,updatedAt,isDraft,reviewDecision,reviewRequests,statusCheckRollup,labels,author
```

**Issues opened in the last 24h**:
```bash
gh issue list -R $repo --state open --limit 20 \
  --json number,title,url,createdAt,labels,author
```
Filter client-side to items where `createdAt` is within the last 24h.

**Releases published in the last 24h** (skip drafts and prereleases):
```bash
gh release list -R $repo --limit 5 --exclude-drafts --exclude-pre-releases \
  --json tagName,publishedAt,name,url
```
Filter client-side to items where `publishedAt` is within the last 24h.

If any single `gh` call fails (network, auth, 404), record it as `gh_error(<code>)` for that repo and keep going — one repo's failure must not abort the whole run.

## 2. Classify into tiers

Walk every collected item and assign it to exactly one tier. Drop items that match no tier.

**Tier precedence (when multiple criteria qualify, pick the highest):** `ACT NOW > REVIEW > INFO`. Evaluate ACT NOW rules first; if any match, lock the tier and skip further checks for that item. Only fall through to REVIEW if no ACT NOW rule matched, and to INFO only if neither matched.

**ACT NOW** — needs a human decision today:
- Open PR, not draft, with any `statusCheckRollup[].conclusion == "FAILURE"`
- Open PR, not draft, `reviewRequests` non-empty, `updatedAt` older than 72h (reviewer ghosted)
- New issue whose labels match any of: `security`, `critical`, `p0`, `regression`, `outage`, `incident`
- Release whose `tagName` is a major bump vs. the previously logged tag (e.g. `v2.0.0` after `v1.*`)

**REVIEW** — worth a look, not urgent:
- Open PR, not draft, `reviewDecision == "REVIEW_REQUIRED"`, `updatedAt` 48–72h ago
- Open PR, not draft, `mergeStateStatus`/merge conflict markers flagged in `statusCheckRollup`
- New issue labelled `bug` or `p1`
- Release that is a minor or patch bump

**INFO** — background signal:
- Other open, non-draft PRs with `updatedAt` older than 48h
- New issue with no priority label
- Anything else passing the 24/48h windows

Drafts are never ACT NOW or REVIEW — at most INFO, and only if stale >7d. Do not alert on draft PRs just because they're idle.

Cap each tier at 5 items. If a tier would exceed 5, keep the top 5 by (tier rank, then most recently active) and append `…and N more` as the last bullet.

## 3. Dedup

Keep dedup simple — no escalation-history tracking:

- PRs: every run emits the PR's **current tier**. If an operator sees the same PR listed at the same tier day after day, that repetition is the intended signal (it has been sitting unresolved) — not noise.
- Issues: `${repo}!${number}` — alert once, then skip in subsequent runs within the last 48h of logs.
- Releases: `${repo}@${tagName}` — alert once, then skip in subsequent runs within the last 48h of logs.

Record each PR identifier and its assigned tier in the log (step 5) for traceability, but do not consult prior runs to gate PR re-emission.

## 4. Notify

Compose **one** consolidated `./notify` message. Requirements:

- Verdict line first: `*GitHub Monitor* — N repos scanned, M need action` (M = count of ACT NOW items).
- Skip any empty tier entirely (no `▶ ACT NOW` header if zero items).
- Every bullet **starts with an imperative verb** (Review, Triage, Unblock, Merge, Note, Close) and **ends with the item URL**.
- Each bullet includes the one fact that justifies the tier (CI failing Nx, security label, reviewer idle Xh, major bump from v1.x, etc.) — not just the title.
- If any repo errored, append a single footer line: `sources: repoA=ok repoB=gh_error(404)` — so the reader can see which repos were scanned vs. skipped.

Template:
```
*GitHub Monitor* — 4 repos scanned, 2 need action
▶ ACT NOW
  • Review owner/repo#12 — CI failing 3×, author pinged 26h ago — <url>
  • Triage owner/repo!30 — security label, opened 2h ago — <url>
▶ REVIEW
  • Review owner/repo#15 — review requested, 50h idle — <url>
▶ INFO
  • Note owner/repo v1.2.0 shipped (minor) — <url>
sources: owner/repo=ok another/repo=gh_error(404)
```

**If every tier is empty, do not send a notification.** Just log `GITHUB_MONITOR_OK repos=N` (step 5) and end. Silence is the correct signal when nothing changed.

## 5. Log

Append to `memory/logs/${today}.md` under a `### github-monitor` heading:

- Tier counts: `ACT_NOW=N REVIEW=N INFO=N`
- Each surfaced item's stable identifier and tier (plain lines like `owner/repo#12 ACT_NOW`), so tomorrow's run can dedup and detect escalations.
- `sources:` line mirroring the notification footer, including any `gh_error(...)` entries.
- If nothing was notified: a single line `GITHUB_MONITOR_OK repos=N`.
- If `watched-repos.md` was missing/empty: `GITHUB_MONITOR_EMPTY_CONFIG`.
- If all repo calls errored: `GITHUB_MONITOR_ERROR sources=...` (do not notify in this case — silent failure to the user, visible failure in logs).

## Sandbox note

`gh` authenticates using the workflow's `GITHUB_TOKEN` and works inside the sandbox — no curl fallback needed. If a per-repo call errors, tag it as `gh_error(<code>)` in the sources footer and continue. Do not retry in a loop.

## Secur