Create a pull request or merge request with rich, context-aware description and inline review comments. Analyzes changes to explain what changed, why, and where reviewers should focus attention. Handles branch creation, commits, push, platform detection (GitHub/GitLab), and label assignment. Use this skill whenever creating a PR/MR, even for simple changes — it always produces better descriptions than a manual `gh pr create`. Accepts optional context from callers like player-coach for even richer descriptions with implementation journey and friction logs.
From cata-helpersnpx claudepluginhub niekcandaele/claude-helpers --plugin cata-helpersThis skill uses the workspace's default tool permissions.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
Create a PR/MR with a description that transfers your context to the reviewer. When you create a PR, you know everything about the change — the reviewer knows nothing. Your job is to bridge that gap.
Parse $ARGUMENTS for:
--context=path — path to a context file with additional structured data (from player-coach or similar)--no-comments — skip inline review commentsORIGINAL_BRANCH=$(git branch --show-current)
This becomes the PR target branch. All PRs go back to whatever branch you started from.
# GitHub
gh pr view --json url,number 2>/dev/null
# GitLab
glab mr view --output json 2>/dev/null
If a PR/MR already exists:
ORIGINAL_BRANCH to the PR's base branch (from gh pr view --json baseRefName / MR target branch), not from git branch --show-currentREMOTE_URL=$(git remote get-url origin)
github.com → GitHub (use gh)gitlab.com or other GitLab instance → GitLab (use glab)Verify the CLI tool is installed (which gh / which glab). If not installed, provide installation instructions and stop.
Generate a branch name from the PR title (if provided) or from analysis of the changes:
feature/brief-descriptionfix/issue-descriptiondocs/update-descriptionrefactor/component-nameRules: kebab-case, max 50 chars, valid git branch name. Add timestamp suffix if branch exists.
git checkout -b [branch-name]
git status --porcelain
If changes exist, stage and commit on the feature branch. Generate a descriptive commit message from the changes. All commits happen on the feature branch, never the original.
git push -u origin [feature-branch]
Fetch available labels first — never assume labels exist:
GitHub:
AVAILABLE_LABELS=$(gh label list --json name --jq '.[].name' 2>/dev/null || echo "")
GitLab:
AVAILABLE_LABELS=$(glab label list 2>/dev/null | cut -f1 || echo "")
If fetching fails, proceed without labels.
Simple matching — propose labels from:
feature/* → "enhancement", fix/* → "bug", docs/* → "documentation"feat: → "enhancement", fix: → "bug", docs: → "documentation"Only apply labels that exist in AVAILABLE_LABELS. If no matches, create PR without labels.
Understand the change deeply enough to write a useful description. Two paths depending on invocation:
--context=path)Read the context file. It contains structured data from the caller (e.g., player-coach):
Also read the diff for code-level understanding:
git diff $ORIGINAL_BRANCH..HEAD
git diff --stat $ORIGINAL_BRANCH..HEAD
Gather context yourself:
Read the diff:
git diff $ORIGINAL_BRANCH..HEAD --stat
git diff $ORIGINAL_BRANCH..HEAD
For large diffs (20+ files), use --stat first and selectively read key files.
Read the commit log:
git log $ORIGINAL_BRANCH..HEAD --format='%s%n%n%b---'
Check for a plan file:
ls .claude/plans/*.md 2>/dev/null
If found, read it — it explains the "why" behind the change.
Check for issue references:
Scan commit messages for #NNN patterns. Fetch context:
gh issue view NNN --json title,bodyglab issue view NNNCheck for engineer skill:
ls .claude/skills/*-engineer/SKILL.md 2>/dev/null
If found, read for architecture context.
The description is the reviewer's primary entry point. Write it for someone who has zero context on this work.
PR titles appear in changelogs and release notes. They must be user-facing, not technical.
Write for end users: describe the user impact, not the code change. "Speed up page loading times" not "feat: implement Redis caching layer."
Templates:
Avoid: class names, function names, file names, technical patterns (middleware, service, controller), implementation details (cache, queue, worker).
Core sections (always present):
## Summary
{2-4 sentences: what was built/changed and WHY. Include the problem being
solved or the need being addressed. Write for someone with zero context.}
## Architecture
{ASCII diagram of component relationships, data flow, or request paths
relevant to the change. Show how the pieces fit together.
Skip this section for trivial changes (< 3 files, no new components,
pure bug fixes, config changes).}
## What Changed
{Changes grouped by component/area, not by file. Each item explains
WHAT and WHY at the component level.}
- **Area/Component**: What was done and why
- **Another area**: What was done and why
- **Tests**: Summary of test coverage added
## Reviewer Guide
{Help the reviewer navigate the change efficiently.}
- **Start here**: {entry point file/function — where to begin reading}
- **Pay attention to**: {areas that are tricky, non-obvious, or critical}
- **Design decision**: {choices made and why, alternatives considered}
Additional sections when context file is provided (e.g., from player-coach):
## Implementation Journey
{Turn history and narrative from the context file. Include the turn table
and a brief narrative if the run was rough.}
## Friction Log
{Only if friction occurred. Each item references specific files/lines
and explains what was hard, why, and what the human should check.
Omit entirely for clean runs.}
## Below-Threshold Issues
{Issues that passed the severity bar but the reviewer may want to address.
Omit if none.}
Create the PR/MR with the rich description from Phase 3.
GitHub:
gh pr create \
--title "$TITLE" \
--body "$(cat <<'PRBODY'
{composed body}
PRBODY
)" \
--base "$ORIGINAL_BRANCH" \
$LABEL_FLAGS
GitLab:
glab mr create \
--title "$TITLE" \
--description "$(cat <<'MRBODY'
{composed body}
MRBODY
)" \
--target-branch "$ORIGINAL_BRANCH" \
$LABEL_FLAGS
If a PR/MR already existed (detected in Phase 1 step 2), update the description instead:
GitHub:
gh pr edit "$PR_NUMBER" --body "$(cat <<'PRBODY'
{composed body}
PRBODY
)"
GitLab:
glab mr update "$MR_IID" --description "$(cat <<'MRBODY'
{composed body}
MRBODY
)"
Extract and store the PR/MR URL and number for Phase 5.
Skip this phase if --no-comments was passed or if there are no attention-worthy areas.
Inline comments are like a self-review: they guide the reviewer to specific lines that need attention. A human author would leave these to explain non-obvious decisions, flag workarounds, or highlight critical sections. Do the same.
When context file is provided:
When standalone (no context file): Scan the diff for:
Guardrails:
GitHub — via PR reviews API:
Write comments to a temp JSON file, then post as a review:
cat > /tmp/pr-review-comments.json << 'EOF'
{
"body": "Self-review: areas flagged for reviewer attention",
"event": "COMMENT",
"comments": [
{
"path": "src/auth/middleware.ts",
"line": 45,
"side": "RIGHT",
"body": "This retry logic works but is a workaround for the race condition in token refresh. Consider a proper mutex if this path gets higher traffic."
}
]
}
EOF
gh api repos/{owner}/{repo}/pulls/{pr_number}/reviews \
--method POST \
--input /tmp/pr-review-comments.json
The line parameter is the line number in the new version of the file. side: "RIGHT" means the new file (not the old). Use gh api repos/{owner}/{repo}/pulls/{pr_number} --jq '.head.sha' if you need the head SHA.
GitLab — via MR discussions API:
GitLab requires diff position SHAs for inline notes. Fetch them first:
# Get the MR's diff refs
DIFF_REFS=$(glab api projects/{project_id}/merge_requests/{mr_iid} --jq '.diff_refs')
BASE_SHA=$(echo "$DIFF_REFS" | jq -r '.base_sha')
START_SHA=$(echo "$DIFF_REFS" | jq -r '.start_sha')
HEAD_SHA=$(echo "$DIFF_REFS" | jq -r '.head_sha')
Then post each comment as a discussion:
glab api projects/{project_id}/merge_requests/{mr_iid}/discussions \
--method POST \
-f "body=This retry logic works but is a workaround..." \
-f "position[base_sha]=$BASE_SHA" \
-f "position[start_sha]=$START_SHA" \
-f "position[head_sha]=$HEAD_SHA" \
-f "position[position_type]=text" \
-f "position[new_path]=src/auth/middleware.ts" \
-f "position[new_line]=45"
For the project ID and MR IID, extract from the MR created in Phase 4:
MR_JSON=$(glab mr view --output json)
PROJECT_ID=$(echo "$MR_JSON" | jq -r '.project_id')
MR_IID=$(echo "$MR_JSON" | jq -r '.iid')
Post each comment individually (GitLab doesn't support batched review comments like GitHub).
## PR/MR Created
**URL**: {url}
**Branch**: {feature-branch} → {original-branch}
**Platform**: {GitHub/GitLab}
**Labels**: {applied labels, or "none"}
**Description**: Rich context with {list of sections included}
**Inline comments**: {N} reviewer attention flags posted {or "skipped"}
.git before proceedingorigin is configuredbrew install gh / sudo apt install gh + gh auth login; GitLab: brew install glab / download from releases + glab auth login)