From review-story
Generate a narrative story of a PR's changes with embedded code snippets. Use when the user asks to create a PR story, review story, or narrative walkthrough of a pull request's changes.
npx claudepluginhub forketyfork/agentic-skills --plugin review-storyThis skill uses the workspace's default tool permissions.
You are generating a structured narrative that tells the story of a pull request. The output must be parseable for later visualization.
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Guides building MCP servers enabling LLMs to interact with external services via tools. Covers best practices, TypeScript/Node (MCP SDK), Python (FastMCP).
Generates original PNG/PDF visual art via design philosophy manifestos for posters, graphics, and static designs on user request.
You are generating a structured narrative that tells the story of a pull request. The output must be parseable for later visualization.
The user will provide a PR number or URL. Use it in the gh commands below.
Run these commands to collect context:
gh pr view <pr> --json title,body,author,baseRefName,headRefName,commits,files,additions,deletions
Extract the PR number, branch name, base branch, title, and description. Pay attention to the PR description (body) — it often explains the author's intent, motivation, and context that aren't visible from the code alone. Use this to inform your narrative.
Fetch conversation comments and review comments to understand the discussion around the PR.
Important: In interactive Bash shells, the history expansion character can break jq expressions that use the "not equal" operator. Avoid using that operator in jq; use length > 0 instead. Also avoid jq string interpolation \(...) inside arguments — use string concatenation with + instead.
gh pr view <pr> --json comments --jq '.comments[] | "**" + .author.login + "**: " + .body'
For review-level comments:
gh pr view <pr> --json reviews --jq '.reviews[] | select(.body | length > 0) | "**" + .author.login + "** (" + .state + "): " + .body'
For inline code-level review comments, first get the repo from the PR URL, then use the API:
gh pr view <pr> --json url --jq '.url'
gh api repos/<owner>/<repo>/pulls/<pr-number>/comments --paginate --jq '.[] | "**" + .user.login + "** on `" + .path + "`:\n" + .body + "\n---"'
These comments provide valuable context — they may reveal why certain decisions were made, what was revised, or what trade-offs were considered. Weave relevant insights from the discussion into your narrative where appropriate.
gh pr view <pr> --json commits --jq '.commits[] | .oid + " " + .messageHeadline'
If there are multiple commits, this is important — you will narrate the evolution of changes commit by commit.
gh pr diff <pr>
If the diff is very large (over ~2000 lines), focus on the most structurally significant changes. Skip trivial changes like import reordering, whitespace, lock files, and auto-generated code.
For each significant commit, look at what specifically changed. Use the GitHub API so commits are available even when the local clone doesn't have the objects (e.g. fork-based PRs):
gh api repos/<owner>/<repo>/commits/<commit-sha> --jq '.files[] | .filename + " | " + .status + " | +" + (.additions | tostring) + " -" + (.deletions | tostring)'
gh api repos/<owner>/<repo>/commits/<commit-sha> --jq '.files[] | select(.filename == "<specific-file>") | .patch'
This helps you explain HOW the code evolved across commits, not just the final state.
Write a Markdown document. The narrative is prose text explaining what the author did and why, interspersed with code snippets.
Every code snippet must be wrapped in a fenced block with the story-diff info string and a JSON metadata comment on the first line:
Some narrative explaining what happens next...
```story-diff
<!-- {"file": "src/api/users.ts", "commit": "a1b2c3d", "type": "addition", "description": "New user validation endpoint"} -->
+export async function validateUser(req: Request) {
+ const { email, password } = req.body;
+ if (!email || !password) {
+ throw new ValidationError('Missing credentials');
+ }
+}
```
Then the author moved on to...
Metadata fields:
file — the file pathcommit — short SHA (if attributable to a specific commit, otherwise omit)type — one of: addition, deletion, modification, rename, contextdescription — brief label for what this snippet representsWhen the prose needs to point the reader to specific lines in the immediately following snippet, use line references:
**[N]** — visible bold markers that readers can follow<!--ref:N--> appended to the referenced line<!--ref:N-->The author initializes the connection pool **[1]** but defers cleanup
to a shutdown hook **[2]**, which ensures graceful teardown even on
SIGTERM.
```story-diff
<!-- {"file": "src/db/pool.ts", "commit": "f4e5d6c", "type": "addition", "description": "Connection pool with graceful shutdown"} -->
+const pool = new Pool({ <!--ref:1-->
+ max: 20,
+ idleTimeoutMillis: 30000,
+});
+
+process.on('SIGTERM', async () => {
+ await pool.end(); <!--ref:2-->
+ process.exit(0);
+});
```
Code snippet rules:
+/- prefixes for added/removed linesSave the story as pr-story-<pr-number>.md in the current directory.