Claude-ops ops-merge
Autonomous PR merge pipeline. Scans all repos for open PRs, dispatches subagents to fix CI, resolve conflicts, address review comments, then merges. Use --main to also sync dev↔main branches.
git clone https://github.com/Lifecycle-Innovations-Limited/claude-ops
T=$(mktemp -d) && git clone --depth=1 https://github.com/Lifecycle-Innovations-Limited/claude-ops "$T" && mkdir -p ~/.claude/skills && cp -r "$T/claude-ops/skills/ops-merge" ~/.claude/skills/lifecycle-innovations-limited-claude-ops-ops-merge && rm -rf "$T"
claude-ops/skills/ops-merge/SKILL.mdRuntime Context
Before executing, load:
- Preferences:
— readcat ${CLAUDE_PLUGIN_DATA_DIR:-$HOME/.claude/plugins/data/ops-ops-marketplace}/preferences.json
,owner
, project registrytimezone - Daemon health:
— ifcat ${CLAUDE_PLUGIN_DATA_DIR}/daemon-health.json
set, surface to useraction_needed - Secrets: GitHub token: env
→ Doppler MCP ($GITHUB_TOKEN
) →mcp__doppler__*
→ password managerdoppler secrets get GITHUB_TOKEN --plain
OPS ► MERGE
CLI/API Reference
gh CLI (GitHub)
| Command | Usage | Output |
|---|---|---|
| List PRs with status | JSON array |
| PR details | JSON |
| CI check status | Check list |
| Squash merge PR | Merge result |
| Create PR | PR URL |
| CI runs | JSON array |
| Failed CI logs | Log output |
| Stream CI run | Live output (use with Monitor) |
| PR review comments | Comment text |
Agent Teams support
If
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 is set, use Agent Teams for fixer agents (Phase 3). This enables:
- Steering fixers mid-flight if priorities change (e.g., a critical PR should be merged first)
- Fixers can report blockers and you can redirect them without waiting for completion
- Shared context: if fixer-A discovers a breaking change that affects fixer-B's PR, you can notify B
Team setup (only when flag is enabled, Phase 3):
TeamCreate("merge-fixers") Agent(team_name="merge-fixers", name="fixer-[repo]", ...)
Use
SendMessage(to="fixer-my-api", content="PR #2958 was just merged — rebase your branch") to coordinate.
If the flag is NOT set, fall back to standard parallel subagents with
isolation: "worktree".
Pre-gathered PR data
${CLAUDE_PLUGIN_ROOT}/bin/ops-merge-scan 2>/dev/null || echo '{"prs":[],"error":"merge-scan failed"}'
Your task
You are the merge orchestrator. Your job is to get every open PR across the owner's repos merged — fixing whatever blocks them first.
Parse arguments
From
$ARGUMENTS:
→ after all PRs merge to dev, also sync dev↔main for repos that have both branches--main
→ scope to one repo only (e.g.,--repo <slug>
)--repo Lifecycle-Innovations-Limited/my-api
→ report what would happen, don't dispatch agents or merge anything--dry-run
→ skip the confirmation prompt before merging--force- (empty) → process all repos, merge to dev only
Phase 1 — Classify the PR queue
Parse the pre-gathered JSON. For each PR, it's already classified as one of:
| Classification | Meaning | Action |
|---|---|---|
| CI green, approved, no conflicts | Merge immediately |
| | Dispatch fixer: rebase on base branch |
| CI failures in | Dispatch fixer: investigate logs, fix, push |
| | Dispatch fixer: resolve comments |
| (branch protection, required reviews) | Note why, skip |
| | Skip — not ready for merge |
Print the queue:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ OPS ► MERGE — PR Queue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ | Repo | PR | Title | Status | Action | |------|----|-------|--------|--------| | my-api | #2958 | fix(migration) | ready | merge | | my-app | #4456 | feat(apple-04) | needs-ci-fix | dispatch fixer | | ... | ... | ... | ... | ... | Ready: N | Fix needed: N | Blocked: N | Draft: N ──────────────────────────────────────────────────────
If
--dry-run, stop here. Print the queue and exit.
Phase 2 — Confirm and merge ready PRs
Unless
--force was passed, use AskUserQuestion to confirm before merging:
Ready to merge N PRs: [repo]#[number] — [title] → [base] [repo]#[number] — [title] → [base] [Merge all N now] [Let me pick which ones] [Dry run — don't merge]
If user picks "Let me pick", show each PR with
[Merge] / [Skip] options via AskUserQuestion.
For each confirmed PR:
- Verify CI is still green:
gh pr checks <number> --repo <repo> - If green:
gh pr merge <number> --repo <repo> --squash --admin - Report:
✓ Merged <repo>#<number> to <base>
Phase 3 — Dispatch fixers for PRs that need work
For PRs classified as
needs-rebase, needs-ci-fix, or needs-review-response:
Dispatch subagents in parallel (max 5 concurrent, one repo per agent):
Each fixer agent gets a worktree and this brief:
Task: Fix PR #<number> in <repo> (<classification>) Repo path: <path from registry> Branch: <headRefName> <classification-specific instructions> For needs-rebase: 1. Create worktree: `git worktree add /tmp/ops-rebase-<pr-number> <headRefName>` 2. cd into worktree: `cd /tmp/ops-rebase-<pr-number>` 3. Fetch latest: `git fetch origin` 4. Attempt rebase: `git rebase origin/<baseBranchRef> 2>&1` 5. If rebase SUCCEEDS (exit 0): - Push force-with-lease: `git push --force-with-lease origin <headRefName>` - Clean up worktree: `git worktree remove /tmp/ops-rebase-<pr-number> --force` - Report: `✓ Rebased <repo>#<number> — conflict resolved` 6. If rebase FAILS (exit non-zero): - Capture the conflicting files: `git diff --name-only --diff-filter=U` - Show the diff: `git diff HEAD` - Abort the rebase: `git rebase --abort` - Clean up worktree: `git worktree remove /tmp/ops-rebase-<pr-number> --force` - Surface to orchestrator with the diff output and a structured conflict report: ```json { "pr": <number>, "repo": "<repo>", "status": "conflict", "conflicting_files": ["<file1>", "<file2>"], "diff_summary": "<first 500 chars of diff>" } ``` For needs-ci-fix: 1. Get failed check logs: `gh run view <id> --repo <repo> --log-failed | tail -80` 2. Diagnose the failure 3. Fix the code in a worktree 4. Commit + push --no-verify 5. Wait for CI to re-run (or report what was fixed) For needs-review-response: 1. Read review comments: `gh api repos/<repo>/pulls/<number>/comments --jq '.[].body'` 2. Address each comment in code 3. Reply to each comment via gh api 4. Push fixes 5. Re-request review if needed After fixing: - Report back: what was wrong, what was fixed, is CI green now? - Do NOT auto-merge after fixing. Report the fix and let Phase 4 handle confirmation.
Use
model: "sonnet" for all fixer agents.
Phase 4 — Resolve surfaced conflicts
For each PR returned with
status: "conflict" from a fixer agent:
- Display the conflict summary:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ OPS ► MERGE — Conflict in <repo>#<number> ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Branch: <headRefName> → <baseBranchRef> Conflicting files: - <file1> - <file2> <diff_summary> ──────────────────────────────────────────────────────
- Use AskUserQuestion (max 4 options — CLAUDE.md Rule 1):
[Accept incoming (theirs)] [Keep current branch (ours)] [Open manual resolution] [Skip this PR]
- Based on response:
- Accept incoming (theirs): Create worktree, rebase with
on each conflicting file,git checkout --theirs .
,git add .
, push force-with-leasegit rebase --continue - Keep current branch (ours): Create worktree, rebase with
on each conflicting file,git checkout --ours .
,git add .
, push force-with-leasegit rebase --continue - Open manual resolution: Print step-by-step instructions for the operator to resolve manually, then check in with
confirmation before continuing the merge pipelinegit push - Skip this PR: Note as
, include in final reportunresolved-conflict
- Accept incoming (theirs): Create worktree, rebase with
Phase 5 — Collect results and confirm merges
As fixers complete:
- Verify the PR is now green:
gh pr checks <number> --repo <repo> - If green, use
to confirm (unlessAskUserQuestion
):--forceFixer resolved [repo]#[number] — [what was fixed]. CI is now green. [Merge now] [Skip — I'll review manually] - If still red: report what's still broken, do not merge
Phase 6 — --main
sync (only if flag is set)
--mainFor each repo that has separate
dev and main branches:
- Check if dev is ahead of main:
git -C <path> log main..dev --oneline | head -5 - If ahead, show the commits and use
:AskUserQuestion[repo]: dev is N commits ahead of main: [commit list] [Create sync PR and merge] [Create PR only — I'll review] [Skip this repo] - If confirmed: create sync PR:
gh pr create --repo <repo> --base main --head dev --title "chore: sync dev → main" - Wait for CI:
(background, max 10 min)gh pr checks <sync-pr-number> --repo <repo> --watch - If CI green:
(merge commit, not squash)gh pr merge <sync-pr-number> --repo <repo> --merge --admin - Pull main back into dev:
git -C <path> fetch origin && git -C <path> checkout dev && git -C <path> merge origin/main --no-edit
Phase 7 — Final report
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ OPS ► MERGE COMPLETE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ | Repo | PR | Result | |------|----|--------| | my-api | #2958 | ✓ merged to dev | | my-app | #4456 | ✓ fixed CI + merged | | mise | #10 | ✗ 3 critical bugs — skipped | Merged: N PRs across M repos Skipped: N (blocked/draft) Failed: N (still need manual attention) Main sync: N repos synced (dev → main → dev) ──────────────────────────────────────────────────────
Safety Rails (NEVER violate)
- NEVER force-push to main/master
- NEVER merge with red CI — fix root cause first
- NEVER bypass review on PRs touching auth, payments, PII, or secrets — these require
subagent audit before mergesecurity-reviewer - NEVER run
on shared branchesgit reset --hard - ALWAYS use worktrees for fixes (multiple agents may be active)
- ALWAYS use
only for squash merges to dev (not main, unless--admin
flag)--main - Max 10 PRs per invocation to avoid GitHub API throttling
- If a PR has > 50 files changed, flag it for manual review instead of auto-merging
Native tool usage
Monitor — live CI watching
When waiting for CI after a fixer pushes (Phase 3-4), use
Monitor to stream the GitHub Actions run output instead of polling:
Monitor(command: "gh run watch <run-id> --repo <repo>")
This avoids sleep loops and gives real-time feedback on CI progress.
Tasks — progress tracking
Create a
TaskCreate for the overall merge pipeline and individual tasks per PR. Update with TaskUpdate as each PR is fixed/merged/skipped. This gives the user a live checklist view.
WebSearch — CI failure context
When a fixer agent encounters an obscure CI failure, use
WebSearch to find known issues (e.g., npm registry outages, GitHub Actions incidents, flaky test patterns).