From 08a57ce60c7bb8a3efe58231807d2bb024f5aafa Mon Sep 17 00:00:00 2001 From: Snider Date: Mon, 2 Feb 2026 07:31:23 +0000 Subject: [PATCH] feat(code): add /code:pr command to generate pull requests (#101) Add PR generation command that: - Auto-generates title from branch name - Creates body with commit list and changed files - Supports --draft flag for draft PRs - Supports --reviewer flag to request reviews Migrated from core-claude PR #46. Co-authored-by: Claude Opus 4.5 --- claude/code/commands/pr.md | 28 +++++++++ claude/code/scripts/generate-pr.sh | 94 ++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 claude/code/commands/pr.md create mode 100755 claude/code/scripts/generate-pr.sh diff --git a/claude/code/commands/pr.md b/claude/code/commands/pr.md new file mode 100644 index 0000000..04d75d3 --- /dev/null +++ b/claude/code/commands/pr.md @@ -0,0 +1,28 @@ +--- +name: pr +description: Create a PR with a generated title and description from your commits. +args: [--draft] [--reviewer @user] +--- + +# Create Pull Request + +Generates a pull request with a title and body automatically generated from your recent commits. + +## Usage + +Create a PR: +`/code:pr` + +Create a draft PR: +`/code:pr --draft` + +Request a review: +`/code:pr --reviewer @username` + +## Action + +This command will execute the following script: + +```bash +"${CLAUDE_PLUGIN_ROOT}/scripts/generate-pr.sh" "$@" +``` diff --git a/claude/code/scripts/generate-pr.sh b/claude/code/scripts/generate-pr.sh new file mode 100755 index 0000000..dbc50ee --- /dev/null +++ b/claude/code/scripts/generate-pr.sh @@ -0,0 +1,94 @@ +#!/bin/bash +set -euo pipefail + +# Default values +DRAFT_FLAG="" +REVIEWERS="" + +# Parse arguments +while [[ $# -gt 0 ]]; do + case "$1" in + --draft) + DRAFT_FLAG="--draft" + shift + ;; + --reviewer) + if [[ -n "$2" ]]; then + REVIEWERS="$REVIEWERS --reviewer $2" + shift + shift + else + echo "Error: --reviewer flag requires an argument." >&2 + exit 1 + fi + ;; + *) + echo "Unknown option: $1" >&2 + exit 1 + ;; + esac +done + +# --- Git data --- +# Get default branch (main or master) +DEFAULT_BRANCH=$(git remote show origin | grep 'HEAD branch' | cut -d' ' -f5) +if [[ -z "$DEFAULT_BRANCH" ]]; then + # Fallback if remote isn't set up or is weird + if git show-ref --verify --quiet refs/heads/main; then + DEFAULT_BRANCH="main" + else + DEFAULT_BRANCH="master" + fi +fi + +# Get current branch +CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) +if [[ "$CURRENT_BRANCH" == "HEAD" ]]; then + echo "Error: Not on a branch. Aborting." >&2 + exit 1 +fi + +# Get merge base +MERGE_BASE=$(git merge-base HEAD "$DEFAULT_BRANCH") +if [[ -z "$MERGE_BASE" ]]; then + echo "Error: Could not find a common ancestor with '$DEFAULT_BRANCH'. Are you up to date?" >&2 + exit 1 +fi + + +# --- PR Content Generation --- + +# Generate Title +# Convert branch name from kebab-case/snake_case to Title Case +TITLE=$(echo "$CURRENT_BRANCH" | sed -E 's/^[a-z-]+\///' | sed -e 's/[-_]/ /g' -e 's/\b\(.\)/\u\1/g') + +# Get list of commits +COMMITS=$(git log "$MERGE_BASE"..HEAD --pretty=format:"- %s" --reverse) + +# Get list of changed files +CHANGED_FILES=$(git diff --name-only "$MERGE_BASE"..HEAD) + +# --- PR Body --- +BODY=$(cat <&2 +echo "Title: $TITLE" >&2 +echo "---" >&2 +echo "$BODY" >&2 +echo "---" >&2 + +# The command to be executed by the plugin runner +gh pr create --title "$TITLE" --body "$BODY" $DRAFT_FLAG $REVIEWERS