Loading...
Loading...
Fetch GitHub issues, spawn sub-agents to implement fixes and open PRs, then monitor and address PR review comments. Usage: /gh-issues [owner/repo] [--label bug] [--limit 5] [--milestone v1.0] [--assignee @me] [--fork user/repo] [--watch] [--interval 5] [--reviews-only] [--cron] [--dry-run] [--model glm-5] [--notify-channel -1002381931352]
npx skill4agent add steipete/clawdis gh-issuesghcurl -s -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" ...git remote get-url origin| Flag | Default | Description |
|---|---|---|
| --label | (none) | Filter by label (e.g. bug, |
| --limit | 10 | Max issues to fetch per poll |
| --milestone | (none) | Filter by milestone title |
| --assignee | (none) | Filter by assignee ( |
| --state | open | Issue state: open, closed, all |
| --fork | (none) | Your fork ( |
| --watch | false | Keep polling for new issues and PR reviews after each batch |
| --interval | 5 | Minutes between polls (only with |
| --dry-run | false | Fetch and display only — no sub-agents |
| --yes | false | Skip confirmation and auto-process all filtered issues |
| --reviews-only | false | Skip issue processing (Phases 2-5). Only run Phase 6 — check open PRs for review comments and address them. |
| --cron | false | Cron-safe mode: fetch issues and spawn sub-agents, exit without waiting for results. |
| --model | (none) | Model to use for sub-agents (e.g. |
| --notify-channel | (none) | Telegram channel ID to send final PR summary to (e.g. -1002381931352). Only the final result with PR links is sent, not status updates. |
--reviews-only--cron--yes--reviews-onlyecho $GH_TOKENcat ~/.openclaw/openclaw.json | jq -r '.skills.entries["gh-issues"].apiKey // empty'/data/.clawdbot/openclaw.jsoncat /data/.clawdbot/openclaw.json | jq -r '.skills.entries["gh-issues"].apiKey // empty'export GH_TOKEN="<token>"curl -s -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/{SOURCE_REPO}/issues?per_page={limit}&state={state}&{query_params}"GET /user"GitHub authentication failed. Please check your apiKey in the OpenClaw dashboard or in ~/.openclaw/openclaw.json under skills.entries.gh-issues."
| # | Title | Labels |
|---|---|---|
| 42 | Fix null pointer in parser | bug, critical |
| 37 | Add retry logic for API calls | enhancement |
"Fork mode: branches will be pushed to {PUSH_REPO}, PRs will target"{SOURCE_REPO}
--dry-run--yes42, 37git status --porcelain"Working tree has uncommitted changes. Sub-agents will create branches from HEAD — uncommitted changes will NOT be included. Continue?" Wait for confirmation. If declined, stop.
git rev-parse --abbrev-ref HEADforkgit remote get-url forkgit remote add fork https://x-access-token:$GH_TOKEN@github.com/{PUSH_REPO}.gitgit ls-remote --exit-code origin HEADgit ls-remote --exit-code origin HEADcurl -s -o /dev/null -w "%{http_code}" -H "Authorization: Bearer $GH_TOKEN" https://api.github.com/user"GitHub authentication failed. Please check your apiKey in the OpenClaw dashboard or in ~/.openclaw/openclaw.json under skills.entries.gh-issues."
curl -s -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/{SOURCE_REPO}/pulls?head={PUSH_REPO_OWNER}:fix/issue-{N}&state=open&per_page=1"PUSH_REPO"Skipping #{N} — PR already exists: {html_url}"
fix/issue-{N}curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer $GH_TOKEN" \
"https://api.github.com/repos/{PUSH_REPO}/branches/fix/issue-{N}""Skipping #{N} — branch fix/issue-{N} exists on {PUSH_REPO}, fix likely in progress"
git ls-remote{}CLAIMS_FILE="/data/.clawdbot/gh-issues-claims.json"
if [ ! -f "$CLAIMS_FILE" ]; then
mkdir -p /data/.clawdbot
echo '{}' > "$CLAIMS_FILE"
fiCLAIMS=$(cat "$CLAIMS_FILE")
CUTOFF=$(date -u -d '2 hours ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-2H +%Y-%m-%dT%H:%M:%SZ)
CLAIMS=$(echo "$CLAIMS" | jq --arg cutoff "$CUTOFF" 'to_entries | map(select(.value > $cutoff)) | from_entries')
echo "$CLAIMS" > "$CLAIMS_FILE"{SOURCE_REPO}#{N}"Skipping #{N} — sub-agent claimed this issue {minutes}m ago, still within timeout window"
{minutes}--cronCURSOR_FILE="/data/.clawdbot/gh-issues-cursor-{SOURCE_REPO_SLUG}.json"
# SOURCE_REPO_SLUG = owner-repo with slashes replaced by hyphens (e.g., openclaw-openclaw)if [ ! -f "$CURSOR_FILE" ]; then
echo '{"last_processed": null, "in_progress": null}' > "$CURSOR_FILE"
filast_processedin_progresscleanup: "keep"runTimeoutSeconds: 3600--modelmodel: "{MODEL}"--notify-channel{SOURCE_REPO}#{N}--cronsubagents.maxConcurrent: 8{SOURCE_REPO}#{N}forkorigin--notify-channelYou are a focused code-fix agent. Your task is to fix a single GitHub issue and open a PR.
IMPORTANT: Do NOT use the gh CLI — it is not installed. Use curl with the GitHub REST API for all GitHub operations.
First, ensure GH_TOKEN is set. Check: `echo $GH_TOKEN`. If empty, read from config:
GH_TOKEN=$(cat ~/.openclaw/openclaw.json 2>/dev/null | jq -r '.skills.entries["gh-issues"].apiKey // empty') || GH_TOKEN=$(cat /data/.clawdbot/openclaw.json 2>/dev/null | jq -r '.skills.entries["gh-issues"].apiKey // empty')
Use the token in all GitHub API calls:
curl -s -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" ...
<config>
Source repo (issues): {SOURCE_REPO}
Push repo (branches + PRs): {PUSH_REPO}
Fork mode: {FORK_MODE}
Push remote name: {PUSH_REMOTE}
Base branch: {BASE_BRANCH}
Notify channel: {notify_channel}
</config>
<issue>
Repository: {SOURCE_REPO}
Issue: #{number}
Title: {title}
URL: {url}
Labels: {labels}
Body: {body}
</issue>
<instructions>
Follow these steps in order. If any step fails, report the failure and stop.
0. SETUP — Ensure GH_TOKEN is available:If that fails, also try:Verify: echo "Token: ${GH_TOKEN:0:10}..."
1. CONFIDENCE CHECK — Before implementing, assess whether this issue is actionable:
- Read the issue body carefully. Is the problem clearly described?
- Search the codebase (grep/find) for the relevant code. Can you locate it?
- Is the scope reasonable? (single file/function = good, whole subsystem = bad)
- Is a specific fix suggested or is it a vague complaint?
Rate your confidence (1-10). If confidence < 7, STOP and report:
> "Skipping #{number}: Low confidence (score: N/10) — [reason: vague requirements | cannot locate code | scope too large | no clear fix suggested]"
Only proceed if confidence >= 7.
1. UNDERSTAND — Read the issue carefully. Identify what needs to change and where.
2. BRANCH — Create a feature branch from the base branch:
git checkout -b fix/issue-{number} {BASE_BRANCH}
3. ANALYZE — Search the codebase to find relevant files:
- Use grep/find via exec to locate code related to the issue
- Read the relevant files to understand the current behavior
- Identify the root cause
4. IMPLEMENT — Make the minimal, focused fix:
- Follow existing code style and conventions
- Change only what is necessary to fix the issue
- Do not add unrelated changes or new dependencies without justification
5. TEST — Discover and run the existing test suite if one exists:
- Look for package.json scripts, Makefile targets, pytest, cargo test, etc.
- Run the relevant tests
- If tests fail after your fix, attempt ONE retry with a corrected approach
- If tests still fail, report the failure
6. COMMIT — Stage and commit your changes:
git add {changed_files}
git commit -m "fix: {short_description}
Fixes {SOURCE_REPO}#{number}"
7. PUSH — Push the branch:
First, ensure the push remote uses token auth and disable credential helpers:
git config --global credential.helper ""
git remote set-url {PUSH_REMOTE} https://x-access-token:$GH_TOKEN@github.com/{PUSH_REPO}.git
Then push:
GIT_ASKPASS=true git push -u {PUSH_REMOTE} fix/issue-{number}
8. PR — Create a pull request using the GitHub API:
If FORK_MODE is true, the PR goes from your fork to the source repo:
- head = "{PUSH_REPO_OWNER}:fix/issue-{number}"
- base = "{BASE_BRANCH}"
- PR is created on {SOURCE_REPO}
If FORK_MODE is false:
- head = "fix/issue-{number}"
- base = "{BASE_BRANCH}"
- PR is created on {SOURCE_REPO}
curl -s -X POST \
-H "Authorization: Bearer $GH_TOKEN" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/repos/{SOURCE_REPO}/pulls \
-d '{
"title": "fix: {title}",
"head": "{head_value}",
"base": "{BASE_BRANCH}",
"body": "## Summary\n\n{one_paragraph_description_of_fix}\n\n## Changes\n\n{bullet_list_of_changes}\n\n## Testing\n\n{what_was_tested_and_results}\n\nFixes {SOURCE_REPO}#{number}"
}'
Extract the `html_url` from the response — this is the PR link.
9. REPORT — Send back a summary:
- PR URL (the html_url from step 8)
- Files changed (list)
- Fix summary (1-2 sentences)
- Any caveats or concerns
10. NOTIFY (if notify_channel is set) — If {notify_channel} is not empty, send a notification to the Telegram channel:</instructions>
<constraints>
- No force-push, no modifying the base branch
- No unrelated changes or gratuitous refactoring
- No new dependencies without strong justification
- If the issue is unclear or too complex to fix confidently, report your analysis instead of guessing
- Do NOT use the gh CLI — it is not available. Use curl + GitHub REST API for all GitHub operations.
- GH_TOKEN is already in the environment — do NOT prompt for auth
- Time limit: you have 60 minutes max. Be thorough — analyze properly, test your fix, don't rush.
</constraints>--modelmodel: "{MODEL}""#{N} — Timed out (issue may be too complex for auto-fix)"
--cronOPEN_PRS| Issue | Status | PR | Notes |
|---|---|---|---|
| #42 Fix null pointer | PR opened | https://github.com/.../pull/99 | 3 files changed |
| #37 Add retry logic | Failed | -- | Could not identify target code |
| #15 Update docs | Timed out | -- | Too complex for auto-fix |
| #8 Fix race condition | Skipped | -- | PR already exists |
"Processed {N} issues: {success} PRs opened, {failed} failed, {skipped} skipped."
--notify-channelmessageUse the message tool with:
- action: "send"
- channel: "telegram"
- target: "{notify-channel}"
- message: "✅ GitHub Issues Processed
Processed {N} issues: {success} PRs opened, {failed} failed, {skipped} skipped.
{PR_LIST}"
Where PR_LIST includes only successfully opened PRs in format:
• #{issue_number}: {PR_url} ({notes})fix/issue-*--reviews-only--cron --reviews-only--cron--reviews-onlyfix/issue-*cleanup: "keep"runTimeoutSeconds: 3600--modelmodel: "{MODEL}"OPEN_PRS--reviews-onlyfix/issue-curl -s -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/{SOURCE_REPO}/pulls?state=open&per_page=100"head.reffix/issue-numberhead.refhtml_urltitlebodycurl -s -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/{SOURCE_REPO}/pulls/{pr_number}/reviews"curl -s -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/{SOURCE_REPO}/pulls/{pr_number}/comments"curl -s -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/{SOURCE_REPO}/issues/{pr_number}/comments"<!-- greptile_comment -->curl -s -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/{SOURCE_REPO}/pulls/{pr_number}"bodycurl -s -H "Authorization: Bearer $GH_TOKEN" https://api.github.com/user | jq -r '.login'BOT_USERNAMEuser.loginBOT_USERNAMEAPPROVEDCHANGES_REQUESTEDCOMMENTED<!-- greptile_comment -->| PR | Branch | Actionable Comments | Sources |
|----|--------|---------------------|---------|
| #99 | fix/issue-42 | 2 comments | @reviewer1, greptile |
| #101 | fix/issue-37 | 1 comment | @reviewer2 |--yesYou are a PR review handler agent. Your task is to address review comments on a pull request by making the requested changes, pushing updates, and replying to each comment.
IMPORTANT: Do NOT use the gh CLI — it is not installed. Use curl with the GitHub REST API for all GitHub operations.
First, ensure GH_TOKEN is set. Check: echo $GH_TOKEN. If empty, read from config:
GH_TOKEN=$(cat ~/.openclaw/openclaw.json 2>/dev/null | jq -r '.skills.entries["gh-issues"].apiKey // empty') || GH_TOKEN=$(cat /data/.clawdbot/openclaw.json 2>/dev/null | jq -r '.skills.entries["gh-issues"].apiKey // empty')
<config>
Repository: {SOURCE_REPO}
Push repo: {PUSH_REPO}
Fork mode: {FORK_MODE}
Push remote: {PUSH_REMOTE}
PR number: {pr_number}
PR URL: {pr_url}
Branch: {branch_name}
</config>
<review_comments>
{json_array_of_actionable_comments}
Each comment has:
- id: comment ID (for replying)
- user: who left it
- body: the comment text
- path: file path (for inline comments)
- line: line number (for inline comments)
- diff_hunk: surrounding diff context (for inline comments)
- source: where the comment came from (review, inline, pr_body, greptile, etc.)
</review_comments>
<instructions>
Follow these steps in order:
0. SETUP — Ensure GH_TOKEN is available:Verify: echo "Token: ${GH_TOKEN:0:10}..."
1. CHECKOUT — Switch to the PR branch:
git fetch {PUSH_REMOTE} {branch_name}
git checkout {branch_name}
git pull {PUSH_REMOTE} {branch_name}
2. UNDERSTAND — Read ALL review comments carefully. Group them by file. Understand what each reviewer is asking for.
3. IMPLEMENT — For each comment, make the requested change:
- Read the file and locate the relevant code
- Make the change the reviewer requested
- If the comment is vague or you disagree, still attempt a reasonable fix but note your concern
- If the comment asks for something impossible or contradictory, skip it and explain why in your reply
4. TEST — Run existing tests to make sure your changes don't break anything:
- If tests fail, fix the issue or revert the problematic change
- Note any test failures in your replies
5. COMMIT — Stage and commit all changes in a single commit:
git add {changed_files}
git commit -m "fix: address review comments on PR #{pr_number}
Addresses review feedback from {reviewer_names}"
6. PUSH — Push the updated branch:
git config --global credential.helper ""
git remote set-url {PUSH_REMOTE} https://x-access-token:$GH_TOKEN@github.com/{PUSH_REPO}.git
GIT_ASKPASS=true git push {PUSH_REMOTE} {branch_name}
7. REPLY — For each addressed comment, post a reply:
For inline review comments (have a path/line), reply to the comment thread:
curl -s -X POST \
-H "Authorization: Bearer $GH_TOKEN" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/repos/{SOURCE_REPO}/pulls/{pr_number}/comments/{comment_id}/replies \
-d '{"body": "Addressed in commit {short_sha} — {brief_description_of_change}"}'
For general PR comments (issue comments), reply on the PR:
curl -s -X POST \
-H "Authorization: Bearer $GH_TOKEN" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/repos/{SOURCE_REPO}/issues/{pr_number}/comments \
-d '{"body": "Addressed feedback from @{reviewer}:\n\n{summary_of_changes_made}\n\nUpdated in commit {short_sha}"}'
For comments you could NOT address, reply explaining why:
"Unable to address this comment: {reason}. This may need manual review."
8. REPORT — Send back a summary:
- PR URL
- Number of comments addressed vs skipped
- Commit SHA
- Files changed
- Any comments that need manual attention
</instructions>
<constraints>
- Only modify files relevant to the review comments
- Do not make unrelated changes
- Do not force-push — always regular push
- If a comment contradicts another comment, address the most recent one and flag the conflict
- Do NOT use the gh CLI — use curl + GitHub REST API
- GH_TOKEN is already in the environment — do not prompt for auth
- Time limit: 60 minutes max
</constraints>--modelmodel: "{MODEL}"| PR | Comments Addressed | Comments Skipped | Commit | Status |
|----|-------------------|-----------------|--------|--------|
| #99 fix/issue-42 | 3 | 0 | abc123f | All addressed |
| #101 fix/issue-37 | 1 | 1 | def456a | 1 needs manual review |ADDRESSED_COMMENTS"Next poll in {interval} minutes... (say 'stop' to end watch mode)"