From exarchos
Resolves merged PR workflows to completed state: verifies merge, backfills metadata, cleans up branches/worktrees. Use after PRs are merged.
How this skill is triggered — by the user, by Claude, or both
Slash command
/exarchos:cleanupThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
This skill uses VCS operations through Exarchos MCP actions (`list_prs`, `get_pr_comments`, etc.).
This skill uses VCS operations through Exarchos MCP actions (list_prs, get_pr_comments, etc.).
These actions automatically detect and route to the correct VCS provider (GitHub, GitLab, Azure DevOps).
No gh/glab/az commands needed — the MCP server handles provider dispatch.
Resolve merged workflows to completed state in a single operation. Replaces the manual multi-step process of navigating HSM guards after PR stacks merge.
For bulk cleanup of accumulated stale or abandoned workflows (as opposed to resolving a single merged workflow), use @skills/prune/SKILL.md. That skill invokes exarchos_orchestrate prune_stale_workflows in dry-run mode, displays candidates, and applies after user confirmation. Safeguards automatically skip workflows with open PRs or recent commits.
Rule of thumb: cleanup is per-workflow (one merged feature → completed); prune is bulk (N inactive workflows → cancelled). They are complementary, not alternatives.
Activate this skill when:
cleanup commandRead workflow state to get current phase and metadata:
exarchos:exarchos_workflow({ action: "get", featureId: "<id>" })
If featureId not provided, use pipeline view to list active workflows:
exarchos:exarchos_view({ action: "pipeline" })
The pipeline view is repo-scoped by default — only the caller's repo. A workflow started in another repo won't appear; when the response reports unscopedTotal greater than page.total, re-query with scope: "all" to reveal the hidden rows.
For each PR associated with the workflow, verify it is merged.
Primary method — VCS MCP action:
exarchos_orchestrate({ action: "list_prs", state: "merged" })
For individual PR details, use exarchos_orchestrate({ action: "get_pr_comments", prId: "<number>" }) or the VCS provider's native API.
Collect from merged PRs:
prUrl: The PR URL (or array of URLs for stacked PRs)mergedBranches: The head branch names that were mergedSafety check: If ANY PR is not merged, abort with clear error message.
For detailed verification guidance, see references/merge-verification.md.
After verifying merge status, run the post-merge regression check:
exarchos_orchestrate({
action: "check_post_merge",
featureId: "<id>",
prUrl: "<url>",
mergeSha: "<sha>"
})
This check is advisory — findings are reported but do not block cleanup. If findings are detected, log them for the user's awareness before proceeding.
Call the MCP cleanup action with collected data:
exarchos:exarchos_workflow({
action: "cleanup",
featureId: "<id>",
mergeVerified: true,
prUrl: "<url-or-array>",
mergedBranches: ["branch1", "branch2"]
})
This single call:
synthesis.prUrl and synthesis.mergedBranchesapprovedcompleted via universal cleanup pathworkflow.cleanup event to event storeReclaim all worktrees associated with the workflow through the governed
garbage-collector prune_worktrees — not ad-hoc git worktree remove.
GC cadence — after synthesize (INV-12). Governed worktrees become reclaimable once a workflow reaches synthesis; cleanup runs post-merge (after synthesize completes), so this is the natural point to apply the reclamation. The
next_actionsprojection surfaces the sameprune_worktreesdry-run affordance from synthesis onward.
prune_worktrees runs the fail-closed safety ladder (it refuses to destroy a
worktree with unsaved work) and auto-emits the worktree.remove.requested /
worktree.remove.executed pair per deleted worktree. Dry-run first (the default
— reports candidates + reclaimable bytes + grouped skip reasons, deletes
nothing), then apply:
// Dry-run (default) — preview candidates, delete nothing
exarchos:exarchos_orchestrate({ action: "prune_worktrees", repoRoot: "<repo-root>" })
// Apply — reclaim the delete-eligible candidates
exarchos:exarchos_orchestrate({ action: "prune_worktrees", repoRoot: "<repo-root>", dryRun: false })
Handle gracefully if worktrees are already removed. If the GC skips a worktree (e.g. uncommitted work), resolve the reported reason before re-applying — never force-remove a dirty worktree by hand.
Remove merged local branches:
git fetch --prune
git branch -d <merged-branch-1> <merged-branch-2> ...
Output summary:
## Cleanup Complete
**Feature:** <featureId>
**Transition:** <previousPhase> → completed
**PRs merged:** <count>
**Worktrees removed:** <count>
**Branches synced:** ✓
Use dryRun: true to preview what cleanup would do without modifying state:
exarchos:exarchos_workflow({
action: "cleanup",
featureId: "<id>",
mergeVerified: true,
dryRun: true
})
| Error | Cause | Resolution |
|---|---|---|
| STATE_NOT_FOUND | Invalid featureId | Check pipeline view for active workflows (repo-scoped by default; add scope: "all" if the workflow may live in another repo) |
| ALREADY_COMPLETED | Workflow already done | No action needed |
| INVALID_TRANSITION | Workflow is cancelled | Cannot cleanup cancelled workflows |
| GUARD_FAILED | mergeVerified is false | Verify PRs are merged before cleanup |
| Don't | Do Instead |
|---|---|
| Use cleanup as escape hatch during implementation | Only use after PRs are merged |
| Skip merge verification | Always verify via GitHub API |
| Manually navigate HSM guards post-merge | Use cleanup |
| Leave worktrees after cleanup | Include worktree removal in process |
The cleanup action auto-emits events — do NOT manually emit:
workflow.cleanup — emitted by the MCP cleanup action for the phase change to completednpx claudepluginhub lvlup-sw/exarchosMerges a PR, removes a Git worktree, and deletes the associated state file. Final phase of a multi-step local branch/PR workflow.
Merges reviewed PRs when triggered by /pr-merge or merge commands. Handles squash/rebase, worktrees, integration branches, and auto-merge for CI gating.
Merges all open PRs in dependency order, closes linked issues, deletes feature branches, and cleans up local/remote refs. Use when completing features or finalizing a release cycle.