Core Commands
Essential slash commands: /commit, /pr, /cpm (commit-PR-merge), /gs (git status), /ghi (create issue).
Tags
README
commands-core
Essential slash commands for everyday git and GitHub workflows.
What This Module Does
Provides five foundational commands that cover the most common development operations:
- /commit - Stage and commit changes with conventional format
- /pr - Push branch and create a pull request that closes an issue
- /cpm - One-shot commit + PR + merge workflow for solo developers
- /gs - Show git status and project overview
- /ghi - Create a GitHub issue with proper labels
Also ships two reusable skills:
- pr-description - Pure writer that returns
{title, body}for a PR in CCGM voice. Callable from/pr,/cpm, or any agent that needs a PR body without the publishing plumbing. Does NOT invokegh pr createorgh pr edit. - cpm - Sequenced commit-PR-merge workflow encoded as a skill so other commands can embed it.
Files
| File | Type | Description |
|---|---|---|
commands/commit.md |
command | Stage all changes and commit with conventional format |
commands/pr.md |
command | Push branch and create PR closing an issue |
commands/cpm.md |
command | Commit, create PR, and merge in one shot |
commands/gs.md |
command | Git status dashboard with project info |
lib/gs-gather.sh |
lib | Helper script that gathers git and project info for /gs |
commands/ghi.md |
command | Create GitHub issue with labels |
skills/cpm/SKILL.md |
skill | Sequenced commit-PR-merge workflow |
skills/pr-description/SKILL.md |
skill | Pure PR title and body writer (returns structured output, no publishing) |
skills/pr-description/references/default-template.md |
skill-reference | Fallback PR body structure when no repo template exists |
Dependencies
None.
Manual Installation
Copy command files to your Claude Code commands directory:
# Create commands directory if it does not exist
mkdir -p ~/.claude/commands
# Copy each command
cp commands/commit.md ~/.claude/commands/commit.md
cp commands/pr.md ~/.claude/commands/pr.md
cp commands/cpm.md ~/.claude/commands/cpm.md
cp commands/gs.md ~/.claude/commands/gs.md
cp commands/ghi.md ~/.claude/commands/ghi.md
# Lib helper
mkdir -p ~/.claude/lib
cp lib/gs-gather.sh ~/.claude/lib/gs-gather.sh
# Skills
mkdir -p ~/.claude/skills/cpm ~/.claude/skills/pr-description/references
cp skills/cpm/SKILL.md ~/.claude/skills/cpm/SKILL.md
cp skills/pr-description/SKILL.md ~/.claude/skills/pr-description/SKILL.md
cp skills/pr-description/references/default-template.md ~/.claude/skills/pr-description/references/default-template.md
After copying, the commands are available as /commit, /pr, /cpm, /gs, and /ghi in Claude Code. The pr-description and cpm skills are invocable by name from other commands or agents.
Will install
| Path | Action | Target | Type |
|---|---|---|---|
commands/commit.md | → | commands/commit.md | command |
commands/pr.md | → | commands/pr.md | command |
commands/cpm.md | → | commands/cpm.md | command |
commands/gs.md | → | commands/gs.md | command |
lib/gs-gather.sh | → | lib/gs-gather.sh | lib |
commands/ghi.md | → | commands/ghi.md | command |
skills/cpm/SKILL.md | → | skills/cpm/SKILL.md | skill |
skills/pr-description/SKILL.md | → | skills/pr-description/SKILL.md | skill |
skills/pr-description/references/default-template.md | → | skills/pr-description/references/default-template.md | skill-reference |
Dependencies
No dependencies.
Required by
No other module depends on this one.
Included in presets
Install this module
Agent prompt
Recommended for agent users -- hands the whole install off to your assistant.
Fetch https://cd23a9be.ccgm-site.pages.dev/modules/commands-core.md and install this module into my Claude Code setup.
Native plugin marketplace
One command via the native plugin marketplace -- additive, does not merge settings.json.
claude plugin install commands-core@ccgm
The marketplace path is additive, not a replacement: it installs commands, agents, and skills as native plugin components, but it does not perform the bash installer's deep settings.json merge, and it does not write the always-loaded global CLAUDE.md context. Rules are only injected via an opt-in SessionStart hook rather than being auto-loaded. Use the bash installer when those pieces matter to you.
Files
command (5)
commands/commit.md
---
description: Stage all changes and commit with conventional format
allowed-tools: Agent
---
# /commit - Stage and Commit Changes
Use the Agent tool to execute this entire workflow on a cheaper model:
- **model**: sonnet
- **description**: commit workflow
Pass the agent all workflow instructions below. Include the received arguments: `$ARGUMENTS`
After the agent completes, relay its final report to the user exactly as received.
---
## Workflow Instructions
Stage all current changes and create a commit with conventional format.
Arguments: $ARGUMENTS
### 1. Verify There Are Changes to Commit
```bash
git status --short
```
If no changes exist, report that there is nothing to commit and stop.
### 2. Understand the Context
Gather context to write a good commit message:
```bash
# Current branch name (often contains issue number)
git branch --show-current
# What has changed
git diff --stat
git diff --cached --stat
# Recent commits for style reference
git log --oneline -5
```
### 3. Extract Issue Number
Derive the issue number from the branch name. Convention: branches are named `{issue-number}-{description}`.
```bash
BRANCH=$(git branch --show-current)
ISSUE_NUM=$(echo "$BRANCH" | grep -oE '^[0-9]+')
```
If no issue number is found in the branch name and the arguments contain an issue number, use that instead. If neither source has an issue number, proceed without one.
### 4. Run Verification
Before committing, run the project's verification suite to ensure nothing is broken:
```bash
# Check for common verification commands (adapt to project)
# Look for package.json scripts
cat package.json 2>/dev/null | grep -E '"(lint|type-check|test:run|test|build)"'
```
Run available checks:
- Linting (if available)
- Type checking (if TypeScript project)
- Tests (if available)
- Build (if available)
If any check fails, fix the issue before proceeding. Do not commit broken code.
### 5. Stage All Changes
```bash
git add -A
```
Review what is staged:
```bash
git diff --cached --stat
```
### 6. Create the Commit
Format: `{issue_number}: {brief description}`
If an issue number was found:
```bash
git commit -m "{issue_number}: {brief description of changes}"
```
If no issue number:
```bash
git commit -m "{brief description of changes}"
```
Rules for the commit message:
- Keep the first line under 72 characters
- Use imperative mood ("Add feature" not "Added feature")
- Be specific about what changed
- Do not include any AI attribution or co-author trailers
- If the arguments contain a specific message, use it (but still prepend the issue number)
### 7. Confirm Success
```bash
git log --oneline -1
```
Report the commit hash and message to the user.
commands/pr.md
---
description: Push branch and create a pull request that closes an issue
allowed-tools: Agent
---
# /pr - Push Branch and Create Pull Request
Use the Agent tool to execute this entire workflow on a cheaper model:
- **model**: sonnet
- **description**: push and create PR
Pass the agent all workflow instructions below. Include the received arguments: `$ARGUMENTS`
After the agent completes, relay its final report to the user exactly as received.
---
## Workflow Instructions
Push the current branch to the remote and create a PR that closes the associated issue.
Arguments: $ARGUMENTS
### 1. Pre-Flight Checks
Verify the working directory is clean:
```bash
git status --short
```
If there are uncommitted changes, warn the user and suggest running `/commit` first. Do not proceed with uncommitted changes.
### 2. Gather Context
```bash
# Current branch
BRANCH=$(git branch --show-current)
# Extract issue number from branch name
ISSUE_NUM=$(echo "$BRANCH" | grep -oE '^[0-9]+')
# Check we are not on main
if [ "$BRANCH" = "main" ] || [ "$BRANCH" = "master" ]; then
echo "ERROR: Cannot create PR from main/master branch"
exit 1
fi
# Get commit history for this branch
git log --oneline origin/main..HEAD 2>/dev/null || git log --oneline -5
```
### 3. Run Verification
Run the project's full verification suite before pushing:
```bash
# Detect and run available checks
npm run lint 2>/dev/null
npm run type-check 2>/dev/null
npm run test:run 2>/dev/null || npm test 2>/dev/null
npm run build 2>/dev/null
```
All checks must pass. Fix any failures before proceeding.
### 4. Rebase on Main
Ensure the branch is up to date with the latest main:
```bash
git fetch origin
git rebase origin/main
```
If there are conflicts, resolve them. After resolving:
```bash
git rebase --continue
```
### 5. Push the Branch
```bash
git push -u origin "$BRANCH"
```
If the branch was rebased and already existed on the remote:
```bash
git push --force-with-lease -u origin "$BRANCH"
```
### 6. Check for PR Template
One local check — if a template file is in the repo, use it; otherwise write a value-first body (do NOT query the org's `.github` repo or create a template):
```bash
ls pull_request_template.md PULL_REQUEST_TEMPLATE.md \
.github/pull_request_template.md .github/PULL_REQUEST_TEMPLATE.md 2>/dev/null
```
If a template is found, read it and structure the PR body using the template's sections and headings.
### 7. Create the Pull Request
Build the PR title and body:
- **Title**: `{issue_number}: {brief description}` (matching commit format)
- **Body**: Must include `Closes #{issue_number}` to auto-close on merge
If a PR template was found, fill in its sections. Otherwise use:
```bash
gh pr create \
--title "{issue_number}: {description}" \
--body "## Summary
{Summary of changes}
## Changes
{Key changes made}
## Test Plan
{How this was tested}
## Issue
Closes #{issue_number}"
```
### 8. Tracking Update
Note: Tracking status is updated automatically by the PostToolUse hook on `gh pr create` (sets status to "pr-created"). No manual label management needed.
### 9. Report Result
Display:
- PR URL
- PR number
- Issue it closes
- Any CI checks that are running
commands/cpm.md
---
description: One-shot commit, create PR, and merge workflow
allowed-tools: Agent
---
# /cpm - Commit, PR, and Merge
Use the Agent tool to execute this entire workflow on a cheaper model:
- **model**: sonnet
- **description**: cpm git workflow
Pass the agent all workflow instructions below. Include the received arguments: `$ARGUMENTS`
After the agent completes, relay its final report to the user exactly as received.
---
## Workflow Instructions
A one-shot workflow that commits current changes, creates a PR, and merges it. Designed for repos where you merge your own PRs (solo developer or self-merge workflow).
Arguments: $ARGUMENTS
### 1. Pre-Flight Checks
```bash
# Verify we have changes
git status --short
# Verify we are on a feature branch, not main
BRANCH=$(git branch --show-current)
if [ "$BRANCH" = "main" ] || [ "$BRANCH" = "master" ]; then
echo "ERROR: Cannot run /cpm from main/master. Create a feature branch first."
exit 1
fi
```
If no changes exist and no commits ahead of main, report that there is nothing to do.
### 2. Extract Issue Number
```bash
BRANCH=$(git branch --show-current)
ISSUE_NUM=$(echo "$BRANCH" | grep -oE '^[0-9]+')
```
If arguments contain an issue number, prefer that. If neither source has one, proceed without it.
### 3. Run Verification
Run the project's full verification suite:
```bash
# Detect and run available checks
npm run lint 2>/dev/null
npm run type-check 2>/dev/null
npm run test:run 2>/dev/null || npm test 2>/dev/null
npm run build 2>/dev/null
```
All checks must pass. Fix failures before proceeding. Do not skip verification.
### 4. Commit (if uncommitted changes exist)
```bash
git add -A
git diff --cached --stat
```
If there are staged changes:
```bash
git commit -m "{issue_number}: {brief description}"
```
Rules:
- Imperative mood
- Under 72 characters
- No AI attribution
- If arguments include a message, use it (prepend issue number)
### 5. Rebase on Main
```bash
git fetch origin
git rebase origin/main
```
Resolve conflicts if any arise.
### 6. Push
```bash
git push -u origin "$BRANCH"
```
Or if rebased and remote branch exists:
```bash
git push --force-with-lease -u origin "$BRANCH"
```
### 7. Create PR
Check for a PR template first:
```bash
ls pull_request_template.md PULL_REQUEST_TEMPLATE.md .github/pull_request_template.md .github/PULL_REQUEST_TEMPLATE.md 2>/dev/null
```
Create the PR:
```bash
gh pr create \
--title "{issue_number}: {description}" \
--body "## Summary
{Summary of what this PR does}
## Changes
{Key changes}
## Test Plan
{How it was verified}
## Issue
Closes #{issue_number}"
```
### 8. Merge the PR
Merge immediately with admin bypass — do not wait for GitHub Actions:
```bash
gh pr merge --squash --delete-branch --admin
```
Local pre-push verification (lint + type-check + tests + build) is the source of truth. Remote CI is best-effort: Actions minutes budget runs out, runners stall, queues back up — none of those are reasons to block a merge. `--admin` bypasses the BLOCKED state from "checks pending" or "no required reviewer present" when you ARE the repo admin. It does NOT force-merge through an actually-FAILED check; if a check is in FAILURE state (not PENDING), stop and investigate — local pre-push should have caught it.
If `--admin` itself fails — merge conflict, missing PR, you are not the admin in this repo — report and stop. Do not retry the same command; investigate the cause.
### 9. Close the Issue
If the PR body included `Closes #N`, GitHub auto-closes the issue on merge. Verify:
```bash
gh issue view "$ISSUE_NUM" --json state --jq '.state' 2>/dev/null
```
If still open, close manually:
```bash
gh issue close "$ISSUE_NUM" --comment "Completed via PR merge"
```
Note: Tracking status is updated automatically by the PostToolUse hook. The hook sets status to "closed" on `gh issue close` and "merged" on `gh pr merge`. No manual label management needed.
### 10. Return to Main
```bash
git checkout main
git pull origin main --ff-only
```
### 11. Report Result
Display:
- Commit hash and message
- PR number and URL
- Merge status
- Issue close status
- Current state (on main, clean working directory)
commands/gs.md
---
description: Show git status and project overview
allowed-tools: Agent
---
# /gs - Git Status Dashboard
Use the Agent tool to execute this entire workflow on a cheaper model:
- **model**: sonnet
- **description**: git status dashboard
Pass the agent all workflow instructions below. Include the received arguments: `$ARGUMENTS`
After the agent completes, relay its dashboard output to the user exactly as received.
---
## Workflow Instructions
Display a comprehensive overview of the current repository state.
Arguments: $ARGUMENTS
### Step 1: Gather Data
Run the gather script to collect all git data in parallel:
```bash
bash ~/.claude/lib/gs-gather.sh
```
This outputs structured `=== SECTION ===` blocks with all data needed.
### Step 2: Present Dashboard
Format the gathered data into this dashboard. Omit any section that is empty.
```
Repository: {name from REPO section}
Branch: {branch} -> {upstream}
Status: {clean / N files changed based on STATUS section}
Sync:
Main: {ahead_behind from SYNC main: line - format as "N ahead, N behind"}
Remote: {ahead_behind from SYNC upstream: line - format as "N unpushed, N to pull"}
Recent Commits:
{LOG section content}
Open PRs:
{PRS section content, highlight any from current branch}
Sibling Sessions (same repo):
{SESSIONS content, or omit if empty}
Changes:
{DIFF section content - summarize staged/unstaged/untracked}
Suggested: {recommended next action per table below}
```
| State | Recommendation |
|-------|---------------|
| Uncommitted changes on feature branch | Run `/commit` to commit your changes |
| Committed changes, no PR | Run `/pr` to push and create a pull request |
| On main with no changes | Create a feature branch or run `/ghi` |
| Behind main on feature branch | Run `git fetch origin && git rebase origin/main` |
| PR open and CI passing | Run `gh pr merge --squash --delete-branch` |
| Clean state on main | Ready for new work |
commands/ghi.md
---
description: Create a new GitHub issue with proper labels
allowed-tools: Agent
---
# /ghi - Create GitHub Issue
Use the Agent tool to execute this workflow on a cheaper model:
- **model**: haiku
- **description**: create GitHub issue
Pass the agent all workflow instructions below. Include the received arguments: `$ARGUMENTS`
After the agent completes, relay its report to the user exactly as received.
---
## Workflow Instructions
Create a new GitHub issue with appropriate labels based on the type of work.
Arguments: $ARGUMENTS
### 1. Gather Issue Details
If the arguments provide enough context (title and description), use them directly. Otherwise, ask the user for:
- **Title**: A concise, descriptive title
- **Type**: feature, bug, refactor, chore, documentation, or human-agent
- **Description**: What needs to be done and why
### 2. Determine Issue Type and Labels
Map the issue type to the appropriate label:
| Type | Label | Color | Description |
|------|-------|-------|-------------|
| feature | `enhancement` | `a2eeef` | New feature or improvement |
| bug | `bug` | `d73a4a` | Something is not working |
| refactor | `chore` | `e4e669` | Maintenance, refactoring, config |
| chore | `chore` | `e4e669` | Maintenance, dependencies, config |
| documentation | `documentation` | `0075ca` | Documentation changes |
| human-agent | `human-agent` | `f9d0c4` | Requires manual human action |
### 3. Check Existing Labels
Verify the required label exists in the repo:
```bash
gh label list | grep -i "{label-name}"
```
If the label does not exist, create it:
```bash
gh label create "{label-name}" --color "{color}" --description "{description}"
```
### 4. Build the Issue Body
Structure the issue body based on the type:
**For features/enhancements:**
```markdown
## Summary
{What this feature does and why it is needed}
## Implementation Steps
{Numbered steps if known, or "TBD - to be planned"}
## Acceptance Criteria
- [ ] {Criterion 1}
- [ ] {Criterion 2}
```
**For bugs:**
```markdown
## Bug Description
{What is happening vs. what should happen}
## Steps to Reproduce
1. {Step 1}
2. {Step 2}
## Expected Behavior
{What should happen}
## Actual Behavior
{What is happening}
```
**For human-agent tasks:**
```markdown
## Context
{Why this manual action is needed}
## Required Actions
- [ ] {Action 1}
- [ ] {Action 2}
## Instructions
{Step-by-step guide for the human}
```
### 5. Create the Issue
```bash
gh issue create \
--title "{title}" \
--label "{label}" \
--body "{body}"
```
For human-agent issues, also assign to the repo owner if known:
```bash
gh issue create \
--title "{title}" \
--label "human-agent" \
--body "{body}"
```
### 6. Report Result
Display:
- Issue number
- Issue URL
- Title
- Labels applied
- Suggested next step (e.g., "Create a branch with `git checkout -b {issue-number}-{description} origin/main`")
skill (2)
skills/cpm/SKILL.md
# /cpm — Commit, PR, Merge
One-shot workflow: commit all changes, create a PR, merge it, close the issue, and rebase on main.
## Usage
```
/cpm
```
No arguments needed. Derives the issue number from the current branch name (expects `{issue-number}-{description}` format).
## Instructions
Execute the following steps sequentially. Do NOT skip steps or proceed if a step fails.
### Phase 1: Pre-flight
1. Run `git status` to confirm there are changes to commit.
2. Run `git diff --stat` to see what changed.
3. Extract the issue number from the current branch name (the leading digits before the first `-`).
4. Run `git log --oneline -5` to check recent commit style.
If there are no changes and no unpushed commits, stop and report "Nothing to commit or push."
### Phase 2: Commit
1. Stage all changed files with `git add` (prefer specific files over `git add -A`; never stage `.env` or credential files).
2. Create a commit with message format: `{issue-number}: {concise description of changes}`
3. Do NOT add any Co-Authored-By trailers or AI attribution.
### Phase 3: Push & Create PR
1. Push the branch: `git push -u origin HEAD`
2. Check for a PR template at `.github/PULL_REQUEST_TEMPLATE.md` or `pull_request_template.md` in the repo root.
3. Create the PR using `gh pr create`:
- Title: `{issue-number}: {concise description}`
- Body: Use the PR template if found, otherwise use Summary + Test Plan format
- Include `Closes #{issue-number}` in the body
4. Capture the PR URL.
### Phase 4: Merge
1. Merge with admin bypass so you do not wait on GitHub Actions:
`gh pr merge --squash --delete-branch --admin`
2. Confirm the merge succeeded.
Local pre-push verification is the source of truth. Remote Actions stall, run out of budget, and queue — those are not reasons to block a merge. `--admin` bypasses the BLOCKED state caused by "checks pending" or "no required reviewer present" when you are the repo admin. It does NOT force-merge through an actually-FAILED check; a FAILURE check (not PENDING) means local verification missed something — stop and investigate, do not retry with `--admin`.
### Phase 5: Close Issue
1. The issue should auto-close from "Closes #N" in the PR body.
2. Verify with `gh issue view {issue-number} --json state`.
3. If still open, close it manually: `gh issue close {issue-number}`
### Phase 6: Return to Main
1. `git checkout main`
2. `git pull origin main --ff-only`
3. If `--ff-only` fails (local main diverged), fall back to `git fetch origin && git reset --hard origin/main`
4. Confirm clean state with `git status`.
### Phase 7: Report
Output a summary in this format:
```
## Completed
- **Issue**: #{issue-number} — {issue title}
- **PR**: {PR URL} (merged)
- **Commit**: {short SHA} — {commit message}
- **Branch**: Deleted `{branch-name}`, now on `main`
- **Status**: Clean, up to date with origin/main
```
## Error Handling
- If `gh pr merge --admin` fails for a real reason — merge conflict, missing PR, you are not the admin in this repo, a check in FAILURE state — report and stop. Do not retry the same command; investigate the cause.
- A FAILURE check (not PENDING) is the one signal that should block a merge. Pre-push verification should have caught it. If a remote check disagrees with local, investigate before merging.
- If `git pull --ff-only` fails, fall back to `git fetch origin && git reset --hard origin/main`.
- If any step fails, stop and report what succeeded and what failed.
skills/pr-description/SKILL.md
---
name: pr-description
description: Pure writer for PR titles and bodies. Takes a PR reference (or the current branch), reads diff + commits + linked issue + PR template, and returns structured {title, body}. Does NOT call `gh pr create` or `gh pr edit`. Invoke from `/pr`, `/cpm`, or any caller that needs a CCGM-voice PR body without the publishing plumbing.
disable-model-invocation: false
---
# PR Description Writer
A pure writer skill. One job: produce `{title, body}` for a pull request in CCGM voice, value-first, matching the repo's PR template when one exists.
Never publishes. Never calls `gh pr create`, `gh pr edit`, `gh pr comment`, or any mutating GitHub command. The caller is responsible for doing something with the returned text.
## When to Run
- A caller (e.g., `/pr`, `/cpm`, a coordinator agent) needs PR text and wants the voice separated from the publishing flow
- Rewriting an existing PR body to sharpen it before a second review pass
- Generating text for a PR that does not yet exist, so the caller can preview before pushing
Do NOT run this skill when the caller already has a finalized title and body - pass them through instead.
## Input Parsing
Accept any of the following as the PR reference:
| Form | Example | Meaning |
|------|---------|---------|
| bare number | `561` | PR #561 in the current repo |
| hash number | `#561` | same |
| prefixed | `pr:561` | same |
| full URL | `https://github.com/owner/repo/pull/561` | PR in that repo |
| branch name | `288-pr-description-writer-skill` | find the open PR for this branch, or fall through to "no PR yet" |
| empty / current | (no argument) | current branch; PR may or may not exist |
| steering text | `emphasize the benchmarks` | applied on top of any other input as a tone/content hint |
Multiple forms can coexist. `pr:561 emphasize the perf numbers` means "PR #561, lean on perf."
If no PR exists yet (e.g., the caller is about to create one), operate on the branch: compare `origin/main...HEAD` for the diff and commit set.
## Inputs to Collect
Collect in this order. Stop once each input is captured or confirmed absent.
1. **Linked issue** - from the branch name (`{issue-number}-{description}` convention) or from the PR body's `Closes #N` line. Read with `gh issue view {num}`.
2. **Commits on the branch** - `git log origin/main..HEAD --pretty=format:"%s%n%n%b%n---"`
3. **Diff stat** - `git diff origin/main...HEAD --stat`
4. **Full diff** - `git diff origin/main...HEAD` (sampled; see "Diff Sampling" below)
5. **PR template** - check in order:
- `pull_request_template.md` in the repo root
- `PULL_REQUEST_TEMPLATE.md` in the repo root
- `.github/pull_request_template.md`
- `.github/PULL_REQUEST_TEMPLATE.md`
- If none found, use the fallback structure in `references/default-template.md`
6. **Existing PR body** - if a PR already exists, `gh pr view {num} --json body,title`. Treat as prior art to improve, not replace wholesale.
7. **Steering text** - whatever hint the caller passed. Apply after drafting; do not let it override the template structure.
### Diff Sampling
For diffs over ~500 lines, sample rather than dump:
- Read the full diff stat (every file, every ± count)
- Read full diffs for files with substantive changes (>20 lines added or removed)
- For large generated/lockfile changes, record one line: "`{file}`: {N} lines; generated/lockfile, skipped"
Never claim coverage of a file you did not actually read.
## Title Rules
- Conventional-commit shape: `{type}({scope}): {summary}` or CCGM-style `#{issue}: {summary}` if the branch name carries an issue number
- Under 72 characters total, including any prefix
- Imperative mood (`add`, `extract`, `fix`), not past tense
- Lead with the value or action, not the filename
- If the repo uses `#{issue}:` prefix (check recent `git log --oneline -20` on main), match that convention
Examples:
| Bad | Good |
|-----|------|
| Updated pr.md and cpm.md to use new skill | #288: extract PR description writer as reusable skill |
| Refactor commands-core | #288: move inline PR body generation into pr-description skill |
| Big changes to review flow | feat(review): add scope-drift audit before specialist agents |
## Body Rules - Value-First
The body leads with what the PR enables, fixes, or changes in the user's world. File churn is supporting evidence, not the lead.
Write it in plain words: state what changed and why, active voice, short words. No achievement language — no "comprehensive", no "robust", no "seamless", no "Successfully". A reviewer should know what the PR does in one read. The full standard is `~/.claude/rules/writing-system.md` when the writing-system module is installed.
### Structure (when no PR template exists)
1. **Closes #N** - first line if the PR closes an issue. No other content on this line.
2. **One-sentence summary** - what this PR does, in user-facing terms. No filenames.
3. **Why** - what problem this solves or what capability it unlocks. Two sentences max.
4. **What changed** - bulleted list of concrete changes, each one a noun phrase with a verb:
- "Adds `pr-description` skill under `commands-core`"
- "Updates `/pr` to delegate body generation to the skill"
- "Removes inline body template from `cpm.md`"
5. **Test plan** - how the change was verified. Name commands: `bash tests/test-modules.sh`, manual smoke test of `/pr` on a test issue, etc.
6. **Notes / follow-ups** - optional; only include if there is real carry-over work.
### When a PR Template Exists
Fill the template's sections verbatim. Do not add sections the template does not include. Do not remove sections the template marks required.
If a section in the template does not apply to this PR (e.g., "Screenshots" for a backend-only change), write `N/A - {one-line reason}` rather than leaving it blank.
### Value-First Rationalizations to Avoid
| You are about to write... | The reality is... |
|---------------------------|-------------------|
| "This PR modifies `foo.ts` and `bar.ts`..." | Lead with what those modifications do for the user. File names are not value. |
| "I refactored the review flow for cleanliness." | Cleanliness is not a user-visible outcome. What does the refactor enable? |
| "Adds a new module." | Which module, what does it do, why does that matter? One sentence each. |
| "Various improvements." | If you cannot name them, do not mention them. Delete the bullet. |
| "Comprehensive error handling has been implemented..." | "Adds error handling to every API endpoint." State the change; drop the adjectives and the passive. |
## Output Format
Return exactly this structure as the skill's output. The caller parses it.
```
### TITLE
{title, single line, no trailing punctuation}
### BODY
{full body, markdown, starts with `Closes #N` line if applicable}
### METADATA
- Issue: #{num} or "none"
- Branch: {branch-name}
- Commits: {count}
- Files changed: {count}
- Template used: {path} or "default"
- Steering applied: {yes/no}; {one-line summary if yes}
```
Do NOT wrap in additional prose. Do NOT invoke `gh` commands with the result. Do NOT emit a "here's your PR body" preamble.
## Non-Goals
- Creating the PR (`gh pr create`)
- Editing an existing PR (`gh pr edit`)
- Commenting on the PR
- Pushing the branch
- Running verification (tests, lint, build)
- Deciding whether the PR is mergeable
The caller handles all of the above.
## Integration With Callers
### `/pr` and `/cpm`
Both commands currently write PR bodies inline. A caller that delegates to this skill should:
1. Gather context the skill needs (branch, issue number, template detection) if it already did that work
2. Pass `$ARGUMENTS` (steering text) straight through
3. Use the returned `TITLE` and `BODY` blocks as `--title` and `--body` args to `gh pr create`
4. Leave publishing, merging, and issue-closing to the caller's own flow
This keeps the writer pure and the publisher in charge of side effects.
### Headless Mode
When invoked by another skill or agent (not a human), behave as if `mode:headless`:
- No clarifying questions
- No asking the user to choose between drafts
- Return the single best draft given the inputs available
- If a required input is missing, emit a one-line `BLOCKED` note at the top of the output and stop
## Source
Ported from EveryInc/compound-engineering's `skills/ce-pr-description/SKILL.md`. Adapted to CCGM voice, to match existing commands-core conventions (`{issue}: {description}` title prefix, `Closes #N` body line), and to slot into the skill-authoring rules (imperative voice, no AI attribution, value-first body, references file for the default template).
lib (1)
lib/gs-gather.sh
#!/usr/bin/env bash
# gs-gather.sh - Parallel data gathering for /gs command
# Runs git status, PR, and session checks concurrently.
TMPDIR=$(mktemp -d)
trap "rm -rf $TMPDIR" EXIT
# --- Identity (synchronous) ---
BRANCH=$(git branch --show-current 2>/dev/null || echo "detached")
UPSTREAM=$(git rev-parse --abbrev-ref @{upstream} 2>/dev/null || echo "No upstream tracking branch")
REPO_NAME=$(git remote get-url origin 2>/dev/null | xargs basename 2>/dev/null | sed 's/\.git$//' || echo "unknown")
# --- Parallel jobs ---
# 1. Fetch + sync status
(
git fetch origin 2>/dev/null
AB_MAIN=$(git rev-list --left-right --count origin/main...HEAD 2>/dev/null || echo "? ?")
AB_UP=$(git rev-list --left-right --count @{upstream}...HEAD 2>/dev/null || echo "? ?")
echo "main:$AB_MAIN"
echo "upstream:$AB_UP"
) > "$TMPDIR/sync" 2>/dev/null &
# 2. Working directory status
(
git status --short 2>/dev/null
) > "$TMPDIR/status" 2>/dev/null &
# 3. Recent commits
(
git log --oneline -5 2>/dev/null
) > "$TMPDIR/log" 2>/dev/null &
# 4. Open PRs
(
gh pr list --state open --limit 10 2>/dev/null || echo "none"
) > "$TMPDIR/prs" 2>/dev/null &
# 5. Sibling sessions
(
python3 ~/.claude/lib/agent_sessions.py --repo "$REPO_NAME" --exclude-cwd "$PWD" --text 2>/dev/null || true
) > "$TMPDIR/sessions" 2>/dev/null &
# 6. Diff stats
(
echo "---UNSTAGED---"
git diff --stat 2>/dev/null
echo "---STAGED---"
git diff --cached --stat 2>/dev/null
) > "$TMPDIR/diff" 2>/dev/null &
wait
# --- Output ---
cat <<GATHER_EOF
=== REPO ===
name:${REPO_NAME}
branch:${BRANCH}
upstream:${UPSTREAM}
=== SYNC ===
$(cat "$TMPDIR/sync")
=== STATUS ===
$(cat "$TMPDIR/status")
=== LOG ===
$(cat "$TMPDIR/log")
=== PRS ===
$(cat "$TMPDIR/prs")
=== SESSIONS ===
$(cat "$TMPDIR/sessions")
=== DIFF ===
$(cat "$TMPDIR/diff")
GATHER_EOF
skill-reference (1)
skills/pr-description/references/default-template.md
# Default PR Body Template (value-first, no repo template found)
Use this structure when the target repo does not ship a PR template under the four paths the skill checks.
```markdown
Closes #{issue_number}
{One-sentence summary of what the PR does, in user-facing terms.}
## Why
{Two sentences max. What problem this solves, or what capability it unlocks.
Lead with the user outcome, not the implementation.}
## What Changed
- {Concrete change as a noun phrase with a verb}
- {...}
- {...}
## Test Plan
- {Named command or manual step, one line each}
- {...}
## Notes
{Optional. Include only if there is real carry-over work, a follow-up issue,
or a known limitation. Delete the section if empty.}
```
## Rules
- `Closes #N` goes on the first line, alone. GitHub uses it to auto-close the issue on merge.
- No `Co-Authored-By: Claude`, `Generated with Claude Code`, or any AI-attribution footer.
- If a section has nothing real to say, omit it rather than padding with filler.
- Keep bullets under ~12 words each. Long bullets are a sign the change should be split.
## When to Skip the Default
If any of these are true, do NOT use this template - the skill should have detected and used the repo's own template instead:
- A file named `pull_request_template.md` or `PULL_REQUEST_TEMPLATE.md` exists in the repo root
- A file exists under `.github/` with either casing
The check is local-only: do not query the org's `.github` repo over the API. A missing repo-level template means use this default, not that you should hunt further.