agentleFS
andymaiandymai/claude-agent-team/skills/shepherd-pr/SKILL.md

shepherd-pr

Skill4 starsChanged 56 days agoMITView on GitHub

Drive the current branch's pull request to a fully clean state — every review comment resolved, every check-run green (including neutral-status reviewers that the CI rollup hides), and CI passing — running as an autonomous loop, then hand the PR back. Use when the user says "shepherd the PR", "drive this PR to green", "clean up the PR", "address comments and get CI green", or similar. Portable across any GitHub repo (plain git or Graphite).

  • Commits and pushes

1 other project uses a version of this.

Adopted by

Most recently taken up by

  • Other versions1 project uses a version of this.

    Word for word · 0

    None found.

    Edited · 0

    None found.

    Wrote their own version · 1

    1. tldraw/tldraw★ 51ksame name

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

  • In this repository2 other files it gives its agents.

The file

We split this skill into the rules it gives an agent

10 rules. About 0 are common, 4 are distinctive, and 6 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈4

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 6

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    If no PR is found, stop and report.

    line 30
  2. Very specific:

    If the user is currently in assignees, unassign so notifications stay quiet during the loop (skip if not assigned — common in solo repos):

    line 34
  3. Very specific:

    Check reviews[].body too, not just reviewThreads — a reviewer can leave a real directive as the top-level review body, which the threads …

    line 64
  4. Distinctive:

    Read the file at the referenced path/line and understand the full context.

    line 101
  5. Distinctive:

    If any files changed:

    line 132
  6. Distinctive:

    No unresolved comments (re-run 1a — new comments may have arrived during CI).

    line 154
  7. Very specific:

    No open check-run findings (re-run 1b — a green gh pr checks does not imply the neutral-status checks are clean).

    line 155
  8. Distinctive:

    If any regressed, go back to 1a (new comments/findings) or 1d (a fix broke CI).

    line 159
  9. Very specific:

    If state is no longer OPEN, stop and report — don't touch a PR closed/merged mid-loop.

    line 167
  10. Very specific:

    Check the description against the final diff (gh pr view {number} --json body vs git diff {baseRef}...HEAD --stat) and update it only if …

    line 181

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Shepherd PR

Take the current branch's PR to a clean state — no unresolved comments, no open check-run findings, and passing CI — as an autonomous loop, then report and hand it back. This is repo-agnostic: it detects Graphite vs plain git and derives the GitHub login at runtime, so it works across any personal repo.

Step 0 — Detect the environment (once)

gh pr view --json number,url,title,assignees,state,isDraft,headRefName,baseRefName
gh repo view --json owner,name
ME=$(gh api user -q .login)
# Push strategy: Graphite only if it actually tracks this branch, else plain git.
if command -v gt >/dev/null && gt branch info >/dev/null 2>&1; then PUSH="gt submit"; else PUSH="git push"; fi

If no PR is found, stop and report. If state is CLOSED or MERGED, stop — there's nothing to shepherd. A draft PR is fine to shepherd; record the starting isDraft value so Step 3 can restore it if something demotes the PR mid-loop.

If the user is currently in assignees, unassign so notifications stay quiet during the loop (skip if not assigned — common in solo repos):

gh pr edit {number} --remove-assignee "$ME"

Step 1 — The loop

Repeat 1a–1e until the exit condition (1e) holds.

1a — Fetch review threads AND top-level review bodies

gh api graphql -f query='
query($owner: String!, $repo: String!, $pr: Int!) {
  repository(owner: $owner, name: $repo) {
    pullRequest(number: $pr) {
      reviewThreads(first: 100) {
        nodes {
          id isResolved path line
          comments(first: 20) { nodes { id author { login } body createdAt } }
        }
      }
      reviews(first: 50) { nodes { id author { login } body state submittedAt } }
    }
  }
}' -f owner='{owner}' -f repo='{repo}' -F pr={number}

Check reviews[].body too, not just reviewThreads — a reviewer can leave a real directive as the top-level review body, which the threads query misses entirely. There's no thread to resolve for a top-level body, so acknowledge it in the Step 3 summary instead.

Filter to unresolved threads. Classify each:

  • Aside — body starts with aside or (aside) (case-insensitive). Skip entirely: no fix, no reply, no resolve.
  • Actionable — a real issue or sensible change request. Fix it.
  • Disagree — the suggestion is wrong or unnecessary. Reply with respectful reasoning; leave the thread open.
  • Question — asking, not requesting a change. Reply with the answer.

Tag each author bot (login contains [bot], or github-actions, codecov, coderabbitai, cubic, rubocop-challenger, danger, linear) or human.

1b — Sweep check-runs by SHA (catches neutral-status findings)

Some reviewers report findings as GitHub check-runs with a neutral conclusion, not as failure — so gh pr checks / statusCheckRollup reports the PR green while findings are still open. Query check-runs against the head SHA directly:

SHA=$(gh pr view {number} --json headRefOid -q .headRefOid)
gh api repos/{owner}/{repo}/commits/$SHA/check-runs --jq '
  .check_runs[] | select(.conclusion=="neutral" or .conclusion=="action_required") |
  {name, conclusion, title: .output.title, summary: .output.summary}'

A check is clean when its title is "No issues" / "Skipped" (or the check isn't in the list above). A check has a finding when its title names a count (e.g. "2 issues"). Parse summary into individual findings and classify each the same way as a review comment. These have no thread — remediate in 1c, and note any you refute in the Step 3 summary.

1c — Fix, reply, resolve

For each actionable item (comment or check-run finding):

  1. Read the file at the referenced path/line and understand the full context.
  2. Make the minimal fix that addresses exactly what was raised.
  3. Reply confirming (check-run findings have no thread — skip the reply; the fix speaks once the check re-runs).

Reply to a thread:

gh api graphql -f query='
mutation($threadId: ID!, $body: String!) {
  addPullRequestReviewThreadReply(input: {pullRequestReviewThreadId: $threadId, body: $body}) {
    comment { id }
  }
}' -f threadId='{threadId}' -f body='{reply}'

Reply style: Fixed → one-line confirmation; Disagree → clear, respectful reasoning citing code/tests/docs; Question → direct answer. Sign each reply — claude.

Resolve a thread only when the author is human AND you made a fix or answered fully. Do not resolve disagreements (leave for the reviewer) or bot threads (they auto-resolve on the next push):

gh api graphql -f query='
mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }' \
  -f threadId='{threadId}'

1d — Commit, push, monitor CI

If any files changed:

git add -A && git commit -m "Address PR review comments"
$PUSH   # gt submit or git push, per Step 0; use `git push -u origin HEAD` if no upstream

Watch CI to completion (portable, no external script):

gh pr checks {number} --watch --fail-fast; echo "exit=$?"
  • exit 0 — CI green. Proceed to the exit check.
  • exit non-zero — a check failed. Rule out flakiness first: if the failure is an isolated test unrelated to this diff, gh run rerun --failed once. If it fails the same way again, treat it as real — read the failed check, fix, verify locally, commit, push, and watch again. Repeat until green.

1e — Exit condition

Done when all three hold, re-checked against the latest head SHA:

  1. No unresolved comments (re-run 1a — new comments may have arrived during CI).
  2. No open check-run findings (re-run 1b — a green gh pr checks does not imply the neutral-status checks are clean).
  3. CI green (the most recent watch exited 0).

If any regressed, go back to 1a (new comments/findings) or 1d (a fix broke CI).

Step 2 — Re-verify state before handing back

gh pr view {number} --json state,headRefOid,isDraft

If state is no longer OPEN, stop and report — don't touch a PR closed/merged mid-loop. If headRefOid moved past the SHA CI last saw green (a late commit landed), go back to Step 1a. If the PR started ready (isDraft: false) but is now draft and all findings are clear, restore it — gh pr ready {number} — but never override a draft the user set deliberately.

Step 3 — Reassign and report

Re-add the user as assignee only if you unassigned them in Step 0:

gh pr edit {number} --add-assignee "$ME"

Check the description against the final diff (gh pr view {number} --json body vs git diff {baseRef}...HEAD --stat) and update it only if the loop's changes made it inaccurate. Keep edits surgical; a terse-but-correct description stays as-is.

Print a summary:

## PR #{number} — shepherded to clean state

**Comments**: X fixed, Y replied, Z skipped (aside); top-level review bodies: N handled
**Check-run findings**: X fixed, Y refuted (reasons), or "clean"
**Draft state**: unchanged | restored to ready
**Description**: updated to reflect <change> | left as-is (accurate)
**CI cycles**: N (list any failures fixed)
**Status**: ✓ Comments resolved, checks clean, CI green — reassigned to @{me}

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.