# quilt-loader: a mod loader that keeps the old API alive beside the new one

> quilt-loader is the runtime for Quilt mods, and its source tree is organised around a promise it makes explicit: the API package is public, the implementation package is not, and three separate packages hold the fabric-loader code that mods still depend on. The contributing rules track where every class came from, and the licensing splits the loader from one SPDX data file.

**QuiltMC/quilt-loader** — The loader for Quilt mods.

- Repository: https://github.com/QuiltMC/quilt-loader
- Stars: 521 · Forks: 93
- Language: Java
- License: Apache-2.0
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/quiltmc-quilt-loader

## A loader that carries the old API alongside the new one

quilt-loader is the loader for mods under Quilt, and it provides mod loading facilities and useful abstractions for other mods to use. That is the whole description, and it is accurate because the project is the runtime rather than the tooling around it.

What makes it unusual is the source layout, and the layout is the design. The main source tree holds the normal loader code, and inside it the public API package is treated as quilt-loader's public API, where mods can freely make use of any of those classes and interfaces. Beside it sits the implementation package, which contains the loader internals, and the documentation is blunt that these can change at any time and so mods should not use any of them.

That split is the ordinary contract for a mod loader, and stating it in the source tree rather than only in the documentation is a useful signal. A mod that imports from the API package gets something the project intends to keep. A mod that reaches into the implementation package is relying on internals, and the loader will not protect it.

The default branch is named develop rather than main or master, which is the convention of a project that keeps its stable releases on tags while the working branch moves. The last push was on 2026-09-05, the repository is not archived, and there are no GitHub releases in the listing, so the artefacts are distributed through the channels the project uses rather than through tagged releases on the repository page.

The primary language is Java and the licence is Apache-2.0. The topic tags are short, just mod and quiltmc, which is what you would expect from a project whose scope is defined by the ecosystem it serves rather than by the problems it solves.

## The fabric-loader tree, kept in four separate packages

The most distinctive part of the repository is a set of source directories for the code inherited from fabric-loader, and the four packages are separated by a distinction that is easy to miss until you read all four descriptions.

The first holds all fabric-loader APIs, and specifically the non-deprecated APIs that any fabric mod can use. The second holds fabric-loader internal code that is nonetheless used by mods, even though this is discouraged. The third holds fabric-loader internal deprecated code, also used by mods and also discouraged, and the difference from the second package is that this one is for the classes and interfaces that fabric-loader itself has deprecated. The fourth package, for the test sources, is not built into the main jar file at all.

So there are four kinds of code in the tree and each has a different status. Public API is safe. Current internals are used but unsupported. Deprecated internals are used but unsupported and are on their way out. And the test sources are excluded from the shipped artefact.

The rule for adding to it is stated in the same place. When adding fabric internal compatibility classes they should always be annotated with the Deprecated annotation, to discourage quilt mods from accidently using them.

That instruction is the mechanism behind the whole arrangement. A class that exists for compatibility with the older loader is on its way out, so it is marked deprecated at the point it is added, which means the deprecation shows up in the consumer's editor rather than only in a changelog. The package layout and the annotation policy are two halves of the same decision.

One note in the fabric API package explains what the non-deprecated status does and does not mean. Some classes in that package are not deprecated, and this generally means quilt-loader does not have a replacement for it yet.

That is an honest reading of a transitional codebase. The absence of a deprecation mark can mean the API is stable, and it can also mean the project has not got around to replacing it, and the loader does not pretend otherwise.

## Two header files, and what they tell you about the code's provenance

The contributing section is short and it is about how a new file should be marked, and the two cases it names are the interesting part.

When adding new classes that you wrote yourself, they should use the quilt-only header file. When adding classes that contain code from fabric-loader, they should use the modified header file.

So the project tracks the provenance of every class in its source, and it does it in the file header rather than in a separate manifest. A class written from scratch and a class carried over from the older loader are distinguishable at the top of the file, which matters for a codebase that is part original work and part inherited compatibility surface.

The two header files live in a codeformat/ directory at the top level, which is where the build's formatting rules also live, alongside a checkstyle.xml for the Java style checks. That grouping is sensible: the header says what a file is, and the checkstyle configuration says what shape it has to be.

The encoding rule is the last thing stated. All files are expected to be encoded in UTF-8.

None of this is exciting on its own, and it is exactly the kind of detail that determines whether a large collaborative codebase stays navigable after a few years. When every file carries a marker of where it came from, the question of whether a class can be changed is answerable without archaeology.

The repository layout supports that too. There is a codeformat/ directory, a checkstyle.xml, an .editorconfig and a .gitattributes, plus a .github/ directory for the workflows. The Gradle build files are build.gradle and settings.gradle with a gradle.properties, a gradle/ directory and the gradlew wrapper alongside gradlew.bat for the Windows side.

## A licensing arrangement with one exception in it

The licence section has two parts, and the second one is the reason to read it.

The loader is licensed under the Apache License 2.0, with the LICENSE file at the repository root. That is the licence a project like this needs, because a mod loader sits between the game and the mods, and both sides need permission to redistribute what it does.

Then there is the exception. The license.json file that is included in the loader, which is used to generate SPDX license instances, is licensed under Creative Commons Attribution 3.0 with the SPDX License ID CC-BY-3.0, from SPDX.

So the loader is Apache-2.0 and one JSON file inside it is CC-BY-3.0. The reason is specific and not arbitrary: the file is a list of licence identifiers, and SPDX publishes those lists under a Creative Commons Attribution licence, so including the list and calling it Apache-2.0 would be a misattribution of somebody else's data.

That is a detail most projects get wrong by accident, and it is worth noticing here because the file is named in the readme rather than buried. The practical consequence for anyone redistributing the loader is that the attribution obligation travels with that one file.

For a mod loader, the licensing of the loader itself is not a formality, because the loader is what puts third party code into the game's process. A project whose users run arbitrary mods on their own installations needs the loader to be permissively licensed so that those mods can be, and so that the loader can be shipped with the game or with a mod pack without a licensing argument.

The repository also carries a LICENSE file at the root, and the Apache-2.0 identifier is what the project metadata records.

## The build directories, and what they say about what gets shipped

The top level of the repository lists a set of directories whose names map onto the build, and three of them are worth explaining because they show what ends up in the artefact.

There is a dependencies/ directory, a junit/ directory, a minecraft/ directory and a minecraft-test/ directory, along with the src/ directory that holds the loader sources described earlier. The gradle/ directory holds the wrapper and its configuration, and gradlew with gradlew.bat provide the wrapper scripts for Unix and for Windows.

The presence of a minecraft/ directory and a separate minecraft-test/ directory tells you that the game is not simply a dependency pulled from a repository. The loader is built against the game, so the game has to be present as a source set, and the test directory is the counterpart that keeps the tests from being folded into the shipped jar.

That matches what the source layout says about the test sources not being built into the main jar file. The separation is deliberate and appears twice, once in the build directories and once in the source tree description.

The dependencies/ directory is a further sign of how the build is put together. A loader that ships with the game needs the game's libraries at a fixed version, and the presence of a local dependencies directory suggests those are vendored rather than resolved fresh each time, which is what you want when the artefact has to be reproducible for a specific game version.

None of this is documented in the readme in those terms, and it should be read as an inference from the directory names rather than as a claim about the build internals. But the names are specific enough to say something useful: this is a project that builds the game and the loader together, keeps the tests separate from the shipped artefact, and pins its dependencies.

What the readme does not document is equally worth noting. There is no installation section, no configuration reference and no description of how a mod is actually loaded at runtime, and no list of what the loader provides beyond mod loading facilities and abstractions other mods can use. For a project of this size that is a thin document, and the source tree and the build directories carry most of the information a reader would otherwise want.

## Conclusion

quilt-loader suits a mod author working in the Quilt ecosystem who needs the fabric-loader API surface to keep working while the ecosystem moves, since the deprecated internals are still present and still marked as such in your editor. It does not suit you as a stable dependency to build a library against, since the implementation package can change at any time and only the API package carries a promise. Before you write a mod against it, check whether the class you want lives in the API package or in one of the three fabric packages, because that choice decides whether a later loader update breaks you, and read the header file rules before you contribute a class back.

## FAQ

### What is quilt-loader and what does it provide?

It is the loader for mods under Quilt, providing mod loading facilities and useful abstractions for other mods to use. Mods can freely use the classes and interfaces in the public API package, while the implementation package holds internals that can change at any time and should not be used by mods.

### What is the difference between the fabric-loader packages in quilt-loader?

There are three of them. One holds the non-deprecated fabric-loader APIs that any fabric mod can use, one holds fabric-loader internal code that is used by mods even though that is discouraged, and one holds fabric-loader internal deprecated code, used by mods even though it is discouraged, which is the package for the classes and interfaces fabric-loader itself has deprecated.

### Why should fabric internal compatibility classes be annotated with Deprecated?

The contributing guidance says they should always be annotated with Deprecated to discourage quilt mods from accidently using them. The annotation means the deprecation appears in the consumer's editor rather than only in a changelog.

### How is quilt-loader licensed?

The loader is licensed under the Apache License 2.0. The license.json file included in the loader, which is used to generate SPDX licence instances, is licensed under Creative Commons Attribution 3.0 with the SPDX Licence ID CC-BY-3.0, because the identifier lists come from SPDX under that licence.

### What are the header files used for when contributing to quilt-loader?

New classes you wrote yourself should use the quilt-only header file in the codeformat directory, and classes that contain code from fabric-loader should use the modified header file. All files are expected to be encoded in UTF-8.

## Sources

- [Issues](https://github.com/QuiltMC/quilt-loader/issues)
- [License: Apache-2.0](https://github.com/QuiltMC/quilt-loader/blob/develop/LICENSE)
- [QuiltMC/quilt-loader on GitHub](https://github.com/QuiltMC/quilt-loader)
- [README](https://github.com/QuiltMC/quilt-loader/blob/develop/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/quiltmc-quilt-loader
