Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Create, triage, label, assign GitHub issues via gh or REST.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-19 | ✗→✓ | ▲ Improved | 36% | 0% |
| case-01 | ✓→✗ | ▼ Worse | 164% | 0% |
| case-10 | ✓→✓ | = Same ✓ | 614% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 300% | 0% |
| case-04 | ✓→✓ | = Same ✓ | 141% | 0% |
Create, search, triage, and manage GitHub issues. Each section shows gh first, then the curl fallback.
github-auth skill)bashif command -v gh &>/dev/null && gh auth status &>/dev/null; then AUTH="gh" else AUTH="git" if [ -z "$GITHUB_TOKEN" ]; then if [ -f ~/.hermes/.env ] && grep -q "^GITHUB_TOKEN=" ~/.hermes/.env; then GITHUB_TOKEN=$(grep "^GITHUB_TOKEN=" ~/.hermes/.env | 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 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)
With gh:
bashgh issue list gh issue list --state open --label "bug" gh issue list --assignee @me gh issue list --search "authentication error" --state all gh issue view 42
With curl:
bash# List open issues curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ "https://api.github.com/repos/$OWNER/$REPO/issues?state=open&per_page=20" \ | python3 -c " import sys, json for i in json.load(sys.stdin): if 'pull_request' not in i: # GitHub API returns PRs in /issues too labels = ', '.join(l['name'] for l in i['labels']) print(f\"#{i['number']:5} {i['state']:6} {labels:30} {i['title']}\")" # Filter by label curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ "https://api.github.com/repos/$OWNER/$REPO/issues?state=open&labels=bug&per_page=20" \ | python3 -c " import sys, json for i in json.load(sys.stdin): if 'pull_request' not in i: print(f\"#{i['number']} {i['title']}\")" # View a specific issue curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$REPO/issues/42 \ | python3 -c " import sys, json i = json.load(sys.stdin) labels = ', '.join(l['name'] for l in i['labels']) assignees = ', '.join(a['login'] for a in i['assignees']) print(f\"#{i['number']}: {i['title']}\") print(f\"State: {i['state']} Labels: {labels} Assignees: {assignees}\") print(f\"Author: {i['user']['login']} Created: {i['created_at']}\") print(f\"\n{i['body']}\")" # Search issues curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ "https://api.github.com/search/issues?q=authentication+error+repo:$OWNER/$REPO" \ | python3 -c " import sys, json for i in json.load(sys.stdin)['items']: print(f\"#{i['number']} {i['state']:6} {i['title']}\")"
With gh:
bashgh issue create \ --title "Login redirect ignores ?next= parameter" \ --body "## Description After logging in, users always land on /dashboard. ## Steps to Reproduce 1. Navigate to /settings while logged out 2. Get redirected to /login?next=/settings 3. Log in 4. Actual: redirected to /dashboard (should go to /settings) ## Expected Behavior Respect the ?next= query parameter." \ --label "bug,backend" \ --assignee "username"
With curl:
bashcurl -s -X POST \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$REPO/issues \ -d '{ "title": "Login redirect ignores ?next= parameter", "body": "## Description\nAfter logging in, users always land on /dashboard.\n\n## Steps to Reproduce\n1. Navigate to /settings while logged out\n2. Get redirected to /login?next=/settings\n3. Log in\n4. Actual: redirected to /dashboard\n\n## Expected Behavior\nRespect the ?next= query parameter.", "labels": ["bug", "backend"], "assignees": ["username"] }'
## Bug Description
<What's happening>
## Steps to Reproduce
1. <step>
2. <step>
## Expected Behavior
<What should happen>
## Actual Behavior
<What actually happens>
## Environment
- OS: <os>
- Version: <version>## Feature Description
<What you want>
## Motivation
<Why this would be useful>
## Proposed Solution
<How it could work>
## Alternatives Considered
<Other approaches>With gh:
bashgh issue edit 42 --add-label "priority:high,bug" gh issue edit 42 --remove-label "needs-triage"
With curl:
bash# Add labels curl -s -X POST \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$REPO/issues/42/labels \ -d '{"labels": ["priority:high", "bug"]}' # Remove a label curl -s -X DELETE \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$REPO/issues/42/labels/needs-triage # List available labels in the repo curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$REPO/labels \ | python3 -c " import sys, json for l in json.load(sys.stdin): print(f\" {l['name']:30} {l.get('description', '')}\")"
With gh:
bashgh issue edit 42 --add-assignee username gh issue edit 42 --add-assignee @me
With curl:
bashcurl -s -X POST \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$REPO/issues/42/assignees \ -d '{"assignees": ["username"]}'
With gh:
bashgh issue comment 42 --body "Investigated — root cause is in auth middleware. Working on a fix."
With curl:
bashcurl -s -X POST \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$REPO/issues/42/comments \ -d '{"body": "Investigated — root cause is in auth middleware. Working on a fix."}'
With gh:
bashgh issue close 42 gh issue close 42 --reason "not planned" gh issue reopen 42
With curl:
bash# Close curl -s -X PATCH \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$REPO/issues/42 \ -d '{"state": "closed", "state_reason": "completed"}' # Reopen curl -s -X PATCH \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$REPO/issues/42 \ -d '{"state": "open"}'
Issues are automatically closed when a PR merges with the right keywords in the body:
Closes #42
Fixes #42
Resolves #42To create a branch from an issue:
With gh:
bashgh issue develop 42 --checkout
With git (manual equivalent):
bashgit checkout main && git pull origin main git checkout -b fix/issue-42-login-redirect
When asked to triage issues:
bash# With gh gh issue list --label "needs-triage" --state open # With curl curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ "https://api.github.com/repos/$OWNER/$REPO/issues?labels=needs-triage&state=open" \ | python3 -c " import sys, json for i in json.load(sys.stdin): if 'pull_request' not in i: print(f\"#{i['number']} {i['title']}\")"
For batch operations, combine API calls with shell scripting:
With gh:
bash# Close all issues with a specific label gh issue list --label "wontfix" --json number --jq '.[].number' | \ xargs -I {} gh issue close {} --reason "not planned"
With curl:
bash# List issue numbers with a label, then close each curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ "https://api.github.com/repos/$OWNER/$REPO/issues?labels=wontfix&state=open" \ | python3 -c "import sys,json; [print(i['number']) for i in json.load(sys.stdin)]" \ | while read num; do curl -s -X PATCH \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$REPO/issues/$num \ -d '{"state": "closed", "state_reason": "not_planned"}' echo "Closed #$num" done
| Action | gh | curl endpoint | |--------|-----|--------------| | List issues | gh issue list | GET /repos/{o}/{r}/issues | | View issue | gh issue view N | GET /repos/{o}/{r}/issues/N | | Create issue | gh issue create ... | POST /repos/{o}/{r}/issues | | Add labels | gh issue edit N --add-label ... | POST /repos/{o}/{r}/issues/N/labels | | Assign | gh issue edit N --add-assignee ... | POST /repos/{o}/{r}/issues/N/assignees | | Comment | gh issue comment N --body ... | POST /repos/{o}/{r}/issues/N/comments | | Close | gh issue close N | PATCH /repos/{o}/{r}/issues/N | | Search | gh issue list --search "..." | GET /search/issues?q=... |
Other measured skills in the registry, with their headline benchmark lift.