GitHub Operations Comprehensive GitHub CLI ( ) operations for project management, from basic issue creation to advanced Projects v2 integration and milestone tracking via REST API. Overview - Creating and managing GitHub issues and PRs - Working with GitHub Projects v2 custom fields - Managing milestones (sprints, releases) via REST API - Automating bulk operations with - Running GraphQL queries for complex operations --- CRITICAL: Task Management is MANDATORY (CC 2.1.16) BEFORE doing ANYTHING else, create tasks to track progress: Quick Reference Issue Operations PR Operations Tip (CC 2.1.27)…

)\necho \"Created issue #$ISSUE_NUM\"\n```\n\n### Find Untriaged Issues\n\n```bash\n# Issues with no labels\ngh issue list --json number,title,labels \\\n --jq '[.[] | select(.labels | length == 0)]'\n```\n\n### Issue Statistics\n\n```bash\n# Count by label\ngh issue list --state all --json labels \\\n --jq '[.[].labels[].name] | group_by(.) | map({label: .[0], count: length}) | sort_by(-.count)'\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5262,"content_sha256":"b1595f885bc5fc9035aedb10f6ebfb8b580a29ff922bae1a3901accf7d82b45b"},{"filename":"references/milestone-api.md","content":"# Milestone API Reference\n\nGitHub CLI has NO native milestone commands. Use `gh api` REST calls for all milestone operations.\n\n> **Critical footgun — NAME vs NUMBER:**\n> - `gh issue edit --milestone` / `gh issue list --milestone` → accepts **milestone NAME** (string, e.g. `\"Sprint 8\"`)\n> - `gh api repos/:owner/:repo/milestones/:number` → accepts **milestone NUMBER** (integer, e.g. `5`)\n>\n> These are **different identifiers**. Passing a number to `--milestone` silently fails. To get a number from a name: `gh api repos/:owner/:repo/milestones --jq '.[] | select(.title==\"Sprint 8\") | .number'`\n\n## API Endpoints\n\n| Operation | Method | Endpoint |\n|-----------|--------|----------|\n| List | GET | `/repos/:owner/:repo/milestones` |\n| Get | GET | `/repos/:owner/:repo/milestones/:number` |\n| Create | POST | `/repos/:owner/:repo/milestones` |\n| Update | PATCH | `/repos/:owner/:repo/milestones/:number` |\n| Delete | DELETE | `/repos/:owner/:repo/milestones/:number` |\n\n---\n\n## Create Milestone\n\n```bash\n# Minimal\ngh api -X POST repos/:owner/:repo/milestones \\\n -f title=\"Sprint 10\"\n\n# Full options\ngh api -X POST repos/:owner/:repo/milestones \\\n -f title=\"Sprint 10: Performance\" \\\n -f state=\"open\" \\\n -f description=\"Focus on frontend performance optimization\" \\\n -f due_on=\"2026-03-15T00:00:00Z\"\n\n# Create and capture number\nMILESTONE_NUM=$(gh api -X POST repos/:owner/:repo/milestones \\\n -f title=\"Sprint 8\" \\\n --jq '.number')\necho \"Created milestone #$MILESTONE_NUM\"\n```\n\n---\n\n## List Milestones\n\n```bash\n# All open (default)\ngh api repos/:owner/:repo/milestones\n\n# All milestones (including closed)\ngh api \"repos/:owner/:repo/milestones?state=all\"\n\n# Closed only\ngh api \"repos/:owner/:repo/milestones?state=closed\"\n\n# Sorted by due date\ngh api \"repos/:owner/:repo/milestones?sort=due_on&direction=asc\"\n\n# With jq formatting\ngh api repos/:owner/:repo/milestones --jq '\n .[] | {\n number,\n title,\n state,\n due: .due_on,\n progress: \"\\(.closed_issues)/\\(.open_issues + .closed_issues)\"\n }'\n\n# Progress summary\ngh api repos/:owner/:repo/milestones --jq '.[] | \"\\(.title): \\(.closed_issues)/\\(.open_issues + .closed_issues) done\"'\n```\n\n---\n\n## Get Single Milestone\n\n```bash\ngh api repos/:owner/:repo/milestones/1\n```\n\n---\n\n## Update Milestone\n\n```bash\n# Change title\ngh api -X PATCH repos/:owner/:repo/milestones/1 \\\n -f title=\"New Title\"\n\n# Update description\ngh api -X PATCH repos/:owner/:repo/milestones/1 \\\n -f description=\"Updated scope: includes auth improvements\"\n\n# Update due date\ngh api -X PATCH repos/:owner/:repo/milestones/1 \\\n -f due_on=\"2026-04-01T00:00:00Z\"\n```\n\n---\n\n## Close/Reopen Milestone\n\n```bash\n# Close milestone\ngh api -X PATCH repos/:owner/:repo/milestones/5 -f state=closed\n\n# Reopen milestone\ngh api -X PATCH repos/:owner/:repo/milestones/5 -f state=open\n```\n\n---\n\n## Delete Milestone\n\n```bash\n# Warning: removes milestone from all issues!\ngh api -X DELETE repos/:owner/:repo/milestones/1\n```\n\n---\n\n## Workflow Patterns\n\n### Sprint Workflow\n\n```bash\n# 1. Create sprint milestone\ngh api -X POST repos/:owner/:repo/milestones \\\n -f title=\"Sprint 8: Auth & Performance\" \\\n -f due_on=\"2026-02-14T00:00:00Z\"\n\n# 2. Assign issues to sprint\ngh issue edit 123 124 125 --milestone \"Sprint 8: Auth & Performance\"\n\n# 3. Check progress mid-sprint\ngh api repos/:owner/:repo/milestones --jq '\n .[] | select(.title | contains(\"Sprint 8\")) |\n \"Progress: \\(.closed_issues)/\\(.open_issues + .closed_issues) (\\((.closed_issues / (.open_issues + .closed_issues) * 100) | floor)%)\"'\n\n# 4. Close sprint when done\nMILESTONE_NUM=$(gh api repos/:owner/:repo/milestones --jq '.[] | select(.title | contains(\"Sprint 8\")) | .number')\ngh api -X PATCH repos/:owner/:repo/milestones/$MILESTONE_NUM -f state=closed\n```\n\n### Release Workflow\n\n```bash\n# 1. Create release milestone\ngh api -X POST repos/:owner/:repo/milestones \\\n -f title=\"v2.0.0\" \\\n -f description=\"Major release: New auth system, performance improvements\" \\\n -f due_on=\"2026-03-01T00:00:00Z\"\n\n# 2. Tag issues for release\ngh issue list --milestone \"v2.0.0\" --json number,title --jq '.[] | \"#\\(.number): \\(.title)\"'\n\n# 3. When ready, close and create release\ngh api -X PATCH repos/:owner/:repo/milestones/10 -f state=closed\ngh release create v2.0.0 --generate-notes\n```\n\n---\n\n## Useful Aliases\n\nAdd to `~/.config/gh/config.yml`:\n\n```yaml\naliases:\n ms: api repos/:owner/:repo/milestones --jq '.[] | \"#\\(.number) \\(.title) [\\(.state)] \\(.closed_issues)/\\(.open_issues+.closed_issues)\"'\n ms-create: '!f() { gh api -X POST repos/:owner/:repo/milestones -f title=\"$1\" ${2:+-f due_on=\"$2\"} ${3:+-f description=\"$3\"}; }; f'\n ms-close: '!f() { gh api -X PATCH repos/:owner/:repo/milestones/$1 -f state=closed; }; f'\n ms-open: '!f() { gh api -X PATCH repos/:owner/:repo/milestones/$1 -f state=open; }; f'\n ms-progress: '!f() { gh api repos/:owner/:repo/milestones/$1 --jq \"\\\"Progress: \\\\(.closed_issues)/\\\\(.open_issues + .closed_issues) (\\\\((.closed_issues * 100 / (.open_issues + .closed_issues)) | floor)%)\\\"\"; }; f'\n```\n\nUsage:\n\n```bash\ngh ms # List all\ngh ms-create \"Sprint 11\" # Create\ngh ms-create \"v2.0\" \"2026-04-01\" # With due date\ngh ms-close 5 # Close\ngh ms-progress 1 # Check progress\n```\n\n---\n\n## Best Practices\n\n1. **Use ISO 8601 dates** - `YYYY-MM-DDTHH:MM:SSZ` format for due_on\n2. **Meaningful titles** - Include sprint number and focus area\n3. **Close on time** - Even with open issues, close at deadline\n4. **Don't delete** - Close instead to preserve history\n5. **Link to Projects** - Use Projects v2 Iteration field for cross-repo tracking\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5637,"content_sha256":"100d371e89378d906fa3d213983f87431d69557874b3962064d4cedfc3654cc2"},{"filename":"references/pr-workflows.md","content":"# Pull Request Workflows\n\n## Creating PRs\n\n### Basic Creation\n\n```bash\n# Interactive (opens editor)\ngh pr create\n\n# Non-interactive with auto-fill from commits\ngh pr create --fill\n\n# Explicit title and body\ngh pr create \\\n --title \"feat(#123): Add hybrid search with PGVector\" \\\n --body \"Description...\" \\\n --base dev \\\n --head feature/pgvector-search\n```\n\n### Full PR Creation Pattern\n\n```bash\ngh pr create \\\n --title \"feat(#${ISSUE_NUM}): Implement Langfuse tracing\" \\\n --body \"$(cat \u003c\u003c'EOF'\n## Summary\n- Added @observe decorator to workflow functions\n- Implemented CallbackHandler for LangChain\n- Added session and user tracking\n\n## Changes\n- `backend/app/shared/services/langfuse/` - New Langfuse client\n- `backend/app/workflows/nodes/` - Added tracing decorators\n- `backend/tests/unit/services/` - Langfuse unit tests\n\n## Test Plan\n- [ ] Unit tests pass (`poetry run pytest tests/unit/`)\n- [ ] Integration test with real Langfuse instance\n- [ ] Verify traces appear in Langfuse UI\n\nCloses #372\n\nCo-Authored-By: Claude Opus 4.6 \[email protected]>\nEOF\n)\" \\\n --base dev \\\n --label \"enhancement,backend\" \\\n --assignee \"@me\" \\\n --reviewer \"teammate\"\n```\n\n### Using Body File\n\n```bash\ngh pr create --title \"...\" --body-file pr-description.md\n```\n\n---\n\n## PR Checks and Status\n\n### View Check Status\n\n```bash\n# List all checks\ngh pr checks 456\n\n# Watch checks in real-time\ngh pr checks 456 --watch\n\n# Wait for specific check\ngh pr checks 456 --watch --fail-fast\n```\n\n### JSON Output for Automation\n\n```bash\n# Get check status\ngh pr checks 456 --json name,state,conclusion\n\n# Check if all passed\ngh pr checks 456 --json conclusion \\\n --jq 'all(.[].conclusion == \"SUCCESS\")'\n```\n\n### Wait for Checks Pattern\n\n```bash\nPR_NUMBER=456\n\nwhile true; do\n STATUS=$(gh pr view $PR_NUMBER --json statusCheckRollupState --jq '.statusCheckRollupState')\n\n case \"$STATUS\" in\n \"SUCCESS\")\n echo \"All checks passed!\"\n break\n ;;\n \"FAILURE\")\n echo \"Checks failed!\"\n gh pr checks $PR_NUMBER\n exit 1\n ;;\n *)\n echo \"Waiting... (status: $STATUS)\"\n sleep 30\n ;;\n esac\ndone\n```\n\n---\n\n## PR Reviews\n\n### Requesting Reviews\n\n```bash\n# Request review\ngh pr edit 456 --add-reviewer \"username1,username2\"\n\n# Remove reviewer\ngh pr edit 456 --remove-reviewer \"username\"\n```\n\n### Submitting Reviews\n\n```bash\n# Approve\ngh pr review 456 --approve\n\n# Approve with comment\ngh pr review 456 --approve --body \"LGTM! Clean implementation.\"\n\n# Request changes\ngh pr review 456 --request-changes --body \"Need tests for edge cases\"\n\n# Comment without approval/rejection\ngh pr review 456 --comment --body \"Nice refactoring!\"\n```\n\n### View Review Status\n\n```bash\n# Get review decision\ngh pr view 456 --json reviewDecision\n\n# List reviews\ngh pr view 456 --json reviews \\\n --jq '.reviews[] | \"\\(.author.login): \\(.state)\"'\n```\n\n---\n\n## Merging PRs\n\n### Merge Strategies\n\n```bash\n# Merge commit (default)\ngh pr merge 456 --merge\n\n# Squash merge (recommended for clean history)\ngh pr merge 456 --squash\n\n# Rebase merge\ngh pr merge 456 --rebase\n\n# With branch deletion\ngh pr merge 456 --squash --delete-branch\n```\n\n### Auto-Merge\n\n```bash\n# Enable auto-merge (merges when checks pass + approved)\ngh pr merge 456 --auto --squash --delete-branch\n\n# Disable auto-merge\ngh pr merge 456 --disable-auto\n```\n\n### Admin Merge (Bypass Protections)\n\n```bash\n# Bypass branch protection rules (requires admin)\ngh pr merge 456 --admin --squash\n```\n\n---\n\n## Safe Merge Pattern\n\n```bash\n#!/bin/bash\nPR_NUMBER=$1\n\n# 1. Verify checks passed\nif ! gh pr view $PR_NUMBER --json statusCheckRollupState \\\n --jq '.statusCheckRollupState == \"SUCCESS\"' | grep -q true; then\n echo \"ERROR: Checks not passed\"\n gh pr checks $PR_NUMBER\n exit 1\nfi\n\n# 2. Verify approved\nAPPROVED=$(gh pr view $PR_NUMBER --json reviewDecision --jq '.reviewDecision')\nif [[ \"$APPROVED\" != \"APPROVED\" ]]; then\n echo \"ERROR: PR not approved (status: $APPROVED)\"\n exit 1\nfi\n\n# 3. Verify mergeable\nMERGEABLE=$(gh pr view $PR_NUMBER --json mergeable --jq '.mergeable')\nif [[ \"$MERGEABLE\" != \"MERGEABLE\" ]]; then\n echo \"ERROR: PR has conflicts\"\n exit 1\nfi\n\n# 4. Merge\ngh pr merge $PR_NUMBER --squash --delete-branch\necho \"Successfully merged PR #$PR_NUMBER\"\n```\n\n---\n\n## PR Comments\n\n```bash\n# Add comment\ngh pr comment 456 --body \"Addressed review feedback in latest commit\"\n\n# View comments\ngh pr view 456 --comments\n```\n\n---\n\n## Checkout and Edit\n\n```bash\n# Checkout PR locally\ngh pr checkout 456\n\n# Edit PR metadata\ngh pr edit 456 --title \"New title\" --add-label \"urgent\"\n\n# Close without merging\ngh pr close 456 --comment \"Superseded by #789\"\n\n# Reopen\ngh pr reopen 456\n```\n\n---\n\n## PR Listing and Search\n\n```bash\n# My open PRs\ngh pr list --author @me --state open\n\n# PRs needing my review\ngh pr list --search \"review-requested:@me\"\n\n# Ready to merge\ngh pr list --json number,title,reviewDecision,statusCheckRollupState \\\n --jq '[.[] | select(.reviewDecision == \"APPROVED\" and .statusCheckRollupState == \"SUCCESS\")]'\n\n# Draft PRs\ngh pr list --draft\n```\n\n---\n\n## Convert Draft to Ready\n\n```bash\n# Mark ready for review\ngh pr ready 456\n\n# Convert to draft\ngh pr ready 456 --undo\n```\n\n---\n\n## PR Diff and Files\n\n```bash\n# View diff\ngh pr diff 456\n\n# List changed files\ngh pr view 456 --json files --jq '.files[].path'\n\n# View specific file\ngh pr diff 456 -- path/to/file.py\n```\n\n---\n\n## Common Patterns\n\n### Create PR from Current Branch\n\n```bash\n# Push and create PR in one flow\ngit push -u origin $(git branch --show-current) && \\\ngh pr create --fill --base dev\n```\n\n### Find Stale PRs\n\n```bash\n# PRs not updated in 7 days\ngh pr list --json number,title,updatedAt \\\n --jq '[.[] | select(.updatedAt \u003c (now - 604800 | todate))]'\n```\n\n### PR Statistics\n\n```bash\n# Average time to merge\ngh pr list --state merged --limit 20 --json createdAt,mergedAt \\\n --jq '[.[] | (.mergedAt | fromdateiso8601) - (.createdAt | fromdateiso8601)] | add / length / 3600 | \"Average: \\(.) hours\"'\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5962,"content_sha256":"e581768277960882d6621c9d92ec0c2b201c0ee01d9b25f49a00a1bb1c643322"},{"filename":"references/projects-v2.md","content":"# GitHub Projects v2\n\n## Overview\n\nGitHub Projects v2 uses custom fields for advanced project management. The `gh project` commands provide basic operations, but setting custom fields requires GraphQL.\n\n---\n\n## Basic Project Commands\n\n```bash\n# List projects\ngh project list --owner @me\n\n# View project\ngh project view 1 --owner @me\n\n# List fields\ngh project field-list 1 --owner @me --format json\n\n# Add item to project\ngh project item-add 1 --owner @me \\\n --url \"https://github.com/org/repo/issues/123\"\n\n# Remove item from project\ngh project item-delete 1 --owner @me --id \"PVTI_abc123\"\n```\n\n---\n\n## Setting Custom Fields (GraphQL)\n\n### Set Single Select Field (Status, Priority, etc.)\n\n```bash\nPROJECT_ID=\"PVT_kwHOAS8tks4BIL_t\"\nITEM_ID=\"PVTI_...\" # From item-add result\nFIELD_ID=\"PVTSSF_lAHOAS8tks4BIL_tzg4uOTk\"\nOPTION_ID=\"92ee1ecd\" # Option value ID\n\ngh api graphql -f query='\n mutation($projectId: ID!, $itemId: ID!, $fieldId: ID!, $optionId: String!) {\n updateProjectV2ItemFieldValue(input: {\n projectId: $projectId\n itemId: $itemId\n fieldId: $fieldId\n value: { singleSelectOptionId: $optionId }\n }) {\n projectV2Item {\n id\n }\n }\n }\n' \\\n -f projectId=\"$PROJECT_ID\" \\\n -f itemId=\"$ITEM_ID\" \\\n -f fieldId=\"$FIELD_ID\" \\\n -f optionId=\"$OPTION_ID\"\n```\n\n### Set Text Field\n\n```bash\ngh api graphql -f query='\n mutation($projectId: ID!, $itemId: ID!, $fieldId: ID!, $text: String!) {\n updateProjectV2ItemFieldValue(input: {\n projectId: $projectId\n itemId: $itemId\n fieldId: $fieldId\n value: { text: $text }\n }) {\n projectV2Item { id }\n }\n }\n' \\\n -f projectId=\"$PROJECT_ID\" \\\n -f itemId=\"$ITEM_ID\" \\\n -f fieldId=\"$TEXT_FIELD_ID\" \\\n -f text=\"Custom value\"\n```\n\n### Set Number Field\n\n```bash\ngh api graphql -f query='\n mutation($projectId: ID!, $itemId: ID!, $fieldId: ID!, $number: Float!) {\n updateProjectV2ItemFieldValue(input: {\n projectId: $projectId\n itemId: $itemId\n fieldId: $fieldId\n value: { number: $number }\n }) {\n projectV2Item { id }\n }\n }\n' \\\n -f projectId=\"$PROJECT_ID\" \\\n -f itemId=\"$ITEM_ID\" \\\n -f fieldId=\"$NUMBER_FIELD_ID\" \\\n -F number=5\n```\n\n---\n\n## Complete Workflow: Create Issue + Add to Project\n\n```bash\n#!/bin/bash\n# create-and-track.sh\n\nTITLE=\"$1\"\nBODY=\"$2\"\nLABELS=\"${3:-enhancement}\"\nSTATUS_OPTION=\"${4:-19303ae5}\" # Default: ready\n\n# Configuration\nPROJECT_NUMBER=1\nPROJECT_OWNER=\"username\"\nPROJECT_ID=\"PVT_...\"\nSTATUS_FIELD_ID=\"PVTSSF_...\"\nREPO=\"org/repo\"\n\n# 1. Create issue\nISSUE_URL=$(gh issue create \\\n --repo \"$REPO\" \\\n --title \"$TITLE\" \\\n --body \"$BODY\" \\\n --label \"$LABELS\" \\\n --json url --jq '.url')\n\necho \"Created: $ISSUE_URL\"\n\n# 2. Add to project\nITEM_ID=$(gh project item-add $PROJECT_NUMBER \\\n --owner $PROJECT_OWNER \\\n --url \"$ISSUE_URL\" \\\n --format json | jq -r '.id')\n\necho \"Added to project: $ITEM_ID\"\n\n# 3. Set status\ngh api graphql -f query='\n mutation($projectId: ID!, $itemId: ID!, $fieldId: ID!, $optionId: String!) {\n updateProjectV2ItemFieldValue(input: {\n projectId: $projectId\n itemId: $itemId\n fieldId: $fieldId\n value: { singleSelectOptionId: $optionId }\n }) {\n projectV2Item { id }\n }\n }\n' \\\n -f projectId=\"$PROJECT_ID\" \\\n -f itemId=\"$ITEM_ID\" \\\n -f fieldId=\"$STATUS_FIELD_ID\" \\\n -f optionId=\"$STATUS_OPTION\"\n\necho \"Set status\"\n```\n\n---\n\n## Query Project Items\n\n### Get All Items with Status\n\n```bash\ngh api graphql -f query='\n query($owner: String!, $number: Int!) {\n user(login: $owner) {\n projectV2(number: $number) {\n items(first: 50) {\n nodes {\n id\n content {\n ... on Issue {\n number\n title\n }\n ... on PullRequest {\n number\n title\n }\n }\n fieldValues(first: 10) {\n nodes {\n ... on ProjectV2ItemFieldSingleSelectValue {\n name\n field { ... on ProjectV2SingleSelectField { name } }\n }\n }\n }\n }\n }\n }\n }\n }\n' -f owner=\"username\" -F number=1\n```\n\n### Get Items by Status\n\n```bash\n# Get all \"In Development\" items\ngh api graphql -f query='\n query($owner: String!, $number: Int!) {\n user(login: $owner) {\n projectV2(number: $number) {\n items(first: 100) {\n nodes {\n content {\n ... on Issue { number title }\n }\n fieldValues(first: 5) {\n nodes {\n ... on ProjectV2ItemFieldSingleSelectValue {\n name\n }\n }\n }\n }\n }\n }\n }\n }\n' -f owner=\"username\" -F number=1 \\\n --jq '.data.user.projectV2.items.nodes[] | select(.fieldValues.nodes[].name == \"In Development\") | .content'\n```\n\n---\n\n## Discovering Field IDs\n\nIf you need to find field/option IDs for a project:\n\n```bash\n# Get all fields with options\ngh api graphql -f query='\n query($owner: String!, $number: Int!) {\n user(login: $owner) {\n projectV2(number: $number) {\n id\n fields(first: 20) {\n nodes {\n ... on ProjectV2Field {\n id\n name\n }\n ... on ProjectV2SingleSelectField {\n id\n name\n options {\n id\n name\n }\n }\n ... on ProjectV2IterationField {\n id\n name\n }\n }\n }\n }\n }\n }\n' -f owner=\"username\" -F number=1 | jq '.data.user.projectV2'\n```\n\n---\n\n## Move Item Between Statuses\n\n```bash\n# Helper function\nmove_to_status() {\n local ITEM_ID=\"$1\"\n local STATUS_OPTION_ID=\"$2\"\n\n gh api graphql -f query='\n mutation($projectId: ID!, $itemId: ID!, $fieldId: ID!, $optionId: String!) {\n updateProjectV2ItemFieldValue(input: {\n projectId: $projectId\n itemId: $itemId\n fieldId: $fieldId\n value: { singleSelectOptionId: $optionId }\n }) {\n projectV2Item { id }\n }\n }\n ' \\\n -f projectId=\"$PROJECT_ID\" \\\n -f itemId=\"$ITEM_ID\" \\\n -f fieldId=\"$STATUS_FIELD_ID\" \\\n -f optionId=\"$STATUS_OPTION_ID\"\n}\n\n# Usage\nmove_to_status \"PVTI_abc123\" \"92ee1ecd\" # Move to In Development\n```\n\n---\n\n## Organization Projects\n\nFor organization-owned projects, use `organization` instead of `user`:\n\n```bash\ngh api graphql -f query='\n query($org: String!, $number: Int!) {\n organization(login: $org) {\n projectV2(number: $number) {\n id\n title\n }\n }\n }\n' -f org=\"my-org\" -F number=1\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":6677,"content_sha256":"e944e9791228c7b2e63287391ba7964810d523af3ebc5deac3fad6ffddf2c908"},{"filename":"rules/_sections.md","content":"---\ntitle: GitHub Operations Rule Categories\nversion: 1.0.0\n---\n\n# Rule Categories\n\n## 1. Issue Tracking Automation (tracking) — HIGH — 1 rule\n\nAutomated progress updates from commits, branch detection, and session summaries. Eliminates manual status updates.\n\n- `issue-tracking-automation.md` — Auto-progress from commits, sub-task completion, session summaries\n\n## 2. Issue-Branch Linking (linking) — MEDIUM — 1 rule\n\nConnecting issues to branches, PRs, and commits for traceability. Enables automatic issue closure and progress visibility.\n\n- `issue-branch-linking.md` — Branch naming conventions, commit references, PR linking patterns\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":652,"content_sha256":"3fb48eb093599cbfd9b43f5e3df1d40868ad905c37b90071469fce1e5e4816c0"},{"filename":"rules/_template.md","content":"---\ntitle: \"[Rule Name]\"\nimpact: \"[CRITICAL | HIGH | MEDIUM | LOW]\"\nimpactDescription: \"[What goes wrong without this rule]\"\ntags: []\n---\n\n## [Rule Name]\n\n[Brief description — 1-2 sentences.]\n\n**Incorrect:**\n```\n// Bad pattern\n```\n\n**Correct:**\n```\n// Good pattern\n```\n\n**Key rules:**\n- [Rule 1]\n- [Rule 2]\n- [Rule 3]\n\nReference: [link]\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":339,"content_sha256":"1f6b17cb8c02a543b46a648f062ff0a0c93635b93d51663bc299033be4dc3f83"},{"filename":"rules/issue-branch-linking.md","content":"---\ntitle: Linking Issues to Branches and PRs\nimpact: MEDIUM\nimpactDescription: \"Unlinked issues and PRs break traceability — reviewers lack context and issues stay open after merging fixes\"\ntags: github, issues, branches, pr, linking, traceability\n---\n\n## Linking Issues to Branches and PRs\n\nEstablish bidirectional links between issues, branches, commits, and PRs for full traceability and automatic issue closure.\n\n### Branch Naming Convention\n\n```bash\n# Pattern: {type}/{issue-number}-{description}\nissue/123-implement-feature\nfix/456-resolve-timeout-bug\nfeature/789-add-search-api\n\n# Creates automatic link: branch -> issue\n```\n\n### Commit Linking\n\n```bash\n# Reference in commit message\ngit commit -m \"feat(#123): Add user validation\"\n\n# Auto-close keywords (in commit or PR body)\ngit commit -m \"fix: Resolve timeout (closes #456)\"\ngit commit -m \"feat: Add search (fixes #789)\"\n```\n\n### PR Linking\n\n```bash\n# Create PR that auto-closes issue on merge\ngh pr create --title \"feat(#123): Add search\" \\\n --body \"Closes #123\n\n## Changes\n- Added search API endpoint\n- Added search UI component\"\n\n# Link existing PR to issue\ngh issue edit 123 --add-label \"has-pr\"\n```\n\n### PR-Aware Session Resumption\n\n```bash\n# Resume with full PR context (CC 2.1.27+)\nclaude --from-pr 42 # Loads PR diff, comments, review status\n```\n\n### Linking Checklist\n\n| Link | How | Automatic? |\n|------|-----|------------|\n| Branch to issue | Branch name `issue/N-*` | Yes (hooks) |\n| Commit to issue | `#N` in commit message | Yes (GitHub) |\n| PR to issue | `Closes #N` in PR body | Yes (GitHub) |\n| Issue to PR | `has-pr` label | Manual or hook |\n\n**Incorrect — Branch without issue number prefix:**\n```bash\ngit checkout -b implement-feature\ngit commit -m \"Add user validation\"\n# No automatic linking - reviewer lacks context\n```\n\n**Correct — Issue-prefixed branch with linked commit:**\n```bash\ngit checkout -b issue/123-implement-feature\ngit commit -m \"feat(#123): Add user validation\"\n# Auto-links: branch → issue, commit → issue\n```\n\n### Key Rules\n\n- Always start branches with **issue number prefix** for automatic detection\n- Use **`Closes #N`** in PR body for automatic issue closure on merge\n- Include **`#N`** in every commit that relates to an issue\n- Use **conventional commit format** for consistent linking\n- Add **`has-pr` label** to issues when a PR is created\n- Use **`--from-pr`** to resume sessions with full PR context\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2426,"content_sha256":"1a921b9ca6e93b5a6a03c9599933966f9e092ee984bb608c8619c69a7977409d"},{"filename":"rules/issue-tracking-automation.md","content":"---\ntitle: Automate issue progress updates so stakeholders always see current status\nimpact: HIGH\nimpactDescription: \"Without automation, issue status drifts from reality — stakeholders see stale progress and make wrong decisions\"\ntags: github, issues, progress, tracking, automation, commits, hooks\n---\n\n## Automated Issue Progress Updates\n\nTrack issue progress automatically through commit detection, sub-task matching, and session summaries. Eliminates manual status updates.\n\n### Three-Hook Pipeline\n\n| Hook | Trigger | Action |\n|------|---------|--------|\n| Commit Detection | Each commit | Extracts issue number, queues for batch comment |\n| Sub-task Updater | Commit message match | Checks off matching `- [ ]` items in issue body |\n| Session Summary | Session end | Posts consolidated progress comment |\n\n### Issue Number Extraction\n\n```bash\n# From branch name (priority)\nissue/123-implement-feature # Extracts: 123\nfix/456-resolve-bug # Extracts: 456\nfeature/789-add-tests # Extracts: 789\n\n# From commit message (fallback)\n\"feat(#123): Add user validation\" # Extracts: 123\n\"fix: Resolve bug (closes #456)\" # Extracts: 456\n```\n\n### Sub-task Auto-Completion\n\nCommit messages are matched against issue checkboxes using normalized text comparison:\n\n```markdown\n# Issue body (before)\n- [ ] Add input validation\n- [ ] Write unit tests\n\n# Commit: \"feat(#123): Add input validation\"\n\n# Issue body (after)\n- [x] Add input validation\n- [ ] Write unit tests\n```\n\n### Session Summary Format\n\n```markdown\n## Claude Code Progress Update\n\n**Session**: `abc12345...`\n**Branch**: `issue/123-implement-feature`\n\n### Commits (3)\n- `abc1234`: feat(#123): Add input validation\n- `def5678`: test(#123): Add unit tests\n\n### Files Changed\n- `src/validation.ts` (+45, -12)\n- `tests/validation.test.ts` (+89, -0)\n\n### Sub-tasks Completed\n- [x] Add input validation\n- [x] Write unit tests\n```\n\n**Incorrect — Manual issue updates without automation:**\n```bash\n# Commit without issue reference\ngit commit -m \"Add validation\"\n\n# Manually comment on issue #123:\n\"Added validation - see commit abc1234\"\n[Time-consuming, error-prone]\n```\n\n**Correct — Automated progress tracking:**\n```bash\n# Issue-prefixed branch\ngit checkout -b issue/123-validation\n\n# Conventional commit\ngit commit -m \"feat(#123): Add input validation\"\n\n# Hook auto-posts to issue:\n\"[Session abc123] feat(#123): Add input validation\nFiles: src/validation.ts (+45)\"\n```\n\n### Key Rules\n\n- Use **issue-prefixed branches** (`issue/N-`, `fix/N-`, `feature/N-`) for automatic detection\n- Include **`#N`** in commit messages as fallback for issue linking\n- Use **conventional commits** (`feat(#123):`, `fix(#123):`) for reliable matching\n- Match commit message text to **checkbox descriptions** for auto-completion\n- Post **consolidated summaries** at session end, not per-commit\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2851,"content_sha256":"fe9bbbc72fd58e2506bbd053f83664bd41d3501c9b5089698f7d75ead62e2700"},{"filename":"test-cases.json","content":"{\n \"skill\": \"github-operations\",\n \"version\": \"1.0.0\",\n \"testCases\": [\n {\n \"id\": \"basic-create-5-issues-for\",\n \"rule\": \"\",\n \"query\": \"Create 5 issues for Sprint 9 with labels, assign them to the milestone, and then list all open issues in that milestone with their progress.\",\n \"expectedBehavior\": [\n \"Claude uses gh issue create with --title, --label, and --milestone flags\",\n \"Claude passes milestone by NAME (not number) to --milestone flag\",\n \"Claude captures created issue numbers with --json number --jq '.number'\",\n \"Claude uses gh api repos/:owner/:repo/milestones --jq for progress display\",\n \"Claude uses non-interactive mode with explicit flags for all operations\"\n ]\n },\n {\n \"id\": \"negative-close-milestone-sprint-7\",\n \"rule\": \"\",\n \"query\": \"Close milestone 'Sprint 7' using the REST API and find all approved PRs with passing CI that are ready to merge.\",\n \"expectedBehavior\": [\n \"Claude looks up milestone NUMBER via gh api (not using name directly in API)\",\n \"Claude uses gh api -X PATCH with the milestone number to close it\",\n \"Claude queries PRs with --json reviewDecision,statusCheckRollupState\",\n \"Claude filters for APPROVED reviewDecision and SUCCESS statusCheckRollupState\",\n \"Claude does NOT use gh issue close on any issues (issues close only via PR merge)\"\n ]\n },\n {\n \"id\": \"negative-write-unit-tests-for\",\n \"rule\": \"\",\n \"query\": \"Write unit tests for the UserService class that cover the login, logout, and password reset methods.\",\n \"expectedBehavior\": [\n \"Claude does NOT invoke the github-operations skill\",\n \"Claude writes test files using standard tools (Read, Write, Bash)\",\n \"Claude does not run any gh CLI commands for a testing task\"\n ]\n },\n {\n \"id\": \"issue-branch-linking\",\n \"rule\": \"issue-branch-linking\",\n \"query\": \"How do I link my branch and PR to the GitHub issue so it auto-closes on merge?\",\n \"expectedBehavior\": [\n \"Uses branch naming convention: type/issue-number-description for automatic issue linking\",\n \"Includes Closes #N or Fixes #N in the PR body to auto-close the issue on merge\",\n \"References issue number in commit messages using the type(#N): description format\",\n \"Establishes bidirectional traceability between issues, branches, commits, and pull requests\"\n ]\n },\n {\n \"id\": \"issue-tracking-automation\",\n \"rule\": \"issue-tracking-automation\",\n \"query\": \"How can I automate issue progress updates so stakeholders always see current status?\",\n \"expectedBehavior\": [\n \"Uses commit detection hook to extract issue numbers and queue batch progress comments\",\n \"Implements sub-task updater that checks off matching checklist items in the issue body\",\n \"Posts consolidated session summary comments at session end with completed work details\",\n \"Eliminates manual status updates by automating the commit to issue linking pipeline\"\n ]\n }\n ]\n}\n","content_type":"application/json; charset=utf-8","language":"json","size":3096,"content_sha256":"e55f8a6202862b164cdffc561ae1c4363b1d5b66136a1165be6d65d9f74ce7a6"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"GitHub Operations","type":"text"}]},{"type":"paragraph","content":[{"text":"Comprehensive GitHub CLI (","type":"text"},{"text":"gh","type":"text","marks":[{"type":"code_inline"}]},{"text":") operations for project management, from basic issue creation to advanced Projects v2 integration and milestone tracking via REST API.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Overview","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Creating and managing GitHub issues and PRs","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Working with GitHub Projects v2 custom fields","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Managing milestones (sprints, releases) via REST API","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Automating bulk operations with ","type":"text"},{"text":"gh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Running GraphQL queries for complex operations","type":"text"}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"CRITICAL: Task Management is MANDATORY (CC 2.1.16)","type":"text"}]},{"type":"paragraph","content":[{"text":"BEFORE doing ANYTHING else, create tasks to track progress:","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"# 1. Create main task IMMEDIATELY\nTaskCreate(\n subject=\"GitHub Operations: {target}\",\n description=\"Managing GitHub issues, PRs, milestones, or Projects\",\n activeForm=\"Managing GitHub resources\"\n)\n\n# 2. Create subtasks matching the operation scope\nTaskCreate(subject=\"Issue management\", activeForm=\"Creating/updating issues\")\nTaskCreate(subject=\"PR management\", activeForm=\"Managing pull requests\")\nTaskCreate(subject=\"Milestone tracking\", activeForm=\"Updating milestones\")\n\n# 3. Set dependencies if operations are sequential\nTaskUpdate(taskId=\"3\", addBlockedBy=[\"2\"])\nTaskUpdate(taskId=\"4\", addBlockedBy=[\"3\"])\n\n# 4. Before starting each task, verify it's unblocked\ntask = TaskGet(taskId=\"2\") # Verify blockedBy is empty\n\n# 5. Update status as you progress\nTaskUpdate(taskId=\"2\", status=\"in_progress\") # When starting\nTaskUpdate(taskId=\"2\", status=\"completed\") # When done","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Quick Reference","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Issue Operations","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Create issue with labels and milestone\ngh issue create --title \"Bug: API returns 500\" --body \"...\" --label \"bug\" --milestone \"Sprint 5\"\n\n# List and filter issues\ngh issue list --state open --label \"backend\" --assignee @me\n\n# Edit issue metadata\ngh issue edit 123 --add-label \"high\" --milestone \"v2.0\"","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"PR Operations","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Create PR with reviewers\ngh pr create --title \"feat: Add search\" --body \"...\" --base dev --reviewer @teammate\n\n# Watch CI status and auto-merge\ngh pr checks 456 --watch\ngh pr merge 456 --auto --squash --delete-branch\n\n# Resume a session linked to a PR (CC 2.1.27)\nclaude --from-pr 456 # Resume session with PR context (diff, comments, review status)\nclaude --from-pr https://github.com/org/repo/pull/456","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Tip (CC 2.1.27):","type":"text","marks":[{"type":"strong"}]},{"text":" Sessions created via ","type":"text"},{"text":"gh pr create","type":"text","marks":[{"type":"code_inline"}]},{"text":" are automatically linked to the PR. Use ","type":"text"},{"text":"--from-pr","type":"text","marks":[{"type":"code_inline"}]},{"text":" to resume with full PR context.","type":"text"}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Milestone Operations (REST API)","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Footgun:","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"gh issue edit --milestone","type":"text","marks":[{"type":"code_inline"}]},{"text":" takes a ","type":"text"},{"text":"NAME","type":"text","marks":[{"type":"strong"}]},{"text":" (string), not a number. The REST API uses a ","type":"text"},{"text":"NUMBER","type":"text","marks":[{"type":"strong"}]},{"text":" (integer). Never pass a number to ","type":"text"},{"text":"--milestone","type":"text","marks":[{"type":"code_inline"}]},{"text":". Load ","type":"text"},{"text":"Read(\"${CLAUDE_SKILL_DIR}/references/cli-vs-api-identifiers.md\")","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# List milestones with progress\ngh api repos/:owner/:repo/milestones --jq '.[] | \"\\(.title): \\(.closed_issues)/\\(.open_issues + .closed_issues)\"'\n\n# Create milestone with due date\ngh api -X POST repos/:owner/:repo/milestones \\\n -f title=\"Sprint 8\" -f due_on=\"2026-02-15T00:00:00Z\"\n\n# Close milestone (API uses number, not name)\nMILESTONE_NUM=$(gh api repos/:owner/:repo/milestones --jq '.[] | select(.title==\"Sprint 8\") | .number')\ngh api -X PATCH repos/:owner/:repo/milestones/$MILESTONE_NUM -f state=closed\n\n# Assign issues to milestone (CLI uses name, not number)\ngh issue edit 123 124 125 --milestone \"Sprint 8\"","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Projects v2 Operations","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Add issue to project\ngh project item-add 1 --owner @me --url https://github.com/org/repo/issues/123\n\n# Set custom field (requires GraphQL)\ngh api graphql -f query='mutation {...}' -f projectId=\"...\" -f itemId=\"...\"","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"JSON Output Patterns","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Get issue numbers matching criteria\ngh issue list --json number,labels --jq '[.[] | select(.labels[].name == \"bug\")] | .[].number'\n\n# PR summary with author\ngh pr list --json number,title,author --jq '.[] | \"\\(.number): \\(.title) by \\(.author.login)\"'\n\n# Find ready-to-merge PRs\ngh pr list --json number,reviewDecision,statusCheckRollupState \\\n --jq '[.[] | select(.reviewDecision == \"APPROVED\" and .statusCheckRollupState == \"SUCCESS\")]'","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Key Concepts","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Milestone vs Epic","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Milestones","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Epics","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Time-based (sprints, releases)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Topic-based (features)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Has due date","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"No due date","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Progress bar","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Task list checkbox","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Native REST API","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Needs workarounds","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"Rule","type":"text","marks":[{"type":"strong"}]},{"text":": Use milestones for \"when\", use parent issues for \"what\".","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Projects v2 Custom Fields","type":"text"}]},{"type":"paragraph","content":[{"text":"Projects v2 uses GraphQL for setting custom fields (Status, Priority, Domain). Basic ","type":"text"},{"text":"gh project","type":"text","marks":[{"type":"code_inline"}]},{"text":" commands work for listing and adding items, but field updates require GraphQL mutations.","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Rules Quick Reference","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Rule","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Impact","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"What It Covers","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"issue-tracking-automation (load ","type":"text"},{"text":"${CLAUDE_SKILL_DIR}/rules/issue-tracking-automation.md","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"HIGH","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Auto-progress from commits, sub-task completion, session summaries","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"issue-branch-linking (load ","type":"text"},{"text":"${CLAUDE_SKILL_DIR}/rules/issue-branch-linking.md","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"MEDIUM","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Branch naming, commit references, PR linking patterns","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Batch Issue Creation","type":"text"}]},{"type":"paragraph","content":[{"text":"When creating multiple issues at once (e.g., seeding a sprint), use an array-driven loop:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Define issues as an array of \"title|labels|milestone\" entries\nSPRINT=\"Sprint 9\"\nISSUES=(\n \"feat: Add user auth|enhancement,backend|$SPRINT\"\n \"fix: Login redirect loop|bug,high|$SPRINT\"\n \"chore: Update dependencies|maintenance|$SPRINT\"\n)\n\nfor entry in \"${ISSUES[@]}\"; do\n IFS='|' read -r title labels milestone \u003c\u003c\u003c \"$entry\"\n NUM=$(gh issue create \\\n --title \"$title\" \\\n --label \"$labels\" \\\n --milestone \"$milestone\" \\\n --body \"\" \\\n --json number --jq '.number')\n echo \"Created #$NUM: $title\"\ndone","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Tip:","type":"text","marks":[{"type":"strong"}]},{"text":" Capture the created issue number with ","type":"text"},{"text":"--json number --jq '.number'","type":"text","marks":[{"type":"code_inline"}]},{"text":" so you can reference it immediately (e.g., add to Projects v2, link in PRs).","type":"text"}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Best Practices","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Always use ","type":"text","marks":[{"type":"strong"}]},{"text":"--json","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" for scripting","type":"text","marks":[{"type":"strong"}]},{"text":" - Parse with ","type":"text"},{"text":"--jq","type":"text","marks":[{"type":"code_inline"}]},{"text":" for reliability","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Non-interactive mode for automation","type":"text","marks":[{"type":"strong"}]},{"text":" - Use ","type":"text"},{"text":"--title","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"--body","type":"text","marks":[{"type":"code_inline"}]},{"text":" flags","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Check rate limits before bulk operations","type":"text","marks":[{"type":"strong"}]},{"text":" - ","type":"text"},{"text":"gh api rate_limit","type":"text","marks":[{"type":"code_inline"}]},{"text":". On CC ≥ 2.1.116, the Bash tool surfaces a rate-limit hint in the transcript when ","type":"text"},{"text":"gh","type":"text","marks":[{"type":"code_inline"}]},{"text":" hits 403 — ","type":"text"},{"text":"treat that hint as authoritative and back off","type":"text","marks":[{"type":"strong"}]},{"text":", don't blind-retry. Before 2.1.116, agents had no signal and would burn all retry attempts in ~13 s.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use heredocs for multi-line content","type":"text","marks":[{"type":"strong"}]},{"text":" - ","type":"text"},{"text":"--body \"$(cat \u003c\u003c'EOF'...EOF)\"","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Link issues in PRs","type":"text","marks":[{"type":"strong"}]},{"text":" - ","type":"text"},{"text":"Closes #123","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"Fixes #456","type":"text","marks":[{"type":"code_inline"}]},{"text":" — GitHub auto-closes on merge","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use ISO 8601 dates","type":"text","marks":[{"type":"strong"}]},{"text":" - ","type":"text"},{"text":"YYYY-MM-DDTHH:MM:SSZ","type":"text","marks":[{"type":"code_inline"}]},{"text":" for milestone due_on","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Close milestones, don't delete","type":"text","marks":[{"type":"strong"}]},{"text":" - Preserve history","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"--milestone","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" takes NAME, not number","type":"text","marks":[{"type":"strong"}]},{"text":" - Load ","type":"text"},{"text":"Read(\"${CLAUDE_SKILL_DIR}/references/cli-vs-api-identifiers.md\")","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Never ","type":"text","marks":[{"type":"strong"}]},{"text":"gh issue close","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" directly","type":"text","marks":[{"type":"strong"}]},{"text":" - Comment progress with ","type":"text"},{"text":"gh issue comment","type":"text","marks":[{"type":"code_inline"}]},{"text":"; issues close only when their linked PR merges to the default branch","type":"text"}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"2026 CLI changes — what to know","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"gh-copilot","type":"text","marks":[{"type":"code_inline"}]},{"text":" extension is retired","type":"text"}]},{"type":"paragraph","content":[{"text":"GitHub retired the ","type":"text"},{"text":"gh-copilot","type":"text","marks":[{"type":"code_inline"}]},{"text":" extension in ","type":"text"},{"text":"October 2025","type":"text","marks":[{"type":"strong"}]},{"text":". Copilot is now a standalone binary:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# OLD — no longer supported\ngh extension install github/gh-copilot # fails\ngh copilot suggest \"revert last commit\" # fails\n\n# NEW — standalone `copilot` binary\ncopilot suggest \"revert last commit\"\ncopilot explain \"git rebase -i HEAD~5\"","type":"text"}]},{"type":"paragraph","content":[{"text":"Install from ","type":"text"},{"text":"cli.github.com/copilot","type":"text","marks":[{"type":"code_inline"}]},{"text":" or via Homebrew (","type":"text"},{"text":"brew install github/gh/copilot","type":"text","marks":[{"type":"code_inline"}]},{"text":"). Authentication is shared with ","type":"text"},{"text":"gh auth","type":"text","marks":[{"type":"code_inline"}]},{"text":" when both are installed.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"gh agent-task","type":"text","marks":[{"type":"code_inline"}]},{"text":" (2026)","type":"text"}]},{"type":"paragraph","content":[{"text":"New subcommand for managing Copilot coding-agent tasks:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"gh agent-task create --repo owner/repo --title \"Fix flaky login test\"\ngh agent-task list --state open\ngh agent-task view 42 --log # stream agent log\ngh agent-task watch 42 # live-follow until completion\ngh agent-task cancel 42","type":"text"}]},{"type":"paragraph","content":[{"text":"Pairs with the REST endpoint ","type":"text"},{"text":"POST /repos/{owner}/{repo}/agent-tasks","type":"text","marks":[{"type":"code_inline"}]},{"text":" for CI-driven task creation.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Sub-issues (native, 2026)","type":"text"}]},{"type":"paragraph","content":[{"text":"Sub-issues are now a native GitHub concept — no extension required:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# List sub-issues of parent #123\ngh api repos/{owner}/{repo}/issues/123/sub_issues\n\n# Add an existing issue #456 as sub-issue of #123\ngh api -X POST repos/{owner}/{repo}/issues/123/sub_issues \\\n -f sub_issue_id=$(gh api repos/{owner}/{repo}/issues/456 --jq .node_id)\n\n# Remove a sub-issue relationship\ngh api -X DELETE repos/{owner}/{repo}/issues/123/sub_issue \\\n -F sub_issue_id=\u003cid>","type":"text"}]},{"type":"paragraph","content":[{"text":"The old ","type":"text"},{"text":"gh-sub-issue","type":"text","marks":[{"type":"code_inline"}]},{"text":" third-party extension still works but is superseded. GraphQL sub-issue mutations still require the issue ","type":"text"},{"text":"node_id","type":"text","marks":[{"type":"code_inline"}]},{"text":" (see ","type":"text"},{"text":"references/cli-vs-api-identifiers.md","type":"text","marks":[{"type":"code_inline"}]},{"text":").","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Related Skills","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"ork:create-pr","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Create pull requests with proper formatting and review assignments","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"ork:review-pr","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Comprehensive PR review with specialized agents","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"ork:release-management","type":"text","marks":[{"type":"code_inline"}]},{"text":" - GitHub release workflow with semantic versioning and changelogs","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"stacked-prs","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Manage dependent PRs with rebase coordination","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"ork:issue-progress-tracking","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Automatic issue progress updates from commits","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Key Decisions","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Decision","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Choice","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Rationale","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"CLI vs API","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"gh CLI preferred","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Simpler auth, better UX, handles pagination automatically","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Output format","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--json with --jq","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Reliable parsing for automation, no regex parsing needed","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Milestones vs Epics","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Milestones for time","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Milestones have due dates and progress bars, epics for topic grouping","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Projects v2 fields","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"GraphQL mutations","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"gh project commands limited, GraphQL required for custom fields","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Milestone lifecycle","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Close, don't delete","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Preserves history and progress tracking","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"References","type":"text"}]},{"type":"paragraph","content":[{"text":"Load on demand with ","type":"text"},{"text":"Read(\"${CLAUDE_SKILL_DIR}/references/\u003cfile>\")","type":"text","marks":[{"type":"code_inline"}]},{"text":":","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"File","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Content","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"issue-management.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Bulk operations, templates, sub-issues","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"pr-workflows.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Reviews, merge strategies, auto-merge","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"milestone-api.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"REST API patterns for milestone CRUD","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"projects-v2.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Custom fields, GraphQL mutations","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"graphql-api.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Complex queries, pagination, bulk operations","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"cli-vs-api-identifiers.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"NAME vs NUMBER footguns, milestone/project ID mapping","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Examples","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Load: ","type":"text"},{"text":"Read(\"${CLAUDE_SKILL_DIR}/examples/automation-scripts.md\")","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Ready-to-use scripts for bulk operations, PR automation, milestone management","type":"text"}]}]},"metadata":{"date":"2026-06-05","name":"github-operations","tags":["github","gh","cli","issues","pr","milestones","projects","api"],"author":"@skillopedia","source":{"stars":180,"repo_name":"orchestkit","origin_url":"https://github.com/yonatangross/orchestkit/blob/HEAD/src/skills/github-operations/SKILL.md","repo_owner":"yonatangross","body_sha256":"ce96bd28a22bb50652ce8cf2e42e48795bb3bb71937d9724bebf90a7db6cadd8","cluster_key":"dc246354d67715512aca392dd76545addd3bb9a5a3d11464ff3acdb1ff4d842b","clean_bundle":{"format":"clean-skill-bundle-v1","source":"yonatangross/orchestkit/src/skills/github-operations/SKILL.md","attachments":[{"id":"b28f0d5b-c656-59cb-acbf-5e2c163b5986","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b28f0d5b-c656-59cb-acbf-5e2c163b5986/attachment.md","path":"examples/automation-scripts.md","size":6341,"sha256":"7565d8d519a5b6969fe65fc572842438c46981d4cda2c2e36ce7de23c33b3aa9","contentType":"text/markdown; charset=utf-8"},{"id":"fb93bb48-39d1-5f5c-aa21-0583db17152a","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/fb93bb48-39d1-5f5c-aa21-0583db17152a/attachment.md","path":"references/cli-vs-api-identifiers.md","size":3816,"sha256":"23e18221850c4f67c2d7b2746d9298f13c20f6a4e4312700b57dacd12ae66709","contentType":"text/markdown; charset=utf-8"},{"id":"cb6da6c7-cda8-51d7-83b9-9b921579cceb","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/cb6da6c7-cda8-51d7-83b9-9b921579cceb/attachment.md","path":"references/graphql-api.md","size":7317,"sha256":"b9a285bcc73c104bfbef6a41fc753d4cc93e383a7f8a1f29fba13c704101733a","contentType":"text/markdown; charset=utf-8"},{"id":"9d27fa98-15a2-52d0-9476-d856dea245a4","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9d27fa98-15a2-52d0-9476-d856dea245a4/attachment.md","path":"references/issue-management.md","size":5262,"sha256":"b1595f885bc5fc9035aedb10f6ebfb8b580a29ff922bae1a3901accf7d82b45b","contentType":"text/markdown; charset=utf-8"},{"id":"18d0915c-0dc8-529c-b7b1-a95530461dab","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/18d0915c-0dc8-529c-b7b1-a95530461dab/attachment.md","path":"references/milestone-api.md","size":5637,"sha256":"100d371e89378d906fa3d213983f87431d69557874b3962064d4cedfc3654cc2","contentType":"text/markdown; charset=utf-8"},{"id":"dc890ed5-73fc-51ee-84e0-e91b35ddf7bb","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/dc890ed5-73fc-51ee-84e0-e91b35ddf7bb/attachment.md","path":"references/pr-workflows.md","size":5962,"sha256":"e581768277960882d6621c9d92ec0c2b201c0ee01d9b25f49a00a1bb1c643322","contentType":"text/markdown; charset=utf-8"},{"id":"2a80603f-13ac-506a-8a87-d4a38c328553","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/2a80603f-13ac-506a-8a87-d4a38c328553/attachment.md","path":"references/projects-v2.md","size":6677,"sha256":"e944e9791228c7b2e63287391ba7964810d523af3ebc5deac3fad6ffddf2c908","contentType":"text/markdown; charset=utf-8"},{"id":"5aca0ca7-5035-5a73-bff3-34fb09895df9","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/5aca0ca7-5035-5a73-bff3-34fb09895df9/attachment.md","path":"rules/_sections.md","size":652,"sha256":"3fb48eb093599cbfd9b43f5e3df1d40868ad905c37b90071469fce1e5e4816c0","contentType":"text/markdown; charset=utf-8"},{"id":"1cb80a6f-ce18-5ee0-948e-c1b9d9df9ea5","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1cb80a6f-ce18-5ee0-948e-c1b9d9df9ea5/attachment.md","path":"rules/_template.md","size":339,"sha256":"1f6b17cb8c02a543b46a648f062ff0a0c93635b93d51663bc299033be4dc3f83","contentType":"text/markdown; charset=utf-8"},{"id":"6fd8aee2-dc7f-5c06-8eab-938f80368d60","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/6fd8aee2-dc7f-5c06-8eab-938f80368d60/attachment.md","path":"rules/issue-branch-linking.md","size":2426,"sha256":"1a921b9ca6e93b5a6a03c9599933966f9e092ee984bb608c8619c69a7977409d","contentType":"text/markdown; charset=utf-8"},{"id":"9644934d-1915-5d7d-9b21-a03d4402b313","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9644934d-1915-5d7d-9b21-a03d4402b313/attachment.md","path":"rules/issue-tracking-automation.md","size":2851,"sha256":"fe9bbbc72fd58e2506bbd053f83664bd41d3501c9b5089698f7d75ead62e2700","contentType":"text/markdown; charset=utf-8"},{"id":"f6866146-8473-5a31-a378-353b8357a465","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f6866146-8473-5a31-a378-353b8357a465/attachment.json","path":"test-cases.json","size":3096,"sha256":"e55f8a6202862b164cdffc561ae1c4363b1d5b66136a1165be6d65d9f74ce7a6","contentType":"application/json; charset=utf-8"}],"bundle_sha256":"0af7336cb6a24a67c00982022c4091fc6f56a9780e6ef61bd48c04677eff8b1d","attachment_count":12,"text_attachments":12,"attachment_storage":"skillopedia-attachments-v1","binary_attachments":0,"excluded_attachments":[]},"cluster_size":2,"skill_md_path":"src/skills/github-operations/SKILL.md","import_metadata":{"date":"2026-06-05","author":"@skillopedia","version":"v1","category":"integrations-apis","category_label":"Integrations"},"exact_dupes_collapsed_into_this":1},"context":"fork","license":"MIT","version":"v1","category":"integrations-apis","metadata":{"category":"workflow-automation"},"complexity":"medium","import_tag":"clean-skills-v1","description":"GitHub CLI operations for issues, PRs, milestones, and Projects v2. Covers gh commands, REST API patterns, and automation scripts. Use when managing GitHub issues, PRs, milestones, or Projects with gh.","allowed-tools":["Read","Glob","Grep","Bash","Write","Edit","TaskCreate","TaskUpdate","TaskList"],"compatibility":"Claude Code 2.1.148+. Requires gh CLI.","user-invocable":false,"persuasion-type":"guidance"}},"renderedAt":1782986221163}

GitHub Operations Comprehensive GitHub CLI ( ) operations for project management, from basic issue creation to advanced Projects v2 integration and milestone tracking via REST API. Overview - Creating and managing GitHub issues and PRs - Working with GitHub Projects v2 custom fields - Managing milestones (sprints, releases) via REST API - Automating bulk operations with - Running GraphQL queries for complex operations --- CRITICAL: Task Management is MANDATORY (CC 2.1.16) BEFORE doing ANYTHING else, create tasks to track progress: Quick Reference Issue Operations PR Operations Tip (CC 2.1.27)…