Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Pr Ship

ASecurity

Autonomously iterate on a PR — local CI, code review, remote CI, review comments, merge conflicts — until ready to merge

8 stars
0 votes
0 copies
0 views
Added 9/20/2026
developmenttypescriptpythonrustgojavakotlinbashtestinggitapi

Works with

cliapi

Security Analysis

A100/100

Scanned 9/20/2026

Install to Claude Code

$npx -y skills add tstapler/dotfiles --skill pr-ship --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Pr Ship?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Pr Ship
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tstapler-pr-ship/badge)](https://www.skillsdirectory.com/skills/tstapler-pr-ship)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
description: Autonomously iterate on a PR — local CI, code review, remote CI, review comments, merge conflicts — until ready to merge
prompt: |
  # PR Ship Loop — Make It Ready to Merge

  Drive PR `${1:-$(gh pr list --head $(git branch --show-current) --json number --jq '.[0].number')}` to a mergeable state by iterating through five ordered gates until all are green.

  ## State File

  All progress is tracked in `/tmp/pr-ship-${REPO_SLUG}-${BRANCH_SLUG}-${PR}.md`. Read it at the start of every iteration to understand what's already done. Update it after every action. This is your working memory across ScheduleWakeup wakeups.

  **State file format** (initialize if missing):
  ```markdown
  # PR Ship State — PR #N
  Iteration: 0
  Branch: <branch>
  Base: <base-branch>

  ## Changed Files
  (populated once from `gh pr diff "$PR" --name-only`)
  - path/to/file.go

  ## Gate Status
  - [ ] Gate 1a: Local compile
  - [ ] Gate 1b: Local tests (changed packages only)
  - [ ] Gate 2:  Code review clean
  - [ ] Gate 3:  PR review comments addressed
  - [ ] Gate 4:  Remote CI green
  - [ ] Gate 5:  No merge conflicts

  ## Push History
  (append after each push: `- COMMIT_SHA pushed at ITERATION N`)

  ## Code Review Issues
  ### Open
  (populated after Gate 2 runs; format: `- [ ] FILE:LINE — DESCRIPTION [severity]`)

  ### Resolved
  (moved here when fixed; format: `- [x] FILE:LINE — DESCRIPTION [fixed in COMMIT]`)

  ## Decision Log
  (one line per iteration: what gate advanced, what was done, commits made)
  ```

  ## Entry Check

  ```bash
  PR="${1:-$(gh pr list --head $(git branch --show-current) --json number --jq '.[0].number')}"
  REPO=$(gh repo view --json nameWithOwner --jq '.nameWithOwner' | tr '/' '-')
  BRANCH=$(gh pr view "$PR" --json headRefName --jq '.headRefName' | tr '/' '-' | tr '_' '-' | cut -c1-40)
  STATE="/tmp/pr-ship-${REPO}-${BRANCH}-${PR}.md"
  gh pr view "$PR" --json number,title,state,mergeable,mergeStateStatus,headRefName,baseRefName
  ```

  If the PR is already merged or closed, report that and stop.

  Read the state file. If it doesn't exist, initialize it. Populate **Changed Files** once using:
  ```bash
  gh pr diff "$PR" --name-only
  ```
  Never re-derive the changed files list from scratch — use what's in the state file.

  ---

  ## Context Discipline — Orchestrator Only

  **This skill is an orchestrator, not a worker.** Delegate all file editing, compiling, and committing to fresh subagents. Never accumulate file contents or diffs in this context — only gate status and state file updates. This is the `lean-agent-loop` skill pattern: the state file is the coordinator's memory, each fresh subagent is a Ralph Wiggum agent, and the five gates are the loop condition.

  ```
  Orchestrator (this context)
    └─ reads state file, checks gate, collects failure details
       └─ spawns Agent(prompt="Fix these specific failures: ...") → waits for result
          └─ fresh agent does all file reading, editing, testing, committing, pushing
  ```

  After each agent returns: verify the fix locally (run the relevant check command), update the state file, append to Decision Log, then advance to the next gate.

  ---

  ## The Loop (max 10 iterations; stop if no gate advances)

  At the top of each iteration, increment `Iteration:` in the state file. Read Gate Status. Skip gates already marked `[x]`. Process gates in order — do not jump ahead.

  ### Gate 1a — Local Compile

  Only run if `[ ]`. Detect stack from repo contents, then compile:

  | Stack | Compile check |
  |-------|--------------|
  | Java/Maven | `./mvnw compile -q` |
  | Kotlin/KMP | `./gradlew compileTestKotlinJvm --no-daemon` |
  | Go | `go build ./...` |
  | TypeScript | `npx tsc --noEmit` |
  | JS | `npm run build` |

  If it fails: delegate to a fresh agent with the exact error and the repo path. After agent returns, re-run the same compile command to verify — do not mark `[x]` until you confirm it passes. Update state file.

  ### Gate 1b — Local Tests (changed packages only)

  Only run if `[ ]` and Gate 1a is `[x]`. Scope tests to only the packages/modules containing changed files:

  | Stack | Scoped test command |
  |-------|-------------------|
  | Go | `go test $(git diff --name-only origin/<base>...HEAD \| grep '\.go$' \| xargs -I{} dirname {} \| sort -u \| sed 's|^|./|' \| tr '\n' ' ')` |
  | Java/Maven | `./mvnw test -pl $(changed modules) -q` |
  | TypeScript | `npm test -- --testPathPattern="<changed files>"` |
  | Kotlin/KMP | `./gradlew jvmTest --no-daemon` |

  If a scoped command is too complex to derive, fall back to the full test suite. If it fails: delegate to a fresh agent with failing test output. After agent returns, re-run the failing tests to verify — not the full suite, just the specific failing ones. Mark `[x]` only after the re-run passes.

  **Good Samaritan rule**: fix any failing or flaky test you encounter here, even if it's unrelated to this PR's changes and not this PR's fault. Leaving a known-broken or flaky test for someone else to hit isn't shipping — include it in the same delegated fix, and log it separately in the Decision Log as a pre-existing failure fixed in passing.

  ### Gate 2 — Code Review (changed files only)

  Only run if `[ ]` and Gates 1a+1b are `[x]`.

  Invoke the code review skill on the current diff (it naturally scopes to changed files):
  ```
  /code:review --fix
  ```

  Parse the findings. Write all **BLOCKER** and **CRITICAL** issues to `## Code Review Issues → Open` in the state file. Write **MAJOR** issues too. Suggestions/NITs are optional — log them but don't block.

  Delegate a fresh agent to fix all BLOCKER/CRITICAL/MAJOR issues. Include in the agent prompt:
  - The state file path
  - Each open issue with file, line, severity, description
  - Instruction to commit (but NOT push — Gate 3 handles the push decision)

  After the agent returns:
  1. Re-run `/code:review` to verify no new BLOCKER/CRITICAL issues
  2. Move fixed issues to `Resolved` in the state file with the commit SHA
  3. Repeat until no BLOCKER/CRITICAL/MAJOR issues remain
  4. Mark `[x]` in state file

  ### Gate 3 — PR Review Comments

  Only run if `[ ]` and Gates 1a+1b+2 are `[x]`. Address all reviewer feedback **before** pushing so CI runs on code reviewers have already seen and haven't flagged.

  #### Copilot Review Check (run first)

  Before processing any threads, check whether Copilot was requested as a reviewer:

  ```bash
  REPO_NWO=$(gh repo view --json nameWithOwner --jq '.nameWithOwner')
  OWNER="${REPO_NWO%%/*}"; REPO_NAME="${REPO_NWO##*/}"

  # Is Copilot a requested reviewer?
  COPILOT_REQUESTED=$(gh pr view "$PR" --json reviewRequests \
    --jq '[.reviewRequests[] | (.login // .name // "")] | map(select(test("copilot";"i"))) | length > 0')
  ```

  If `COPILOT_REQUESTED == true`:

  ```bash
  # Has Copilot already posted a review?
  COPILOT_REVIEWED=$(gh pr view "$PR" --json reviews \
    --jq '[.reviews[] | select(.author.login | test("copilot";"i"))] | length > 0')

  # Has Copilot posted a rate-limit / skip comment?
  COPILOT_RATE_LIMITED=$(gh api "repos/$OWNER/$REPO_NAME/issues/$PR/comments" \
    --jq '[.[] | select(.user.login | test("copilot";"i")) | .body] | map(select(test("rate.limit|quota|unavailable|temporarily|skip|unable|error";"i"))) | length > 0')
  ```

  Decision:
  - **`COPILOT_REVIEWED == true`** → include Copilot's review comments in Gate 3 processing below (treat like any other reviewer).
  - **`COPILOT_REVIEWED == false` + `COPILOT_RATE_LIMITED == true`** → log "Copilot rate-limited — skipping Copilot review" in Decision Log and proceed to thread processing.
  - **`COPILOT_REVIEWED == false` + `COPILOT_RATE_LIMITED == false`** → Copilot review is still pending. Use `ScheduleWakeup` with `delaySeconds: 90` and stop. Do **not** advance Gate 3. Log "Waiting for Copilot review" in Decision Log.

  #### Thread Processing

  Use the `github-address-pr-comments` skill (`~/.claude/skills/github-address-pr-comments/SKILL.md`) to:
  1. Fetch all unresolved threads (single GraphQL call) — via the shared `~/.claude/scripts/pr-threads.py fetch` script, the same one Gate 4's staleness re-check and `/code:review` use, so all three stay in sync on one aggregation implementation instead of drifting.
  2. For each thread: fix/decline/defer per decision rules below
  3. Reply + resolve each thread
  4. Commit any code changes locally (do NOT push yet — push happens in Gate 4)

  Decision rules (encode in every delegated agent prompt):
  - **Fix**: bugs, logic errors, security, clarity, naming, missing tests, valid perf issues
  - **Also fix**: cosmetic/style if small and clearly correct
  - **Defer**: valid-but-large refactors — reply "Deferring to follow-up — too broad for this PR"
  - **Decline**: only if factually wrong or contradicts a documented design decision
  - **CHANGES_REQUESTED**: treat every item as blocking

  Mark `[x]` when all threads are resolved or explicitly declined with a reply. Record the check time in the state file as `Gate 3 last verified: <ISO8601 timestamp of this check>` — Gate 4 diffs against this, not a guess, to decide if anything new landed.

  ### Gate 4 — Remote CI

  Only run if `[ ]` and Gates 1a+1b+2+3 are `[x]`. Push all local commits now:
  ```bash
  git push origin HEAD
  # append to Push History in state file: "- <sha> pushed at iteration N"
  ```

  Then check:
  ```bash
  gh pr checks "$PR" --watch=false
  ```

  - **Pending/in_progress**: use `ScheduleWakeup` (see Pacing section) and stop. Do not mark gate.
  - **All success**: re-run the Gate 3 staleness check using the **same shared script** `github-address-pr-comments` uses for thread fetching — this is the fix for a real incident where a bot comment landed after Gate 3's last check and the loop never re-polled GitHub because it trusted a stale "all green" state file:
    ```bash
    python3 ~/.claude/scripts/pr-threads.py summary \
      --owner "$OWNER" --repo "$REPO_NAME" --pr "$PR" \
      --since "<Gate 3 last verified timestamp from state file>" \
      [--hostname <enterprise-host-if-applicable>]
    ```
    Read `new_since_count` from the JSON output — do not eyeball `unresolved_count` alone, since a thread can be unresolved-but-already-known. If `new_since_count > 0`, reset Gate 3 to `[ ]`, log the new thread count in Decision Log, and loop. If `new_since_count == 0`, mark Gate 4 `[x]`.
  - **Failing**: collect the logs:
    ```bash
    gh run list --branch $(git branch --show-current) \
      --json databaseId,name,status,conclusion \
      --jq '.[] | select(.conclusion == "failure") | .databaseId'
    gh run view <RUN_ID> --log-failed
    ```
    Delegate to a fresh agent with the exact error lines. Apply the same Good Samaritan rule as Gate 1b: fix flaky or pre-existing CI failures too, not just failures caused by this PR's diff. Agent commits locally. Then re-run Gate 3 (address any new comments), then push again and set a ScheduleWakeup.

  ### Gate 5 — Merge Conflicts

  Only run if `[ ]` and Gate 4 is `[x]`.

  ```bash
  gh pr view "$PR" --json mergeable,mergeStateStatus
  ```

  If `mergeable == "CONFLICTING"`: delegate to a fresh agent to fetch + merge base, resolve conflicts, commit, and push. Mark `[x]` when `mergeable == "MERGEABLE"`.

  ---

  ## Progress Check

  After each gate transitions `[ ]` → `[x]`, append to Decision Log:
  ```
  Iteration N — Gate X: <what was done, commits made, issues found/fixed count>
  ```

  If an entire iteration completes with **zero gates newly marked `[x]`** (no progress), stop and report:
  - Which gates are still open
  - What was attempted
  - What's blocking (with exact error or status)

  ---

  ## Exit Condition

  When all five gates are `[x]`, report:

  ```markdown
  ## PR #N is Ready to Merge

  - Gate 1a Local compile: green
  - Gate 1b Local tests: green
  - Gate 2  Code review: N issues fixed, N deferred, N declined
  - Gate 3  PR review comments: N threads resolved
  - Gate 4  Remote CI: all checks green
  - Gate 5  Merge conflicts: none

  Decision log:
  <paste from state file>

  Merge with: gh pr merge N --squash --delete-branch
  ```

  Do NOT merge automatically — leave the final merge to the user.

  ---

  ## Pacing with ScheduleWakeup

  When Remote CI checks are still running:
  - Pending < 2 min → `delaySeconds: 90`
  - Pending 2–10 min → `delaySeconds: 270`
  - Pending > 10 min → `delaySeconds: 600`

  Always pass `prompt: "/github:pr-ship <PR_NUMBER>"` so the loop re-enters and reads the state file (the repo/branch slug is re-derived from the live PR on each entry).

  ---

  ## Never

  - Push code before Gates 1a and 1b are `[x]`
  - Push code before Gate 2 (code review) is `[x]`
  - Push code before Gate 3 (PR comments) is `[x]` — reviewers' feedback must be addressed first
  - Force-push over others' commits without asking
  - Merge the PR automatically
  - Skip `--no-verify` or bypass hooks
  - Re-derive changed files — always use the state file's list
---

**Usage**: `/github:pr-ship` (current branch) or `/github:pr-ship 61`

Gates run in order: local compile → local tests (scoped) → code review → **PR comments** → remote CI → merge conflicts. Push only happens at Gate 4, after all local work and reviewer feedback is incorporated. After CI passes, re-check for new comments before marking done. State tracked in `/tmp/pr-ship-{repo}-{branch}-{PR}.md`.

Attribution

tstaplertstapler
View sourceMore from tstapler →
SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Related Skills

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

281612 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2132 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

9881 votes

Pentest

PTES-aligned adversarial security audit for backend, frontend, and mobile applications. Produces a CVSS-scored Hacker Report with verified PoCs and phased remediation.

5491 votes
View all in development →