skills/drain-pr-queue/SKILL.md
--- name: drain-pr-queue description: Merge a stack of open PRs sequentially without babysitting each one. Discovers (or accepts) a list of PRs, arms auto-merge on all of them, then update-branches in a loop as each one lands so the next becomes mergeable. Handles BEHIND, DIRTY, and CI-failure cases. Use when you have several PRs ready to ship and don't want to merge them one at a time. Sibling to /ro:gh-ship (that one drives a single feature; this one drains a queue). category: development argu
npx skillsauth add RonanCodes/ronan-skills skills/drain-pr-queueInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Merge a stack of N open PRs to main without manual hand-holding. Each merge invalidates the others (BEHIND main), so the loop keeps update-branching the rest until the queue is empty.
/ro:drain-pr-queue # all open PRs by current user
/ro:drain-pr-queue --prs 37,39,40 # explicit list
/ro:drain-pr-queue --author app/dependabot # drain dependabot's queue
/ro:drain-pr-queue --dry-run # show plan, don't merge
main, all CI-green, all reviewed.gh pr merge directly).Unless --prs is given, list candidates:
gh pr list --state open --author "${AUTHOR:-@me}" \
--json number,title,headRefName,mergeStateStatus,mergeable,statusCheckRollup,autoMergeRequest \
--limit 50
Filter out:
Show the user the filtered list and confirm before proceeding (unless --dry-run, in which case just print and stop).
For each PR, get the changed files:
gh pr view N --json files -q '.files[].path'
Sort the queue so:
pnpm-lock.yaml, package-lock.json, yarn.lock, Cargo.lock) go LAST. They invalidate every other PR's lockfile when they land, but landing first means everyone behind needs a lockfile rebase.for pr in "${QUEUE[@]}"; do
gh pr merge "$pr" --squash --delete-branch --auto
done
If gh pr merge --auto fails with "Auto merge is not allowed for this repository", run once:
gh repo edit "$REPO" --enable-auto-merge
Then retry.
Do NOT change merge strategy without checking. Default to squash; respect the repo if it enforces a different strategy (look at branch protection: gh api repos/$REPO/branches/main/protection).
for pr in "${QUEUE[@]}"; do
gh api -X PUT "repos/$REPO/pulls/$pr/update-branch" 2>&1 | head -c 200
done
This kicks off CI on the rebased commits. As each one passes, auto-merge fires.
Cache-aware sleep is critical. Anthropic prompt cache TTL is 5min:
Default to 240s between checks during a drain (CI on this codebase is ~3min per cycle, so 240s usually catches the next batch of merges).
Each cycle:
gh api -X PUT .../update-branch to bring current.gh run view --log-failed. Don't try to fix; that's outside scope.For dependabot PRs:
gh pr comment "$pr" --body "@dependabot rebase"
Wait one cycle (240s), then re-check. Dependabot typically rebases within 1-3min.
For user-authored PRs (or if dependabot rebase failed):
git fetch origin "pull/$pr/head:pr-$pr-tmp" --force
git checkout "pr-$pr-tmp"
# Reset to current main and re-apply just the PR's logical change.
# This works when the conflict is purely lockfile/generated noise. For
# semantic conflicts, BAIL and tell the user — don't guess.
git reset --hard origin/main
# <re-apply the change manually here, OR cherry-pick the original head>
git push origin "pr-$pr-tmp:$BRANCH" --force
git checkout main
git branch -D "pr-$pr-tmp"
Auto-merge stays armed across force-pushes (verify with gh pr view N --json autoMergeRequest).
When the queue empties:
Drained N PRs in ~M minutes:
✅ #N1 — <title>
✅ #N2 — <title>
...
⚠️ #N3 — BLOCKED on <reason> (left open)
--no-verify, --admin, force-push to main).main/master. Force-push only to feature branches you control.A typical drain of 5 PRs on a repo with ~3min CI is ~50min wall clock. Most of that is CI wait. The watch loop should NOT busy-poll under 60s.
Without the skill: merge → wait for CI on next → realise it's BEHIND → update-branch → wait again → merge → repeat. You're context-switching every 3min.
With the skill: arm auto-merge once, then update-branch + sleep loop. You get notified at the end.
/ro:gh-ship ships ONE feature branch (PR open + watch + merge)./ro:drain-pr-queue ships N already-open PRs in sequence./ro:gh-ship per feature, then /ro:drain-pr-queue once you have a backlog.development
--- name: worktree description: Coordinate multiple agents on one repo via a worktree-lock pool, so two agents never clobber each other's working tree. Acquire the first free slot (main, then beta/gamma… worktrees, created on demand), work there on your own branch, release when you've pushed. Use before modifying any repo that might be in use by another agent (factory, dataforce, etc.), or whenever you're told a repo is being worked on. Backed by `ro worktree`. category: development argument-hin
testing
--- name: ship description: Ship a feature branch the local-CI-first way — run the full local gate, push, open a PR, squash-merge, then deploy, without waiting on GitHub Actions. Use when a branch is ready for main and you want it merged and deployed now. Reads CI policy from `ro ci` (default skips remote CI because GitHub Actions billing keeps hitting limits). Sibling to /ro:gh-ship (waits on GitHub checks) and /ro:cf-ship (the deploy half). Triggers on "ship it", "ship this", "merge and deploy
testing
--- name: setup-logging description: Set up (or audit) the observability stack in a TanStack Start + Cloudflare Workers app so it is "diagnosable by default" — structured logging (logtape) with a request context carrying trace_id + userId + tenant/orgId, a trace_id propagated FE→BE→logs→Sentry→PostHog, Cloudflare Workers observability enabled, and Sentry + PostHog wired. Two modes: `setup` (wire it into an app) and `audit` (check an existing app + report gaps). Use when scaffolding a new app, wh
development
Manage credentials INSIDE the active ~/.claude/.env file — read which token/account to use for a given app (Simplicity vs Dataforce vs Ronan-personal), add or update a secret WITHOUT it passing through the chat (an interactive Terminal window prompts for it), and track secrets that were exposed in a transcript so they get rotated. Sibling to /ro:context (which switches WHICH env file is active). Use when the user wants to add an API key/token/secret, asks "which credential do I use for X", needs the env organized/labelled, or a secret was pasted into the chat and should be rotated.