Help us improve
Share bugs, ideas, or general feedback.
From agent-squad-hr
Coordinate GitHub issue pickup across parallel Claude Code sessions (or human + agent) using BOTH `assignees` and a `wip` label, so sibling sessions detect the claim and skip. Use BEFORE writing any code that closes / addresses a GitHub issue when there's any chance another session is working the same repo. Trigger on phrases like "pick up issue
npx claudepluginhub wan-huiyan/agent-squad-hrHow this skill is triggered — by the user, by Claude, or both
Slash command
/agent-squad-hr:gh-issue-claim-coordinationThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
When multiple Claude Code sessions (or human + agent) work the same repo in parallel, two sessions can independently pick up the same issue, do parallel implementations, and collide at PR time — burning hours of duplicated work and forcing one branch to be rebased or abandoned.
Guides technical evaluation of code review feedback: read fully, restate for understanding, verify against codebase, respond with reasoning or pushback before implementing.
Share bugs, ideas, or general feedback.
When multiple Claude Code sessions (or human + agent) work the same repo in parallel, two sessions can independently pick up the same issue, do parallel implementations, and collide at PR time — burning hours of duplicated work and forcing one branch to be rebased or abandoned.
Default agent behaviour is silent. An agent dispatched to "work on the bug-tagged issues" does not automatically check whether another session is already on issue #N. There's no built-in coordination unless this skill (or equivalent) runs at pickup.
This skill installs a 60-second protocol — preflight check, atomic claim, stale-claim sweep, release on completion — using two GitHub-native primitives so the claim is visible everywhere (issue list UI, gh issue list, dashboards, sibling sessions).
assignee AND a wip label?They cost ~0 to set together and cover different failure modes:
assignees is GitHub's canonical "who's on this" primitive. gh issue list --assignee "" cleanly enumerates unclaimed work; agents tend to surface assignees in their own context without prompting.wip label is far more visible in the GitHub issue list UI (a coloured chip next to the title) and lets you find every active claim with one query: gh issue list --label wip. It also survives the case where someone reassigns the issue without thinking about coordination.Belt and suspenders. If the assignee gets dropped on a bulk edit, the label still flags it; if the label gets dropped, the assignee still says it.
wip label exists (idempotent — runs every time)Don't carry "did I do the setup yet?" state. The label create is cheap and noisy on success only the first time; on subsequent runs it just exits non-zero with "already exists", which || true swallows. Bake it into every pickup so a fresh repo or a teammate's repo just works.
gh label create wip \
--description "Claimed by an active session — do not start parallel work" \
--color FBCA04 \
|| true
If this fails with a permissions error (rare; happens on repos where your account can't manage labels), fall back to assignee-only claim and tell the user.
Before writing any code for an issue:
ISSUE=123 # the issue you're about to start
gh issue view "$ISSUE" \
--json number,state,assignees,labels,updatedAt \
--jq '{number, state, assignees: [.assignees[].login], labels: [.labels[].name], updatedAt}'
Read the result against this decision table:
| State + assignees + labels | Action |
|---|---|
OPEN, assignees: [], no wip label | Free — claim it. Proceed to claim step. |
OPEN, assigned to you, has wip label | Yours — resume. No re-claim needed. |
OPEN, assigned to someone else, OR wip label set by another | STOP. Surface to user with assignee + updatedAt. Do not start parallel work. |
OPEN, has wip but updatedAt > stale window with no linked PR | Likely abandoned — see Stale-claim sweep before claiming. |
CLOSED | Issue is done. Confirm scope with user before reopening; the merged PR's diff may already cover what you were going to build. |
gh issue edit "$ISSUE" --add-assignee @me --add-label wip
These are independent edits — both should succeed (Step 0 already ensured the wip label exists). If only one succeeds because of a transient blip, retry the missing one before starting work. A half-claim is worse than no claim because it confuses future preflights.
When the preflight shows another session has the claim, do not proceed. Tell the user something like:
Issue #123 is currently claimed by
@other-session(wiplabel, last touched 2h ago at 2026-05-08T09:14Z). Want me to (a) wait, (b) work on a different issue, or (c) override the claim because you know that session is dead?
The user owns the override decision. They might know the other session crashed; they might not. Surfacing the timestamp + claimant lets them choose; do not unilaterally override.
Sessions crash, get cancelled, get forgotten. Without a sweep, a stale wip label can lock an issue forever.
Default rule: a claim is stale if updatedAt is more than 24 hours old AND no PR is linked. Adjust the window to your workflow (shorter for fast-moving repos, longer if multi-day issues are normal).
Find candidates:
gh issue list --label wip --state open \
--json number,title,assignees,updatedAt,url \
--jq '.[] | select((now - (.updatedAt | fromdateiso8601)) > 86400)'
(86400 = 24 hours in seconds. Change to 43200 for 12h, 14400 for 4h, etc.)
When you find a stale claim, ask the user before clearing it — the assignee may have paused intentionally (waiting on an external dep, debugging out of band, etc.). If cleared, drop both:
gh issue edit "$ISSUE" --remove-assignee <stale-assignee> --remove-label wip
GitHub auto-handles the happy path: a merged PR with a closing keyword (Closes #123 / Fixes #123 / Resolves #123) closes the issue and the assignee becomes irrelevant. The wip label, however, is not auto-removed by PR merge — and a CLOSED issue still showing wip clutters gh issue list --label wip and confuses future stale-claim sweeps.
After PR merge, drop the wip label:
gh issue edit "$ISSUE" --remove-label wip
The assignee can stay (it's useful history of who shipped the fix). Only the label needs cleaning.
If your PR only addresses part of an issue (Addresses Part 1.3 of #500 rather than Closes #500), keep the issue claimed:
wip label after merging the partial PR.GitHub's closing-keyword parser is permissive enough to auto-close the parent issue on partial PRs if the wording drifts (e.g. Closes Part 1 of #500 will close #500 wholesale). The defensive PR-body phrasing ("Addresses Part X of #N", no closing keyword anywhere near #N) is independent guidance — see the project memory file feedback_pr_partial_close_phrasing.md if you have one.
gh issue edit error). Fall back to label-only with a comment recording your session ID.# Pickup (Step 0: ensure label exists — idempotent, runs every time)
ISSUE=123
gh label create wip --color FBCA04 \
--description "Claimed by an active session — do not start parallel work" || true
gh issue view "$ISSUE" --json number,state,assignees,labels,updatedAt \
--jq '{number, state, assignees: [.assignees[].login], labels: [.labels[].name], updatedAt}'
# (read decision table; if free:)
gh issue edit "$ISSUE" --add-assignee @me --add-label wip
# Stale sweep (24h window)
gh issue list --label wip --state open \
--json number,title,assignees,updatedAt,url \
--jq '.[] | select((now - (.updatedAt | fromdateiso8601)) > 86400)'
# Release after merge (only the label; assignee can stay)
gh issue edit "$ISSUE" --remove-label wip
feedback_track_partial_batch_filings.md — different problem (knowing what YOU filed when a sandbox cancels mid-batch). This skill prevents the upstream collision; that one cleans up after a different failure mode.feedback_coordination_framing_for_parallel_artifact_collisions.md — what to do AFTER two parallel artifacts have already collided. This skill prevents the collision; that one frames the recovery.feedback_pr_partial_close_phrasing.md — keeps GitHub's closing-keyword parser from auto-closing on partial PRs. Pairs with the partial-scope guardrail above.barryu-pr-conflict-site-regen — resolves rebase conflicts when parallel PRs collide on generated site files. Downstream of a missed claim; if this skill runs, that one fires less often.