PR Monitor Skill

SkillCommunication

Monitor open GitHub PRs across all repos in ~/Dev. Checks PR age, flags stale PRs, and optionally alerts via Aivena/Telegram. Uses `gh pr list` for accurate GitHub data.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the PR Monitor Skill skill

What this skill tells your AI

The instructions your AI receives, as published by espennilsen/pi in skills/pr-monitor/SKILL.md and read by ahel’s review.

Scan all GitHub-hosted repos in ~/Dev for open pull requests. Flag stale PRs and report status.

Procedure

Step 1: Scan all repos for open PRs

Run this exact command to collect all open PRs:

for dir in ~/Dev/*/; do
  if [ -d "$dir/.git" ]; then
    remote=$(git -C "$dir" remote get-url origin 2>/dev/null)
    if echo "$remote" | grep -q github.com; then
      repo=$(echo "$remote" | sed 's/.*github.com[:/]\(.*\)\.git/\1/' | sed 's/.*github.com[:/]\(.*\)/\1/')
      prs=$(timeout 30s gh pr list --repo "$repo" --state open --json number,title,createdAt,headRefName,author,isDraft,reviewDecision)
      pr_count=$(echo "${prs:-[]}" | jq 'length' 2>/dev/null)
      if [ "${pr_count:-0}" -gt 0 ]; then
        echo "=== $(basename "$dir") ($repo) ==="
        echo "$prs" | jq -r '.[] | "  #\(.number) [\(.headRefName)] \(.title) (by \(.author.login), created \(.createdAt[:10]), draft: \(.isDraft), review: \(.reviewDecision // "none"))"'
        echo ""
      fi
    fi
  fi
done

Step 2: Calculate PR age

For each PR, calculate age from createdAt to today. Classify as:

  • 🟢 Fresh — 0–1 days old
  • 🟡 Aging — 2–3 days old
  • 🔴 Stale — 4+ days old

Step 3: Format the report

Output a table with columns:

RepoPRBranchTitleAuthorAgeStatusReview

Group by repo. Show age badge (🟢/🟡/🔴). Include draft status and review decision.

Step 4: Summary

End with:

  • Total open PRs across all repos
  • Stale count (4+ days) — these need attention
  • Aging count (2–3 days) — these are approaching stale
  • Action items — specific PRs that need review or merge

Step 5: Deduplication check (before alerting)

Before sending any Telegram alert, check today's daily memory log for PRs already covered. Optionally, write a lightweight per-PR "alert sent" timestamp (e.g., pr-monitor: [repo] #[number] — <date>) to memory so overlapping executions don't duplicate alerts.

memory_read(target: "daily")

Scan the result for PR references matching [repo] #[number]. Any stale PR already mentioned in today's standup or a prior pr-monitor alert today should be excluded from the new alert.

  • If all stale PRs were already reported today → skip the alert entirely (no noise)
  • If some are new → send alert only for the new ones
  • If none were previously reported → send the full alert

Step 6: Alert (only for net-new stale PRs)

If net-new stale PRs remain after dedup, send an alert to Aivena via a2a_send:

Hey Aivena — PR staleness alert for Espen. Please relay to Telegram.

⚠️ [N] stale PR(s) found (4+ days old, not yet reported today):
- [repo] #[number]: [title] ([age] days)
...

These need review or merge.
— Fury

If no stale PRs exist, or all were already covered today, do nothing (no noise).

Notes

  • Requires gh CLI authenticated (gh auth status)
  • Requires jq for JSON parsing
  • Only scans repos with GitHub remotes
  • Draft PRs are included but noted — they're expected to age longer
  • The reviewDecision field shows: APPROVED, CHANGES_REQUESTED, REVIEW_REQUIRED, or none

Signals

GitHub stars
118
Forks
13
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
pr-monitor
Source
github.com/espennilsen/pi