--- name: git-commit-push-pr description: 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: ```bash 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: ```bash 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: ```bash 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: ```bash 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 `, 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 ..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 `. 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: ```bash git add file1 file2 file3 && git commit -m "$(cat <<'EOF' commit message here EOF )" ``` ### Step 5: Push ```bash 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): ```bash 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:** ```bash gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name' ``` Use `origin`. 4. **Common names** -- check `main`, `master`, `develop`, `trunk` in order: ```bash git rev-parse --verify origin/ ``` 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: ```bash git rev-parse --verify / 2>/dev/null || git fetch --no-tags ``` Gather merge base, commit list, and full diff in a single call: ```bash MERGE_BASE=$(git merge-base / 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:** ```markdown --- [![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) ```bash 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: ```bash gh pr edit --body "$(cat <<'EOF' Updated description here EOF )" ``` - If **no** -- done. ### Step 8: Report Output the PR URL.