Pull Request Writing skill for Codex
PR descriptions reviewers can approve fast. Codex reads the branch diff against the merge base, checks size before writing, and fills the repo's own PR template or a structured default covering why, behaviour changes, reading order, risk, rollback and testing. Test evidence is limited to commands it actually ran, screenshots are handled honestly since gh cannot upload images, and PRs open as drafts only after you confirm.
curl -fsSL codexskills.dev/install.sh \ | sh -s -- pull-request-writing Installs to ~/.agents/skills/pull-request-writing/ for every project on this machine.
curl -fsSL codexskills.dev/cli.mjs -o codex-skills.mjsnode codex-skills.mjs install pull-request-writing The CLI also searches, updates and removes skills. Run it with no arguments to pick from a list. Needs Node 20.12+.
curl -fsSL codexskills.dev/install.sh \ | sh -s -- --project pull-request-writing Installs to .agents/skills/pull-request-writing/ in the current repository. Commit it and everyone who runs Codex there gets it.
curl -fsSLO codexskills.dev/downloads/pull-request-writing.zipunzip -o pull-request-writing.zip -d ~/.agents/skills/ The archive holds the skill folder with its generated agents/openai.yaml. Unzip into .agents/skills/ to scope it to a repo.
& ([scriptblock]::Create((irm codexskills.dev/install.ps1))) pull-request-writing PowerShell 5.1 or 7. Installs to %USERPROFILE%\.agents\skills\. Add -Project for the current repo.
104-line POSIX script. No sudo, no telemetry. Read install.sh
Use it in Codex
Start a prompt with $pull-request-writing, or pick it from /skills.
You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.
What Codex reads before loading it
Writes pull request titles and descriptions reviewers can act on - the problem, the approach and rejected alternatives, risk and rollout, real test evidence, before/after screenshots and a guided reading order - and sizes or splits PRs so they can be reviewed in one sitting. Fills the repo's PR template and opens drafts with gh pr create --body-file after confirmation. Use when asked to open a PR, write or improve a PR description, summarise a branch for review, or when a diff is too large to review.
Use it when
- A branch is ready and needs a PR title and description
- An existing PR description is thin or out of date
- A diff looks too large to review in one sitting
Use something else when
- You are reviewing someone else's PR: use code-review
- You need a chain of dependent PRs: use stacked-pull-requests
How to check the result
Each claim in the description maps to a hunk in the three-dot diff, each test result was run in the session, and gh pr view renders the body correctly.
The mistake it prevents
Listing changed files instead of changed behaviour, and claiming tests pass without having run them on the final commit.
A good PR lets a reviewer decide in the first screen whether the change is right, then verify it without asking questions: why it exists, what it does, what could break, and proof that it works. The diff shows how; the description owns why and how you know.
Gather before writing
git fetch origin # needs network
git log --oneline origin/main..HEAD
git diff --stat origin/main...HEAD # three dots: changes since the merge base
git diff origin/main...HEAD -- . ':(exclude)*.lock' ':(exclude)package-lock.json' | head -400
ls .github/pull_request_template.md .github/PULL_REQUEST_TEMPLATE/ docs/pull_request_template.md 2>/dev/null
Also read AGENTS.md and CONTRIBUTING.md for required sections, labels, changelog
entries or sign-off. If the repo has a PR template, fill every section of it; do not
replace it with your own structure.
Find the linked issue or ticket. If the user has not given one, ask instead of guessing.
Size check first
| Changed lines (excluding generated/lockfiles) | Action |
|---|---|
| Under ~400 | One PR |
| 400-1000 | One PR only if it is a single concern; add a reading order |
| Over 1000, or mixes refactor + feature + migration | Propose a split before writing |
Common split lines: preparatory refactor, then behaviour change; schema migration, then code using it; mechanical rename (reviewed by skim), then logic (reviewed carefully). For dependent PRs, see stacked-pull-requests. Never split so that an intermediate PR leaves main broken.
Title
- One line, about 72 characters max, says what changes in imperative form:
Cap bulk discounts at a single tier. Follow Conventional Commits if the repo squash merges with PR titles (fix(cart): cap bulk discounts at a single tier). - No ticket number alone, no “Fixes stuff”, no branch name.
Description structure
Default template when the repo has none:
## Why
<The problem in user or system terms, with the issue link. One short paragraph.>
## What changed
- <Behavioural change 1>
- <Behavioural change 2>
- <Notable internal change, only if a reviewer needs to know>
## How to review
<Suggested reading order for anything over ~300 lines. Point at the one file that
matters most; mark mechanical parts as skimmable.>
## Risk and rollout
- Risk: <what could break, for whom; "low: covered by X" is fine when true>
- Rollout: <feature flag, migration order, config change, none>
- Rollback: <revert is safe | needs down-migration | flag off>
## Testing
- [x] `pytest -q` - 214 passed
- [x] New: `test_bulk_discount_single_tier` (fails on main, passes here)
- [x] Manual: placed a 100-unit order in local dev, total 880.00 (was 836.00)
- [ ] Not tested: <what and why>
## Screenshots
| Before | After |
|---|---|
| <image> | <image> |
Closes #812
Section rules
- Why must survive the reviewer not opening the issue. Paste the key sentence.
- What changed lists behaviour, not files. “Adds
tier_for()” is noise unless the function is new public API. - Alternatives considered: add a line when a reviewer would plausibly ask “why not X?”.
- Testing contains evidence you actually observed in this session: commands and results, not “tests pass” from memory. Unchecked boxes for things not done are honest and useful; fabricated checks are a serious breach of trust.
- Screenshots for any visible UI change, before and after at the same viewport.
ghcannot upload images; produce the files (for example with Playwright) and tell the user to drag them into the PR, or reference images already hosted in the repo. - Use
Closes #n/Fixes #nonly if merging should close the issue; otherwiseRefs #n. - Call out anything requiring reviewer action: migrations to run, env vars to add, secrets to rotate, downstream teams to notify.
Opening the PR
Opening a PR publishes to a shared system, so confirm with the user first unless they already asked for it. Prefer a draft when tests are still running or the description has open questions.
git push -u origin HEAD # confirm first; needs network
gh pr create --draft --base main \
--title "Cap bulk discounts at a single tier" \
--body-file "$TMPDIR/pr-body.md"
gh pr edit <n> --body-file "$TMPDIR/pr-body.md" # update later without losing formatting
gh pr ready <n> # when it is reviewable
Write the body to a file; inline --body strings mangle backticks and newlines in the
shell. Do not add reviewers, labels or assignees the user did not ask for unless
AGENTS.md or CODEOWNERS automation expects them.
When Codex authored most of the change, say so plainly in the description if the team’s policy requires disclosure; agentic-pr-workflow covers that policy in depth.
Gotchas
- Two-dot
git diff main..HEADincludes changes on main since you branched; use three dots for “what this PR changes”. - Lockfile and snapshot churn hides real changes in the stat. Exclude them when summarising and mention them in one line.
- A description written before the last round of commits goes stale. Regenerate the “What changed” list from the final diff before marking ready.
- Never paste secrets, internal hostnames or customer data from logs into the PR body.
Verification
- Every claim in “What changed” maps to something in the diff, and every significant hunk in the diff is covered by a claim.
- Every command in “Testing” was run in this session and the result shown is real.
- Template sections are all filled or marked N/A with a reason.
- The title alone tells a release-notes reader what changed.
- Rendered preview checked:
gh pr view <n>shows the body as intended.
What the zip contains
SKILL.md plus the interface file below. Nothing runs on install.
agents/openai.yaml
Gives the Codex app a display name, a one-line description and a starter prompt for this skill.
interface:
display_name: "Pull Request Writing"
short_description: "PR descriptions reviewers can approve fast"
default_prompt: "$pull-request-writing Write the PR description for this branch and open it as a draft" About this skill
Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.