github-pr-workflow
**github-pr-workflow** automates the complete pull request lifecycle including branch creation, committing changes, opening PRs, checking CI status, applying auto-fixes to failures, and merging. Use this skill when you need to manage GitHub contributions end-to-end, whether your environment has the GitHub CLI (`gh`) installed or must fall back to git commands with REST API calls via curl.
git clone --depth 1 https://github.com/moltis-org/moltis /tmp/github-pr-workflow && cp -r /tmp/github-pr-workflow/crates/skills/src/assets/github/github-pr-workflow ~/.claude/skills/github-pr-workflowSKILL.md
# GitHub Pull Request Workflow
Complete guide for managing the PR lifecycle. Each section shows the `gh` way first, then the `git` + `curl` fallback for machines without `gh`.
## Prerequisites
- Authenticated with GitHub (see `github-auth` skill)
- Inside a git repository with a GitHub remote
### Quick Auth Detection
```bash
# Determine which method to use throughout this workflow
if command -v gh &>/dev/null && gh auth status &>/dev/null; then
AUTH="gh"
else
AUTH="git"
# Ensure we have a token for API calls
if [ -z "$GITHUB_TOKEN" ]; then
if [ -f your environment ] && grep -q "^GITHUB_TOKEN=" your environment; then
GITHUB_TOKEN=$(grep "^GITHUB_TOKEN=" your environment | head -1 | cut -d= -f2 | tr -d '\n\r')
elif grep -q "github.com" ~/.git-credentials 2>/dev/null; then
GITHUB_TOKEN=$(grep "github.com" ~/.git-credentials 2>/dev/null | head -1 | sed 's|https://[^:]*:\([^@]*\)@.*|\1|')
fi
fi
fi
echo "Using: $AUTH"
```
### Extracting Owner/Repo from the Git Remote
Many `curl` commands need `owner/repo`. Extract it from the git remote:
```bash
# Works for both HTTPS and SSH remote URLs
REMOTE_URL=$(git remote get-url origin)
OWNER_REPO=$(echo "$REMOTE_URL" | sed -E 's|.*github\.com[:/]||; s|\.git$||')
OWNER=$(echo "$OWNER_REPO" | cut -d/ -f1)
REPO=$(echo "$OWNER_REPO" | cut -d/ -f2)
echo "Owner: $OWNER, Repo: $REPO"
```
---
## 1. Branch Creation
This part is pure `git` — identical either way:
```bash
# Make sure you're up to date
git fetch origin
git checkout main && git pull origin main
# Create and switch to a new branch
git checkout -b feat/add-user-authentication
```
Branch naming conventions:
- `feat/description` — new features
- `fix/description` — bug fixes
- `refactor/description` — code restructuring
- `docs/description` — documentation
- `ci/description` — CI/CD changes
## 2. Making Commits
Use the agent's file tools (`write_file`, `patch`) to make changes, then commit:
```bash
# Stage specific files
git add src/auth.py src/models/user.py tests/test_auth.py
# Commit with a conventional commit message
git commit -m "feat: add JWT-based user authentication
- Add login/register endpoints
- Add User model with password hashing
- Add auth middleware for protected routes
- Add unit tests for auth flow"
```
Commit message format (Conventional Commits):
```
type(scope): short description
Longer explanation if needed. Wrap at 72 characters.
```
Types: `feat`, `fix`, `refactor`, `docs`, `test`, `ci`, `chore`, `perf`
## 3. Pushing and Creating a PR
### Push the Branch (same either way)
```bash
git push -u origin HEAD
```
### Create the PR
**With gh:**
```bash
gh pr create \
--title "feat: add JWT-based user authentication" \
--body "## Summary
- Adds login and register API endpoints
- JWT token generation and validation
## Test Plan
- [ ] Unit tests pass
Closes #42"
```
Options: `--draft`, `--reviewer user1,user2`, `--label "enhancement"`, `--base develop`
**With git + curl:**
```bash
BRANCH=$(git branch --show-current)
curl -s -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/$OWNER/$REPO/pulls \
-d "{
\"title\": \"feat: add JWT-based user authentication\",
\"body\": \"## Summary\nAdds login and register API endpoints.\n\nCloses #42\",
\"head\": \"$BRANCH\",
\"base\": \"main\"
}"
```
The response JSON includes the PR `number` — save it for later commands.
To create as a draft, add `"draft": true` to the JSON body.
## 4. Monitoring CI Status
### Check CI Status
**With gh:**
```bash
# One-shot check
gh pr checks
# Watch until all checks finish (polls every 10s)
gh pr checks --watch
```
**With git + curl:**
```bash
# Get the latest commit SHA on the current branch
SHA=$(git rev-parse HEAD)
# Query the combined status
curl -s \
-H "Authorization: token $GITHUB_TOKEN" \
https://api.github.com/repos/$OWNER/$REPO/commits/$SHA/status \
| python3 -c "
import sys, json
data = json.load(sys.stdin)
print(f\"Overall: {data['state']}\")
for s in data.get('statuses', []):
print(f\" {s['context']}: {s['state']} - {s.get('description', '')}\")"
# Also check GitHub Actions check runs (separate endpoint)
curl -s \
-H "Authorization: token $GITHUB_TOKEN" \
https://api.github.com/repos/$OWNER/$REPO/commits/$SHA/check-runs \
| python3 -c "
import sys, json
data = json.load(sys.stdin)
for cr in data.get('check_runs', []):
print(f\" {cr['name']}: {cr['status']} / {cr['conclusion'] or 'pending'}\")"
```
### Poll Until Complete (git + curl)
```bash
# Simple polling loop — check every 30 seconds, up to 10 minutes
SHA=$(git rev-parse HEAD)
for i in $(seq 1 20); do
STATUS=$(curl -s \
-H "Authorization: token $GITHUB_TOKEN" \
https://api.github.com/repos/$OWNER/$REPO/commits/$SHA/status \
| python3 -c "import sys,json; print(json.load(sys.stdin)['state'])")
echo "Check $i: $STATUS"
if [ "$STATUS" = "success" ] || [ "$STATUS" = "failure" ] || [ "$STATUS" = "error" ]; then
break
fi
sleep 30
done
```
## 5. Auto-Fixing CI Failures
When CI fails, diagnose and fix. This loop works with either auth method.
### Step 1: Get Failure Details
**With gh:**
```bash
# List recent workflow runs on this branch
gh run list --branch $(git branch --show-current) --limit 5
# View failed logs
gh run view <RUN_ID> --log-failed
```
**With git + curl:**
```bash
BRANCH=$(git branch --show-current)
# List workflow runs on this branch
curl -s \
-H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/repos/$OWNER/$REPO/actions/runs?branch=$BRANCH&per_page=5" \
| python3 -c "
import sys, json
runs = json.load(sys.stdin)['workflow_runs']
for r in runs:
print(f\"Run {r['id']}: {r['name']} - {r['conclusion'] or r['status']}\")"
# Get failed job logs (download as zip, extract, read)
RUN_ID=<run_id>
curl -s -L \
-H "Authorization: token $GITHUB_TOKEN" \
https://api.github.com/repos/$OWNER/Commit all changes, push branch, create/update PR, and run local validation
Manage Apple Notes via the memo CLI on macOS (create, view, search, edit).
Manage Apple Reminders via remindctl CLI (list, add, complete, delete).
Track Apple devices and AirTags via FindMy.app on macOS using AppleScript and screen capture.
Send and receive iMessages/SMS via the imsg CLI on macOS.
Transcribe audio via OpenAI Audio Transcriptions API (Whisper).
Local speech-to-text with the Whisper CLI (no API key).
ElevenLabs text-to-speech with mac-style say UX.