Turns GitHub issues into pull requests. Label an issue auto-pr, and a local loop picks it up, runs it through a multi-step Claude pipeline (research, plan, implement, review), and opens a PR.
This runs locally on your machine — you keep a terminal running with the loop. There's no hosted service or CI integration out of the box. If you want to run it in CI/CD, on Codex, or anywhere else, use this as a starting point and adapt it to your setup (or point your agent at opensrc and ask it to build what you need).
The point of this tool is to invert how you spend your time. Instead of thinking about how hard something is to implement, you focus on experiencing your product, noticing what could be improved, and writing clear, well-defined issues for everything you want. The pipeline handles the initial implementation attempt.
Even when a PR isn't perfect, the artifacts it produces (research, plan, review) teach you about your own codebase. You can delete a PR you don't like and re-run it. You can tweak the prompt templates to get better results over time. The issues themselves become the valuable asset — once you have a collection of high-quality issues, you start seeing patterns, missing primitives, and real priorities.
When you batch-process multiple issues, you also get something you'd never get working on them one at a time: you can read across the research and plans and spot connections — a utility three different issues are reinventing separately, a shared abstraction that would simplify all of them, an API boundary that keeps showing up as a pain point. That cross-issue perspective is hard to get when you're tunnel-visioned on a single implementation.
This isn't about replacing your judgment. It's about letting you focus on what to build instead of dreading how to build it, and letting AI automation handle the first pass.
- Node.js v20+
- GitHub CLI (
gh) — authenticated withgh auth login - Claude Code CLI (
claude) — installed and authenticated
-
Copy
scripts/auto-pr/into your project:# from your project root cp -r path/to/auto-pr/scripts/auto-pr scripts/auto-pr -
Add dependencies and script to your
package.json(seepackage.jsonin this repo for a complete reference):pnpm add execa pnpm add -D tsx typescript @types/node
Then add the script:
{ "scripts": { "auto-pr": "pnpm exec tsx ./scripts/auto-pr/index.ts" } } -
Edit
scripts/auto-pr/auto-pr.config.ts— point it at your repos (see Configuration below). -
Add Claude Code permissions — copy
.claude/settings.jsonfrom this repo into your project root (or merge the permissions into your existing one). This lets Claude commit code during the pipeline without prompting for approval each time. -
Start the loop:
pnpm auto-pr
Important: Run this from a separate copy of your repo, not your active working directory. The loop checks out branches, stashes changes, and makes commits — it will interfere with whatever you're working on. Clone or copy your repo into a dedicated directory for auto-pr:
cp -r my-project my-project-auto-pr
cd my-project-auto-pr
pnpm auto-prEdit scripts/auto-pr/auto-pr.config.ts:
export const config: Config = {
triggerLabel: "auto-pr",
repos: [{ repo: "owner/my-repo", path: "." }],
maxImplementIterations: 100,
loopIntervalMinutes: 30,
loopRetryEnabled: false,
retryDelayMs: 30_000,
maxRetryDelayMs: 300_000,
};| Field | What it does |
|---|---|
triggerLabel |
GitHub label that triggers the pipeline. Add this label to an issue to start. |
repos |
Array of repos to scan. repo is the GitHub owner/name where issues live. path is the directory in your codebase Claude should focus on ("." for root). |
maxImplementIterations |
Max times the implement step loops before giving up. Each iteration picks up the next unchecked task. |
loopIntervalMinutes |
Minutes between polling iterations. |
loopRetryEnabled |
Retry failed Claude invocations with exponential backoff. Automatically enabled in loop mode. |
retryDelayMs / maxRetryDelayMs |
Initial and max retry delay for exponential backoff. |
Optional fields (add if needed):
| Field | Default | What it does |
|---|---|---|
mainBranch |
"master" |
Your main branch name. Set to "main" if that's what you use. |
remote |
"origin" |
Git remote name. |
maxTurns |
unlimited | Max turns per Claude CLI invocation. |
If you're on a Claude Code subscription with usage limits, you can distribute issue processing over time using loopIntervalMinutes and --limit. For example, setting a 30-minute interval with --limit 1 processes one issue per cycle, letting the loop steadily work through a backlog without hitting rate limits. Adjust these to match your subscription — shorter intervals and higher limits if you have headroom, longer gaps if you're close to your cap.
If you have a monorepo and use separate GitHub repos for issues (one per app), map each to its directory:
repos: [
{ repo: "acme/app-issues", path: "apps/my-app" },
{ repo: "acme/api-issues", path: "apps/my-api" },
{ repo: "acme/shared-issues", path: "packages/shared" },
],# Start the loop (default) — polls every 30min
pnpm auto-pr
# Custom interval and issue limit per iteration
pnpm auto-pr -- --interval 15 --limit 3
# Process a specific issue (runs once, then exits)
pnpm auto-pr -- --issue 42
# Process an issue from a specific repo
pnpm auto-pr -- --issue 42 --repo my-repo
# Stop after a specific step (useful for reviewing the plan before implementation)
pnpm auto-pr -- --issue 42 --until plan
# Reset local state for an issue (deletes artifacts, forces restart)
pnpm auto-pr -- --reset 42 --repo my-repo
# Rebase a stale PR branch onto current main
pnpm auto-pr -- --refresh --issue 42
# Run one iteration then exit (no loop)
pnpm auto-pr -- --onceWhen an issue is picked up, it goes through these steps:
Fetch → Research → Plan → [Annotations] → Plan-Implementation → Implement → Review → Create PR → Remove Label
| Step | What happens | Artifact |
|---|---|---|
| Fetch | Finds open issues with the trigger label | initial-ramblings.md |
| Research | Claude explores the codebase to understand what's needed | research.md |
| Plan | Claude writes a high-level implementation plan | plan.md |
| Annotations | (optional) If you created plan-annotations.md, Claude addresses your feedback |
updates plan.md |
| Plan-Implementation | Claude breaks the plan into an ordered checkbox task list | plan-implementation.md |
| Implement | Claude works through the checklist, making commits for each task | completed-summary.md |
| Review | Claude self-reviews all changes and fixes issues | review.md |
| Create PR | Pushes the branch and opens a PR on GitHub | GitHub PR |
| Remove Label | Removes the trigger label so the issue isn't picked up again | — |
The pipeline has no state file. It checks which artifact files exist to decide where to resume. If a step fails, the next run picks up from exactly that step.
When you have multiple issues being processed, PRs pile up. As you merge some, the remaining PRs fall behind main — imports break, APIs change, merge conflicts appear. The --refresh command handles this: it rebases the PR branch onto current main, then lets Claude fix whatever broke (resolve conflicts, update imports, adapt to renamed functions, etc.).
pnpm auto-pr -- --refresh --issue 42If main has changed so fundamentally that the PR can't be salvaged with minor fixes, Claude will flag it as NEEDS-ATTENTION instead of forcing broken code through.
You can review the plan before implementation starts:
- Run
pnpm auto-pr -- --issue 42 --until plan - Review
.auto-pr/{repo}/issue-42/plan.md - Create
plan-annotations.mdin the same directory with your notes - Run
pnpm auto-pr -- --issue 42— Claude will address your notes, then continue
Each pipeline step is driven by a markdown template in scripts/auto-pr/prompt-templates/. Edit these to change how Claude approaches research, planning, implementation, or review. Templates use tokens like {{SCOPE_PATH}} and {{ISSUE_DIR}} that get resolved at runtime — check utils.ts for the full list.
All pipeline artifacts are stored in .auto-pr/ at your project root and committed with the PR branch.
.auto-pr/
my-repo/
issue-42/
initial-ramblings.md # issue title + body
research.md # codebase research
plan.md # implementation plan
plan-implementation.md # checkbox task list
completed-summary.md # completion signal
review.md # self-review summary
Resolved prompts (prompt-*.md) are gitignored by default to reduce noise — they're generated from templates each run and contain no unique information. If you want to preserve them (e.g. for debugging or auditing), remove the .auto-pr/**/prompt-*.md line from your .gitignore.
The artifacts are valuable beyond the PRs they produce. After processing a batch of issues, you can feed the collected research, plans, and reviews into AI to surface patterns across your codebase — shared abstractions multiple issues are reinventing, API boundaries that keep causing friction, recurring complexity that points to a missing primitive. This works especially well when you have 5-10+ issues worth of artifacts to analyze together.
- Replace
execaCLI calls with Claude Agent SDK for a proper programmatic integration instead of shelling out toclaude -p - Explore Codex support as an alternative runtime for the pipeline steps
- Adopt better-result to replace try/catch blocks with typed
Resultvalues and simplify retry/error flows
The multi-step pipeline approach (research, plan, implement, review, annotation) was inspired from How I Use Claude Code by Boris Tane.
This project is also homework in preparation for trying Gateproof by Jordan Coeyman, which has some pretty advanced setups with AI