Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
179 changes: 179 additions & 0 deletions .claude/commands/pr.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
---
description: Create a PR on GitHub for the current branch
argument_hint: "[branch] [--dry] [--draft]"
allowed_tools: Bash, Read, Glob, Grep, Write, AskUserQuestion, mcp__github__create_pull_request, mcp__github__list_pull_requests, mcp__github__get_file_contents, mcp__github__issue_read
---

Create a PR on GitHub using the `gh` CLI for the currently checked-out branch.

**Examples:**
- `/pr` - Interactive mode, prompts for PR type
- `/pr master` - Interactive with explicit base branch
- `/pr --dry` - Generate description only, save to `.ai/`
- `/pr --draft` - Create as draft PR
- `/pr develop --draft` - Draft PR against non-default branch

## Steps

### 1. Check for Existing PR
Run `gh pr view --json number,url 2>/dev/null` to check if a PR already exists for this branch.
- If PR exists: Output `PR already exists: [URL]` and stop
- If no PR: Continue

### 2. Parse Arguments
- `--dry`: Skip PR creation, only generate and save description
- `--draft`: Create PR as draft
- First non-flag argument: base branch (default: auto-detected, see Step 2.5)
- **If no flags provided**: Use `AskUserQuestion` to prompt user:
- Open PR (create and publish)
- Draft PR (create as draft)
- Dry run (save locally only)

### 2.5. Determine Base Branch
If no base branch argument provided, detect the repo's default branch:
- Run: `git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'`
- Use result as default (typically `main` or `master`)
- If command fails, fall back to `master`

### 3. Gather Context
- Get current branch name: `git branch --show-current`
- Extract repo identifier: `git remote get-url origin | sed 's/\.git$//' | sed -E 's#.*[:/]([^/]+/[^/]+)$#\1#'` (e.g., `synonymdev/bitkit-ios`)
- Read PR template from `.github/pull_request_template.md`
- Fetch 10 most recent PRs (open or closed) from the extracted repo for writing style reference
- Run `git log $base..HEAD --oneline` for commit messages
- Run `git diff $base...HEAD --stat` for understanding scope of changes

### 4. Extract Linked Issues
Scan commits for issue references:
- Pattern to match: `#123` (just the issue number reference)
- Extract unique issue numbers: `git log $base..HEAD --oneline | grep -oE "#[0-9]+" | sort -u`
- Fetch each issue title: `gh api "repos/$REPO/issues/NUMBER" --jq '.title'` (using repo from Step 3)
- These will be used to start the PR description with linking keywords (see Step 6)

### 5. Identify Suggested Reviewers
Find potential reviewers based on:
- `.github/CODEOWNERS` file patterns (if exists)
- Recent contributors to changed files: `git log --format='%an' -- $(git diff $base..HEAD --name-only) | sort | uniq -c | sort -rn | head -3`
- Exclude the current user from suggestions

### 6. Generate PR Description
Starting from the template in `.github/pull_request_template.md`:

**Title Rules:**
- Format: `prefix: title` (e.g., `feat: add user settings screen`)
- Keep under 50 characters
- Use branch name as concept inspiration
- Prefixes: `feat`, `fix`, `chore`, `refactor`, `docs`, `test`

**Issue Linking (at the very start):**
If linked issues were found in commit messages, begin the PR description with linking keywords:
- Use `Fixes #123` for bug fixes
- Use `Closes #123` for features/enhancements
- One per line, before the "This PR..." opening separated by one empty line
- Reference: https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/using-keywords-in-issues-and-pull-requests

Example:
```
Fixes #528
Closes #418

This PR adds support for...
```

**Opening Format:**
- Single change: Start with "This PR [verb]s..." as a complete sentence
- Example: `This PR adds a Claude Code /pr command for generating PRs.`
- Multiple changes: Start with "This PR:" followed by a numbered list
- Example:
```
This PR:
1. Adds a Claude Code /pr command for generating PRs
2. Fixes issue preventing Claude Code reviews to be added as PR comments
3. Updates reviews workflow to minimize older review comments
```
- Each list item should start with a verb (Adds, Fixes, Updates, Removes, Refactors, etc.)

**Description Rules:**
- Base content around all commit messages in the branch
- Use branch name as the conceptual anchor
- Match writing style of recent PRs
- Focus on functionality over technical details
- Avoid excessive bold formatting like `**this:** that`
- Minimize code and file references like `TheClassName` or `someFunctionName`, `thisFileName.ext`
- Exception: for refactoring PRs (1:10 ratio of functionality to code changes), more technical detail is ok

**QA Notes / Testing Scenarios:**
- Structure with numbered headings and steps
- Make steps easily referenceable
- Be specific about what to test and expected outcomes

**For library repos (has `bindings/` directory or `Cargo.toml`):**
Structure QA Notes around testing and integration:

Example:
```
### QA Notes

#### Testing
- [ ] `cargo test` passes
- [ ] `cargo clippy` clean
- [ ] Android bindings: `./build_android.sh`
- [ ] iOS bindings: `./build_ios.sh`

#### Integration
- Tested in: [bitkit-android#XXX](link)
- Or N/A if internal refactor with no API changes
```

**Preview Section (conditional):**
Only include if the PR template (`.github/pull_request_template.md`) contains a `### Preview` heading:
- Create placeholders for media: `IMAGE_1`, `VIDEO_2`, etc.
- Add code comment under each placeholder describing what it should show
- Example: `<!-- VIDEO_1: Record the send flow by scanning a LN invoice and setting amount to 5000 sats -->`

### 7. Save PR Description
Before creating the PR:
- Get next PR number: `gh api "repos/$REPO/issues?per_page=1&state=all&sort=created&direction=desc" --jq '.[0].number'` then add 1 (using repo from Step 3)
- Create `.ai/` directory if it doesn't exist
- Save to `.ai/pr_NN.md` where `NN` is the predicted PR number

### 8. Create the PR (unless --dry)
If not dry run:
```bash
gh pr create --base $base --title "..." --body "..." [--draft]
```
- Add `--draft` flag if draft mode selected
- If actual PR number differs from predicted, rename the saved file

### 9. Output Summary

**If PR created:**
```
PR Created: [PR URL]
Saved: .ai/pr_NN.md

Suggested reviewers:
- @username1 (X files modified recently)
- @username2 (CODEOWNER)
```

**If dry run:**
```
Dry run complete
Saved: .ai/pr_NN.md

To create PR: /pr [--draft]

Suggested reviewers:
- @username1 (X files modified recently)
- @username2 (CODEOWNER)
```

**Media TODOs (only if Preview section was included):**
If the PR description includes a Preview section with media placeholders, append:
```
## TODOs
- [ ] IMAGE_1: [description]
- [ ] VIDEO_2: [description]
```
List all media placeholders as TODOs with their descriptions.
1 change: 1 addition & 0 deletions .cursor/commands/pr.md
43 changes: 25 additions & 18 deletions .github/workflows/claude-code-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Claude Code Review

on:
pull_request:
types: [opened, synchronize]
types: [opened, synchronize, ready_for_review, reopened]
# Optional: Only run on specific file changes
# paths:
# - "src/**/*.ts"
Expand Down Expand Up @@ -31,27 +31,34 @@ jobs:
with:
fetch-depth: 1

- name: Minimize old Claude comments
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
REPO="${{ github.repository }}"
PR_NUMBER="${{ github.event.pull_request.number }}"

# Minimize issue comments from claude[bot]
gh api "repos/$REPO/issues/$PR_NUMBER/comments" --jq '.[] | select(.user.login == "claude[bot]") | .node_id' | while read -r node_id; do
if [ -n "$node_id" ]; then
echo "Minimizing comment: $node_id"
gh api graphql -f query='
mutation($id: ID!) {
minimizeComment(input: {subjectId: $id, classifier: OUTDATED}) {
minimizedComment { isMinimized }
}
}' -f id="$node_id" || true
fi
done

- name: Run Claude Code Review
id: claude-review
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
use_sticky_comment: true
additional_permissions: |
actions: read
prompt: |
REPO: ${{ github.repository }}
PR NUMBER: ${{ github.event.pull_request.number }}

Please review this pull request and provide feedback on:
- Code quality and best practices
- Potential bugs or issues
- Performance considerations
- Security concerns
- Test coverage

Use the repository's CLAUDE.md for guidance on style and conventions. Be constructive and helpful in your feedback.

plugin_marketplaces: 'https://github.com/anthropics/claude-code.git'
plugins: 'code-review@claude-code-plugins'
prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}'
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://code.claude.com/docs/en/cli-reference for available options
claude_args: '--allowed-tools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"'

4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,7 @@ buildServer.json

# VSCode
.vscode/

# AIs
.ai/
.claude/*.local*
Loading