| name | github-remote |
| description | Read-first wrapper around the GitHub REST API. Single-call PR/branch overviews (PR state + checks + reviews + workflow runs + mergeable) for triage. Use whenever the user wants the state of a PR, a branch's CI, or a failing run — without you chaining `gh pr view`, `gh pr checks`, `gh run view`, `gh pr list --head` per investigation. Resolves PRs and issues by branch/title. `run wait` polls on a run ID or branch. One write surface, `pr comment`. |
| when_to_use | Trigger on phrases like "is this PR green", "what's the state of <branch>", "is this mergeable", "why did CI fail", "what's blocking this PR", "resolve the PR for <branch>", "tail the failing job logs", "wait for the run on <branch>", "post a comment on PR <N>". |
| allowed-tools | Bash(github-remote:*) Bash(python3 *github-remote*:*) |
github-remote
Project-scoped CLI that wraps the GitHub REST API into a read-first, JSON-output triage tool. Stdlib-only Python 3 (no pip installs, no venvs). Designed for agent-driven PR/CI inspection — one call returns PR state + checks + reviews + runs so you don't burn tool calls chaining gh pr view / gh pr checks / gh run view per investigation.
Lives at ${CLAUDE_SKILL_DIR}/../../bin/github-remote; the plugin auto-adds bin/ to PATH, so just run github-remote ....
Prerequisites
GITHUB_TOKEN set in project .env / .env.local / shell env, OR gh logged in (the CLI falls back to gh auth token). Get a PAT at https://github.com/settings/tokens.
- Repo resolution: pass
--repo owner/name, or set GITHUB_REPO, or run from a git checkout whose origin points at github.com.
The CLI bails with a clear missing-config message if neither auth nor repo is resolvable.
When to reach for this
- User asks "is this PR green / mergeable" → run
overview <branch-or-pr-number> --pretty. One call → PR + checks + reviews + runs + mergeable + review comment count.
- User asks "why did CI fail on " → run
overview <branch> to see failing job names, then run logs <run-id> --errors-only --tail 100.
- User asks "resolve the PR for " → run
pr resolve <branch>. Exits non-zero with candidates on ambiguity; never auto-picks.
- User asks "wait for the run on main" → run
run wait main --timeout 1800. Accepts a branch or a run ID. Exits non-zero on timeout or non-success conclusion.
- User asks "post a comment on PR 498" → run
pr comment 498 --body '…'. Posts via /issues/{n}/comments (issue-style comments on PRs, which is what gh pr comment does).
Headline commands
github-remote pr list [--state open|closed|merged|all] [--base <branch>] [--author <u>] [--limit 50]
github-remote pr resolve <branch-or-partial-title>
github-remote pr show <N-or-branch>
github-remote pr comment <N-or-branch> --body <text>
github-remote issue list [--state open|closed|all] [--assignee <u>] [--label <l>] [--limit 50]
github-remote issue resolve <title-pattern>
github-remote issue show <N>
github-remote run list [--branch <b>] [--status in_progress|completed|queued] [--limit 20]
github-remote run show <RUN_ID>
github-remote run logs <RUN_ID> [--job <name>] [--errors-only] [--tail 50]
github-remote run wait <RUN_ID-or-branch> [--timeout 1800] [--poll-interval 10]
github-remote overview <branch-or-pr-number>
github-remote whoami [--json]
All list/show commands emit JSON to stdout. Use --pretty for indentation.
jq-friendly. Default compact JSON pipes cleanly into jq. Every dict payload also carries a top-level tool: {name, version} field (injected by _with_tool_meta) so agents can self-diagnose version drift from the output alone — no extra --version subprocess call needed. Prefer jq against stable keys (.pr.number, .checks.failing_jobs[], .runs[].conclusion) rather than parsing human output.
Offloading large responses with --output
GitHub responses balloon quickly — run logs on a failing build, long pr list, run show with dozens of check annotations. Pulling the full payload through the model's context wastes tokens when you only need a slice.
Pass --output <path> before the subcommand (it's a top-level flag, same position as --pretty):
github-remote --output /tmp/run.json run logs 1234567890 --errors-only
github-remote --output /tmp/prs.json pr list --state open --limit 100
Stdout returns a compact envelope instead of the full payload:
{
"tool": {"name": "github-remote", "version": "..."},
"payloadPath": "/tmp/run.json",
"bytes": 93420,
"fileLineCount": 2104,
"payloadKeys": ["run_id", "jobs", "failing_jobs"],
"payloadShape": {
"run_id": {"type": "number"},
"jobs": {"type": "list", "length": 12,
"sample": {"type": "dict", "keys": 6,
"shape": {"name": {"type": "string", "length": 8},
"conclusion": {"type": "string", "length": 7},
"annotations": {"type": "list", "length": 23}}}},
"failing_jobs": {"type": "list", "length": 2}
}
}
How to act on it:
payloadShape tells you what's in the file without reading it. Agent sees jobs[0].annotations.length: 23 and knows the interesting data is nested under each job.
- Use
Read with offset/limit to pull only the slice you need.
- For list-shaped responses (
pr list, run list), the envelope has payloadType: "list" + payloadLength + sampleShape.
--shape-depth <1|2|3> controls recursion depth. Default is 3 (two layers — surfaces checks[0].annotations.length or prs[0].head.sha). --shape-depth 1 gives a minimal top-level-only envelope.
When NOT to use --output: small responses (pr resolve, issue show for a single item), or when you need the data in the same turn to act on.
Design rules (agent-plus patterns)
- Aggregate server-side.
overview returns PR state + mergeable + check-runs rollup + review summary + latest runs in one call — replaces 4-6 gh invocations.
- Resolve by name.
pr resolve feat/foo and issue resolve 'flaky test' — you never copy PR numbers between commands. Ambiguity never auto-picks: exits non-zero with up to 10 candidates so the agent can re-query.
--wait on async flows. run wait polls on a run ID or branch name with a 30-min default timeout and 10s poll interval. On timeout: non-zero exit with partial JSON including last-known state. Never hangs.
--json is the default. No human-prose output paths. Pipe to jq freely.
- Zero token leakage. Every API response walks through
_scrub(), which redacts token, password, authorization, client_secret, private_key, webhook_url_with_secret, access_token, refresh_token, secret, api_key. Free-text log blobs from run logs are regex-scrubbed for ghp_…, github_pat_…, gho_…, ghu_…, ghs_…, ghr_…, AKIA…, and Bearer … patterns. A canary no-leak test asserts a known secret substring cannot appear on any output path.
Overview output caps
Documented in --help and honoured by the CLI so agents can budget context:
- Reviews: 10 latest
- Failing jobs: 20
- Workflow runs tied to head SHA: 5
Config precedence (highest first)
--token / --repo CLI flags
--env-file <path> if passed
.env.local / .env walked up from cwd (closest wins)
- Shell env
Only GITHUB_* prefixed vars are picked up.
Auth precedence (highest first)
GITHUB_TOKEN env var (explicit, CI-friendly; fine-grained and classic PATs both flow here)
gh auth token subprocess (inherits your local gh login — best DX on dev machines)
- Fail with a missing-config message pointing at
.env, ~/.claude/settings.json, and gh auth login.
Rate limits
X-RateLimit-Remaining / X-RateLimit-Reset headers are read on every response. When remaining < 50, a warning goes to stderr.
- Primary rate limit (429 or 403 +
Retry-After): auto-retried once with the backoff the header suggests.
- Secondary rate limit (403 + 'secondary rate limit' / 'abuse' in body): NOT auto-retried. Surfaces a clear error — back off several minutes, not seconds.
Safety
- Read-only by default.
pr comment is the sole write in v1.
pr comment requires non-empty --body; rejects whitespace-only.
- Out of scope for v1:
pr create, pr merge, issue create, issue close. Those carry distinct confirmation contracts and are deferred.
Error message contract
Every error emits problem + cause + fix + link:
- Missing token → "GITHUB_TOKEN not set and 'gh auth token' returned nothing. Set in .env / ~/.claude/settings.json, or run 'gh auth login'. Get a PAT: https://github.com/settings/tokens"
- 401 → "Token rejected. Regenerate or run 'gh auth refresh'."
- 403 scope → "Token lacks required scope. Classic PATs need 'repo'+'workflow'; fine-grained PATs need Contents+Pull requests+Actions(read)+Issues+Metadata."
- 404 → "Repo not found or token lacks access. Private repos require 'repo' scope."
- 422 → "GitHub rejected the request. Common cause: field validation (e.g. empty body on pr comment)."
- 429 / primary → "Primary rate limit hit. See X-RateLimit-Reset for when it resets."
- 403 secondary → "Secondary rate limit (abuse detection). Back off several minutes."
When NOT to use this — fall back to gh CLI or the GitHub REST API directly
This wrapper is read-first by design. The only write surface is pr comment. Every other state-changing GitHub operation is deliberately unwrapped — if the user wants to DO something (merge, close, create, dispatch), skip github-remote entirely and use gh (already authed on their machine) or curl https://api.github.com/* with Authorization: Bearer $GITHUB_TOKEN.
Specific cases where you should use gh ... or the REST API directly, not github-remote:
- Creating, merging, closing, or reviewing PRs. →
gh pr create, gh pr merge, gh pr close, gh pr review --approve|--request-changes. github-remote intentionally ships none of these (distinct safety/confirmation contracts).
- Creating, closing, or commenting on issues. →
gh issue create, gh issue close, gh issue comment. Only pr comment is wrapped; issue writes are not.
- Running or dispatching workflows. →
gh workflow run <name>, gh workflow list, or POST /repos/{owner}/{repo}/actions/workflows/{id}/dispatches. github-remote run * is read-only (list/show/logs/wait).
- Releases, tags, team/repo admin, branch protection, secrets management. →
gh release ..., gh api ..., or the dashboard. Entirely out of wrapper scope.
- GitHub Enterprise Server (non-
api.github.com hosts). → gh with GH_HOST set, or curl against your GHES base URL. GITHUB_API_URL is reserved but not wired up in v1.
- Git operations — cloning, checkouts, pushing, branch creation, local diffs. → plain
git and gh repo clone. The wrapper has no git surface at all.
Don't get stuck in a loop. If the user's request obviously needs a write github-remote doesn't support (merge, create, dispatch, close), immediately switch to gh or curl rather than hunting for a wrapper flag that doesn't exist. The wrapper exists to make reading PR/CI state faster and safer — it is not a replacement for gh.
What it doesn't do
Deliberately out of scope for v1:
pr create, pr merge, issue create, issue close (deferred — distinct safety contracts)
- Workflow authoring or
workflow dispatch / workflow run
- Team, releases, repo admin, secrets management
- GitHub Enterprise Server (v1 assumes
api.github.com; GITHUB_API_URL is reserved for future GHES support)
- GraphQL migration (REST covers every v1 command)
Use the gh CLI or dashboard for those. This plugin is read-first PR/CI triage plus one write.