Skip to content

How to contribute

mcrs takes pull requests from outside. This page helps you pick a role, explains what the clean-room rule asks of you, and follows a change from an issue to a merge.

Role What you do Read first
Specification author Write the behavior of the game as rules in docs/spec/. You may read any source, the game’s code included. Specs and parity
Implementer Write Rust code and tests from a specification. You never read the game’s code. Clean-room
Parity tester Compare our output with output the game produced, and report or fix a difference. Specs and parity
Docs and translation Write or translate pages of this site. Write these docs

You can take a different role for each piece of work, but you cannot take two roles for the same behavior. The clean-room rule below is the reason.

mcrs implements the behavior of the game from specifications and never from the game’s code. To keep it that way, two people do the two halves of the work.

A specification author can read any source. The specification they write states behavior only, which means inputs, outputs, order, timing and constants. An implementer writes the code from that specification and reads only four things: docs/spec/, public player-facing documentation, artifacts the game produced, and the code of this repository. One person does not take both roles for the same behavior.

The repository also holds no names of classes, methods or fields of the game’s code. Six names are exempt because the community uses them as common terms: ResourceKey, TagKey, BlockPos, SectionPos, ColumnPos and PalettedContainer.

The full rules are in docs/clean-room.md, and Clean-room in practice retells them.

Many Paper and Fabric developers read decompiled game code every day. That knowledge is useful here, because you can be the specification author for the behavior you know. If you read the game’s code for some behavior, you do not write its code here by hand.

You can still deliver the implementation by giving it to an AI agent. You read the specification and make sure that it is correct, and you make sure that the agent has no access to the game’s code or to pieces of it. mcrs does not restrict AI contributions. We welcome them, provided that you know how the game is structured. Clean-room in practice has the conditions.

These precautions make sure that nobody copies code or algorithms from the original game, or from modifications of it, by accident. If you are not sure whether you have read the code about a task, say so in the issue. Nobody will mind.

  1. Find or open an issue. A new game behavior needs two issues. The first asks for the specification, and the second asks for the implementation and cites the rule IDs of the specification. The section “A new behaviour” of docs/clean-room.md describes the pair.
  2. Write the specification, or implement an existing one. A test names the rule ID it checks.
  3. Run the tests with the commands below.
  4. Open a PR. The pull request template asks what you changed and why, how you checked it, and whether the docs are updated.
  5. Wait for CI, which runs lint, clippy, test and portability. Build and test explains each of them.
Terminal window
cargo nextest run -p <crate> # one crate
cargo nextest run --workspace # everything, before a commit
cargo nextest run --profile full # plus the exhaustive sweeps

These three commands come from the README Development section. They need the cargo-nextest runner installed, and the first run downloads the game’s client jar to get the data pack.

The instructions for coding agents live in the repository. AGENTS.md is the instruction file for every agent, and CLAUDE.md is a link to it. It holds the rules that apply everywhere: layers, clean-room, style, tests and the path to main. The more specific material sits in four places.

Path What is there
.agents/skills Skills that AGENTS.md names with “Load <name>”, such as rust-style, efficient-testing and ship. .claude/skills/ links to the same folders.
.agents/rules One rule file per domain: codec, memory, rendering and simulation. The header of a rule lists the crate paths it covers. .claude/rules/ links to them.
.claude/agents The roles implementer, spec-author and reviewer.
.claude/hooks/cargo-guard.sh A Claude Code hook that rejects cargo test. Build and test says why.

Claude Code loads the skills, the rules and the roles by itself. With another tool you do the same by hand. Where AGENTS.md says “Load <name>”, read .agents/skills/<name>/SKILL.md. Before you edit a crate, read the rule of its domain. To give an agent a role, copy the text of that role from .claude/agents/ into the brief of the agent.

The agent roles keep the two clean-room roles apart. The spec-author writes behavior and no implementation code, and the implementer never reads decompiled, deobfuscated or mapped game code.

If your change alters behavior that a page of this site describes, update the page in the same PR. A warning on the PR lists the pages whose sources files you touched, and it does not block the merge. Write these docs explains how to write a page.

These six issues fit a first pull request. First tasks says what each one asks for and which role it needs.

  • A bug: the outbound queue drops state packets.1
  • Typed packets for cookies, transfer and chat.2
  • A status ping example.3
  • An echo chat bot over the network layer.4
  • A packet inspector example.5
  • A report of spec rules that no test names.6

By 2026-11-09, 26 pull requests from 5 authors other than the owner had been merged. The median time from opening to merge was about 12 hours. The fastest took about 40 minutes and the slowest about 5 days. The sample is small and one person reviews most of the work, so treat the numbers as a hint and not as a promise.

You can repeat the count with gh pr list -R andreypfau/mcrs --state merged --limit 300 --json number,author,createdAt,mergedAt and then drop the PRs of andreypfau.

Questions go to Discord or to the issue you work on. Decisions are recorded in issues with the label decision.

  1. WIP#308 The outbound queue drops normal and low packets past 256 entries. ↩

  2. WIP#295 Typed packets for cookies, transfer, custom query and player chat. ↩

  3. WIP#290 A status ping example against the embedded server. ↩

  4. WIP#293 An echo chat bot that uses the network layer only. ↩

  5. WIP#289 A packet inspector that decodes a recorded session without unknown packets. ↩

  6. WIP#507 Plans a report of the specification rules that no test checks. ↩

Sources and verification

Verified: 26.4-snapshot-7, f50e2fdf6, 2026-11-10