Write engaging PR titles and descriptions for any forge (GitHub today; Bitbucket planned). Use when creating or updating PRs. Leads with narrative paragraphs and reaches for lists, tables, and diagrams when content is genuinely structured.
Scanned 9/5/2026
Install to Claude Code
npx -y skills add juspay/kolu --skill forge-pr --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Forge Pr?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/juspay-forge-pr-kolu)More formats (shields.io, HTML) on the badges page.
---
name: forge-pr
description: Write engaging PR titles and descriptions for any forge (GitHub today; Bitbucket planned). Use when creating or updating PRs. Leads with narrative paragraphs and reaches for lists, tables, and diagrams when content is genuinely structured.
---
# Forge PR Writing
Write PR descriptions that fellow devs actually want to read. The writing guidance below is forge-agnostic — only the `gh` commands in the "Updating existing PRs" section are GitHub-specific today. Bitbucket support is tracked in [srid/agency#10](https://github.com/srid/agency/issues/10).
## Anti-patterns (what LLMs typically produce)
- Flat bullet lists of every file changed
- Implementation-detail dumps ("added `foo` parameter to `bar` function")
- Generic titles like "Update configuration" or "Fix bug in module"
- "## Changes" / "## Testing" / "## Summary" boilerplate headers
- Restating the diff in English
- Wall of prose for content that's _actually_ a list, comparison, or flow — five features described in one sentence, two before/after fixes blended into a paragraph, an architecture seam explained in words instead of drawn
## What to write instead
**Title**: Short, specific, interesting. Convey _what changed from a user/dev perspective_, not which files were touched. Use imperative mood. Under 70 chars.
**Body**: Open with a paragraph. Structure:
1. **Opening paragraph** — What this PR does and _why_, in 2-3 sentences. Bold the key behavioral change. If there's a motivating problem, state it directly.
2. **Details** — paragraph(s), bullet list, table, or fenced diagram, whichever fits the shape of the content (see [Use structure when content is structured](#use-structure-when-content-is-structured) below). Only include if the approach is non-obvious, has trade-offs worth calling out, or has discrete moving parts that benefit from being shown rather than described. Use _italics_ for subtle points; keep it high-level.
3. **Anything notable** — Breaking changes, migration steps, or things reviewers should pay attention to. Only if applicable. Use `> blockquote` for callouts.
## Use structure when content is structured
Narrative is the right tool for the opening "what changed and why" paragraph and for asides — but the moment you find yourself writing _"three loaders"_, _"two refinements landed"_, or _"the data passes through X then Y then Z"_, that's structure asking to be made visible. A comma-separated list of five features in prose is harder to scan than five bullets; a table beats a paragraph that says "previously Foo did X, now it does Y, and Bar previously did Z, now it does W."
Reach for these when they earn their keep:
- **Bullet lists** — discrete features, keyboard shortcuts, refinements, anything that isn't a narrative
- **Tables** — before/after fixes, per-variant comparisons (e.g. loader → format → vendor), trade-off matrices
- **Fenced ASCII or mermaid diagrams** — data flow, architecture seams, anything with shape that's easier to draw than describe
- **`###` subheaders** — break long bodies into navigable sections (still avoid generic `## Summary` / `## Changes`)
The rule is _use structure when content is structured_, not _always add structure_. A small PR with one paragraph of motivation is fine; don't reach for a table just to look thorough.
## Style rules
- Write for a dev skimming their PR feed — they should get the gist in 5 seconds
- **Bold** the most important phrase in each paragraph
- _Italics_ for nuance, caveats, secondary points
- Bullet lists, tables, and fenced diagrams are encouraged when the content is genuinely structured (see [Use structure when content is structured](#use-structure-when-content-is-structured)). Don't list the diff file-by-file or restate prose as a bulleted dump.
- `###` subheaders are fine to break up long bodies; skip generic `## Summary` / `## Changes` headers
- No filler: "This PR...", "In this change...", "As part of..." — start with the substance
- Link to issues/discussions where relevant (`Closes #123`, `See #456`)
- If the PR is trivial (typo fix, version bump), a one-liner body is fine
## Attribution footer
End every PR body with a one-line italic footer naming:
- the **invoking workflow** (the slash-command that drove this PR — e.g. `/do`), linked to its source repo (`https://github.com/srid/agency`),
- the **agent** (the harness identity — e.g. `Claude Code`, `Codex`, `opencode`), and
- the **model** (the specific model id you are running on — e.g. `claude-opus-4-7`, `gpt-5-codex`).
Reviewers should be able to tell at a glance what produced the diff:
> _Generated by [`/do`](https://github.com/srid/agency) on Claude Code (model `claude-opus-4-7`)._
Use the values that are actually executing this run — do not guess or fabricate. If you genuinely cannot identify one of agent/model, write `unknown` rather than omitting the footer. If the PR is being written without an invoking workflow (forge-pr loaded directly, no `/`-command), drop the workflow phrase and lead with `_Generated by Claude Code (model `claude-opus-4-7`)._`. When updating an existing PR (see [Updating existing PRs](#updating-existing-prs)) and the current run's agent or model differs from what's already in the body, **edit the existing footer in place** rather than appending a second one.
## Try it locally
If the repo is a **GitHub** Nix flake and the PR branch contains a buildable output (package, NixOS config, etc.), include a "Try it locally" section at the end of the body. Use the GitHub owner/repo and branch name to construct the command, and put it in a **fenced `sh` code block** (not inline backticks) so GitHub renders a copy button and the command doesn't line-wrap awkwardly:
````
### Try it locally
```sh
nix run github:<owner>/<repo>/<branch>
```
````
Adjust the command as needed — `nix build` for non-runnable outputs, add `#<output>` if the default package isn't the relevant one. Omit this section entirely if the change isn't meaningfully testable via `nix run/build` (e.g., CI-only changes, documentation, non-Nix repos, or non-GitHub forges where flake refs would be awkward).
## Passing the body to `gh` safely
**MANDATORY**: Always pass `--body` to `gh pr create` / `gh pr edit` / `gh pr comment` via a **single-quoted heredoc** so backticks, `$`, and `!` survive unescaped. Double-quoted `--body "..."` triggers shell command substitution on backticks, and escaping them with `\`` produces literal backslashes in the rendered PR (breaking code fences — see [juspay/kolu#402](https://github.com/juspay/kolu/pull/402)).
```sh
gh pr create --draft --title "..." --body "$(cat <<'EOF'
...body with ```sh fenced blocks``` intact...
EOF
)"
```
The `'EOF'` (quoted delimiter) is load-bearing — it disables interpolation inside the heredoc. Never write backticks in the body as `\``.
## Updating existing PRs
When the user pushes further changes to an already-PR'd branch:
1. Check if the PR title/description still accurately reflects the full scope
2. If new commits meaningfully change what the PR does, update the title and/or body via the forge's edit command (`gh pr edit` on GitHub)
3. Don't rewrite from scratch — amend the existing description to cover new ground
4. Add a brief note about what changed if the scope expanded significantly
## Examples
Worked bad/good pairs — a typical LLM bullet-dump, a small change carried by
narrative, and a richer one where a diagram and a table earn their keep — are in
[`EXAMPLES.md`](EXAMPLES.md). Read them when you want a model to imitate.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!