From devboy
Addresses reviewer feedback on MRs/PRs: pulls open discussions and diffs, classifies each (accept and fix, push back, or clarify), applies minimal code changes, runs checks, commits, pushes, and replies to threads.
npx claudepluginhub meteora-pro/devboy-tools --plugin devboyThis skill uses the workspace's default tool permissions.
Address a reviewer's feedback on one MR / PR. For every unresolved discussion: decide whether to accept, push back, or clarify; if accepting, make the change locally and verify it; then reply to the thread with a short acknowledgement.
Fetches unresolved GitHub PR comments and threads, analyzes reviewer feedback, implements fixes, builds/tests, commits/pushes changes, replies to comments, and resolves threads.
Addresses code review feedback by validating issues, fixing valid ones, and batch-committing changes. Handles local agent feedback or GitHub PR threads via /fix-code-review-feedback or auto-invocation.
Respond to pull request review feedback interactively, working through each item with verification and code changes. Use when the user wants to address PR review comments.
Share bugs, ideas, or general feedback.
Address a reviewer's feedback on one MR / PR. For every unresolved discussion: decide whether to accept, push back, or clarify; if accepting, make the change locally and verify it; then reply to the thread with a short acknowledgement.
review-mr.devboy tools call get_merge_request_discussions '{"key": "mr#374", "limit": 100}'
The tool returns Discussion { id, resolved, comments, position }. comments is the thread's list of messages; position carries the file path + line number for inline discussions. Reply later using the discussion's id (for GitLab) or the numeric id of one of comments[*] (for GitHub — see the reply section below).
Do not rely on resolved alone to pick threads that need a reply. On GitHub the provider has no reliable resolved-state signal in the REST data it reads, so resolved is always false — treating "unresolved" as "needs reply" will pick every thread and produce infinite reply loops on re-runs. Use a deterministic filter instead:
On GitLab the resolved field is populated correctly and you may lean on it as a hint, but keep the author-based check as a fallback — it works across providers.
devboy tools call get_merge_request_diffs '{"key": "mr#374"}'
You need the diff to reason about where each comment applies — reviewers sometimes comment on context lines, not changed lines.
Walk the discussions in the order the reviewer posted them. For each one, pick exactly one disposition:
Do not batch dispositions. Decide per discussion.
Edit the files locally. Keep the change minimal — a review fix is a fix, not a refactor (see guardrails below). After each logical fix, run the local checks appropriate for the stack touched. For devboy-tools:
cargo fmt --check
cargo clippy --all-targets -- -D warnings
cargo test -p <the-crate-you-touched>
If any of those fails, fix the root cause before moving on — do not commit a half-green state.
Group related fixes into one commit where it reads naturally. Commit messages reference the scope, not the reviewer:
git add -- <paths>
git commit -m "fix(cli): surface a real error when the env var is unset (DEV-XXX)"
git push
Note the commit SHA of each fix — you will reference it in the reply. For fixes that span multiple discussions, one commit covering several threads is fine as long as the body of the commit lists them.
Use create_merge_request_comment in reply mode. The right reply id depends on the provider:
id as discussion_id. GitLab threads are first-class objects and the Discussion.id is what you pass back.in_reply_to on a review comment id, which is numeric. The provider packs that into a Discussion.comments[*].id; pass the id of the comment you are replying to (typically the last one in the thread) as discussion_id.If you get a 404 on reply, the value was the wrong one for the provider — fall back to a top-level comment rather than looping.
Keep the reply one or two sentences:
fixed in <sha> or fixed in <sha> — <one-line what changed>.keeping as-is because <specific technical reason>.could you clarify <specific point>? <short reason you're asking>.# GitLab example
devboy tools call create_merge_request_comment '{
"key": "mr#374",
"discussion_id": "abc123",
"body": "fixed in 9f2a1e4 — switched to `Error::Config` so the CLI prints a real message."
}'
Do not pass file_path / line when replying — the thread already owns a position.
devboy tools call get_merge_request_discussions '{"key": "mr#374", "limit": 100}'
Every thread you handled should now have your reply as the latest note. If a thread is missing your reply, the call either targeted the wrong discussion_id or the provider rejected the body — re-try.
cargo fmt --check, cargo clippy --all-targets -- -D warnings, and the relevant cargo test pass.