This page is for anyone who wants to change MCME's code: fix a bug, add a feature, or release a new version. MCME's plugins and libraries live in the MCME organisation on GitHub, most of them in public repositories. They share one way of working: work happens on a development branch, master holds releases, every change arrives through a pull request, and a release is a tagged commit on master. The details below hold for the active plugin repositories; a repository's own README or Developer Manual wins where it differs.
Branches
| Branch | What it holds | How changes arrive |
|---|---|---|
master |
Releases only. Every release tag sits on a commit of this branch | A pull request from development (or from a release branch) when a version is released |
development |
The next version, being built | Pull requests from work branches |
| work branches | One change each (fix/..., feature/..., docs/...) |
Branch from development; open the pull request into development |
- Both
masteranddevelopmentare protected. Changes arrive only through pull requests, and a pull request needs one approving review. A maintainer merges it. - Merge
developmentintomasterwith a merge commit, not "Squash and merge" or "Rebase and merge". Squashing or rebasing givesmastercommits thatdevelopmentdoes not have, so the two branches look diverged for good. - Exceptions. MCME-Base keeps its 2.x line on
development, and its releases are thev*tags; itsmasterstill holds the old 1.x line. ResourcePackScripts and the resource pack repositories have their own flow, described in The release pipeline. Older repositories may still havedev/...branches from earlier contributors; leave them alone unless their owner agrees.
Pull requests
- Branch from an up-to-date
development. - Keep the pull request to one change. Say what it changes and why, and how you tested it.
- Run the full build with tests before you push:
mvn -B -ntp clean verifyor./gradlew build. CI runs the same build on every pull request in most repositories; it must be green before a merge. - If the change is visible to players, staff or other developers, add a line under
## [Unreleased]in the repository'sCHANGELOG.md. MCME's changelogs follow Keep a Changelog. - Update the README, the User Manual or the Developer Manual in the same pull request when behaviour, commands, permissions or config change.
Commit messages
Recent history in the plugin repositories uses short conventional-commit messages: a type, an optional scope, and what the commit does, in the present tense.
fix(stats): copy statistics out of the results before the main thread applies them
refactor(proxy): remove the legacy MyWarp bridge
build: compile against velocity-api 4.2.0 instead of 4.1.0-SNAPSHOT
docs: describe the network as it is after the cleanup
chore(release): 3.1.1
Versions and releases
Versions are MAJOR.MINOR.PATCH: a patch release fixes things, a minor release adds features, and a new major line usually comes with a platform change (MCME-Architect's 3.x line, for example, is its Paper 26.x line).
A release goes the same way in most repositories:
- Bump the version in
pom.xmlor the Gradle build, in a commit namedchore(release): X.Y.Z, through a pull request intodevelopment. Date the changelog section:## [X.Y.Z] - YYYY-MM-DD. Update the version where the README names it. - Open a pull request from
developmentintomasterand merge it with a merge commit. - Tag the merge commit with an annotated tag and push the tag. Most repositories use
vX.Y.Z; PluginUtils uses the bare number (2.0.6). - CI builds the tag, checks that the tag matches the version in the build file, and publishes the jar to the Maven repository. In several repositories it also checks the changelog section and creates the GitHub Release with the jar and a
.sha256file; where it does not (MCME-Architect), a maintainer makes the GitHub Release by hand.
Two things follow from this:
- A version can be published only once. The
releasesrepository refuses to overwrite a version. If a release is wrong, release the next patch version. - Pin exact dependency versions. No version ranges, no
LATEST. A range makes the same commit build differently from one day to the next.
Jar file names in several plugins carry the build type and the commit: MCME-Architect-3.3.1-DEV-<commit>.jar from a normal build, ...-RELEASE-... with -Dbuild.type=RELEASE. The version inside plugin.yml has no build type, so check the file name to tell a development build from a release. Two builds of one commit on different machines can still differ in their checksums (line endings, timestamps); compare jars entry by entry, not by checksum.
Code conventions
These collect what the repositories already do, and the rules from the older conventions page.
- One source of truth. Use the shared libraries, PluginUtils and MCME-Base, instead of copying their helpers into a plugin. A fix to shared code goes into the library, not into a local copy.
- Names. Repositories are
MCME-<Name>(older) ormcme-<name>; Java packages and Maven group arecom.mcmiddleearth. - Dependencies on other plugins are
provided/compileOnlyand declared inplugin.yml(dependwhen the plugin cannot work without it,softdependwhen it can). Never shade another MCME plugin or library. - Configuration is YAML (
config.yml), with defaults shipped in the jar. - Players are stored by UUID; names are for display.
- Secrets never go into a repository: no tokens, passwords or keys in code, config, poms or workflow files. Build credentials go in
~/.m2/settings.xmlor GitHub Actions secrets. - Don't patch a third-party plugin locally. It creates an invisible fork that the next upstream update undoes. Contribute upstream, replace it, or pin a version instead.
- Plan for missing partners. Code that calls another plugin or a web service must cope when that side is absent or down (see How it fits together).
Keep AI working documents out of repositories
Tools such as Claude Code produce working documents: plans, specs, audits, brainstorm notes, project instruction files. They stay on your own machine and never go into git. They often describe unreleased changes, and once pushed to a public repository they are hard to remove.
The active plugin repositories commit this block in their .gitignore; add it to yours, and to your global git ignore file so new clones are covered too:
# Claude Code / superpowers / AI working docs - internal-only, never commit
CLAUDE.md
.claude/
docs/superpowers/
IMPROVEMENT_PLAN.md
AUDIT.md
audit.md
AUDIT_LOG.md
AUDIT-REMEDIATION-PLAN.md
Audit-*.html
BRAINSTORM-*.md
Stage files by name (git add <path>) rather than git add -A, and look at git status before every commit.
Security problems
Don't open a public GitHub issue for a security problem. Tell the MCME team privately, and give them time to fix it before you talk about it.