pr-recap
Skill9 starsChanged 37 days agoMITView on GitHub
Write or refresh a visual recap of a GitHub pull request for its reviewers, posted as one PR comment between pstack-recap markers. The recap opens with two sentences on why the change exists and what it changes, then one hand-drawn sketch of the changed mechanism, attached as an image, then one line on what the PR does not prove. Risk, SHAs, reading order, and file areas sit in a collapsed block below. Use after you open a PR or push to one when the user or the repository's contributor instructions ask for PR recaps, or when asked to "recap this PR", "visual recap", "PR recap", "diagram this PR", or "summarize this PR for reviewers". Skip trivial PRs.
1 other project uses a version of this.
Adopted by
Most recently taken up by
- grahac/claude_skillstheir own version, first seen Apr 18, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- grahac/claude_skills★ 2same 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 repository64 other files it gives its agents.
- architectSkill
- arenaSkill
- automate-meSkill
- benchmark-checklistSkill
- blast-radiusSkill
- broSkill
- correctSkill
- create-formal-verification-skillSkill
- create-verification-skillSkill
- deslopSkill
- documentation-impactSkill
- figure-it-outSkill
- howSkill
- interrogateSkill
- in-your-own-wordsSkill
- ketchupSkill
- ketchup-videoSkill
- maintain-formal-verification-skillSkill
- maintain-verification-skillSkill
- make-bot-uiSkill
- no-commentsSkill
- poteto-helpSkill
- poteto-modeSkill
- poteto-tddSkill
- poteto-teachSkill
- principle-attack-the-premiseSkill
- principle-boundary-disciplineSkill
- principle-build-the-leverSkill
- principle-encode-lessons-in-structureSkill
- principle-exhaust-the-design-spaceSkill
- principle-experience-firstSkill
- principle-explain-the-numberSkill
- principle-fix-root-causesSkill
- principle-foundational-thinkingSkill
- principle-guard-the-context-windowSkill
- principle-laziness-protocolSkill
- principle-make-operations-idempotentSkill
- principle-migrate-callers-then-delete-legacy-apisSkill
- principle-minimize-reader-loadSkill
- principle-model-the-domainSkill
- principle-never-block-on-the-humanSkill
- principle-outcome-oriented-executionSkill
- principle-prove-it-worksSkill
- principle-redesign-from-first-principlesSkill
- principle-separate-before-serializing-shared-stateSkill
- principle-sequence-verifiable-unitsSkill
- principle-subtract-before-you-addSkill
- principle-test-behavior-not-implementationSkill
- principle-type-system-disciplineSkill
- pstack-harnessSkill
- recallSkill
- reflectSkill
- runtime-probesSkill
- setup-pstackSkill
- sharpenSkill
- show-me-your-workSkill
- spec-probesSkill
- statechartSkill
- swarmSkill
- technical-writingSkill
- The first 60 shown.
The file
Show its rules and text
We split this skill into the rules it gives an agent
18 rules. About 0 are common, 6 are distinctive, and 12 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈6
Distinctive · estimate
This author's own choices. Worth a look.
12
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 8
Write one recap of a pull request for the people who review it.
- Very specific: line 10
Run this workflow locally.
- Very specific: line 25
Read the PR record with gh pr view <n> -R <host>/<owner>/<repo> --json …
- Very specific: line 26
Read the whole diff with gh pr diff <n> -R <host>/<owner>/<repo>.
- Distinctive: line 27
Read the posted reviews, the posted verdict comments, and the CI runs on the head.
- Very specific: line 38
Do not invent a rationale.
- Very specific: line 50
Never copy a secret, token, or credential-looking value from the diff.
- Very specific: line 52
Call the Skill tool with technical-writing on the recap's sentences.
- Very specific: line 56
Use one writable work folder outside the skill for scene.json, sketch.png, story.txt, and recap.md.
- Very specific: line 58
Follow the sketch. In short: pick one drawing from its catalog, write scene.json in the work folder, render it with bun …
- Distinctive: line 65
Check each one against a hunk of the diff or a SHA-pinned line.
- Very specific: line 68
Read headRefOid again. If it moved, rebuild the recap from the new diff.
- Distinctive: line 70
Keep the marks in your notes, not in the comment.
- Very specific: line 97
Keep <current> as <keep> and go to step 4.
- Very specific: line 107
When gh refuses the upload, or has no --attach, the CLI cannot upload to this host.
- Very specific: line 117
No authorization: Remove the image line from recap.md.
- Distinctive: line 119
Delete every other recap of yours, so the PR keeps one.
- Distinctive: line 128
Check the saved comment, count your recaps, then check that the image renders.
≈ “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.
Files
PR recap
Write one recap of a pull request for the people who review it. A reviewer should understand from the first screen why the change exists, what it changes, and how. The recap points into the diff. It does not replace reading the diff.
Run this workflow locally. The recap is one PR comment: GitHub Markdown plus one PNG uploaded to the PR's own host. It needs gh, and for the sketch, Bun and the bundled sketch tool. It posts nothing to any other host.
Decide whether the PR gets a recap
Skip the recap when the diff has no behavior that a reviewer must trace. Examples are a version pin and its hashes, a typo or wording fix, a formatting-only change, a lockfile-only change, and the revert of one commit. A version pin skips even across a major version, because a pin has no mechanism to sketch.
For a skipped PR, post nothing on GitHub. Put one line in your reply:
Recap skipped for PR <n>: <what the diff is>, <why it needs no recap>.
Otherwise, write the recap. Write it again after each push that changes the diff, once the new head is published and any gate run on it has reached its outcome.
Gather the facts
- Resolve
<host>/<owner>/<repo>from origin's fetch URL. Pass-R <host>/<owner>/<repo>to everygh prcall. Pass--hostname <host>to everygh apicall. - Read the PR record with
gh pr view <n> -R <host>/<owner>/<repo> --json number,title,body,baseRefName,baseRefOid,headRefOid,files,commits,reviews,comments,closingIssuesReferences. RecordbaseRefOidandheadRefOid. Every fact in the recap describes the diff between those two SHAs. - Read the whole diff with
gh pr diff <n> -R <host>/<owner>/<repo>. Read the code around each hunk you will describe, its callers, and each linked issue. Make no claim about a file you did not read. - Read the posted reviews, the posted verdict comments, and the CI runs on the head. A verdict that is not posted on the PR is not evidence.
- Build every claim from these records. Session memory can help you find a record. It cannot prove a claim.
Find the story before you write
Answer three questions in your notes, each from a record:
- Why. What went wrong, or what was needed, before this PR? Name the concrete symptom a person saw, such as a lost route, a wrong verdict, or a merge with no watcher. "Improves X" is not a why.
- What. The one mechanism the PR changes. If it changes several, pick the one the why depends on.
- How. The move that fixes it, such as a reorder, a new role, a new check, or a rewired call.
Do not invent a rationale. State a reason only when the diff, the PR body, a linked issue, a commit message, or a posted review gives it. Write any other reason as (a guess).
Write the comment
Copy the template in the block. The first screen has exactly three parts:
- The story. At most two sentences and 60 words. The first says why, with the concrete symptom. The second says what changed and how, in the words a reviewer will find in the diff. No semicolons, no file lists, no counts that the sketch already shows.
- The sketch. One image of the changed mechanism. See the sketch.
- Not covered. One line naming what the PR does not prove, such as an unmeasured runtime, an untested path, or a caveat from the posted verdict.
Everything else goes in one collapsed <details> block after them: the risk line, the SHAs, the reading order, the changed areas as a short list, and links to the proof. Do not use tables.
Never copy a secret, token, or credential-looking value from the diff. Write <redacted> in its place.
Call the Skill tool with technical-writing on the recap's sentences. Then call the Skill tool with unslop.
Draw the sketch
Use one writable work folder outside the skill for scene.json, sketch.png, story.txt, and recap.md. Run the render, reader, and posting commands from that folder. Replace <skill> with the absolute path to this skill's directory.
Follow the sketch. In short: pick one drawing from its catalog, write scene.json in the work folder, render it with bun "<skill>/scripts/sketch/sketch.mjs" scene.json sketch.png, fix every problem it reports, then look at the PNG yourself before you use it.
When your runtime has no Bun or only an older one, render through the npx --allow-scripts=bun bun@1.4.0 route in the sketch. Skip the sketch when that route fails too, or when your runtime cannot show you an image. Post the story, the "Not covered" line, and the details block, and say in your reply that the sketch was skipped and why. Do not substitute a Mermaid diagram or a table.
Check every claim before you post
- List each factual sentence in the recap and each label in the sketch.
- Check each one against a hunk of the diff or a SHA-pinned line. Mark it verified, corrected, unsupported, or unverifiable.
- Fix each corrected claim. Delete each unsupported or unverifiable claim, or rewrite it as a guess. Re-render the sketch if a label changed.
- Check each link. Pin source links to the recorded head SHA. Review and CI links must point at records on the PR, with CI runs on that head. Never include a bot review's URL anywhere in the comment, code spans included. A recap does not triage a review's findings, and watch-pr and merge-gate never count a recap as acknowledging one.
- Read
headRefOidagain. If it moved, rebuild the recap from the new diff.
Keep the marks in your notes, not in the comment. Report the counts in your reply.
Post or update the comment
Write the recap to recap.md in the same work folder, including when the sketch is skipped. With a sketch, the image line is . Run every command from that folder. attachment.mjs is <skill>/scripts/attachment.mjs. Run it with bun or node. Pass the PR's host as --host.
The comment records its sketch on the line after the start marker: <!-- pstack-recap:sketch sha256=<sketch hash> url=<attachment URL> -->. The next refresh reads it back and reuses the upload when the sketch is unchanged. The comment ID is not recorded, because a comment cannot hold its own ID. Find your recap comments by the start marker and author.
Without a sketch, do step 1, skip steps 2 and 3, and write recap.md over current with gh api --hostname <host> -X PATCH "repos/<owner>/<repo>/issues/comments/<current>" -f body="$(cat recap.md)". When there is none, run gh pr comment <n> -R <host>/<owner>/<repo> --body-file recap.md. Take <keep> from the comment, then go to step 4.
- List your recap comments, oldest first. The last one is
current. Without one, go to step 3.
me=$(gh api --hostname <host> user --jq .login)
gh api --hostname <host> --paginate "repos/<owner>/<repo>/issues/<n>/comments" \
--jq ".[] | select(.user.login == \"$me\" and (.body | startswith(\"<!-- pstack-recap:start -->\"))) | .id"
gh api --hostname <host> "repos/<owner>/<repo>/issues/comments/<current>" --jq .body > old.md- Reuse the upload.
reuseprints the recorded URL only whenold.mdrecords the hash of thissketch.png. Thenstampputs that URL and a fresh record into the new body, and the API writes it overcurrent. No attach runs.
url=$(bun "<skill>/scripts/attachment.mjs" reuse --host <host> sketch.png old.md) &&
bun "<skill>/scripts/attachment.mjs" stamp --host <host> sketch.png recap.md "$url" > body.md &&
gh api --hostname <host> -X PATCH "repos/<owner>/<repo>/issues/comments/<current>" -f body="$(cat body.md)"Keep <current> as <keep> and go to step 4. When reuse exits 1, the sketch changed or the comment has no record, so upload.
- Upload the sketch. Try the CLI once:
gh pr comment <n> -R <host>/<owner>/<repo> --body-file recap.md --attach sketch.pngIt prints the new comment's URL. Its #issuecomment-<id> is <keep>. Read that comment's body into new.md with gh api --hostname <host> "repos/<owner>/<repo>/issues/comments/<keep>" --jq .body > new.md, run stamp --host <host> sketch.png new.md > body.md, and PATCH <keep> with body.md. Go to step 4.
When gh refuses the upload, or has no --attach, the CLI cannot upload to this host. Classify it once as a CLI limitation. GHES can reject the upload. It does not show that the repository disallows attachments. Do not retry the route.
The user authorized a manual upload. Give the user the absolute path of
sketch.png. Ask them to drag it into a comment box on the PR in the web UI, without submitting, and paste back the URL or theor<img>markup that appears. Write the paste topaste.txtand run this block:url=$(bun "<skill>/scripts/attachment.mjs" url --host <host> paste.txt) && bun "<skill>/scripts/attachment.mjs" stamp --host <host> sketch.png recap.md "$url" > body.mdurlaccepts the markup forms and prints the bare URL, or exits 1 for any other host or path. The block's exit 1 can come from either command, so read the error.no https://<host>/user-attachments/assets/<uuid> URL foundcomes fromurland means the paste is not an attachment on this host. Treat it as upload unavailable, do not guess the URL, and take the no-authorization path.no <host> attachment image in the body; pass the attachment URL to replace ./sketch.pngorthe body must start with <!-- pstack-recap:start -->comes fromstampand meansrecap.mdhas an authoring error. Fixrecap.mdand rerun the block. When the block exits 0, PATCHcurrentwithbody.md(<keep>iscurrent), or when there is none, POST it withgh api --hostname <host> -X POST "repos/<owner>/<repo>/issues/<n>/comments" -f body="$(cat body.md)"and take<keep>from the returnedid.- No authorization. Remove the image line from
recap.md. Write that body overcurrent, or post it when there is none, and take<keep>. Reportupload unavailable: <the gh error>.
- Delete every other recap of yours, so the PR keeps one.
me=$(gh api --hostname <host> user --jq .login)
gh api --hostname <host> --paginate "repos/<owner>/<repo>/issues/<n>/comments" \
--jq ".[] | select(.user.login == \"$me\" and (.body | startswith(\"<!-- pstack-recap:start -->\")) and .id != <keep>) | .id" |
while read -r id; do gh api --hostname <host> -X DELETE "repos/<owner>/<repo>/issues/comments/$id"; done- Check the saved comment, count your recaps, then check that the image renders. Report the upload, the saved comment, and the render as three separate outcomes.
me=$(gh api --hostname <host> user --jq .login)
gh api --hostname <host> --paginate "repos/<owner>/<repo>/issues/<n>/comments" \
--jq ".[] | select(.user.login == \"$me\" and (.body | startswith(\"<!-- pstack-recap:start -->\"))) | .id" | grep -c .
gh api --hostname <host> "repos/<owner>/<repo>/issues/comments/<keep>" --jq .body > saved.md
bun "<skill>/scripts/attachment.mjs" check --host <host> --head <head SHA, 8 characters> saved.md
curl -s -o /dev/null -w '%{http_code} %{content_type}' -L -H "Authorization: Bearer $(gh auth token --hostname <host>)" "<url that check printed>"check confirms the start marker, the end marker, the head SHA, and an image on this host in either form. When a record is present, it checks that the recorded URL is an image URL in the body. It does not require a record or verify its hash. Read its error to identify which check failed. The count must print 1. Any other number means step 4 failed, so run it again. The fetch must print 200 image/png. A 404 means the asset is unavailable to this request. When a reused URL fails the fetch, treat the record as dead and upload again from step 3. A signed-out fetch can fail on a working upload, so it proves nothing. Without a sketch, run check with --no-image, which checks the markers and the head SHA only, and skip the fetch.
The editor's <img width=... alt=... src="..."> markup passes url and check. Author the recap with the Markdown image form and the alt text from the block. stamp preserves the image form in the body it reads. Hosting the image in the repository or as a release asset is not part of this skill.
Post it as a PR comment, never in the PR body. In a repository gated by no-mistakes, the gate owns the PR body.
Reply
- The comment URL and the head SHA that the recap describes, or the skip line.
- Which catalog drawing you used, or why you skipped the sketch.
- The claim check counts: verified, corrected, and deleted or rewritten as guesses.
CREDITS.md names the sources this skill adapts.
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
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.

