@robhowley/pi-merge-ready
PR merge-readiness for Pi: status bar and slash-command status, exact PR URL targeting, blocker context, and agent repair loops.
Package details
Install @robhowley/pi-merge-ready from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@robhowley/pi-merge-ready- Package
@robhowley/pi-merge-ready- Version
0.7.0- Published
- Jun 12, 2026
- Downloads
- 645/mo · 572/wk
- Author
- robhowley
- License
- MIT
- Types
- extension
- Size
- 197.7 KB
- Dependencies
- 0 dependencies · 2 peers
Pi manifest JSON
{
"extensions": [
"./extensions/merge-ready"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-merge-ready
A Pi package for getting pull requests to green: merge-readiness signal, blocker context, and automated agent repair loops.
It adds:
- a current-branch status bar signal
/merge-readyfor current-branch or exact-URL status/merge-ready watchfor polling PRs and handing actionable blockers off to the agent for automated repairs.- a
merge_ready_status({ url? })agent tool - a
merge-ready-loopskill for working the returned blockers
Installation
pi install npm:@robhowley/pi-merge-ready
Requirements
- Authenticated GitHub CLI (
gh). gitandghavailable in Pi's environment.
The package is fail-closed: if GitHub data is missing, truncated, or ambiguous, it reports status_ambiguous instead of claiming the PR is ready.
What it adds
Status bar
The Pi status bar shows the current branch PR's top merge-readiness state.
Examples:
✅ Ready
❌ Checks failing
🔄 Out of date
❌ 💬 2 unresolved
❔ No PR
Optional unresolved conversations are not blockers, but they can still appear as context:
✅ Mergeable · 💬 2 unresolved
Slash command
Use /merge-ready to inspect the current branch PR:
/merge-ready
Example:
✅ Ready to merge
Target: current branch feat/my-branch (owner/repo)
PR: #64 — Add PR merge-readiness extension
State: ready
Open items: none
You can also target an exact GitHub pull request URL:
/merge-ready --url https://github.com/OWNER/REPO/pull/64
/merge-ready --url https://github.com/OWNER/REPO/pull/64 --json
Example blocked/pending output:
⏳ Checks are still running
Target: current branch feat/my-branch (owner/repo)
PR: #64 — Add PR merge-readiness extension
State: pending
Open items:
- Checks are still running
Only full HTTPS GitHub PR URLs are accepted.
Detail URLs are supporting links for blocker context, not separate action items.
Watch mode
Start a watcher with:
/merge-ready watch
/merge-ready watch --url https://github.com/OWNER/REPO/pull/64
/merge-ready watch --url https://github.com/OWNER/REPO/pull/64 --interval 30
watch is a long-lived foreground TUI command that polls merge readiness.
Press Ctrl-Shift-S in the TUI to stop it.
It will:
- keep polling while checks or required review are still pending
- attempt to repair PR blockers for
branch_out_of_date,merge_conflicts, orci_failing - stop on non-repairable blockers or terminal PR states
Repair model:
- current-branch watch repairs use the ambient checkout after dirty-worktree preflight
- explicit
--urlwatch repairs must not mutate the ambient checkout; they use an isolated worktree for the PR head repo/branch --urlaccepts only the same exact GitHub PR URL form as/merge-ready --url
Watch actionability:
| Status / lifecycle | Watch behavior |
|---|---|
branch_out_of_date, merge_conflicts, ci_failing |
Auto-attempt one bounded repair turn. Current-branch watches repair in the ambient checkout after dirty-worktree preflight; explicit --url watches repair in an isolated worktree for the PR head repo/branch. |
ci_running, review_pending, open PR with no openItems (ready) |
Keep polling and wait for GitHub or review state to change. |
changes_requested, unresolved_conversations, merge_blocked, draft, status_ambiguous, no_pull_request, closed/merged PR lifecycle |
Do not auto-repair; report the blocker or terminal state and stop. |
Watch safety:
- Repeated-blocker guard: after one repair attempt for a blocker,
watchdoes not keep retrying it without a fresh status change or explicit restart. - Dirty-worktree preflight: current-branch
watchrepairs refuse to run when local changes are already present in the ambient checkout. - Explicit
--urlwatch repairs are instructed to use an isolated worktree for the PR head repo/branch and skip ambient dirty-worktree preflight.
Configuration
Watch behavior can be configured in Pi's settings.json (global: ~/.pi/agent/settings.json, project-local: .pi/settings.json).
{
"pi-merge-ready": {
"autoCompactRepair": true
}
}
| Option | Default | Description |
|---|---|---|
autoCompactRepair |
true |
Trigger conversation compaction after successful repair loop completion. Compaction runs before the watch continues polling. Set to false to disable. |
Agent tool
Agents get a merge_ready_status tool:
merge_ready_status({});
merge_ready_status({ url: 'https://github.com/OWNER/REPO/pull/64' });
Rules:
statepluspr.lifecycletells you whether the PR is merge-readyopenItemsis the authoritative blocker listopenItems[].details[]and detail URLs are provenance only- do not pass branch names, PR numbers, repo names, or inferred targets
Example response:
{
"state": "blocked",
"target": {
"mode": "current_branch",
"owner": "owner",
"repo": "repo",
"branch": "feat/my-branch"
},
"pr": {
"lifecycle": "open",
"number": 64,
"title": "...",
"url": "...",
"headRefName": "feat/my-branch",
"baseRefName": "main"
},
"summary": "Required checks are failing",
"openItems": [{ "id": "ci_failing", "summary": "Required checks are failing" }],
"generatedAt": "2026-05-27T00:00:00.000Z"
}
openItems[].details[] rows are supporting provenance for an open item.
{
"id": "ci_failing",
"summary": "Required checks are failing",
"details": [
{
"label": "lint",
"status": "failing",
"url": "https://github.com/OWNER/REPO/actions/runs/123/jobs/456"
}
]
}
Advanced notes:
- The top-level
pr.urlis already the PR URL; do not treat it as a source link. - When
target.modeis"url",pr.headRepositoryis also returned so callers can verify whether the editable head repo matches the targeted PR repo before changing code:
{
"headRepository": {
"owner": "fork-owner",
"repo": "fork-repo"
}
}
- URL-targeted command results do not update the ambient status bar cache; the status bar remains current-branch only.
Merge-ready loop skill
The package includes a merge-ready-loop skill for requests like "make this PR ready to merge".
The skill:
- resolves the current branch or exact PR URL target
- calls
merge_ready_status - works only from the returned
openItems - makes one small verified fix at a time
- distinguishes "addressed locally" from "confirmed cleared by GitHub"
- for watch-triggered URL repairs, uses the PR head repo/branch in an isolated worktree without mutating the ambient checkout
Status states
| State | Meaning |
|---|---|
ready |
An open PR exists and no merge-readiness open items were found. |
blocked |
A blocker requires action before merge. |
pending |
Waiting on checks or required review. |
unknown |
No PR was found, readiness is ambiguous, or the PR is terminal. |
Open item ids
| id | Meaning |
|---|---|
no_pull_request |
No pull request was found for the branch or exact targeted URL. |
status_ambiguous |
Readiness could not be determined safely. |
merge_conflicts |
GitHub reports merge conflicts. |
branch_out_of_date |
The branch is behind the base branch. |
merge_blocked |
GitHub reports a mergeability blocker. |
draft |
The pull request is still a draft. |
ci_failing |
Required checks are failing. |
changes_requested |
A reviewer requested changes. |
unresolved_conversations |
Required review conversations remain open. |
ci_running |
Required checks are still running. |
review_pending |
Required review is still pending. |
Unresolved conversations are requirement-aware:
- Required unresolved conversations block merge readiness.
- Optional unresolved conversations remain in
signals, but not inopenItems. - Unknown conversation requirements produce
status_ambiguous. - Generic
merge_blockedis suppressed when a concrete blocker such as failing checks, draft state, required review, or required conversations already explains GitHub's blocked state. - Closed or merged PRs remain valid targets. They report
pr.lifecycleplus lifecycle-aware summaries likePR is closedorPR is already merged. - URL-targeted command results do not update the ambient status bar cache; the status bar remains current-branch only.
License
MIT