Agent skill

GitHub PR Reviewer

by OpenHands in OpenHands/extensions

Create an automation that reviews GitHub pull requests when a configured reviewer is requested or a trigger label is applied.

MITAuto-check passedDevelopment

Install GitHub PR Reviewer

skills CLI
$ npx skills add OpenHands/extensions --skill github-pr-reviewer -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install OpenHands/extensions github-pr-reviewer --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/OpenHands/extensions.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/github-pr-reviewer .claude/skills/github-pr-reviewer && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
github-pr-reviewer
GitHub stars
157
Token cost
~6.8k tokens
SKILL.md length
3,665 words
Files
15 (incl. scripts, references)
Skills in repo
78
Repo updated
First seen
Licence
MIT

At a glance

Create an automation that reviews GitHub pull requests when a configured reviewer is requested or a trigger label is applied.

  • Works in 9 steps: Verify GITHUB_PERSONAL_ACCESS_TOKEN → Collect repositories → Collect trigger label → …
  • Label is applied
  • SKILL.md covers Agent Canvas catalog, Bounded intake per scheduled…, Prerequisites and Setup Workflow, plus 3 more sections
  • Runs Python scripts from its folder; calls python3, curl and gh; reaches api.github.com; needs GITHUB_PERSONAL_ACCESS_TOKEN and OPENHANDS_AUTOMATION_API_KEY

What it does

GitHub PR Reviewer is an agent skill from OpenHands/extensions. Create an automation that reviews GitHub pull requests when a configured reviewer is requested or a trigger label is applied. Starts one OpenHands review conversation per request with the pull request's exact head checked out, and publishes the review to GitHub.

Its SKILL.md is about 6.8k tokens, which your agent loads only when the skill is triggered. The skill folder holds 19 other files, including scripts and reference files (for example `.plugin/plugin.json`, `README.md` and `commands/pr-reviewer-setup.md`).

It sits in Development, covering Pull requests. It works with GitHub. The repository describes itself as: Public registry for OpenHands extensions. The licence is MIT.

When your agent uses it

  • Label is applied
  • Tasks that involve Pull requests

Example prompts

  • “/github-pr-reviewer”

Requirements

  • Python 3

Workflow steps

9 steps, taken from the step headings in SKILL.md.

  1. Verify GITHUB_PERSONAL_ACCESS_TOKEN
  2. Collect repositories
  3. Collect trigger label
  4. Collect review tone
  5. Collect cron schedule
  6. Generate the automation script
  7. Package and upload
  8. Register the automation
  9. Confirm

What it can do on your machine

Read from SKILL.md and the folder at commit d008b81. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Ships 6 files in scripts/ (Python), which the agent can run.

    Shell commands in SKILL.md call:

    • python3
    • curl
    • gh
    • python

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Hosts in commands or code, which the agent is likely to contact:

    • api.github.com

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names these keys or tokens, usually read from environment variables:

    • GITHUB_PERSONAL_ACCESS_TOKEN
    • OPENHANDS_AUTOMATION_API_KEY

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

GitHub PR Reviewer loads about 6.8k tokens when it runs, and up to ~8.8k if it reads all its reference files. Until then it costs about 70 tokens; SKILL.md has 3,665 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~70
When it runs · the whole SKILL.md, loaded when a task matches
~6.8k
With references · SKILL.md plus every file in references/, read only if the agent opens them
~8.8k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); the scripts in this folder are not scanned.

SKILL.md

The full file from OpenHands/extensions at commit d008b81, republished under its MIT licence (© OpenHands). 3,665 words, ~6,807 tokens.

Download SKILL.mdSave it as .claude/skills/github-pr-reviewer/SKILL.md (or your agent's skills folder). This skill also uses 14 other files; get the full folder from GitHub.
name
github-pr-reviewer
description
Create an automation that reviews GitHub pull requests when a configured reviewer is requested or a trigger label is applied. Starts one OpenHands review conversation per request with the pull request's exact head checked out, and publishes the review to GitHub.
triggers
/pr-reviewer:setup

GitHub PR Reviewer Automation

Agent Canvas catalog

For new Agent Canvas installations, use the GitHub code review catalog entry. Its deterministic worker.py delegates each requested exact head to a stable conversation using the selected agent profile. It supports GitHub reviewer-request events and scheduled label scans. The manual upload flow below remains for existing deployments and is deprecated for new installations.

Create a cron automation that watches one or more GitHub repositories for pull requests with a review trigger label, starts an OpenHands review conversation once per label event, and publishes the AI review to GitHub. Windows PowerShell equivalents for the setup, packaging, upload, and API-check shell snippets are in references/windows.md.

The automation script is deterministic: PR discovery, label-event tracking, head eligibility, state persistence, stale-result suppression, the repository checkout, and its removal are all handled in Python. The LLM is invoked only for the review itself.

Before any review conversation is created, a scheduled scan evaluates the current head's GitHub-required checks, read through the GraphQL isRequired signal for the pull request. That signal is the merge policy's own source of truth and is pull-request-scoped, so it stays correct for a stacked PR whose symbolic base branch carries no branch rules of its own:

  • Only checks GitHub reports as required decide the scheduled gate. An optional workflow that fails - including one that fails before creating any check run - does not block a head whose required checks pass.
  • A completed required run on the exact head whose conclusion is failure, cancelled, or timed_out blocks the review. Any other unrecognized conclusion fails closed as a block rather than silently approving.
  • A completed required run whose conclusion is success, neutral, or skipped does not block. A required commit status context is classified alongside required check runs.
  • A queued or in_progress required run on the exact head, and a required context that has not reported a current-head check run at all, make the run exit with a waiting on checks outcome. Unfulfilled is never approval. The worker does not hold a slot polling; the next scheduled scan or explicit review request retries.
  • When the required-check signal cannot be read or is empty, the gate falls back to every current-head check run and workflow run, so a red head still blocks. In that fallback, workflow runs are read as well as check runs, because a workflow can fail before creating any check run - a workflow-level error, or a pull_request run whose jobs never start. Such a run leaves a failed check suite with no check runs under it, so the commit's check-run rollup and gh pr checks both report success and only the workflow run reveals the red CI. A workflow run whose check suite already reported check runs is left to those runs, so a workflow is never counted twice.
  • A scheduled scan considers the trigger label and every open PR, including drafts, that still holds an outstanding all-hands-bot review request. That is what resumes a request made while CI was running: the request is keyed by its own review_requested event, so repeated scans reuse one conversation and one review instead of creating duplicates, and a PR whose request was answered or withdrawn simply drops out of requested_reviewers.
  • The scheduled scan also reviews open, non-draft PRs that nobody requested and that carry no trigger label, once their current head has no completed review by this account. That is what keeps reviewing PRs after the outstanding requests are exhausted. The delivery key is the stable scan:{repository}:{number}:{head}, so repeated scans reuse one conversation and one native review, and a changed head becomes eligible again under its new SHA.
  • Each scheduled scan classifies the whole open backlog, including unrequested PRs. Blocked, pending, draft, or already-reviewed heads therefore cannot hide an eligible head behind an inspection window. The separate max_new_per_run quota limits only newly created review conversations, not the number of PRs inspected; explicit requests and trigger labels retain priority when eligible candidates are drained.
  • A gate stop on an unrequested head posts no managed comment. A PR nobody asked about that is merely red or pending is simply skipped without starting an agent, which is what keeps a scan over a large backlog from posting a gate comment on every PR. The managed comment is the answer to an explicit request, so a requested or labeled head that is red or pending still gets its explanation.
  • Workflow runs are read as well as check runs, because a workflow can fail before creating any check run - a workflow-level error, or a pull_request run whose jobs never start. Such a run leaves a failed check suite with no check runs under it, so the commit's check-run rollup and gh pr checks both report success and only the workflow run reveals the red CI. A workflow run whose check suite already reported check runs is left to those runs, so a workflow is never counted twice.
  • Runs attributed to any other (obsolete) head SHA are ignored, so a stale failure cannot block the push that fixed it. This applies to workflow runs too.
  • Only the latest run of each logical check or workflow counts. A logical check is its name plus the reporting app identity, and a logical workflow is its name plus workflow ID. The latest is chosen by the run ID (the reliable creation sequence) with the start time as a tie-break, so a re-run that fixed a check supersedes its earlier failure on the same SHA while a newer queued or in-progress re-run supersedes an earlier success and makes the head wait. Ordering by the run ID keeps a run whose start time is still absent in its true creation position in both directions.

An explicit all-hands-bot review request is the intake-policy exception: the caller asked for that head by name, so the request dispatches even when required CI is red or pending, and the gate leaves no explanatory comment. Draft, scope, exact-head, and delivery-deduplication safeguards still apply. A blocked or waiting scheduled stop consumes no trigger: once the head's required checks are non-blocking, the scheduled scan, or a new all-hands-bot review request, starts the normal review.

The gate needs no configured list of check names. When it stops a review it leaves one concise explanation on the PR, identified by a hidden marker carrying the head SHA and gate category, so a later run for a different head updates that comment instead of posting another. Only a marker this reviewer account authored counts as its own comment; every other PR comment is untrusted and can neither suppress the explanation nor be edited. If the repository's own workflow already posted a deterministic remediation comment that names the same current-head checks, the gate adds nothing; a disclosure about some other check does not suppress it. The gate applies to scheduled label scans; an explicit all-hands-bot review request bypasses it by design.

Each explicit review request - a re-applied trigger label, or a new reviewer request in event mode - is a fresh review. The conversation for a PR is reused, but its earlier turns must not be trusted as current: before deciding a verdict the reviewer re-fetches the mutable GitHub state (the exact head, the PR body, review comments and threads, review requests, the linked issues' bodies and labels, and the current-head Actions results) and ignores any earlier finding, verdict, or label/priority claim that state no longer supports. Repository analysis the conversation already did, such as reading AGENTS.md, stays useful and is not repeated.

The waiting and blocked explanations name the retry the deployment actually has. A scheduled run proves a scan is configured, so it says the next scan will retry. An event-only run does not, so it tells the reader to remove the outstanding all-hands-bot request and request all-hands-bot again instead of promising a scan that does not exist: GitHub will not accept a second request while the first is still outstanding.

The gate leaves only one explanation per head. When the same head keeps the same hidden marker but the retry wording changes -- an event-only comment on a head whose automation is later switched to a cron scan -- the scheduled run rewrites that managed comment in place, so the comment always names the retry that is actually deployed, and an unchanged body is left untouched.

Bounded intake per scheduled scan

A scheduled scan drains outstanding reviewer requests fairly, but starting an agent for every eligible pull request at once would overload the deployment, so the scan starts at most MAX_NEW_PER_RUN new review conversations, counted across every configured repository rather than per repository. The default is 2, and the rendered config.json overrides it through the max_new_per_run key that github-issue-to-pr and gitlab-issue-to-mr already use.

  • Eligible candidates are ordered deterministically: an explicit all-hands-bot request (or a trigger label) is ordered before an unrequested PR, then by the oldest all-hands-bot review_requested event for a requested PR or the PR's own creation time (oldest first) for an unrequested one, then by repository, then by pull-request number, so the oldest work drains first and a later scan reaches the remainder.
  • The bound counts the conversations a scan starts. A delivery that only deduplicates or reports an already-running conversation reuses a runtime and consumes no slot, so repeated scans make progress on the backlog instead of re-spending the bound on work already in flight.
  • Reaching the bound never cuts the scan short. The scan still evaluates the exact-head checks of the remaining candidates, reconciles completed reviews, and runs the maintainer handoff. A candidate whose checks are pending or failing starts no conversation and consumes no slot, so it cannot block a later green candidate. Only an explicit request or a trigger label gets a waiting or blocked gate comment; an unrequested head that is merely red or pending is skipped silently.
  • A dispatch that raises is reported and does not consume a slot or abort the scan, so the candidates behind it are still considered.
  • The explicit review_requested event path and the trigger-label scan are unchanged: an explicit request still starts its conversation immediately, and only the scheduled scan's new conversations are bounded.

The review prompt starts with a scope gate: using the repository's own guidance (its scope categories and ownership boundaries, not a list of individual PR numbers), the reviewer decides whether the change belongs in this repository and has the product/architecture direction it needs. When it does not, the review stops with a single event: COMMENT review that says whether the change should move repositories, close, or receive a maintainer decision, and ends with the 🛑 MAINTAINER DECISION REQUIRED verdict. That outcome is neither an approval nor a change request: it does not approve or merge the PR. The completion handler recognizes the verdict and requests one configured maintainer through the same handoff used after an approval. Both paths require a successfully fetched same-repository closing issue labeled priority:medium or priority:high; a missing link or priority label, low/normal priority, unresolved reference, or PR reference does not authorize handoff. One qualifying issue is sufficient even with other low-priority or missing references. Existing manual review requests are unchanged. An in-scope change continues the existing review unchanged.

Before approving a change to user-visible UI behavior, the prompt requires live evidence from a real running application when the repository's guidance demands it: a screenshot, screen recording, or equivalent capture of the running app that exercises the production-facing path. Unit tests, CSS-token or contract assertions, generated mockups, and reconstructed captures may support the review but cannot substitute for that evidence. When the required evidence is missing, the reviewer publishes one event: COMMENT review naming exactly what is missing and ends with 🔄 CHANGES REQUESTED, so approval is withheld and the deterministic maintainer handoff does not fire. Non-UI changes keep the existing requirement of the real command and its observed output, with tests insufficient as sole proof.

The script prepares each review's workspace before the agent starts: the pull request's head commit is downloaded as a tarball and extracted to a directory of its own, which becomes the conversation's working directory. The agent is told not to clone, fetch, check out, or delete anything, and the script removes the checkout once the conversation has stopped. Nothing accumulates between runs.


The script imports shared GitHub transport from scripts/github_client.py, installed with this skill. Include it beside main.py when packaging manually, as shown below; catalog bundles include it automatically.

Prerequisites

Required secret

Verify that the following secret is set in OpenHands Settings -> Secrets:

Secret nameToken typeMinimum permissions
GITHUB_PERSONAL_ACCESS_TOKENClassic PATrepo for private repos or public_repo for public repos
GITHUB_PERSONAL_ACCESS_TOKENFine-grained PATContents: Read, Metadata: Read, Pull requests: Read and Write, Issues: Read and Write

Pull-request write access is required because the agent publishes a pull request review, not just an issue comment. The Agent Canvas catalog worker may also request a configured human reviewer after approval. A token with only Pull requests: Read will poll happily and then fail at the point of publishing or requesting the handoff.

When several repositories are monitored, the token must cover all of them.

Check with:

bash
curl -s https://api.github.com/user \
  -H "Authorization: Bearer $GITHUB_PERSONAL_ACCESS_TOKEN" \
  | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('login') or d.get('message'))"

If the token is missing or invalid, inform the user and stop.


Setup Workflow

Follow these steps in order.

Show full SKILL.md (1,477 more words)Show less
Step 1 - Verify GITHUB_PERSONAL_ACCESS_TOKEN

Run the curl check above.

  • If absent: "GITHUB_PERSONAL_ACCESS_TOKEN is not set. Please add it in OpenHands Settings -> Secrets." Stop.
  • If the API returns {"message": "Bad credentials"}: tell the user the token is invalid and ask them to update it. Stop.
Step 2 - Collect repositories

Ask: "Which GitHub repositories should be monitored? (Format: owner/repo, e.g. myorg/backend. List several separated by commas to review them all from one automation.)"

Validate access to each repository:

bash
curl -s "https://api.github.com/repos/{owner}/{repo}" \
  -H "Authorization: Bearer $GITHUB_PERSONAL_ACCESS_TOKEN" \
  | python3 -c "
import json, sys
d = json.load(sys.stdin)
if 'message' in d:
    print('ERROR:', d['message'])
else:
    print(f\"Accessible. Private: {d.get('private')}. Permissions: {d.get('permissions')}\")
"

Record every accepted repository into REPOS = ["{owner}/{repo}", ...]. If one repository fails the check, say which and ask whether to continue without it.

Each repository is polled independently and keeps its own state, so pull-request numbers never collide between them. The trigger label, tone, and schedule are shared by all of them; a repository needing different settings wants its own automation.

Step 3 - Collect trigger label

Ask: "Which PR label should trigger a review? (Press Enter for the default: openhands-review.)"

Record the answer as TRIGGER_LABEL. If the label does not exist yet, tell the user that GitHub will still record the event once the label is created and applied to a PR.

The automation reviews a PR when it sees the latest matching labeled event for that label. To request another review later, remove and re-apply the label.

Step 4 - Collect review tone

Ask: *"What review tone should the reviewer use?

  1. Thorough (default) - comprehensive coverage of correctness, security, tests, style
  2. Concise - high-signal only, skips minor style feedback
  3. Friendly - constructive and encouraging (Press Enter for Thorough, or type your choice or any custom style description)"*

Map the choice to REVIEW_TONE:

AnswerREVIEW_TONEREVIEW_STYLE_INSTRUCTIONS
1 / Enter"thorough"""
2"concise"""
3"friendly"""
Custom text, e.g. strict but kind"thorough"the custom text verbatim
Step 5 - Collect cron schedule

Ask: "How often should the automation poll for labeled PRs? (Press Enter for the default: every 5 minutes. Use a cron expression for a different interval, e.g. 0 * * * * = hourly)"

Default: */5 * * * *.

Record as CRON_SCHEDULE.

Step 6 - Generate the automation script

Read scripts/main.py from this skill's directory. Apply exactly seven constant substitutions near the top of the file:

The script also reads a config.json shipped beside it, if there is one, over these constants. That is how the catalog entry (automations/catalog/github-pr-reviewer/) configures an unmodified copy, since a declarative host cannot rewrite Python. This setup path substitutes the constants and ships no config.json, so the two never collide.

PlaceholderReplace with
REPOS = ["owner/repo"]REPOS = ["{owner_repo}", ...] - one entry per repository collected in Step 2
TRIGGER_LABEL = "openhands-review"TRIGGER_LABEL = "{trigger_label}"
REVIEW_TONE = "thorough"REVIEW_TONE = "{review_tone}"
REVIEW_STYLE_INSTRUCTIONS = ""REVIEW_STYLE_INSTRUCTIONS = "{style_instructions}"
REPO_REVIEW_GUIDE_PATH = ".agents/skills/custom-codereview-guide.md"leave unchanged to auto-load a repo review guide at this path, or set to "" to disable
MAX_NEW_PER_RUN = 2leave unchanged to bound a scheduled scan to two new review conversations across all repositories, or raise it if the deployment can hold more agents at once
DEFAULT_OPENHANDS_URL = "http://localhost:8000"leave unchanged unless the user has a preference

Use a safe string writer such as json.dumps(value) when inserting user-provided repository names, labels, or style instructions into Python string literals. json.dumps(list_of_repos) produces the whole REPOS list safely in one step.

Run these commands from this skill's directory and write the customized script to a temporary build directory:

bash
mkdir -p /tmp/pr-reviewer-build
cp -L scripts/github_client.py /tmp/pr-reviewer-build/github_client.py
# write the customized main.py to /tmp/pr-reviewer-build/main.py

Validate syntax before packaging:

bash
python3 -m py_compile /tmp/pr-reviewer-build/main.py && echo "Syntax OK"

Fix any syntax errors before proceeding.

Step 7 - Package and upload

Determine the Automation backend URL and auth from the <RUNTIME_SERVICES> block in your system context:

  • OPENHANDS_HOST: the Automation backend url_from_agent
  • Auth: X-Session-API-Key: $OPENHANDS_AUTOMATION_API_KEY
bash
tar -czf /tmp/pr-reviewer.tar.gz -C /tmp/pr-reviewer-build .

TARBALL_PATH=$(curl -s -X POST \
  "${OPENHANDS_HOST}/api/automation/v1/uploads?name=github-pr-reviewer" \
  -H "X-Session-API-Key: $OPENHANDS_AUTOMATION_API_KEY" \
  -H "Content-Type: application/gzip" \
  --data-binary @/tmp/pr-reviewer.tar.gz \
  | python3 -c "import json,sys; print(json.load(sys.stdin)['tarball_path'])")

echo "Uploaded: $TARBALL_PATH"
Step 8 - Register the automation
bash
curl -s -X POST "${OPENHANDS_HOST}/api/automation/v1" \
  -H "X-Session-API-Key: $OPENHANDS_AUTOMATION_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"name\": \"GitHub PR Reviewer: {repo_summary} label {trigger_label}\",
    \"trigger\": {\"type\": \"cron\", \"schedule\": \"{cron_schedule}\"},
    \"tarball_path\": \"$TARBALL_PATH\",
    \"entrypoint\": \"python3 main.py\",
    \"timeout\": 600
  }" | python3 -m json.tool

Use the single repository as {repo_summary} when there is one, and something like 3 repos when there are several. A poll now downloads a tarball per queued review, so the timeout allows for that; a run never waits for a review to finish, only for it to be started.

Record the returned id.

Step 9 - Confirm

Tell the user:

✅ GitHub PR Reviewer is running!

  • Automation ID: {id}
  • Repositories: {owner}/{repo}, ... (one line each)
  • Trigger label: {trigger_label}
  • Review tone: {tone}
  • Polling schedule: {cron_schedule}
  • State file per repository: ~/.openhands/workspaces/automation-state/github_pr_reviewer_label_event_{id}_{owner}__{repo}.json

Apply the {trigger_label} label to a pull request to queue a review. Each label event is processed once. To request another review, remove and re-apply the label.

The review is published as a pull request review on the head commit, with inline comments where a finding maps to a changed line.


Runtime Behaviour (per poll)

Each cron run executes main.py, which resolves and validates GITHUB_PERSONAL_ACCESS_TOKEN once, then processes every repository in REPOS independently. One repository failing does not stop the others; the run fails only if every repository fails.

For each repository:

  1. Loads that repository's state (see references/state-schema.md).
  2. Verifies repository access.
  3. Lists open PRs, newest-updated first.
  4. For each open PR carrying TRIGGER_LABEL:
    • Refetches current PR metadata to avoid acting on stale list data.
    • Finds the latest matching GitHub labeled issue event.
    • Skips the event if it has already been tracked.
    • Downloads the PR's head commit as a tarball and extracts it to {WORKSPACE_BASE}/repositories/{owner}__{repo}/pr-{number}-{sha12}. The archive is checked as it is unpacked: a single root, no absolute or .. paths, and symlinks skipped rather than materialised.
    • Starts an OpenHands conversation whose working directory is that checkout, with a review prompt carrying PR metadata, the exact head SHA, label event details, and the requirement to re-fetch the current mutable GitHub state before deciding a verdict.
    • Posts an acknowledgement comment with the label event, head SHA, and conversation link.
    • Records the review in state with status: "active" and the checkout path.
    • If the checkout or the conversation cannot be created, the checkout is removed and nothing is recorded, so the next poll retries the label event.
  5. For each active review conversation:
    • Marks it closed without posting if the PR has closed or merged.
    • Suppresses stale results if the PR head SHA changed after the review was queued.
    • When the conversation reaches idle, finished, error, or stuck, asks GitHub whether a review by the token's own user exists for that head SHA. If it does, the review is complete. If it does not, the agent's final response is posted as a comment so the work is not lost.
    • Abandons a conversation that has not reached a terminal status within two hours, so its checkout can be reclaimed.
  6. Removes the checkout of every finished review, but only after confirming the conversation has stopped - deleting it under a running agent would remove its working directory. When that cannot be confirmed the directory is left alone and the next poll tries again.
  7. Saves that repository's state atomically.

The completion callback fires once for the whole run.


Additional Resources

  • references/state-schema.md - State JSON schema, field definitions, and review lifecycle diagram.
  • scripts/main.py - The complete automation script. Customize the five constants at the top before packaging.
  • tests/test_main.py - Unit tests for the checkout, its removal, and state handling. Run them from the skill root with python -m pytest tests/ after editing the script.

Troubleshooting

SymptomLikely causeFix
Bot never queues reviewsTrigger label not present or no matching labeled eventApply the configured label to the PR
"Bad credentials" in run logsToken expiredRotate and update GITHUB_PERSONAL_ACCESS_TOKEN
404 on repo accessRepo name wrong or no accessRe-check the entry in REPOS and the token's permissions
One repository is skipped, others workThat repository failed its access checkRead the === owner/repo === block in the run log
Same PR not reviewed after new commitsLabel event was already processedRemove and re-apply the trigger label
Review paused with a failing-check commentA current-head required check reported failure, cancelled, or timed_outFix the named checks and push; the review starts on the new head, or request all-hands-bot to review immediately
Review reported waiting on checksA current-head required check is queued or in_progress, or has not reported yetNo action; a later scan or a new review request retries
Optional workflow failed but no review was pausedThe failed workflow is not required, so the required-only scheduled gate ignored itNo action; only GitHub-required checks gate scheduled discovery
Only a few reviews start on a large backlogThe per-scan max_new_per_run bound (default 2) reachedNo action; later scans drain the remaining oldest eligible PRs, or raise max_new_per_run if the deployment can hold more agents
Review result never postsConversation still running or stuckOpen the conversation link from the acknowledgement comment
Stale review suppressedPR head SHA changed while the agent was reviewingRe-apply the trigger label after the latest commit
Review arrives as a plain comment, not a reviewPublishing failed, so the script posted the text as a fallbackCheck that the token has Pull requests: Read and Write
Agent reports it cannot clone the repoPrompt asked it not to; the workspace is already the checkoutNo action - the code is at the head SHA in its working directory
Checkouts remain under repositories/Their conversations had not stopped yetThey are removed by a later poll once the conversation is terminal

© OpenHands, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 14 other files (scripts, references) in skills/github-pr-reviewer of OpenHands/extensions.

  • SKILL.md
  • .claude-plugin
  • .codex-plugin
  • .plugin/plugin.json
  • README.md
  • commands/pr-reviewer-setup.md
  • references/state-schema.md
  • references/windows.md
  • scripts/agent_conversation.py
  • scripts/github_client.py
  • scripts/main.py
  • scripts/maintainer_handoff.py
  • scripts/publication.py
  • scripts/worker.py
  • tests/test_main.py

Open the folder on GitHubat commit d008b81

Compare with similar skills

GitHub PR Reviewer next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

GitHub PR Reviewer compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
GitHub PR Reviewer this skillOpenHands/extensions157—~6.8kAutomated safety check: PassMIT
PR Babysitteropeninterpreter/openinterpreter69k3 repos~4.2kAutomated safety check: PassApache-2.0
Check PRonyx-dot-app/onyx32k2 repos~2.3kAutomated safety check: PassMIT
Contributor-First PR MergeHKUDS/OpenHarness16k1 repos~847Automated safety check: PassMIT
Create Pull Requestcline/cline70k1 repos~1.6kAutomated safety check: PassApache-2.0
Pull Request Title and Body Writeropeninterpreter/openinterpreter69k2 repos~1.1kAutomated safety check: PassApache-2.0

Similar skills

  • PR Babysitter

    openinterpreter/openinterpreter

    Watches an open GitHub pull request until it merges, handling review comments, diagnosing CI failures and retrying flaky checks along the way.

    69k GitHub starsUsed in 3 repos~4.2k tokens
    DevelopmentAuto-check passed
  • Check PR

    onyx-dot-app/onyx

    Checks a GitHub, GitLab, or Perforce (p4) pull request (or merge request, or shelved changelist) for unresolved review comments, failing status checks, and incomplete PR descriptions.

    32k GitHub starsUsed in 2 repos~2.3k tokens
    DevelopmentAuto-check passed
  • Merges external GitHub pull requests while keeping the original author credited, and fixes conflicts after the merge instead of rewriting the contribution.

    16k GitHub starsUsed in 1 repo~847 tokens
    DevelopmentAuto-check passed
  • Opens a GitHub pull request from your current branch with the gh CLI, after reviewing the commits and diff and gathering the details the PR needs.

    70k GitHub starsUsed in 1 repo~1.6k tokens
    DevelopmentAuto-check passed
  • Pull Request Title and Body Writer

    openinterpreter/openinterpreter

    Rewrites the title and body of one or more pull requests with gh, leading with why the change was made, then what changed, and describing only the net result.

    69k GitHub starsUsed in 2 repos~1.1k tokens
    DevelopmentAuto-check passed
  • Official

    Runs a loop on a GitHub pull request: fetch review state, triage comments into actions, implement them and resolve threads, repeating until nothing actionable is left.

    48k GitHub stars~2.2k tokensUpdated today
    DevelopmentAuto-check passed

More from OpenHands/extensions

All 78 skills in this repo
  • Agent Readiness Report

    OpenHands/extensions

    Evaluate how well a codebase supports autonomous AI-assisted development.

    157 GitHub stars~1.1k tokensUpdated today
    Auto-check passed
  • Discord

    OpenHands/extensions

    Build and automate Discord integrations (bots, webhooks, slash commands, and REST API workflows).

    157 GitHub stars~1.1k tokensUpdated today
    Auto-check passed
  • GitHub

    OpenHands/extensions

    Interact with GitHub repositories, pull requests, issues, and workflows using the GITHUBTOKEN environment variable and GitHub CLI.

    157 GitHub stars~1.7k tokensUpdated today
    Auto-check passed
  • GitHub Issue To PR

    OpenHands/extensions

    Create an automation that implements GitHub issues when a configurable trigger label is applied.

    157 GitHub stars~4.4k tokensUpdated today
    Auto-check passed
  • GitHub Repo Monitor

    OpenHands/extensions

    This skill should be used when the user asks to "monitor a GitHub repository", "watch GitHub for issues or PRs", "respond to @OpenHands mentions on GitHub", "set up an OpenHands GitHub integration"…

    157 GitHub stars~3.1k tokensUpdated today
    Auto-check passed
  • GitLab Issue To Mr

    OpenHands/extensions

    Create an automation that implements GitLab issues when a configurable trigger label is applied.

    157 GitHub stars~4.9k tokensUpdated today
    Auto-check passed

Works with

Categories

Questions about GitHub PR Reviewer

What does GitHub PR Reviewer do?

Create an automation that reviews GitHub pull requests when a configured reviewer is requested or a trigger label is applied. GitHub PR Reviewer is an agent skill from OpenHands/extensions. Create an automation that reviews GitHub pull requests when a configured reviewer is requested or a trigger label is applied.

When should I use GitHub PR Reviewer?

GitHub PR Reviewer fits situations like: label is applied; tasks that involve Pull requests.

How do I install GitHub PR Reviewer in Claude Code?

Run `npx skills add OpenHands/extensions --skill github-pr-reviewer -a claude-code`. Or copy the skill folder (skills/github-pr-reviewer in OpenHands/extensions) into .claude/skills/github-pr-reviewer in your project. Claude Code loads it when a task matches its description.

How do I install GitHub PR Reviewer in Codex?

Run `npx skills add OpenHands/extensions --skill github-pr-reviewer -a codex`. Or copy the skill folder (skills/github-pr-reviewer in OpenHands/extensions) into .agents/skills/github-pr-reviewer in your project. Codex loads it when a task matches its description.

Can I use GitHub PR Reviewer in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add OpenHands/extensions --skill github-pr-reviewer -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/github-pr-reviewer, .gemini/skills/github-pr-reviewer, .github/skills/github-pr-reviewer and .opencode/skills/github-pr-reviewer in your project.

What does GitHub PR Reviewer need to run?

Going by SKILL.md and its folder, GitHub PR Reviewer needs Python for the scripts in its folder, the command-line tools its instructions call (python3, curl, gh and python) and credentials named GITHUB_PERSONAL_ACCESS_TOKEN and OPENHANDS_AUTOMATION_API_KEY. Our summary lists: Python 3.

Does GitHub PR Reviewer access the network?

SKILL.md names 1 domain. In commands or code: api.github.com; the agent is likely to contact it when it follows the instructions. This is read from the text; nothing was executed.

Is GitHub PR Reviewer safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. The check reads SKILL.md only: the scripts in the folder are not scanned, so read them before running anything.

What licence does GitHub PR Reviewer use?

GitHub PR Reviewer is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does GitHub PR Reviewer use?

About 6.8k tokens (SKILL.md is roughly 27k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 2k tokens, read only when the agent opens those files.

What are the alternatives to GitHub PR Reviewer?

Skills that share tags, products or a category with GitHub PR Reviewer: PR Babysitter (openinterpreter/openinterpreter, 69k stars), Check PR (onyx-dot-app/onyx, 32k stars), Contributor-First PR Merge (HKUDS/OpenHarness, 16k stars) and Create Pull Request (cline/cline, 70k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains GitHub PR Reviewer?

OpenHands (a GitHub organization) maintains it in OpenHands/extensions, which has 157 GitHub stars. The repository holds 78 skills in this directory. The repository was last updated on October 6, 2026.

Source: OpenHands/extensions on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.