Skip to main content
This guide covers Paper’s pull request process, policies, and best practices to help your contributions get merged smoothly.

PR Policy

Paper accepts changes that make sense and can be justified. When submitting a PR, consider:
  • Justification: Be able to explain why the change is needed
  • Maintenance costs: Changes affect everyone running Paper, not just your server
  • Obfuscation helpers: Use them to reduce future maintenance burden
  • Formatting: Follow the guidelines in the formatting guide
Paper will fix minor formatting issues, but following the guidelines from the start speeds up the review process.

Target Branch and Versions

Main Branch (Latest Minecraft)

Most PRs should target the main branch, where active development for the latest Minecraft release happens.
If a new Minecraft release is imminent, consider waiting until it’s released and merged to avoid rebasing your PR. The main branch is typically frozen during this time.
Ask in the Paper Discord if you’re unsure about timing.

Older Minecraft Versions

Paper is unlikely to accept PRs for versions not marked as supported at https://fill-ui.papermc.io/projects/paper.

Snapshot and Pre-Release Versions

Only target snapshot/pre-release branches for:
  • Features specific to that version (e.g., new blocks/mobs in upcoming releases)
  • Bugs that only exist in the dev branch
Do not submit PRs for:
  • Version updates (e.g., 25w42a → 25w43a)
  • Changes while there are unapplied source patches
  • Feature patches during early development (wait until pre-release phase)
Before working on snapshot branches: Coordinate with the dev team in Discord or open an issue to ensure Paper wants changes in that area.

PR Submission Process

1

Prepare Your Changes

  1. Make your changes following the patching guide
  2. Ensure code follows the formatting guidelines
  3. Test your changes thoroughly
2

Commit Your Patches

After rebuilding patches:
git add .
git commit -m "Add/Fix/Update: Brief description"
3

Push to Your Fork

git push origin your-branch-name
4

Create the Pull Request

  1. Go to your fork on GitHub
  2. Click “Compare & pull request”
  3. Select the appropriate base branch (usually main)
  4. Fill out the PR template with:
    • Clear description of changes
    • Justification for the change
    • Any relevant issue numbers

Writing Good PR Descriptions

Your PR description should clearly communicate:

Summary

  • What the PR changes
  • Why the change is necessary
  • What problem it solves

Technical Details

For complex or technical changes, explain:
  • Implementation approach
  • Design decisions
  • Trade-offs considered
  • Performance implications
If your patch is technical or complex, Paper may ask you to add notes to the patch header. These notes help maintain the patch long-term, especially across major version changes.

CI Builds

Paper automatically builds all PRs to check for compilation errors.

Skipping CI

If your commit doesn’t need a build (e.g., changes to README.md, CONTRIBUTING.md, or LICENSE.md), add [ci skip] to the start of your commit subject:
git commit -m "[ci skip] Update README.md"

Review Process

What to Expect

  1. Initial Review: A Paper team member will review your PR
  2. Feedback: You may receive requests for changes or clarification
  3. Modifications: Paper may directly modify your PR for minor fixes or rebases
  4. Approval: Once approved, your PR will be merged
This is why using a personal fork (not an organization) is important—it allows Paper to make direct modifications to speed up the process.

Responding to Feedback

When changes are requested:
  1. Make the requested changes
  2. Run ./gradlew rebuildPatches
  3. Commit the changes:
    git add .
    git commit -m "Address review feedback"
    git push
    
No need to force push when addressing feedback—just push normally. Force push is only needed when rebasing.

Testing Your Changes

Using the Test Plugin

Paper includes a test-plugin module for testing API changes:
1

Enable Test Plugin

Enable it in test-plugin.settings.gradle.kts (generated after running Gradle once).
2

Edit the Test Plugin

Add your test code to the test plugin module.
3

Run Development Server

./gradlew runDev

Publishing to Maven Local

To test with external plugins:
1

Publish to Local Repository

./gradlew publishToMavenLocal
2

Configure Your Plugin (Gradle)

Add mavenLocal() as a repository in your build.gradle:
repositories {
    mavenLocal() // Add this above Paper's repository
    maven { url "https://repo.papermc.io/repository/maven-public/" }
}
Remove mavenLocal() when done testing. See the Gradle docs for why.
3

Configure Your Plugin (Maven)

Maven automatically checks your local repository first, so no configuration changes are needed.
You may want to remove the jar from your local Maven repository after testing.

Configuration Changes

If your patch requires configurable values:

Global Configuration

Use GlobalConfiguration for values that must remain the same across all worlds:
public class GlobalConfiguration {
    public class Misc extends ConfigurationPart {
        public int maxNumOfPlayers = 20; // New setting with default value
    }
}
Accessing the value:
int maxPlayers = io.papermc.paper.configuration.GlobalConfiguration.get().misc.maxNumOfPlayers;

World-Specific Configuration

Use WorldConfiguration for values that can differ between worlds (preferred when possible):
public class WorldConfiguration {
    public class Misc extends ConfigurationPart {
        public int maxNumOfPlayers = 20;
    }
}
Accessing the value (requires a Level instance):
int maxPlayers = level.paperConfig().misc.maxNumOfPlayers;
  • Field type determines the setting type
  • Default value is the initial field value
  • Setting name defaults to snake-case of the field name
  • Use @Setting annotation to override the default name

Obfuscation Helpers

Obfuscation helpers improve code readability and maintainability for unmapped variables or poorly-named parameters. Example for local variables:
double d0 = entity.getX(); final double fromX = d0; // Paper - OBFHELPER
// ...
this.someMethod(fromX); // Paper
Obfuscation helpers should be easy for the JVM to inline. The goal is always to improve readability and maintainability.

Common Issues

Patch Conflicts

If your PR conflicts with recent changes:
  1. Follow the rebasing guide
  2. Resolve conflicts
  3. Test your changes still work
  4. Force push to update the PR

Build Failures

If CI builds fail:
  1. Check the build logs for errors
  2. Fix compilation issues locally
  3. Run ./gradlew rebuildPatches
  4. Push the fixes

Review Delays

If your PR hasn’t been reviewed:
  • Be patient—Paper maintainers are volunteers
  • Ensure your PR is complete and follows guidelines
  • Don’t bump the PR repeatedly
  • Consider asking in Discord if it’s been several weeks

Best Practices

  • One feature per PR: Keep PRs focused on a single change
  • Descriptive commits: Write clear commit messages explaining the “why”
  • Test thoroughly: Ensure your changes work in various scenarios
  • Follow guidelines: Adhere to formatting and contribution guidelines
  • Be responsive: Address review feedback promptly
  • Ask questions: Use Discord or GitHub issues if you’re unsure
Remember: Paper maintainers want to help your PR get merged. Following these guidelines makes the process smoother for everyone.

Build docs developers (and LLMs) love