Skip to main content

Split large PRs into stacked PRs using Claude Code

Project description

PullSaw

Split large PRs into stacked PRs using Claude Code.

Overview

pullsaw analyzes a feature branch, generates a plan to split it into smaller, reviewable PRs, and executes each step using Claude Code in headless mode. Each stacked PR is self-contained with passing tests.

Prerequisites

  • Python 3.12+
  • Claude Code installed and authenticated
  • Git repository with a feature branch to split

Installation

# Using uv (recommended)
uv pip install -e .

# Or with pip
pip install -e .

Usage

# Run from a feature branch
git checkout my-feature-branch
pullsaw

# With options
pullsaw --base main --head my-feature --strict --yes

Options

Option Description
--base BRANCH Base branch (default: auto-detect main/master)
--head BRANCH Head branch (default: current branch)
--strict Fail if drift is detected vs original
--yes, -y Skip confirmation prompt
--dry-run Generate plan only, don't execute

How It Works

  1. Check State: Ensures clean working tree and valid branches
  2. Analyze Diff: Gets changed files between base and head
  3. Generate Plan: Uses Claude Code to propose a stacked PR plan
  4. Validate Plan: Ensures all files are covered and steps are valid
  5. Execute Steps: For each step:
    • Create a new branch
    • Claude Code implements the step
    • Enforce allowlist (rollback unauthorized changes)
    • Run format and tests
    • Fix failures (up to N attempts)
    • Commit
  6. Drift Check: Verify final state matches original branch

Configuration

Create .pullsaw/config.yml in your repo:

test_cmd: ["mix", "test", "--max-failures", "1"]
format_cmd: ["mix", "format"]
max_fix_attempts: 5
strict: false

Auto-detection

Without a config file, PullSaw auto-detects based on project files:

File Test Command Format Command
mix.exs mix test mix format
package.json npm/yarn/pnpm test npm run format
Cargo.toml cargo test cargo fmt
pyproject.toml pytest ruff format .
go.mod go test ./... go fmt ./...

Example Session

$ pullsaw

╭──────────────────────────────────╮
│ PullSaw - Stacked PR Splitter      │
╰──────────────────────────────────╯

Checking working tree... clean
Base: main
Head: feature-auth
Changed files: 12

Generating plan via Claude Code...

         Stacked PR Plan
┏━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓
┃ # ┃ Title                         ┃ Files             ┃
┡━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩
│ 1 │ Introduce auth types          │ lib/auth/**       │
│ 2 │ Add auth plug + config        │ lib/auth/plug.ex  │
│ 3 │ Wire up routes                │ lib/web/router.ex │
└───┴───────────────────────────────┴───────────────────┘

Proceed with execution? [y/n] y

Executing plan...

[1/3] Introduce auth types
  Created branch: feature-auth-step-1
  Claude Code: implementing...
  Format: OK
  Tests: PASS
  Committed: step(1): Introduce auth types

[2/3] Add auth plug + config
  Created branch: feature-auth-step-2
  Claude Code: implementing...
  Format: OK
  Tests: PASS
  Committed: step(2): Add auth plug + config

[3/3] Wire up routes
  Created branch: feature-auth-step-3
  Claude Code: implementing...
  Format: OK
  Tests: PASS
  Committed: step(3): Wire up routes

No drift - stack matches original!

Done! Created branches:
  - feature-auth-step-1
  - feature-auth-step-2
  - feature-auth-step-3

Architecture

  • Python CLI (this tool): Orchestration, validation, git operations, test execution
  • Claude Code: LLM work - planning, editing files, fixing failures

Python owns the source of truth for:

  • Branch creation and naming
  • Allowlist enforcement
  • Running tests and format commands
  • Committing changes

Claude Code never has permission to commit, push, or checkout branches.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pullsaw-0.1.0.tar.gz (53.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pullsaw-0.1.0-py3-none-any.whl (25.9 kB view details)

Uploaded Python 3

File details

Details for the file pullsaw-0.1.0.tar.gz.

File metadata

  • Download URL: pullsaw-0.1.0.tar.gz
  • Upload date:
  • Size: 53.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pullsaw-0.1.0.tar.gz
Algorithm Hash digest
SHA256 27d0979eb3c9c030453571553166e927e93c350e69ff4eb1f9979dd2435d4a80
MD5 81de7e9e4995b0acd49fa8f5f1107dbc
BLAKE2b-256 ed52acbeac50401e88fe5efe730398b5cd578ea08e52af0f240bc49d19aef31c

See more details on using hashes here.

Provenance

The following attestation bundles were made for pullsaw-0.1.0.tar.gz:

Publisher: publish.yml on simedw/pullsaw

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pullsaw-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: pullsaw-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 25.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pullsaw-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 eeb1bf2edff9b0a9f380b0a1762325516c148ee647bb12ef38cff2a48de3218e
MD5 cc9f80c388cf4349b6447d76a0e15bff
BLAKE2b-256 69aabd8490bbd4871df849755e8d3b4250b5753ae79abb888f141a4d5d583ac5

See more details on using hashes here.

Provenance

The following attestation bundles were made for pullsaw-0.1.0-py3-none-any.whl:

Publisher: publish.yml on simedw/pullsaw

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page