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.
.claude/skills/nousresearch-github-issues/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-08 | ✗→✓ | ▲ Improved | 275% | 0% |
| case-15 | ✗→✓ | ▲ Improved | 360% | 0% |
| case-07 | ✓→✗ | ▼ Worse | 578% | 0% |
| case-10 | ✓→✗ | ▼ Worse | 301% | 0% |
| case-05 | ✓→✓ | = Same ✓ | 181% | 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 _hermes_env="${HERMES_HOME:-$HOME/.hermes}/.env"; [ -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=$(uv run python "${HERMES_HOME:-$HOME/.hermes}/skills/github/github-auth/scripts/git-credential-token.py") 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" \ | python -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" \ | python -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 \ | python -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" \ | python -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 \ | python -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" \ | python -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" \ | python -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=... |
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-03 | fail→fail | 5,421 | 9,752 | +80% | 1 | 1 | 0% | 1,027 | 4,998 | +387% | 0 | 0 | — |
case-04 | fail→fail | 7,297 | 13,070 | +79% | 1 | 1 | 0% | 1,460 | 5,379 | +268% | 0 | 0 | — |
case-01 | fail→fail | 4,637 | 4,071 | -12% | 1 | 1 | 0% | 222 | 3,215 | +1348% | 0 | 0 | — |
case-02 | fail→fail | 8,791 | 7,568 | -14% | 1 | 1 | 0% | 1,982 | 4,741 | +139% | 0 | 0 | — |
case-05 | pass→pass | 6,806 | 3,508 | -48% | 1 | 1 | 0% | 1,290 | 3,621 | +181% | 0 | 0 | — |
case-06 | pass→pass | 6,427 | 4,539 | -29% | 1 | 1 | 0% | 1,398 | 3,937 | +182% | 0 | 0 | — |
case-07 | pass→fail | 2,961 | 7,056 | +138% | 1 | 1 | 0% | 553 | 3,748 | +578% | 0 | 0 | — |
case-08 | fail→pass | 4,713 | 2,272 | -52% | 1 | 1 | 0% | 905 | 3,391 | +275% | 0 | 0 | — |
case-09 | pass→pass | 4,262 | 2,797 | -34% | 1 | 1 | 0% | 944 | 3,580 | +279% | 0 | 0 | — |
case-10 | pass→fail | 4,589 | 5,315 | +16% | 1 | 1 | 0% | 793 | 3,180 | +301% | 0 | 0 | — |
case-11 | pass→pass | 4,814 | 2,326 | -52% | 1 | 1 | 0% | 1,107 | 3,440 | +211% | 0 | 0 | — |
case-12 | pass→pass | 3,519 | 2,274 | -35% | 1 | 1 | 0% | 685 | 3,411 | +398% | 0 | 0 | — |
case-13 | pass→pass | 1,953 | 1,131 | -42% | 1 | 1 | 0% | 287 | 3,128 | +990% | 0 | 0 | — |
case-14 | pass→pass | 1,775 | 1,360 | -23% | 1 | 1 | 0% | 330 | 3,173 | +862% | 0 | 0 | — |
case-15 | fail→pass | 4,206 | 2,941 | -30% | 1 | 1 | 0% | 776 | 3,568 | +360% | 0 | 0 | — |
case-16 | pass→pass | 4,119 | 2,329 | -43% | 1 | 1 | 0% | 901 | 3,411 | +279% | 0 | 0 | — |
case-17 | pass→pass | 6,748 | 2,128 | -68% | 1 | 1 | 0% | 1,464 | 3,418 | +133% | 0 | 0 | — |
case-18 | pass→pass | 3,945 | 1,929 | -51% | 1 | 1 | 0% | 739 | 3,297 | +346% | 0 | 0 | — |
case-19 | pass→pass | 7,949 | 3,590 | -55% | 1 | 1 | 0% | 1,609 | 3,625 | +125% | 0 | 0 | — |
case-20 | pass→pass | 6,651 | 4,509 | -32% | 1 | 1 | 0% | 1,522 | 3,943 | +159% | 0 | 0 | — |
case-21 | pass→pass | 2,224 | 910 | -59% | 1 | 1 | 0% | 366 | 3,086 | +743% | 0 | 0 | — |
case-22 | pass→pass | 4,023 | 2,815 | -30% | 1 | 1 | 0% | 761 | 3,585 | +371% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 19 counted toward the lift figure. The other 3 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of 0 percentage points is the difference between those two pass rates over the 19 comparable cases. 2 cases got worse with the skill loaded, and they are included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
| Model | Method | Date | Lift |
|---|---|---|---|
| gemini-3.6-flash | verified | 8/8/2026 | +14% |
Other measured skills in the registry, with their headline benchmark lift.