| name | git-gh-client |
| description | Core GitHub CLI operations - check availability, search PRs, get PR details, check status. Invoked by other git skills. |
GitHub CLI (gh) Client Skill
Base skill for interacting with GitHub via the gh CLI tool. This skill is invoked by other git skills that need GitHub operations.
Purpose
Provides reusable GitHub CLI functionality:
- โ
Check if
gh is installed and authenticated
- ๐ List all PRs for the repository
- ๐ Search and filter PRs (by author, label, date, state, etc.)
- ๐ Get PR details and metadata
- โ
Check PR status checks and CI/CD results
- ๐ Create and manage pull requests
Common Use Cases
This skill is used both directly (when user asks to list/filter PRs) and indirectly (invoked by other skills):
Direct usage:
- "List all open PRs" โ Shows all open PRs in current repo
- "Find PRs by username" โ Filters PRs by author
- "Show PRs with label 'bug'" โ Filters by label
- "List recent PRs" โ Shows PRs sorted by date
Invoked by other skills:
git-prepare-pull-request - Creating PRs
pr-review - Reviewing PRs
git-pull-request-status - Checking PR status and CI/CD
Phase 1: Check gh CLI Availability
ALWAYS check if gh is installed before attempting gh commands.
Check Installation
which gh
Check Authentication
gh auth status
If Not Installed
Provide installation instructions:
The GitHub CLI (`gh`) is required for this operation.
## Installation
**Linux (Debian/Ubuntu):**
```bash
sudo apt install gh
Linux (Fedora/RHEL/CentOS):
sudo dnf install gh
macOS:
brew install gh
Windows:
winget install --id GitHub.cli
Other platforms:
Visit https://cli.github.com/manual/installation
Authentication
After installation, authenticate with:
gh auth login
Follow the prompts to authenticate with your GitHub account.
### If Not Authenticated
```bash
gh auth login
Phase 2: List and Filter Pull Requests
This is a CORE capability - used both directly by users and by other skills.
Basic PR Listing
gh pr list
gh pr list --limit 100
gh pr list --json number,title,author,createdAt,state
gh pr list | column -t
Filter by State
gh pr list --state open
gh pr list --state closed
gh pr list --state merged
gh pr list --state all
Filter by Author
gh pr list --author <username>
gh pr list --author @me
gh pr list --search "author:user1 author:user2"
Filter by Label
gh pr list --label bug
gh pr list --label "bug,priority:high"
gh pr list --search "label:enhancement"
Filter by Assignee/Reviewer
gh pr list --assignee <username>
gh pr list --assignee @me
gh pr list --search "review-requested:username"
gh pr list --search "reviewed-by:username"
Search by Keywords
gh pr list --search "keyword"
gh pr list --search "in:title keyword"
gh pr list --search "in:body keyword"
gh pr list --search "keyword1 keyword2"
Filter by Date
gh pr list --search "created:>$(date -d '7 days ago' +%Y-%m-%d)"
gh pr list --search "updated:>$(date -d '1 day ago' +%Y-%m-%d)"
gh pr list --search "created:2024-01-01..2024-01-31"
gh pr list --search "created:<2024-01-01"
Advanced Filtering
gh pr list --search "is:draft"
gh pr list --draft
gh pr list --search "is:open -is:draft"
gh pr list --search "is:open conflicts:>0"
gh pr list --search "is:open -label:has-tests"
gh pr list --search "is:open review:required"
gh pr list --search "is:open review:approved"
gh pr list --search "is:open review:changes_requested"
gh pr list --base main
gh pr list --base develop
gh pr list --search "head:feature/*"
Combined Filters (Real-World Examples)
gh pr list --author @me --state open --search "review:required"
gh pr list --label bug --search "is:open review:approved"
gh pr list --author username --search "created:>$(date -d '7 days ago' +%Y-%m-%d)"
gh pr list --label "priority:high" --search "is:open status:failure"
gh pr list --search "is:open review:approved status:success -conflicts:>0"
Sort and Format Output
gh pr list --json number,title,createdAt --jq 'sort_by(.createdAt) | reverse | .[] | "#\(.number) - \(.title)"'
gh pr list --json number,title,updatedAt --jq 'sort_by(.updatedAt) | reverse | .[] | "#\(.number) - \(.title) (updated: \(.updatedAt))"'
gh pr list --json number,title,author,state,createdAt --jq '.[] |
"#\(.number) [\(.state)] \(.title) by @\(.author.login) (\(.createdAt[:10]))"'
gh pr list --json number,title,author,state,createdAt --jq -r '
["Number","Title","Author","State","Created"],
(.[] | [.number, .title, .author.login, .state, .createdAt]) |
@csv'
gh pr list --json labels --jq '[.[].labels[].name] | group_by(.) | map({label: .[0], count: length})'
Get PR Details
gh pr view <PR_NUMBER>
gh pr view <PR_NUMBER> --json number,title,body,author,state,baseRefName,headRefName,createdAt,updatedAt,labels,reviews,files,commits
gh pr diff <PR_NUMBER>
gh pr view <PR_NUMBER> --json commits --jq '.commits[] | "\(.oid[0:7]) \(.messageHeadline)"'
gh pr view <PR_NUMBER> --json files --jq '.files[] | .path'
gh pr view <PR_NUMBER> --json statusCheckRollup
Common Error: If you see "Projects (classic) is being deprecated" error:
- This means you're requesting deprecated fields (projectCards, projectItems)
- Solution: Only request the safe fields listed above
Phase 3: PR Status Checks
Using gh pr checks
IMPORTANT: gh pr checks returns exit code 1 when ANY check fails. This is NORMAL behavior, NOT an error.
ALWAYS handle the exit code when using this command:
gh pr checks <PR_NUMBER> || true
if gh pr checks <PR_NUMBER> 2>&1; then
echo "All checks passed!"
else
echo "Some checks failed (see output above)"
fi
checks_output=$(gh pr checks <PR_NUMBER> 2>&1 || true)
echo "$checks_output"
gh pr checks <PR_NUMBER>
check_exit_code=$?
if [ $check_exit_code -eq 0 ]; then
echo "All checks passed"
else
echo "Some checks failed (exit code: $check_exit_code)"
fi
Exit code behavior:
- Exit code 0 = All checks passed โ
- Exit code 1 = One or more checks failed โ (this is NOT a command error!)
- The output is always valid and shows check status regardless of exit code
Alternative: Get Status Checks via JSON
If you need programmatic parsing, use JSON:
gh pr view <PR_NUMBER> --json statusCheckRollup --jq '.statusCheckRollup'
Parse Status Check Results
The statusCheckRollup contains all CI/CD checks. Parse it to find failures:
gh pr view <PR_NUMBER> --json statusCheckRollup --jq '
.statusCheckRollup[] |
select(.conclusion == "FAILURE" or .conclusion == "ERROR") |
{
name: .name,
conclusion: .conclusion,
detailsUrl: .detailsUrl
}
'
Status Check Conclusions
| Conclusion | Meaning |
|---|
SUCCESS | Check passed |
FAILURE | Check failed |
ERROR | Check encountered an error |
PENDING | Check is running |
SKIPPED | Check was skipped |
CANCELLED | Check was cancelled |
TIMED_OUT | Check timed out |
Get Check Run Details
gh api repos/{owner}/{repo}/pulls/<PR_NUMBER>/checks --jq '.check_runs[] | {name, conclusion, output: .output.title}'
Get Workflow Run Logs
If a GitHub Actions check failed, get the logs:
gh run list --branch <branch-name> --limit 10
gh run view <RUN_ID> --log
gh run view <RUN_ID> --log-failed
Phase 4: Creating Pull Requests
Create PR with Details
gh pr create
gh pr create --title "PR Title" --body "Description"
gh pr create --title "Feature: Add new capability" --body "$(cat <<'EOF'
## Summary
- Added feature X
- Updated documentation
## Test Plan
- [ ] Unit tests pass
- [ ] Integration tests pass
๐ค Generated with Claude Code
EOF
)"
gh pr create --draft --title "WIP: Feature" --body "Work in progress"
gh pr create --title "Fix bug" --body "..." --reviewer user1,user2 --assignee user3
gh pr create --title "Fix bug" --body "..." --label bug,priority:high
gh pr create --base develop --head feature-branch --title "..." --body "..."
Auto-fill PR Details
gh pr create --fill
gh pr create --fill-first
Phase 5: PR Management
Update PR
gh pr edit <PR_NUMBER> --title "New title"
gh pr edit <PR_NUMBER> --body "New description"
gh pr edit <PR_NUMBER> --add-label bug,priority:high
gh pr edit <PR_NUMBER> --add-reviewer user1,user2
gh pr ready <PR_NUMBER>
gh pr edit <PR_NUMBER> --draft
Merge PR
gh pr merge <PR_NUMBER>
gh pr merge <PR_NUMBER> --merge
gh pr merge <PR_NUMBER> --squash
gh pr merge <PR_NUMBER> --rebase
gh pr merge <PR_NUMBER> --auto
Close PR
gh pr close <PR_NUMBER>
gh pr close <PR_NUMBER> --comment "Closing because..."
Common Use Cases
Use Case 1: List All PRs in Repository
gh pr list
gh pr list --state all
gh pr list --limit 100
Use Case 2: Find My PRs
gh pr list --author @me --state open
gh pr list --author @me --state all
gh pr list --author @me --search "review:required"
Use Case 3: Find PRs by Specific User
gh pr list --author username
gh pr list --author username --search "created:>$(date -d '7 days ago' +%Y-%m-%d)"
Use Case 4: Find PRs with Specific Labels
gh pr list --label bug
gh pr list --label "priority:high"
gh pr list --label "bug,priority:high"
gh pr list --search "is:open -label:needs-review"
Use Case 5: Find PRs Waiting for Review
gh pr list --search "is:open review:required"
gh pr list --search "review-requested:@me"
gh pr list --search "reviewed-by:@me"
Use Case 6: Find Recent/Old PRs
gh pr list --search "created:>$(date -d '7 days ago' +%Y-%m-%d)"
gh pr list --search "updated:>$(date -d '1 day ago' +%Y-%m-%d)"
gh pr list --search "updated:<$(date -d '30 days ago' +%Y-%m-%d)"
Use Case 7: Check PR Before Merging
gh pr view <PR_NUMBER> --json state,statusCheckRollup,reviews
gh pr view <PR_NUMBER> --json statusCheckRollup --jq '
.statusCheckRollup |
map(select(.conclusion != "SUCCESS")) |
length == 0
'
Use Case 4: Get Failed Check Details
gh pr view <PR_NUMBER> --json statusCheckRollup --jq '
.statusCheckRollup[] |
select(.conclusion == "FAILURE") |
{
name: .name,
detailsUrl: .detailsUrl,
conclusion: .conclusion
}
'
Use Case 5: Bulk PR Operations
gh pr list --author @me --search "is:draft" --json number --jq '.[].number' |
xargs -I {} gh pr close {}
gh pr list --state open --json number --jq '.[].number' |
xargs -I {} gh pr edit {} --add-label needs-review
Error Handling
Common Errors and Solutions
| Error | Cause | Solution |
|---|
gh: command not found | gh not installed | Install gh CLI (see Phase 1) |
Not authenticated | No GitHub auth | Run gh auth login |
Could not resolve to a Repository | Not in git repo or no remote | Check git remote |
GraphQL: Resource not accessible by integration | Insufficient permissions | Check token scopes with gh auth status |
Pull request not found | Invalid PR number | Verify PR number with gh pr list |
Projects (classic) is being deprecated | Requesting deprecated fields | DO NOT request: projectCards, projectItems fields |
gh pr checks exits with code 1 | Some checks failed | This is normal! Use gh pr view --json statusCheckRollup instead |
Deprecated Fields (DO NOT USE)
GitHub is deprecating classic projects. Never request these fields:
- โ
projectCards
- โ
projectItems
- โ
projectV2Items (also being phased out)
Safe fields to use:
- โ
number, title, body, author, state
- โ
baseRefName, headRefName, labels, reviews
- โ
statusCheckRollup, reviewDecision, mergeable
- โ
createdAt, updatedAt, files, commits
Handling Check Status Exit Codes
Problem: gh pr checks returns exit code 1 when checks fail.
Solution: ALWAYS handle the exit code when using gh pr checks:
gh pr checks <PR_NUMBER> || true
if ! gh pr checks <PR_NUMBER> 2>&1; then
echo "Some checks failed (this is expected behavior)"
fi
checks_output=$(gh pr checks <PR_NUMBER> 2>&1 || true)
Remember: Exit code 1 means "checks failed", NOT "command failed". The output is still valid and useful!
Verify Prerequisites
cat << 'EOF'
Checking GitHub CLI setup...
1. gh installed: $(which gh > /dev/null && echo "โ" || echo "โ")
2. Authenticated: $(gh auth status > /dev/null 2>&1 && echo "โ" || echo "โ")
3. In git repo: $(git rev-parse --git-dir > /dev/null 2>&1 && echo "โ" || echo "โ")
4. Has remote: $(git remote -v | grep -q origin && echo "โ" || echo "โ")
EOF
Integration with Other Skills
From prepare-pull-request
1. Invoke `git-gh-client` to check if gh is available
2. If available, use gh commands from this skill
3. Create PR using `gh pr create` patterns from Phase 4
From review-pull-request
1. Invoke `git-gh-client` to check availability
2. Use PR search/filter from Phase 2
3. Get PR details and diff from Phase 2
From pr-status
1. Invoke `git-gh-client` to check availability
2. Use status check queries from Phase 3
3. Parse and explain check failures
Advanced: GitHub GraphQL API
For complex queries, use GitHub's GraphQL API via gh:
gh api graphql -f query='
query($owner: String!, $repo: String!, $number: Int!) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $number) {
title
state
commits(last: 1) {
nodes {
commit {
statusCheckRollup {
contexts(first: 100) {
nodes {
... on CheckRun {
name
conclusion
detailsUrl
}
}
}
}
}
}
}
}
}
}
' -f owner=OWNER -f repo=REPO -F number=PR_NUMBER
References