Use when managing PR review threads. Reply does NOT auto-resolve threads. Trigger with /manage-threads.
npx claudepluginhub emasoft/emasoft-plugins --plugin emasoft-integrator-agentThis skill uses the workspace's default tool permissions.
This skill teaches you how to manage GitHub Pull Request review threads. Review threads are conversation containers attached to specific lines of code in a PR diff.
README.mdreferences/thread-conversation-tracking.mdreferences/thread-resolution-protocol.mdscripts/__pycache__/atlas_get_review_threads.cpython-314.pycscripts/__pycache__/atlas_get_thread_by_id.cpython-314.pycscripts/__pycache__/atlas_get_unaddressed_comments.cpython-314.pycscripts/__pycache__/atlas_reply_to_thread.cpython-314.pycscripts/__pycache__/atlas_resolve_thread.cpython-314.pycscripts/__pycache__/atlas_resolve_threads_batch.cpython-314.pycscripts/__pycache__/atlas_unresolve_thread.cpython-314.pycscripts/eia_get_review_threads.pyscripts/eia_get_thread_by_id.pyscripts/eia_get_unaddressed_comments.pyscripts/eia_reply_to_thread.pyscripts/eia_resolve_thread.pyscripts/eia_resolve_threads_batch.pyscripts/eia_unresolve_thread.pyFetches GitHub PR review comments via gh CLI and Python script, creates task checklists for threads, links commits to reviews, and blocks completion until all resolved. Use for systematic PR feedback handling.
Addresses GitHub PR review feedback systematically: fetches inline comments and review bodies, handles outside-diff-range comments, triages by priority, resolves threads with attribution.
Triages unresolved GitHub PR review threads via webform, summarizes reviewer feedback, and dispatches fixes through whip-start. Use after receiving PR reviews.
Share bugs, ideas, or general feedback.
This skill teaches you how to manage GitHub Pull Request review threads. Review threads are conversation containers attached to specific lines of code in a PR diff.
CRITICAL UNDERSTANDING: Replying to a review thread does NOT automatically resolve it. Resolution is a separate GraphQL mutation that must be explicitly called. Many developers assume replying resolves threads - this is incorrect.
gh) installed and authenticatedFollow these steps when managing GitHub PR review threads:
eia_get_review_threads.py --unresolved-only to list all unresolved threads on the PRsuccess field and verify the thread state changed as expectedCopy this checklist and track your progress:
eia_get_review_threads.py --unresolved-onlyeia_resolve_threads_batch.pyeia_get_unaddressed_comments.pyAll scripts in this skill output JSON to stdout with the following standard structure:
| Field | Type | Description |
|---|---|---|
success | boolean | Whether the operation completed successfully |
threadId | string | The GraphQL node ID of the affected thread (PRRT_xxx format) |
isResolved | boolean | Current resolution state of the thread after operation |
commentId | string | (Reply operations only) The GraphQL node ID of the created comment |
results | array | (Batch operations only) Array of per-thread success/failure details |
error | string | (On failure) Human-readable error message explaining what went wrong |
See the Script Usage Details section for script-specific output format variations.
START: You need to handle a review thread
│
├─► Q: Has the requested change been implemented?
│ │
│ ├─► YES: Do you need to explain what was done?
│ │ │
│ │ ├─► YES: Reply THEN Resolve (two operations)
│ │ │ See: scripts/eia_reply_to_thread.py --and-resolve
│ │ │
│ │ └─► NO: Just Resolve (no reply needed)
│ │ See: scripts/eia_resolve_thread.py
│ │
│ └─► NO: Is clarification needed from the reviewer?
│ │
│ ├─► YES: Reply only (keep thread OPEN)
│ │ See: scripts/eia_reply_to_thread.py (without --and-resolve)
│ │
│ └─► NO: Leave thread untouched until you address it
│
├─► Q: Do you need to resolve MULTIPLE threads at once?
│ │
│ └─► YES: Use batch resolution (1 API call for N threads)
│ See: scripts/eia_resolve_threads_batch.py
│
└─► Q: Do you need to find threads that still need attention?
│
├─► Find all unresolved threads:
│ See: scripts/eia_get_review_threads.py --unresolved-only
│
└─► Find comments without any replies:
See: scripts/eia_get_unaddressed_comments.py
| State | Meaning | When to Use |
|---|---|---|
| Unresolved | Thread requires attention | Default state, indicates pending work |
| Resolved | Thread has been addressed | After implementing requested change |
GitHub's API separates these operations because:
You might reply without resolving (asking for clarification), or resolve without replying (when the code change speaks for itself).
See references/thread-resolution-protocol.md
Contents:
See references/thread-conversation-tracking.md
Contents:
All scripts are located in the scripts/ subdirectory and output JSON to stdout.
| Script | Purpose | Key Parameters |
|---|---|---|
eia_get_review_threads.py | List all review threads on a PR | --owner, --repo, --pr, --unresolved-only |
eia_resolve_thread.py | Resolve a single thread | --thread-id |
eia_resolve_threads_batch.py | Resolve multiple threads (1 API call) | --thread-ids (comma-separated) |
eia_reply_to_thread.py | Reply to a thread | --thread-id, --body, --and-resolve |
eia_get_unaddressed_comments.py | Find comments without replies | --owner, --repo, --pr |
# Step 1: Get all unresolved threads
python3 scripts/eia_get_review_threads.py --owner OWNER --repo REPO --pr 123 --unresolved-only
# Step 2: For each thread, make the code change, then resolve
python3 scripts/eia_resolve_thread.py --thread-id PRRT_xxxxx
# When you want to explain what you did AND resolve
python3 scripts/eia_reply_to_thread.py \
--thread-id PRRT_xxxxx \
--body "Fixed by using the recommended approach" \
--and-resolve
# When you've addressed multiple comments in one commit
python3 scripts/eia_resolve_threads_batch.py \
--thread-ids "PRRT_aaa,PRRT_bbb,PRRT_ccc"
# Find comments that haven't received any reply yet
python3 scripts/eia_get_unaddressed_comments.py --owner OWNER --repo REPO --pr 123
# Get all unresolved threads
python3 scripts/eia_get_review_threads.py --owner myorg --repo myrepo --pr 123 --unresolved-only
# Output: [{"id": "PRRT_abc", "path": "src/main.py", "line": 42, ...}]
# Resolve each thread
python3 scripts/eia_resolve_thread.py --thread-id PRRT_abc
# Output: {"success": true, "threadId": "PRRT_abc", "isResolved": true}
python3 scripts/eia_reply_to_thread.py \
--thread-id PRRT_xyz \
--body "Fixed by refactoring the validation logic" \
--and-resolve
# Output: {"success": true, "commentId": "...", "resolved": true}
Cause: The thread ID is incorrect or the thread was deleted.
Solution: Re-fetch thread IDs using eia_get_review_threads.py. Thread IDs start with PRRT_ for review threads.
Cause: The mutation succeeded but the response wasn't checked properly.
Solution: The script verifies resolution by checking the isResolved field in the response. If it returns false, the resolution didn't take effect - check permissions.
Cause: Only the PR author and repository collaborators can resolve threads.
Solution: Ensure you're authenticated as a user with write access to the repository.
Cause: This is expected behavior! Replying does not resolve.
Solution: Use --and-resolve flag with eia_reply_to_thread.py, or call eia_resolve_thread.py separately.
Cause: Too many API calls in short succession.
Solution: Use batch operations (eia_resolve_threads_batch.py) to resolve multiple threads in a single API call instead of individual calls.
python3 scripts/eia_get_review_threads.py \
--owner <repository_owner> \
--repo <repository_name> \
--pr <pull_request_number> \
[--unresolved-only]
Output: JSON array of thread objects with id, isResolved, path, line, body (first comment).
python3 scripts/eia_resolve_thread.py --thread-id <PRRT_xxx>
Output: JSON object with success, threadId, isResolved.
python3 scripts/eia_resolve_threads_batch.py \
--thread-ids "PRRT_aaa,PRRT_bbb,PRRT_ccc"
Output: JSON object with results array containing per-thread success/failure.
python3 scripts/eia_reply_to_thread.py \
--thread-id <PRRT_xxx> \
--body "Your reply message" \
[--and-resolve]
Output: JSON object with success, commentId, resolved (if --and-resolve used).
python3 scripts/eia_get_unaddressed_comments.py \
--owner <repository_owner> \
--repo <repository_name> \
--pr <pull_request_number>
Output: JSON array of comments that have no replies, with threadId, commentId, author, body, path, line.
All scripts use standardized exit codes for consistent error handling:
| Code | Meaning | Description |
|---|---|---|
| 0 | Success | Operation completed successfully |
| 1 | Invalid parameters | Bad thread ID format, missing required args |
| 2 | Resource not found | Thread or PR does not exist |
| 3 | API error | Network, rate limit, timeout |
| 4 | Not authenticated | gh CLI not logged in |
| 5 | Idempotency skip | Thread already resolved (for resolve scripts) |
| 6 | Not mergeable | N/A for these scripts |
Note: eia_resolve_threads_batch.py returns exit code 0 for partial success. Check the JSON output's summary.failed field for individual failures.