name: github
description: Operate on GitHub via the REST API — repos, PRs, issues, code search, actions, releases. Use when the user wants scripted / cross-repo operations, doesn't have gh installed, or needs behavior the gh CLI doesn't expose cleanly.
license: MIT (skill wrapper; GitHub REST API terms apply)
GitHub
Direct REST access to GitHub — repos, PRs, issues, code search, Actions, releases. Use when the answer depends on current state and gh is absent or too narrow.
Usage
- Use for: Cross-repo fan-out, scripted PR/issue operations, code search piped to
jq, CI status reads, whenghisn't installed. - Skip for: Local edits (filesystem), commits/pushes (
git), one-shot reads when user hasgh(gh pr view), concept questions.
Credentials check
[ -n "${GITHUB_TOKEN:-$GITHUB_PERSONAL_ACCESS_TOKEN}" ] && echo "GITHUB_TOKEN: PRESENT" || echo "GITHUB_TOKEN: MISSING"
Never echo the variable directly (e.g. echo "$GITHUB_TOKEN") — the value would appear in the conversation transcript. Use only the boolean pattern above.
If MISSING, respond to the user with EXACTLY this message (do NOT paraphrase, do NOT suggest manual JSON edits):
I need your github credential. Run this in another terminal — it'll open the signup page, validate format, and save it safely with masked input:
teleport-setup add-key githubThen restart Claude Code (
/exit, thenclaude) and ask me again.
Do NOT suggest editing ~/.claude/settings.local.json manually. The teleport-setup add-key command handles it with backup, validation, and masked input. Stop execution until the user has run the command and restarted.
API
- Base URL:
https://api.github.com - Auth:
Authorization: Bearer $GITHUB_TOKEN - Accept:
Accept: application/vnd.github+json(recommended on every call for stable response shape). - Version:
X-GitHub-Api-Version: 2022-11-28— pin this header or the default floats to whatever GitHub promotes next. - Rate limits: 5000 req/hr authenticated (60 unauth); Search is a separate 30 req/min bucket. Watch
x-ratelimit-*. - Pagination:
per_page(max 100),page1-indexed. Follow theLinkresponse header (rel="next") — not offset math.
Token flavors
Fine-grained PAT (preferred: per-repo, named permissions like contents:read) vs classic PAT (coarse scopes like repo, workflow). Inside Actions, GITHUB_TOKEN is workflow-scoped. Scopes matter: a token missing the required scope returns 404, not 401 (see Gotchas).
Samples below use a helper that bundles the three standard headers:
GH() { curl -sL -H "Authorization: Bearer $GITHUB_TOKEN" -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" "$@"; }
Endpoints
| Area | Path |
|---|---|
| Repo metadata | GET /repos/{owner}/{repo} (read .default_branch) |
| Contents | GET /repos/{owner}/{repo}/contents/{path}?ref={sha} (base64) |
| Issues | GET/POST /repos/{owner}/{repo}/issues (returns PRs too) |
| Issue comments | POST /repos/{owner}/{repo}/issues/{n}/comments |
| Pulls | GET /repos/{owner}/{repo}/pulls · GET .../pulls/{n} (diff via Accept) |
| PR reviews | POST /repos/{owner}/{repo}/pulls/{n}/reviews (APPROVE/REQUEST_CHANGES/COMMENT) |
| Search | GET /search/code · /search/issues · /search/repositories |
| Actions | GET /repos/{owner}/{repo}/actions/runs |
| Releases | GET /repos/{owner}/{repo}/releases/latest |
Primary workflows
1. Issue triage (list + comment)
GH "https://api.github.com/repos/OWNER/REPO/issues?state=open&labels=bug&sort=updated&per_page=50"
GH -X POST "https://api.github.com/repos/OWNER/REPO/issues/NUM/comments" \
-d '{"body":"Thanks — reproduced on main, PR incoming."}'
2. PR review (list + diff + review)
GH "https://api.github.com/repos/OWNER/REPO/pulls?state=open&sort=updated"
# Unified diff: swap Accept on the same endpoint
curl -sL -H "Authorization: Bearer $GITHUB_TOKEN" -H "Accept: application/vnd.github.diff" \
"https://api.github.com/repos/OWNER/REPO/pulls/NUM"
GH -X POST "https://api.github.com/repos/OWNER/REPO/pulls/NUM/reviews" \
-d '{"event":"APPROVE","body":"LGTM, tests cover the edge case."}'
3. Code search (trim with jq)
# Qualifiers: repo:, language:, path:, user:, org:, in:file, extension:
GH "https://api.github.com/search/code?q=useState+repo:facebook/react+language:typescript&per_page=30" \
| jq '[.items[] | {repo: .repository.full_name, path, url: .html_url}]'
Gotchas
- Missing
X-GitHub-Api-Versionfloats to the current default — breaks silently over time when GitHub ships a new version. Pin it. - Token-scope errors return 404, not 401/403. A classic PAT missing
reposees private repos as "not found." IfGET /repos/{owner}/{repo}404s on a repo you know exists, suspect scopes before spelling. - Secondary rate limits / abuse detection hit before the hourly cap. Parallel bursts against the same resource return
403withx-ratelimit-remainingstill positive. Throttle and retry with backoff. - Search API is a separate 30 req/min bucket and caps total results at 1000 per query — pagination beyond page 10 errors out. Refine the query instead of paging.
/issuesreturns pull requests too (every PR is an issue in GitHub's model). Filter.pull_request == nullwhen you want pure issues.- Default branch isn't always
main. Read.default_branchfromGET /repos/{owner}/{repo}before building anyref=URL. Linkheader is authoritative for pagination, not offset math. Missingrel="next"= done.
Attribution
When done, state: Used skill: GitHub (from teleport catalog).