fabric-version-porting
Skill4 starsChanged 12 days agoMITView on GitHub
Port a Fabric mod from one Minecraft version to another - including the big Yarn -> Mojang mappings migration required for Minecraft 26.1+, Fabric API renames, reading Fabric and Minecraft changelogs, and fixing compile errors and broken mixins until the build passes. Use when asked to update, port, bump or "make it work on" a different Minecraft version.
In this repository10 other files it gives its agents.
- checkSkill
- fabric-client-renderingSkill
- fabric-config-and-keybindsSkill
- fabric-crash-debuggingSkill
- fabric-mixinsSkill
- fabric-networkingSkill
- fabric-project-setupSkill
- fabric-releaseSkill
- newSkill
- portSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
14 rules. About 0 are common, 8 are distinctive, and 6 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈8
Distinctive · estimate
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 28
Create a branch: git switch -c port/<target-version>.
- Distinctive: line 42
If a required dependency has no build for the target version, stop and tell the user - do not remove features silently.
- Distinctive: line 47
Do this while still on the old Minecraft version, so the code compiles before and after.
- Very specific: line 64
Commit this step on its own: git commit -m "Migrate Yarn to Mojang mappings".
- Very specific: line 78
delete the mappings line
- Distinctive: line 90
Search the Fabric API rename list / porting page for that version.
- Very specific: line 91
Search generated sources (./gradlew genSources) for the class or for a nearby string or constant you know is still there.
- Distinctive: line 93
Look at how vanilla itself does it now (e.g.
- Distinctive: line 94
Use https://mappings.dev or Linkie (https://linkie.shedaniel.dev) to translate between Yarn / Mojang / intermediary names for older …
- Distinctive: line 96
Use the IntelliJ migration map from the 26.1 porting page to bulk-rename Fabric API classes.
- Distinctive: line 97
Keep behaviour identical; a port is not the time to refactor.
- Very specific: line 169
Update CHANGELOG.md, mod_version (porting alone is usually a minor/patch bump - see fabric-release), README "supported versions", and CI …
- Distinctive: line 171
Commit in logical steps: mappings migration, build bump, code fixes, mixin fixes.
- Very specific: line 175
If the user needs more than one Minecraft version at once, do not interleave versions with if checks at runtime.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Fabric version porting
Porting is a loop: bump -> build -> read the first error -> look up the new API -> fix -> build again. The skill is in doing it in the right order and never guessing new names.
Step 1 - Establish where you are and where you are going
grep -E "minecraft_version|yarn_mappings|loader_version|loom_version|fabric_api_version" gradle.properties
grep -nE "fabric-loom|mappings|modImplementation" build.gradle
git status # must be clean - commit or stash firstThen classify the jump:
| From | To | Difficulty |
| X.Y.a | X.Y.b (patch, e.g. 1.21.4 -> 1.21.5) | Can still be large: Mojang ships big refactors in "minor" drops |
| any 1.21.x, Yarn | 26.1+ | Two migrations: Yarn -> Mojang names first, then the version bump. Never both at once |
| any 1.21.x, Mojang mappings | 26.1+ | Remove remapping (plugin id, mappings line, mod* configs), then fix renames |
| 26.x | 26.y | Mojang names on both sides; normal version bump |
Create a branch: git switch -c port/<target-version>.
Step 2 - Gather the change information (read before editing)
| Source | What it tells you |
| https://fabricmc.net/blog/ | Fabric's "Fabric for Minecraft X" post: Loader/Loom/API breaking changes, renamed APIs |
| https://docs.fabricmc.net/develop/porting/ | Version-specific porting guide (use the version selector); for 26.1 there is a full Fabric API rename list and an IntelliJ migration map |
| https://fabricmc.net/develop/ | The exact Loader / Loom / Fabric API versions for the target |
| https://github.com/FabricMC/fabric-example-mod (history) | How the template's build.gradle, Java version and Gradle version changed |
| Minecraft.net Java Edition release article + Minecraft Wiki version page | Gameplay and data-format changes |
NeoForge's version primers (neoforged.net blog / NeoForged/.github primers) | Very detailed vanilla code changes between versions; loader-agnostic for vanilla classes |
| Your dependencies' Modrinth pages | Whether Mod Menu, YACL, etc. have a build for the target yet |
If a required dependency has no build for the target version, stop and tell the user - do not remove features silently.
Step 3 - (Only if leaving Yarn) migrate mappings on the OLD version first
Do this while still on the old Minecraft version, so the code compiles before and after.
# Requires Loom 1.13+ on the old version. Replace 1.21.11 with your CURRENT version.
./gradlew migrateMappings --mappings "net.minecraft:mappings:1.21.11" --overrideInputsIHaveABackup
./gradlew migrateClientMappings --mappings "net.minecraft:mappings:1.21.11" --overrideInputsIHaveABackup # split source sets
./gradlew migrateClassTweakerMappings --mappings "net.minecraft:mappings:1.21.11" --overrideInputsIHaveABackupThen in build.gradle replace the Yarn line with mappings loom.officialMojangMappings(),
remove yarn_mappings from gradle.properties, refresh Gradle and build.
migrateMappingsdoes not handle Kotlin; use the Ravel IntelliJ plugin for Kotlin (it also handles complex projects better because it resolves through the IDE).- Mixin targets in string form (
method = "...",target = "L...;") are often not rewritten. Grep every mixin and fix the strings by hand:grep -rn "target = \|method = " src/*/java/**/mixin. - Commit this step on its own:
git commit -m "Migrate Yarn to Mojang mappings".
Docs: https://docs.fabricmc.net/develop/porting/mappings/
Step 4 - Bump the build
- Gradle wrapper:
./gradlew wrapper --gradle-version <version the template uses>(run twice if the first run upgrades the wrapper only). gradle.properties:minecraft_version,loader_version,loom_version,fabric_api_version, and every dependency version - all from Step 2 sources.- Java: set
options.release,sourceCompatibility, mixincompatibilityLevel, andfabric.mod.json"java"to what the target requires (26.x template: 25; 1.20.5 - 1.21.x: 21). - Crossing into 26.1+:
- plugin id
net.fabricmc.fabric-loom-remap/fabric-loom->net.fabricmc.fabric-loom - delete the
mappingsline modImplementation->implementation,modCompileOnly->compileOnly,modLocalRuntime->localRuntime,modApi->api- anything using
remapJar(publishing tasks, CI artifact paths) ->jar
- plugin id
fabric.mod.json: updatedepends.minecraft(~<target>),fabricloader,java../gradlew --refresh-dependencies build(or./gradlew build --refresh-dependencies).
Step 5 - Fix compile errors systematically
- Work through errors in order of dependency: registration/common code first, then client, then mixins. Fixing a core type often clears dozens of errors at once.
- For each unknown symbol, find the new name - do not invent one:
- Search the Fabric API rename list / porting page for that version.
- Search generated sources (
./gradlew genSources) for the class or for a nearby string or constant you know is still there. - Look at how vanilla itself does it now (e.g. how vanilla's own HUD or screens draw).
- Use https://mappings.dev or Linkie (https://linkie.shedaniel.dev) to translate between Yarn / Mojang / intermediary names for older versions.
- Use the IntelliJ migration map from the 26.1 porting page to bulk-rename Fabric API classes.
- Keep behaviour identical; a port is not the time to refactor.
Typical renames you will meet
Fabric API 26.1 (Yarn-flavoured names -> official names), excerpt:
| Old | New |
KeyBindingHelper.registerKeyBinding (client.keybinding.v1) | KeyMappingHelper.registerKeyMapping (client.keymapping.v1) |
PayloadTypeRegistry.playS2C() / playC2S() | clientboundPlay() / serverboundPlay() |
S2CPlayChannelEvents / C2SPlayChannelEvents | ClientboundPlayChannelEvents / ServerboundPlayChannelEvents |
PacketByteBufs | FriendlyByteBufs |
WorldRenderEvents / WorldRenderContext (rendering.v1.world) | LevelRenderEvents / LevelRenderContext (rendering.v1.level) |
ClientTickEvents.EndWorldTick / ServerWorldEvents | EndLevelTick / ServerLevelEvents |
ItemGroupEvents, FabricItemGroup (itemgroup.v1) | CreativeModeTabEvents, FabricCreativeModeTab (creativetab.v1) |
ClientCommandManager | ClientCommands |
BlockRenderLayerMap | ChunkSectionLayerMap |
ColorProviderRegistry.BLOCK | BlockColorRegistry |
TooltipComponentCallback | ClientTooltipComponentCallback |
EntityModelLayerRegistry | ModelLayerRegistry |
FabricTagProvider (and nested ...TagProvider) | FabricTagsProvider (...TagsProvider) |
ExtendedScreenHandlerType (screenhandler.v1) | ExtendedMenuType (menu.v1) |
FuelRegistryEvents | FuelValueEvents |
Full list: https://docs.fabricmc.net/26.1/develop/porting/fabric-api
Vanilla, Yarn -> Mojang (the names you will see most):
| Yarn | Mojang |
MinecraftClient | Minecraft |
DrawContext | GuiGraphics (26.1+: GuiGraphicsExtractor) |
TextRenderer | Font |
Text / Formatting | Component / ChatFormatting |
PlayerEntity / ServerPlayerEntity / ClientPlayerEntity | Player / ServerPlayer / LocalPlayer |
World / ServerWorld / ClientWorld | Level / ServerLevel / ClientLevel |
BlockState, BlockPos | unchanged |
Identifier.of(ns, path) | Identifier.fromNamespaceAndPath(ns, path) (ResourceLocation before 1.21.11) |
ItemStack#getItem, Item.Settings | ItemStack#getItem, Item.Properties |
ScreenHandler | AbstractContainerMenu |
MatrixStack | PoseStack |
KeyBinding#wasPressed | KeyMapping#consumeClick |
Registries.ITEM / Registry.register | BuiltInRegistries.ITEM / Registry.register |
NbtCompound | CompoundTag |
CustomPayload / PacketCodec | CustomPacketPayload / StreamCodec |
26.1 -> 26.2 also renamed vanilla rendering entry points (for example Screen#render ->
extractRenderState, GuiGraphics#drawString -> text, minecraft.setScreen ->
minecraft.gui.setScreen). 26.3 replaced GLFW with SDL for input: InputConstants.Type.KEYSYM
became KEYBOARD, key codes are SDL scancodes, and org.lwjgl.glfw imports stop compiling (use
InputConstants.KEY_* constants). The F1 flag moved from options.hideGui to
gui.hud.isHidden(). Expect similar churn in every release and verify in sources.
Step 6 - Fix mixins (they fail at runtime, not compile time)
A mixin whose target moved still compiles. Find them before users do:
./gradlew buildand read every mixin annotation-processor warning ("Cannot find target", "Cannot remap") - treat each as an error../gradlew runClient(andrunServer) with"defaultRequire": 1in the mixin configs; any target that no longer matches crashes at startup with the mixin and method named.- For each failing mixin, open the target in the new sources and re-derive the injection point. Often the logic moved to another method or class; sometimes a new Fabric API event makes the mixin unnecessary - prefer deleting the mixin when it does.
- Re-run with
-Dmixin.debug.export=trueto inspect the result (seefabric-mixins).
Step 7 - Verify behaviour, then finish
./gradlew buildpasses with no new warnings.runClient: join a singleplayer world, exercise every feature, open every screen.runServer(if the mod is not client-only): starts withoutClassNotFoundExceptionor "invalid dist" errors; join it from the dev client if possible.- Update
CHANGELOG.md,mod_version(porting alone is usually a minor/patch bump - seefabric-release), README "supported versions", and CI matrices. - Commit in logical steps: mappings migration, build bump, code fixes, mixin fixes.
Supporting several versions
If the user needs more than one Minecraft version at once, do not interleave versions with
if checks at runtime. Use one git branch per version (simplest) or a preprocessor-based
multi-version setup (e.g. Stonecutter). Ask the user before introducing the latter.
Common mistakes
- Bumping Minecraft and migrating Yarn -> Mojang in the same step; nothing compiles and the migration tools stop working (they need the old version to resolve names).
- Guessing new names from memory instead of the rename list or generated sources.
- Keeping a
mappingsline,modImplementation,remapJaror the old plugin id after moving to 26.1+. - Forgetting to bump Java (
options.release, mixincompatibilityLevel,fabric.mod.json). - Updating
build.gradlebut notfabric.mod.jsondepends.minecraft, so the mod refuses to load (or worse, loads on the wrong version). - Declaring the port finished when it compiles. Mixins and registries fail at runtime - run the client and server.
- Silently deleting a feature or a mixin that no longer compiles. Report it to the user.
- Dropping a dependency because "it has no version yet" without asking.
- Large opportunistic refactors during the port, which make regressions impossible to bisect.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

