the01geek/prflow/pr-description
Claude Code and agent skill by the01geek/prflow
- community
Checking that the SKILL.md file is still in the repository.
Use when generating or updating a PR description for the current branch. Takes an optional issue number as argument.
Install
npx vskill@latest install the01geek/prflow/pr-descriptionSKILL.md
/pr-description — Generate or Update PR Description
Generate a structured PR description from the branch diff. For an existing PR, reconcile its title and merge the body with human-added content.
Input: $ARGUMENTS is an optional GitHub issue number. If provided, include a "Resolves #N" link.
Portable helper anchor (single-statement). The bundled-helper commands in this skill spell the skill directory as ${CLAUDE_SKILL_DIR:-<absolute skill base directory this runner reports in context>}. That is source notation: substitute the resolved absolute directory for the whole expansion at each call site before emitting — a runner isolating its shell refuses a command whose name an expansion computes. Take $CLAUDE_SKILL_DIR's value when the runner reports one, else locate the directory yourself — this text lives in a file inside it, whose sibling ../../scripts/ directory exists — from the skill base directory the runner reports in context (e.g. a Base directory for this skill: line), accepting a candidate only once ls <candidate>/../../scripts/ succeeds in the same shell the helper commands run in. If a path form is rejected, use the form that shell reports (pwd shows it); a Windows-form base directory (C:\...) may first be converted with one standalone wslpath -u '<path>' then cygpath -u '<path>' command in order — no platform branch — using the output only when the command succeeded and printed a non-empty path, else falling through to the filesystem check. Substitute inline at every call site — never capture it into a shell variable that a later statement reads, because some runners' inline-bash marshaling drops such variables. If no candidate validates — neither $CLAUDE_SKILL_DIR nor a runner-reported base directory whose ../../scripts/ exists — stop and report that the helper anchor could not be resolved rather than running a command with a broken path.
Consumer prompt extension (load first). This skill's consumer extension reaches you through exactly one channel — the invocation ladder below — so load it yourself with that ladder, unconditionally, at the start of the run. Read the ladder's output whole — no >/dev/null, no | head -<n>, no truncation of any kind — because an extension whose text you never observed governs nothing in this run. From the repo root, emit the granted vendored-literal leading token first:
On a command not found / No such file / exit-127 reading (a checkout where the vendored path is absent, such as a non-Claude-Code runner), fall back to the portable anchor form:
Every extension-state failure arm below fires unconditionally — this ladder is the only channel, so a failure you do not report drops consumer policy from the run silently. If the invocation fails because the helper path does not exist (No such file, exit 127, or the platform equivalent) on every form above, that is the anchor-resolution failure described in the Portable helper anchor note above — report it in the run's output, since it breaks every other bundled-helper call site in this run; fix the anchor, don't report a missing extension. If instead the harness refuses the command outright — a permission denial rather than a missing file — the extension's state is unestablished: report that in the run's output and never treat it as a clean policy pass (unknown is not zero). Otherwise, if the helper exits non-zero, a consumer extension exists but could not be loaded — surface its stderr message and do not silently proceed as if none existed. On exit 0 the helper prints a PROMPT-EXTENSION-STATUS: content-present or PROMPT-EXTENSION-STATUS: present-empty line on stderr; report that token verbatim in the run's output as the extension's resolved status. On content-present, treat the stdout text as additional instructions appended to the end of this skill's own prompt for this run — it is upgrade-safe, consumer-owned customization committed under .prflow/skill-extensions/. On present-empty, proceed unchanged. If no PROMPT-EXTENSION-STATUS line appeared at all — the command produced no output (a harness refusal) or exited non-zero (undeliverable) — the state is unestablished: report unestablished, never collapse it onto present-empty (unknown is not zero).
Classify the delivery from the ladder's own status line, not from whether any classifier ran: arrived only on a produced PROMPT-EXTENSION-STATUS: content-present, absent only on a produced present-empty, and unestablished whenever no status line was produced at all — a helper denied when invoked by path emits no output, byte-identical to silent non-delivery, so it never reads as arrived. On unestablished, force the record to the first available durable surface in this fixed, terminating order: this run's workpad when one exists; else the pull request — its description or a PR comment — when the run has a PR but no workpad; else the run's own output, naming the unestablished state and reporting the record unrecordable. Write the first available surface — never skip an earlier one for a later one. The mechanized classifier is .prflow/vendor/prflow/scripts/prompt-extension-arrival.py classify-ladder-output --skill pr-description — the granted vendored-literal leading token, invoked with the same repo-relative/anchor fallback ladder as the load above; it reads the ladder's captured output on stdin — capture the ladder's combined stdout and stderr when invoking it (the status line is on stderr, so a stdout-only pipe misclassifies every real arrival as unestablished) — and emits final=arrived|absent|unestablished plus, on unestablished, a record= line. Do not depend on it running: where it is not granted or not runnable it produces no output, and its silence is never a classification — the status line you already observed stays authoritative for the states above, and on unestablished the forced durable write happens regardless.
Step 1: Gather Context
Resolve the configured base branch by printing it, then substituting the printed value as a literal:
Read the printed base branch from the tool result. On a non-zero exit or an empty value, fall back to main and log pr-description: could not read .base_branch — falling back to main. Substitute the printed value as a LITERAL into each git fence below (e.g. git diff origin/<base>...HEAD) — never through a shell-variable capture (VAR=$(...)) and never as an origin/$VAR expansion.
Run these commands to understand what changed, with <base> the printed literal (default main):
Read the diff details for any files that need deeper understanding:
If an issue number was provided, fetch the issue for context:
Check for an existing PR on the current branch:
Route on the exit status, stdout and stderr in the tool result:
- Exit 0 with parseable JSON carrying a PR number: an existing PR. Its number and body feed Step 2 and Step 3.
- Non-zero exit whose stderr contains
no pull requests found for branch: no PR, so Mode A; quote that stderr line, which names the branch, in your final message. - Anything else is
unestablished— any other non-zero exit (authentication, network, no git remote,could not determine current branchon a detached HEAD), exit 0 with empty or unparseable output or no PR number, or a harness refusal with no output. Stop: compose no description, make no PATCH, and report the lookup as unestablished in your final message, quoting the stderr or naming the missing output.
Pull post-merge acceptance criteria from the /prflow:implement workpad: /prflow:implement tags each criterion verifiable only after merge with a trailing (post-merge) marker, and the PR body lists them so the merger can tick them off after deploy.
Workpad lookup. With no issue number available (from $ARGUMENTS or extracted from the existing PR body via (?i)(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\s+#(\d+) — mirroring GitHub's own case-insensitive closes-keyword detection), the outcome is no-issue and no call runs. Otherwise emit this plain call, the number substituted as a literal:
Only its exit 0, or its exit 2 with no output, is final. Any other result — not found, rc 127, a usage error (a vendored copy without body --issue), another non-zero status, a harness refusal — falls through to the portable anchor form, whose result is final:
Read each form's exit status and output (stdout and stderr merged) from the tool result, and map the final result to one of four outcomes (no-issue above, or):
read— exit 0 with non-empty output; the output is the workpad body. Aworkpad.pywarning line in it is not body content: report it as a note besideread.no-workpad— exit 2 with no output at all.failed— anything else: exit 0 with empty output; exit 2 with any output (a warning there means the scan may have used the wrong workpad marker); exit 1; exit 3; any other status; a harness refusal. Name the observed cause and each form's output.
Report the outcome in your final message as workpad lookup: <read, <n> post-merge rows[, note: <warning>] | no-workpad | no-issue | failed: <cause>>, never inside the PR body. The lookup never fails the run.
On read, a tagged row is a ## Acceptance Criteria checkbox row section_parse parses — optionally indented - or *, then [ ], [x] or [X] — whose text, joined with indented non-blank continuation lines and right-stripped, is_post_merge_tagged accepts: ending in (post-merge), leading space included. Ticked and unticked rows both count. Strip the checkbox and the tag from each and collect them as POST_MERGE_ITEMS; their number is the tagged-row count. When POST_MERGE_ITEMS is empty, the Post-Merge Verification section is omitted — except that failed in Mode B keeps the existing body's section verbatim.
Source the Test Plan's executed outcomes from this run's tool results and, on read, the workpad's ## Progress notes. On no-issue, no-workpad or failed, use only other observed execution evidence; without it, claim no executed result. Bind current results to the candidate they verified; preserve relevant historical decisions as historical. A diff establishes what checks exist, not that they passed. Report material limits without manufacturing waiver declarations or describing planned or unavailable checks as passes.
Best-effort: pull deferred review findings from the manifest. /prflow:review-and-fix writes each run's manifest run-scoped (.prflow/tmp/review/<slug>/<run-id>/deferrals.json), and /prflow:implement Phase 4.0.5 merges every run-scoped manifest into one slug-level aggregate at .prflow/tmp/review/pr-<N>/deferrals.json, then files follow-up issues and updates that aggregate in place with id and follow_up fields per entry. Read the slug-level aggregate and surface its entries in the PR body as a Scope-Acknowledged Findings block so /prflow:review (run later as a formal merge signal) lists the deferrals in its report; a deferral does not lower a finding's weight in the verdict.
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 90 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/pr-description/SKILL.md
Popularity
- Repository stars
- 80
- Repository forks
- 26
- 7-day trend score
- 22
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/the01geek/prflow/pr-description)