Skip to content
cccskills
FreePublished on GitHub

inbox-triage

Daily GitHub notification inbox triage - surfaces aging vuln PR replies, security advisories, review requests, and mentions that need action

The English summary is being prepared. Showing the original description.

Works withGitHub
See how to install

Files included (1)

  • SKILL.md7.2 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

Today is ${today}. Read memory/MEMORY.md before starting.

Why this skill exists

Hand-tracked follow-ups live in MEMORY.md. vuln-tracker tracks the operator's vuln PRs by scanning branch names and ages the memory/pending-disclosures/ queue. Neither reads from the actual GitHub notification inbox. When a maintainer replies to a vuln PR — or a security advisory opens on a watched repo — it sits unread until someone manually checks GitHub. This skill reads the inbox and routes what needs action.

vuln-tracker covers PR and disclosure lifecycle by branch and draft state. This skill covers the notification layer — inbound responses, review requests, security alerts, mentions.

Steps

1. Fetch GitHub notifications

Run:

gh api /notifications --paginate 2>&1

Parse the JSON array. If the command errors or returns an empty array [], log INBOX_TRIAGE_SKIP: no notifications and stop.

Limit to the first 100 notifications if --paginate returns more (GitHub caps at 50 per page; two pages is enough).

For each notification record:

  • id
  • reason — why you're being notified (mention, review_requested, author, state_change, security_alert, assign, etc.)
  • subject.title
  • subject.type — PullRequest, Issue, Release, etc.
  • subject.url — API URL for the subject
  • repository.full_name
  • updated_at — ISO timestamp

2. Filter

Keep notifications where unread: true AND updated_at is within the last 14 days. Discard older or read ones.

If zero remain after filtering: log INBOX_TRIAGE_SKIP: no actionable notifications within 14 days and stop.

3. Categorize

Assign each notification to exactly one category (first match wins):

CategoryMatch criteria
SECURITYreason == "security_alert" OR title contains any of: vulnerability, vuln, CVE, advisory, security
VULN_REPLYsubject.type == "PullRequest" AND reason is one of: author, state_change, comment AND repository.full_name is NOT under the operator's own account/org (derive the operator's GitHub handle from soul/SOUL.md or the workflow's GITHUB_ACTOR — these are PRs filed on third-party repos by the vuln-scanner)
REVIEW_NEEDEDreason == "review_requested"
MENTIONreason == "mention" OR reason == "team_mention"
GENERALeverything else

4. Age vuln PR replies

For each VULN_REPLY notification, compute age_days = today minus updated_at date (integer days).

Flag urgency:

  • CRITICAL — age_days > 7 (maintainer likely hasn't responded)
  • AGING — age_days 3–7
  • FRESH — age_days < 3

Cross-reference with memory/topics/vuln-followup.md if it exists: look for the PR title in that file and pull any tracked notes (e.g. "approved", "NEEDS-ANSWER", merge status).

5. Resolve HTML URLs for action items

For each notification in SECURITY, VULN_REPLY (CRITICAL or AGING), REVIEW_NEEDED, and MENTION categories:

Try to get the HTML URL via:

gh api {subject.url} --jq '.html_url' 2>/dev/null

If that fails, construct the URL manually: https://github.com/{repository.full_name}/pulls/{number} for PRs https://github.com/{repository.full_name}/issues/{number} for issues

(Extract the number from the tail of subject.url.)

6. Write triage summary

Overwrite memory/topics/inbox-triage.md:

# GitHub Inbox Triage

Last run: {today}
Scanned: {N} unread notifications ({N} within 14 days)

## Action Required

### Security ({count})
{for each SECURITY item, sorted by age:}
- **{repo}**: {title} ({age_days}d) — {html_url}

{if none:}
None.

### Vuln PR Replies ({count_critical} critical, {count_aging} aging)
{for each VULN_REPLY sorted by age desc:}
- **[{CRITICAL|AGING|FRESH}]** `{repo}` ({age_days}d): {title} — {html_url}
  {if vuln-followup note found:} _{tracked note}_

{if none:}
None.

### Review Requested ({count})
{for each REVIEW_NEEDED item:}
- **{repo}**: {title} — {html_url}

{if none:}
None.

### Mentions ({count})
{for each MENTION item:}
- **{repo}**: {title} — {html_url}

{if none:}
None.

## No Action Needed
{count_general} general notifications (subscriptions, automated state changes).

7. Update MEMORY.md known follow-ups

Read memory/MEMORY.md. Find the ## Known Follow-ups section.

Add any VULN_REPLY CRITICAL item not already tracked there — append:

- **{repo} #{number} NEEDS-ANSWER** — {age_days}d since maintainer activity ({url})

Update any existing NEEDS-ANSWER item for a PR that now appears as FRESH in VULN_REPLY (maintainer responded recently) — change its note to RESPONDED — verify resolution.

Do NOT add GENERAL, REVIEW_NEEDED, MENTION, or SECURITY items to MEMORY.md Known Follow-ups (too noisy; security items warrant a separate issue if severe).

8. Send notification

Only send if at least one of:

  • Any SECURITY item
  • Any VULN_REPLY where urgency == CRITICAL
  • Any REVIEW_NEEDED item
  • Three or more MENTION items

Write to .pending-notify-temp/inbox-triage-${today}.md:

inbox — {today}

{if SECURITY:}
security alert: {repo} — {title}

{if VULN_REPLY CRITICAL:}
vuln PRs aging: {comma-separated list of "repo (Nd)"}

{if REVIEW_NEEDED:}
review needed: {comma-separated repo list}

{if 3+ MENTION:}
{N} mentions

read it: memory/topics/inbox-triage.md

Then:

./notify -f .pending-notify-temp/inbox-triage-${today}.md

If nothing meets the threshold: skip notification. Log that no notification was sent.

9. Log

Append to memory/logs/${today}.md:

### inbox-triage
- **Scanned:** {N} notifications
- **Security:** {N}
- **Vuln replies:** {N total} ({N_critical} critical, {N_aging} aging, {N_fresh} fresh)
- **Review needed:** {N}
- **Mentions:** {N}
- **MEMORY.md follow-ups updated:** {yes/no — what changed}
- **Notification sent:** {yes/no}
- INBOX_TRIAGE_OK

If skipped:

### inbox-triage
- INBOX_TRIAGE_SKIP: {reason}

Required Env Vars

None beyond GITHUB_TOKEN, which GitHub Actions sets automatically and gh uses internally.

Network Note

Uses gh api for all GitHub calls — it handles auth internally, so no $SECRET ever appears on the command line for the Bash permission layer to refuse. gh api works in a GitHub Actions run. If gh api /notifications fails (rate limit, auth error), log the error and exit with INBOX_TRIAGE_SKIP: api error. Use WebFetch as a fallback only if gh is unavailable — the endpoint is https://api.github.com/notifications with Authorization: Bearer $GITHUB_TOKEN, but WebFetch can't carry that auth header; prefer gh.

What this is NOT

  • Not a replacement for hand-tracked follow-ups in MEMORY.md. This reads the raw GitHub inbox.
  • Not a duplicate of vuln-tracker — vuln-tracker tracks lifecycle by branch name. This catches inbound maintainer replies via notifications.
  • Not a duplicate of vuln-tracker's disclosure-queue aging - that manages memory/pending-disclosures/ advisory drafts. This reads GitHub security alerts and PR responses.

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

Mention/keyword sweep on social platforms for [REPLACE: KEYWORDS] — trends, sentiment, top posts

The English summary is being prepared. Showing the original description.

aeonfun/aeon777Updated Oct 18, 2026

Price and volume tracker for [REPLACE: TOKEN_SYMBOL] with anomaly alerts above [REPLACE: ALERT_THRESHOLD_PCT]% movement

The English summary is being prepared. Showing the original description.

aeonfun/aeon777Updated Oct 18, 2026

First-touch review of newly opened PRs on [REPLACE: WATCHED_REPO] — verdict + welcoming comment + label

The English summary is being prepared. Showing the original description.

aeonfun/aeon777Updated Oct 18, 2026

Digest of the most interesting new posts on [REPLACE: TOPIC] from RSS feeds and the open web

The English summary is being prepared. Showing the original description.

aeonfun/aeon777Updated Oct 18, 2026

Summary of the [REPLACE: CHANNEL_PLATFORM] channel [REPLACE: CHANNEL_NAME] — top [REPLACE: TOP_N_THREADS] threads + open questions

The English summary is being prepared. Showing the original description.

aeonfun/aeon777Updated Oct 18, 2026

Watch Vercel deploys for [REPLACE: VERCEL_PROJECT] — alert on [REPLACE: ALERT_ON] in the last [REPLACE: LOOKBACK_HOURS] hours

The English summary is being prepared. Showing the original description.

aeonfun/aeon777Updated Oct 18, 2026

See all skills by aeonfun

Report a problem with this skill