Files
claude-engineering-plugin/plugins/compound-engineering/skills/git-commit-push-pr/SKILL.md
2026-04-13 23:22:47 -07:00

18 KiB

name, description
name description
git-commit-push-pr Commit, push, and open a PR with an adaptive, value-first description. Use when the user says "commit and PR", "push and open a PR", "ship this", "create a PR", "open a pull request", "commit push PR", or wants to go from working changes to an open pull request in one step. Also use when the user says "update the PR description", "refresh the PR description", "freshen the PR", or wants to rewrite an existing PR description. Produces PR descriptions that scale in depth with the complexity of the change, avoiding cookie-cutter templates.

Git Commit, Push, and PR

Go from working changes to an open pull request, or rewrite an existing PR description.

Asking the user: When this skill says "ask the user", use the platform's blocking question tool (AskUserQuestion in Claude Code, request_user_input in Codex, ask_user in Gemini). If unavailable, present the question and wait for a reply.

Mode detection

If the user is asking to update, refresh, or rewrite an existing PR description (with no mention of committing or pushing), this is a description-only update. The user may also provide a focus (e.g., "update the PR description and add the benchmarking results"). Note any focus for DU-3.

For description-only updates, follow the Description Update workflow below. Otherwise, follow the full workflow.

Context

If you are not Claude Code, skip to the "Context fallback" section below and run the command there to gather context.

If you are Claude Code, the six labeled sections below contain pre-populated data. Use them directly -- do not re-run these commands.

Git status: !git status

Working tree diff: !git diff HEAD

Current branch: !git branch --show-current

Recent commits: !git log --oneline -10

Remote default branch: !git rev-parse --abbrev-ref origin/HEAD 2>/dev/null || echo 'DEFAULT_BRANCH_UNRESOLVED'

Existing PR check: !gh pr view --json url,title,state 2>/dev/null || echo 'NO_OPEN_PR'

Context fallback

If you are Claude Code, skip this section — the data above is already available.

Run this single command to gather all context:

printf '=== STATUS ===\n'; git status; printf '\n=== DIFF ===\n'; git diff HEAD; printf '\n=== BRANCH ===\n'; git branch --show-current; printf '\n=== LOG ===\n'; git log --oneline -10; printf '\n=== DEFAULT_BRANCH ===\n'; git rev-parse --abbrev-ref origin/HEAD 2>/dev/null || echo 'DEFAULT_BRANCH_UNRESOLVED'; printf '\n=== PR_CHECK ===\n'; gh pr view --json url,title,state 2>/dev/null || echo 'NO_OPEN_PR'

Description Update workflow

DU-1: Confirm intent

Ask the user: "Update the PR description for this branch?" If declined, stop.

DU-2: Find the PR

Use the current branch and existing PR check from context. If the current branch is empty (detached HEAD), report no branch and stop. If the PR check returned state: OPEN, proceed to DU-3. Otherwise, report no open PR and stop.

DU-3: Write and apply the updated description

Read the current PR description:

gh pr view --json body --jq '.body'

Build the updated description:

  1. Get the full branch diff -- follow "Detect the base branch and remote" and "Gather the branch scope" in Step 6. Use the PR found in DU-2 for base branch detection.
  2. Classify commits -- follow "Classify commits before writing" in Step 6.
  3. Decide on evidence -- if the current description already has a ## Demo or ## Screenshots section with image embeds, preserve it unless the user's focus asks to refresh or remove it. If no evidence exists, follow "Evidence for PR descriptions" in Step 6.
  4. Rewrite the description from scratch -- follow the writing principles in Step 6, driven by feature commits, final diff, and evidence decision. Do not layer changes onto the old description or document what changed since the last version. Write as if describing the PR for the first time.
    • If the user provided a focus, incorporate it alongside the branch diff context.
  5. Compare and confirm -- briefly explain what the new description covers differently from the old one. This helps the user decide whether to apply; the description itself does not narrate these differences.
    • If the user provided a focus, confirm it was addressed.
    • Ask the user to confirm before applying.

If confirmed, apply:

gh pr edit --body "$(cat <<'EOF'
Updated description here
EOF
)"

Report the PR URL.


Full workflow

Step 1: Gather context

Use the context above. All data needed for this step and Step 3 is already available -- do not re-run those commands.

The remote default branch value returns something like origin/main. Strip the origin/ prefix. If it returned DEFAULT_BRANCH_UNRESOLVED or a bare HEAD, try:

gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name'

If both fail, fall back to main.

If the current branch is empty (detached HEAD), explain that a branch is required. Ask whether to create a feature branch now.

  • If yes, derive a branch name from the change content, create with git checkout -b <branch-name>, and use that for the rest of the workflow.
  • If no, stop.

If the working tree is clean (no staged, modified, or untracked files), determine the next action:

  1. Run git rev-parse --abbrev-ref --symbolic-full-name @{u} to check upstream.
  2. If upstream exists, run git log <upstream>..HEAD --oneline for unpushed commits.

Decision tree:

  • On default branch, unpushed commits or no upstream -- ask whether to create a feature branch (pushing default directly is not supported). If yes, create and continue from Step 5. If no, stop.
  • On default branch, all pushed, no open PR -- report no feature branch work. Stop.
  • Feature branch, no upstream -- skip Step 4, continue from Step 5.
  • Feature branch, unpushed commits -- skip Step 4, continue from Step 5.
  • Feature branch, all pushed, no open PR -- skip Steps 4-5, continue from Step 6.
  • Feature branch, all pushed, open PR -- report up to date. Stop.

Step 2: Determine conventions

Priority order for commit messages and PR titles:

  1. Repo conventions in context -- follow project instructions if they specify conventions. Do not re-read; they load at session start.
  2. Recent commit history -- match the pattern in the last 10 commits.
  3. Default -- type(scope): description (conventional commits).

Step 3: Check for existing PR

Use the current branch and existing PR check from context. If the branch is empty, report detached HEAD and stop.

If the PR check returned state: OPEN, note the URL -- continue to Step 4 and 5, then skip to Step 7 (existing PR flow). Otherwise, continue through Step 8.

Step 4: Branch, stage, and commit

  1. If on the default branch, create a feature branch first with git checkout -b <branch-name>.
  2. Scan changed files for naturally distinct concerns. If files clearly group into separate logical changes, create separate commits (2-3 max). Group at the file level only (no git add -p). When ambiguous, one commit is fine.
  3. Stage and commit each group in a single call. Avoid git add -A or git add .. Follow conventions from Step 2:
    git add file1 file2 file3 && git commit -m "$(cat <<'EOF'
    commit message here
    EOF
    )"
    

Step 5: Push

git push -u origin HEAD

Step 6: Write the PR description

The working-tree diff from Step 1 only shows uncommitted changes at invocation time. The PR description must cover all commits in the PR.

Detect the base branch and remote

Resolve both the base branch and the remote (fork-based PRs may use a remote other than origin). Stop at the first that succeeds:

  1. PR metadata (if existing PR found in Step 3):
    gh pr view --json baseRefName,url
    
    Extract baseRefName. Match owner/repo from the PR URL against git remote -v fetch URLs to find the base remote. Fall back to origin.
  2. Remote default branch from context -- if resolved, strip origin/ prefix. Use origin.
  3. GitHub metadata:
    gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name'
    
    Use origin.
  4. Common names -- check main, master, develop, trunk in order:
    git rev-parse --verify origin/<candidate>
    
    Use origin.

If none resolve, ask the user to specify the target branch.

Gather the branch scope

Verify the remote-tracking ref exists and fetch if needed:

git rev-parse --verify <base-remote>/<base-branch> 2>/dev/null || git fetch --no-tags <base-remote> <base-branch>

Gather merge base, commit list, and full diff in a single call:

MERGE_BASE=$(git merge-base <base-remote>/<base-branch> HEAD) && echo "MERGE_BASE=$MERGE_BASE" && echo '=== COMMITS ===' && git log --oneline $MERGE_BASE..HEAD && echo '=== DIFF ===' && git diff $MERGE_BASE...HEAD

Use the full branch diff and commit list as the basis for the description.

Evidence for PR descriptions

Decide whether evidence capture is possible from the full branch diff.

Evidence is possible when the diff changes observable behavior demonstrable from the workspace: UI, CLI output, API behavior with runnable code, generated artifacts, or workflow output.

Evidence is not possible for:

  • Docs-only, markdown-only, changelog-only, release metadata, CI/config-only, test-only, or pure internal refactors
  • Behavior requiring unavailable credentials, paid/cloud services, bot tokens, deploy-only infrastructure, or hardware not provided

When not possible, skip without asking. When possible, ask: "This PR has observable behavior. Capture evidence for the PR description?"

  1. Capture now -- load the ce-demo-reel skill with a target description inferred from the branch diff. ce-demo-reel returns Tier, Description, and URL. Build a ## Demo or ## Screenshots section (browser-reel/terminal-recording/screenshot-reel use "Demo", static uses "Screenshots").
  2. Use existing evidence -- ask for the URL or markdown embed.
  3. Skip -- no evidence section.

If capture returns Tier: skipped or URL: "none", do not add a placeholder. Summarize in the final report.

Place evidence before the Compound Engineering badge. Do not label test output as "Demo" or "Screenshots".

Classify commits before writing

Scan the commit list and classify each commit:

  • Feature commits -- implement the PR's purpose (new functionality, intentional refactors, design changes). These drive the description.
  • Fix-up commits -- iteration work (code review fixes, lint fixes, test fixes, rebase resolutions, style cleanups). Invisible to the reader.

When sizing the description, mentally subtract fix-up commits: a branch with 12 commits but 9 fix-ups is a 3-commit PR.

Frame the narrative before sizing

Articulate the PR's narrative frame:

  1. Before: What was broken, limited, or impossible? (One sentence.)
  2. After: What's now possible or improved? (One sentence.)
  3. Scope rationale (only if 2+ separable-looking concerns): Why do these ship together? (One sentence.)

This frame becomes the opening. For small+simple PRs, the "after" sentence alone may be the entire description.

Sizing the change

Assess size (files, diff volume) and complexity (design decisions, trade-offs, cross-cutting concerns) to select description depth:

Change profile Description approach
Small + simple (typo, config, dep bump) 1-2 sentences, no headers. Under ~300 characters.
Small + non-trivial (bugfix, behavioral change) Short narrative, ~3-5 sentences. No headers unless two distinct concerns.
Medium feature or refactor Narrative frame (before/after/scope), then what changed and why. Call out design decisions.
Large or architecturally significant Full narrative: problem context, approach (and why), key decisions, migration/rollback if relevant.
Performance improvement Include before/after measurements if available. Markdown table works well.

When in doubt, shorter is better. Match description weight to change weight.

Writing voice

If the user has documented style preferences, follow those. Otherwise:

  • Active voice. No em dashes or -- substitutes; use periods, commas, colons, or parentheses.
  • Vary sentence length. Never three similar-length sentences in a row.
  • Do not make a claim and immediately explain it. Trust the reader.
  • Plain English. Technical jargon fine; business jargon never.
  • No filler: "it's worth noting", "importantly", "essentially", "in order to", "leverage", "utilize."
  • Digits for numbers ("3 files"), not words ("three files").

Writing principles

  • Lead with value: Open with what's now possible or fixed, not what was moved around. The subtler failure is leading with the mechanism ("Replace the hardcoded capture block with a tiered skill") instead of the outcome ("Evidence capture now works for CLI tools and libraries, not just web apps").
  • No orphaned opening paragraphs: If the description uses ## headings anywhere, the opening must also be under a heading (e.g., ## Summary). For short descriptions with no sections, a bare paragraph is fine.
  • Describe the net result, not the journey: The description covers the end state, not how you got there. No iteration history, debugging steps, intermediate failures, or bugs found and fixed during development. This applies equally to description updates: rewrite from the current state, not as a log of what changed since the last version. Exception: process details critical to understand a design choice.
  • When commits conflict, trust the final diff: The commit list is supporting context, not the source of truth. If commits describe intermediate steps later revised or reverted, describe the end state from the full branch diff.
  • Explain the non-obvious: If the diff is self-explanatory, don't narrate it. Spend space on things the diff doesn't show: why this approach, what was rejected, what the reviewer should watch.
  • Use structure when it earns its keep: Headers, bullets, and tables aid comprehension, not mandatory template sections.
  • Markdown tables for data: Before/after comparisons, performance numbers, or option trade-offs communicate well as tables.
  • No empty sections: If a section doesn't apply, omit it. No "N/A" or "None."
  • Test plan -- only when non-obvious: Include when testing requires edge cases the reviewer wouldn't think of, hard-to-verify behavior, or specific setup. Omit when "run the tests" is the only useful guidance. When the branch adds test files, name them with what they cover.

Visual communication

Include a visual aid only when the change is structurally complex enough that a reviewer would struggle to reconstruct the mental model from prose alone.

When to include:

PR changes... Visual aid
Architecture touching 3+ interacting components Mermaid component or interaction diagram
Multi-step workflow or data flow with non-obvious sequencing Mermaid flow diagram
3+ behavioral modes, states, or variants Markdown comparison table
Before/after performance or behavioral data Markdown table
Data model changes with 3+ related entities Mermaid ERD

When to skip:

  • Sizing routes to "1-2 sentences"
  • Prose already communicates clearly
  • The diagram would just restate the diff visually
  • Mechanical changes (renames, dep bumps, config, formatting)

Format:

  • Mermaid (default) for flows, interactions, dependencies. 5-10 nodes typical, up to 15 for genuinely complex changes. Use TB direction. Source should be readable as fallback.
  • ASCII diagrams for annotated flows needing rich in-box content. 80-column max.
  • Markdown tables for comparisons and decision matrices.
  • Place inline at point of relevance, not in a separate section.
  • Prose is authoritative when it conflicts with a visual.

Verify generated diagrams against the change before including.

Numbering and references

Never prefix list items with # in PR descriptions -- GitHub interprets #1, #2 as issue references and auto-links them.

When referencing actual GitHub issues or PRs, use org/repo#123 or the full URL. Never use bare #123 unless verified.

Compound Engineering badge

Append a badge footer separated by a --- rule. Skip if a badge already exists.

Badge:

---

[![Compound Engineering](https://img.shields.io/badge/Built_with-Compound_Engineering-6366f1)](https://github.com/EveryInc/compound-engineering-plugin)
![HARNESS](https://img.shields.io/badge/MODEL_SLUG-COLOR?logo=LOGO&logoColor=white)

Harness lookup:

Harness LOGO COLOR
Claude Code claude D97757
Codex (omit logo param) 000000
Gemini CLI googlegemini 4285F4

Model slug: Replace spaces with underscores. Append context window and thinking level in parentheses if known. Examples: Opus_4.6_(1M,_Extended_Thinking), Sonnet_4.6_(200K), Gemini_3.1_Pro.

Step 7: Create or update the PR

New PR (no existing PR from Step 3)

gh pr create --title "the pr title" --body "$(cat <<'EOF'
PR description here

---

[![Compound Engineering](https://img.shields.io/badge/Built_with-Compound_Engineering-6366f1)](https://github.com/EveryInc/compound-engineering-plugin)
![Claude Code](https://img.shields.io/badge/Opus_4.6_(1M,_Extended_Thinking)-D97757?logo=claude&logoColor=white)
EOF
)"

Use the badge from the Compound Engineering badge section. Replace harness and model values from the lookup tables. Keep the PR title under 72 characters, following Step 2 conventions.

Existing PR (found in Step 3)

The new commits are already on the PR from Step 5. Report the PR URL, then ask whether to rewrite the description.

  • If yes:

    1. Classify commits -- new commits since last push are often fix-up work and should not appear as distinct items
    2. Size the full PR (not just new commits) using the sizing table
    3. Rewrite from scratch to describe the PR's net result as of now, following Step 6's writing principles. Do not append, amend, or layer onto the old description. The description is not a changelog.
    4. Include the Compound Engineering badge unless already present
    5. Apply:
    gh pr edit --body "$(cat <<'EOF'
    Updated description here
    EOF
    )"
    
  • If no -- done.

Step 8: Report

Output the PR URL.