CurseForge · Minecraft mod
Lite Config
A minecraft JSON5/TOML configuration library
Quick answer
Which Lite Config release should I use?
Lite Config LiteConfig Fabric 1.3.0 for 1.21 targets 1.21, 1.21.8, 1.21.5 with Fabric. The project page does not say whether this file belongs on the client, dedicated server, or both. All 1 required mods have matching files.
Where it goes
Is Lite Config required on the client, server, or both?
The project page does not say whether this file belongs on the client, dedicated server, or both.
The source does not explicitly classify this release as client-only or server-only.
What else does Lite Config LiteConfig Fabric 1.3.0 for 1.21 need?
LiteConfig Fabric 1.3.0 for 1.21. Change the file and its required mods may change too.
Install Fabric API first. We found matching files for this game-version and loader setup.
We only count dependency files that match this setup. A file for another loader does not fill the gap.
Before you install it
Add Lite Config without breaking your instance.
Built for Lite Config LiteConfig Fabric 1.3.0 for 1.21. Pick another file and the loader, install side or required mods may change.
- 01
Stick to this file
Use LiteConfig Fabric 1.3.0 for 1.21. It targets 1.21, 1.21.8, 1.21.5 with Fabric; another release may have different loader, side or dependency requirements.
- 02
Bring the mods it needs
Install Fabric API first. We found matching files for this game-version and loader setup.
- 03
Put it on the correct side
The project page does not say whether this file belongs on the client, dedicated server, or both.
- 04
Pick the file you checked
Use the “Get this file” button beside LiteConfig Fabric 1.3.0 for 1.21. It opens that exact file at the source.
About this project
What does Lite Config add?
Lite Config
Lite Config is a JSON5/TOML configuration library for Minecraft mods on Fabric and NeoForge. Annotate any Java class with @Config and pass it to a builder to get a ConfigHolder that automatically manages file resolution, safe I/O, lifecycle events, sync, and more.
Features:
- Files: Read and write JSON5 or TOML, with defaults and recovery from damaged files.
- Updates: Validate changes and provide copies when you need to edit config data.
- Flexible reads: Read the current config from any thread.
- Ownership: Choose client/server settings or world-owned settings.
- Opt-In Network Sync: Automatically synchronizes marked configs or individual fields from server to client.
- Restart settings: CLIENT changes wait for game startup; WORLD changes apply when that world loads again; SERVER restart settings take effect after a game restart.
- Custom Update API:
updateandupdateAndSavereturn anUpdateResultwith acceptance status and validation violations. - Failure Policies: Granular control over read, write, and update errors, from graceful fallbacks to strict exceptions.
- Lifecycle Events and Hooks: Synchronous load, save, and update events, plus config-level normalization and validation hooks.
- Declared constraints: Enforces numeric bounds, string patterns, and collection sizes, and more via annotations on load/update.
- Runtime Metadata: Access every field's path, type, default, comment, translation key, and constraints at runtime.
- Version Migrations: Uses stamped file revisions to upgrade older configs step-by-step without losing player data.
- Persistence Control: Fully customize file paths, field names, automated comments, and ignored fields.
Outside Lite Config's Scope (yet):
- Config Screen: Lite Config is a data-layer solution and doesn't render config screens by itself, allowing you to pair it with any UI library or custom screens.
Documentation: Wiki
Setup
Lite Config is published to Maven Central under com.gmalvestiti.minecraft, with one artifact per loader:
| Loader | Artifact |
|---|---|
| Fabric | liteconfig-fabric |
| NeoForge | liteconfig-neoforge |
Version numbers include both the Lite Config version and the Minecraft target:
| Minecraft | Lite Config |
|---|---|
1.21-1.21.10 |
1.3.0-1.21 |
1.21.11 |
1.3.0-1.21.11 |
26.1-latest |
1.3.0-26.1 |
The examples below use the 1.21 build.
Fabric
repositories {
mavenCentral()
}
dependencies {
modImplementation 'com.gmalvestiti.minecraft:liteconfig-fabric:1.3.0-1.21'
}
Declare the dependency in fabric.mod.json so Fabric refuses to load the mod without Lite Config:
{
"depends": {
"liteconfig": ">=1.3.0-1.21"
}
}
NeoForge
repositories {
mavenCentral()
}
dependencies {
implementation 'com.gmalvestiti.minecraft:liteconfig-neoforge:1.3.0-1.21'
}
Declare the dependency in META-INF/neoforge.mods.toml:
[[dependencies.yourmodid]]
modId = "liteconfig"
type = "required"
versionRange = "[1.3.0,)"
ordering = "NONE"
side = "BOTH"
Quickstart
Start with one plain config class. Give each persisted field a default value.
@Config(name = "mymod", type = ConfigType.CLIENT) // JSON5, config/mymod.json5
public final class MyModConfig {
public boolean showHints = true;
public int hudScale = 2;
}
To use TOML instead, add format = ConfigFormat.TOML to @Config.
Create one holder during mod initialization and keep it for the life of the mod:
public final class MyMod implements ModInitializer {
public static final ConfigHolder<MyModConfig> CONFIG = LiteConfig.holder(MyModConfig.class)
.label("mymod")
.create();
}
or in the config class itself:
@Config(name = "mymod", type = ConfigType.CLIENT)
public final class MyModConfig {
public boolean showHints = true;
public int hudScale = 2;
public static final ConfigHolder<MyModConfig> CONFIG;
static {
CONFIG = LiteConfig.holder(MyModConfig.class)
.label("mymod")
.create();
}
}
create() validates the config model and loads active local settings, or writes defaults if the file does not exist yet.
Holders can be created before the game starts. Keep constructors, migrations and custom state cloners independent of Minecraft's runtime state.
Read the current published state with data():
if (MyMod.CONFIG.data().showHints) {
// ...
}
Apply runtime changes with update(...) or updateAndSave(...):
MyMod.CONFIG.update(config -> config.hudScale = 3); // memory only
MyMod.CONFIG.updateAndSave(config -> config.hudScale = 4); // memory + disk
Treat data() and its nested values as read-only. Use copy() when you need to edit a separate copy.
If a change is invalid, Lite Config rejects it and keeps the current state:
UpdateResult result = MyMod.CONFIG.update(config -> config.hudScale = 99);
if (!result.accepted()) {
result.violations().forEach(v -> LOGGER.warn("{}: {}", v.id(), v.message()));
}
The saved JSON5 file looks like this:
{
"showHints": true,
"hudScale": 4
}
Full Configuration Example
@Config(
name = "mymodfile",
path = "mymod/mymoddir1/mymoddir2",
type = ConfigType.SERVER,
readOnly = false,
format = ConfigFormat.JSON,
comment = "MyMod settings.",
version = 3,
stateCloner = MyModConfigCloner.class,
readFailurePolicy = FailurePolicy.FALLBACK,
writeFailurePolicy = FailurePolicy.STRICT,
updateFailurePolicy = FailurePolicy.FALLBACK,
restartSyncPolicy = RestartSyncPolicy.DISCONNECT
)
public final class MyModConfig implements ConfigExtension {
@Entry(
name = "hud_scale",
comment = "Scale of the HUD, from 1 to 4.",
translationKey = "mymod.config.hud_scale",
sync = SyncMode.ENABLED,
listener = "onHudScaleChanged"
)
@Range(min = 1, max = 4)
public int hudScale = 2;
@Entry(
comment = "Rendering backend. Applied after the next restart.",
restart = true,
sync = SyncMode.ENABLED
)
public Renderer renderer = Renderer.DEFAULT;
@AllowedValues(
value = {"mysql", "sqlite"},
normalize = EntryNormalization.NONE,
trim = true
)
public String database = "sqlite";
@AllowedValues(value = {"fast", "safe"}, normalize = EntryNormalization.UPPER_CASE)
public String mode = "SAFE";
@AllowedValues(value = {"Custom", "Default"}, normalize = EntryNormalization.NONE, trim = false)
public String label = "Custom";
@NotBlank
@Length(max = 16)
@Pattern("[a-z0-9_]+")
@Entry(comment = {"Profile used by server rules.", "Must be lowercase, alphanumeric, or underscore."})
public String profileName = "default";
@NotNull
@Entry(comment = "Server-owned spawn range.", sync = SyncMode.ENABLED)
public IntRange spawnRange = new IntRange(1, 12);
public Display display = new Display();
@Ignore
public Map<String, String> runtimeCache = new HashMap<>();
@Override
public void afterLoad() {
if (profileName != null) {
profileName = profileName.strip().toLowerCase(Locale.ROOT);
}
}
@Override
public void beforeSave() {
if (display != null && display.hiddenHints != null) {
display.hiddenHints.sort(String::compareTo);
}
}
@Override
public void validate(List<Violation> violations) {
if (spawnRange == null || spawnRange.minimum() > spawnRange.maximum()) {
violations.add(Violation.of(
"spawn-range.order",
"spawnRange minimum must not exceed its maximum"
));
}
}
private void onHudScaleChanged(Integer oldValue, Integer newValue, boolean fromSync) {
System.out.printf("HUD scale: %d -> %d (from server: %s)%n",
oldValue, newValue, fromSync);
}
@Migration(from = 1)
static void toVersion2(ConfigData data) {
data.rename("hudScale", "hud_scale");
}
@Migration(from = 2)
static void toVersion3(ConfigData data) {
if (!data.has("spawnRange")) {
data.set("spawnRange.minimum", 1)
.set("spawnRange.maximum", 12);
}
}
public static final class Display {
@Entry(comment = "Show contextual hints.")
public boolean showHints = true;
@Length(max = 32)
public List<String> hiddenHints = new ArrayList<>();
}
public enum Renderer {
DEFAULT,
COMPATIBILITY
}
}
// Custom type
public record IntRange(int minimum, int maximum) {
public static final Codec<IntRange> CODEC = RecordCodecBuilder.create(instance ->
instance.group(
Codec.INT.fieldOf("minimum").forGetter(IntRange::minimum),
Codec.INT.fieldOf("maximum").forGetter(IntRange::maximum)
).apply(instance, IntRange::new)
);
public static final StreamCodec<ByteBuf, IntRange> STREAM_CODEC =
StreamCodec.composite(
ByteBufCodecs.VAR_INT, IntRange::minimum,
ByteBufCodecs.VAR_INT, IntRange::maximum,
IntRange::new
);
}
// Custom config state cloner
public final class MyModConfigCloner implements StateCloner<MyModConfig> {
@Override
public MyModConfig copy(MyModConfig source) {
MyModConfig copy = new MyModConfig();
copy.hudScale = source.hudScale;
copy.renderer = source.renderer;
copy.database = source.database;
copy.profileName = source.profileName;
copy.spawnRange = source.spawnRange;
copy.display = copyDisplay(source.display);
copy.runtimeCache = source.runtimeCache == null
? new HashMap<>()
: new HashMap<>(source.runtimeCache);
return copy;
}
private static MyModConfig.Display copyDisplay(MyModConfig.Display source) {
if (source == null) {
return null;
}
MyModConfig.Display copy = new MyModConfig.Display();
copy.showHints = source.showHints;
copy.hiddenHints = source.hiddenHints == null
? null
: new ArrayList<>(source.hiddenHints);
return copy;
}
}
Register a custom Codec for file persistence and state copying, and a StreamCodec for synchronization.
public final class MyMod implements ModInitializer {
public static ConfigHolder<MyModConfig> config = LiteConfig.holder(MyModConfig.class, codecs -> codecs
.registerCodec(IntRange.class, IntRange.CODEC)
.registerStreamCodec(IntRange.class, IntRange.STREAM_CODEC))
.label("mymod")
.onUpdate(state -> System.out.println("HUD scale is now " + state.hudScale))
.onSave(state -> System.out.println("Saved MyMod config"))
.create();
@Override
public void onInitialize() {
// Fast shared read. Treat the returned object as read-only.
int currentScale = config.data().hudScale;
// Stable deep copy owned by this caller.
MyModConfig snapshot = config.copy();
snapshot.display.hiddenHints.add("crafting");
// Validated in-memory update.
UpdateResult result = config.update(state -> {
state.hudScale = 3;
state.display.hiddenHints = new ArrayList<>(
snapshot.display.hiddenHints
);
});
if (!result.accepted()) {
result.violations().forEach(violation ->
System.err.println(violation.id() + ": " + violation.message()));
}
// Update and save.
UpdateResult saved = config.updateAndSave(state ->
state.spawnRange = new IntRange(2, 24)
);
System.out.println("Saved: " + saved.accepted());
// Structural metadata for screens, commands, generated help, etc.
config.metadata().flatten().forEach(property ->
System.out.println(property.path() + " -> " + property.type().getSimpleName()));
}
}
The first create() loads config/mymod/mymoddir1/mymoddir2/mymodfile.json5, applies migrations, validates the result, and saves it. Files without configVersion start at version 1.
Only hud_scale, renderer, and spawnRange sync because they opt in with SyncMode.ENABLED.
Built-in values include primitives and wrappers, enums, arrays, typed List/Set/Map collections, UUID, BigInteger, BigDecimal, Duration, Instant, LocalDate, LocalTime, and LocalDateTime.
Lite Config
Lite Config is a JSON5/TOML configuration library for Minecraft mods on Fabric and NeoForge. Annotate any Java class with @Config and pass it to a builder to get a ConfigHolder that automatically manages file resolution, safe I/O, lifecycle events, sync, and more.
Features:
- Files: Read and write JSON5 or TOML, with defaults and recovery from damaged files.
- Updates: Validate changes and provide copies when you need to edit config data.
- Flexible reads: Read the current config from any thread.
- Ownership: Choose client/server settings or world-owned settings.
- Opt-In Network Sync: Automatically synchronizes marked configs or individual fields from server to client.
- Restart settings: CLIENT changes wait for game startup; WORLD changes apply when that world loads again; SERVER restart settings take effect after a game restart.
- Custom Update API:
updateandupdateAndSavereturn anUpdateResultwith acceptance status and validation violations. - Failure Policies: Granular control over read, write, and update errors, from graceful fallbacks to strict exceptions.
- Lifecycle Events and Hooks: Synchronous load, save, and update events, plus config-level normalization and validation hooks.
- Declared constraints: Enforces numeric bounds, string patterns, and collection sizes, and more via annotations on load/update.
- Runtime Metadata: Access every field's path, type, default, comment, translation key, and constraints at runtime.
- Version Migrations: Uses stamped file revisions to upgrade older configs step-by-step without losing player data.
- Persistence Control: Fully customize file paths, field names, automated comments, and ignored fields.
Outside Lite Config's Scope (yet):
- Config Screen: Lite Config is a data-layer solution and doesn't render config screens by itself, allowing you to pair it with any UI library or custom screens.
Documentation: Wiki
Setup
Lite Config is published to Maven Central under com.gmalvestiti.minecraft, with one artifact per loader:
| Loader | Artifact |
|---|---|
| Fabric | liteconfig-fabric |
| NeoForge | liteconfig-neoforge |
Version numbers include both the Lite Config version and the Minecraft target:
| Minecraft | Lite Config |
|---|---|
1.21-1.21.10 |
1.3.0-1.21 |
1.21.11 |
1.3.0-1.21.11 |
26.1-latest |
1.3.0-26.1 |
The examples below use the 1.21 build.
<details> <summary>Fabric</summary>
repositories {
mavenCentral()
}
dependencies {
modImplementation 'com.gmalvestiti.minecraft:liteconfig-fabric:1.3.0-1.21'
}
Declare the dependency in fabric.mod.json so Fabric refuses to load the mod without Lite Config:
{
"depends": {
"liteconfig": ">=1.3.0-1.21"
}
}
</details>
<details> <summary>NeoForge</summary>
repositories {
mavenCentral()
}
dependencies {
implementation 'com.gmalvestiti.minecraft:liteconfig-neoforge:1.3.0-1.21'
}
Declare the dependency in META-INF/neoforge.mods.toml:
[[dependencies.yourmodid]]
modId = "liteconfig"
type = "required"
versionRange = "[1.3.0,)"
ordering = "NONE"
side = "BOTH"
</details>
Quickstart
Start with one plain config class. Give each persisted field a default value.
@Config(name = "mymod", type = ConfigType.CLIENT) // JSON5, config/mymod.json5
public final class MyModConfig {
public boolean showHints = true;
public int hudScale = 2;
}
To use TOML instead, add format = ConfigFormat.TOML to @Config.
Create one holder during mod initialization and keep it for the life of the mod:
public final class MyMod implements ModInitializer {
public static final ConfigHolder<MyModConfig> CONFIG = LiteConfig.holder(MyModConfig.class)
.label("mymod")
.create();
}
or in the config class itself:
@Config(name = "mymod", type = ConfigType.CLIENT)
public final class MyModConfig {
public boolean showHints = true;
public int hudScale = 2;
public static final ConfigHolder<MyModConfig> CONFIG;
static {
CONFIG = LiteConfig.holder(MyModConfig.class)
.label("mymod")
.create();
}
}
create() validates the config model and loads active local settings, or writes defaults if the file does not exist yet.
Holders can be created before the game starts. Keep constructors, migrations and custom state cloners independent of Minecraft's runtime state.
Read the current published state with data():
if (MyMod.CONFIG.data().showHints) {
// ...
}
Apply runtime changes with update(...) or updateAndSave(...):
MyMod.CONFIG.update(config -> config.hudScale = 3); // memory only
MyMod.CONFIG.updateAndSave(config -> config.hudScale = 4); // memory + disk
Treat data() and its nested values as read-only. Use copy() when you need to edit a separate copy.
If a change is invalid, Lite Config rejects it and keeps the current state:
UpdateResult result = MyMod.CONFIG.update(config -> config.hudScale = 99);
if (!result.accepted()) {
result.violations().forEach(v -> LOGGER.warn("{}: {}", v.id(), v.message()));
}
The saved JSON5 file looks like this:
{
"showHints": true,
"hudScale": 4
}
Full Configuration Example
@Config(
name = "mymodfile",
path = "mymod/mymoddir1/mymoddir2",
type = ConfigType.SERVER,
readOnly = false,
format = ConfigFormat.JSON,
comment = "MyMod settings.",
version = 3,
stateCloner = MyModConfigCloner.class,
readFailurePolicy = FailurePolicy.FALLBACK,
writeFailurePolicy = FailurePolicy.STRICT,
updateFailurePolicy = FailurePolicy.FALLBACK,
restartSyncPolicy = RestartSyncPolicy.DISCONNECT
)
public final class MyModConfig implements ConfigExtension {
@Entry(
name = "hud_scale",
comment = "Scale of the HUD, from 1 to 4.",
translationKey = "mymod.config.hud_scale",
sync = SyncMode.ENABLED,
listener = "onHudScaleChanged"
)
@Range(min = 1, max = 4)
public int hudScale = 2;
@Entry(
comment = "Rendering backend. Applied after the next restart.",
restart = true,
sync = SyncMode.ENABLED
)
public Renderer renderer = Renderer.DEFAULT;
@AllowedValues(
value = {"mysql", "sqlite"},
normalize = EntryNormalization.NONE,
trim = true
)
public String database = "sqlite";
@AllowedValues(value = {"fast", "safe"}, normalize = EntryNormalization.UPPER_CASE)
public String mode = "SAFE";
@AllowedValues(value = {"Custom", "Default"}, normalize = EntryNormalization.NONE, trim = false)
public String label = "Custom";
@NotBlank
@Length(max = 16)
@Pattern("[a-z0-9_]+")
@Entry(comment = {"Profile used by server rules.", "Must be lowercase, alphanumeric, or underscore."})
public String profileName = "default";
@NotNull
@Entry(comment = "Server-owned spawn range.", sync = SyncMode.ENABLED)
public IntRange spawnRange = new IntRange(1, 12);
public Display display = new Display();
@Ignore
public Map<String, String> runtimeCache = new HashMap<>();
@Override
public void afterLoad() {
if (profileName != null) {
profileName = profileName.strip().toLowerCase(Locale.ROOT);
}
}
@Override
public void beforeSave() {
if (display != null && display.hiddenHints != null) {
display.hiddenHints.sort(String::compareTo);
}
}
@Override
public void validate(List<Violation> violations) {
if (spawnRange == null || spawnRange.minimum() > spawnRange.maximum()) {
violations.add(Violation.of(
"spawn-range.order",
"spawnRange minimum must not exceed its maximum"
));
}
}
private void onHudScaleChanged(Integer oldValue, Integer newValue, boolean fromSync) {
System.out.printf("HUD scale: %d -> %d (from server: %s)%n",
oldValue, newValue, fromSync);
}
@Migration(from = 1)
static void toVersion2(ConfigData data) {
data.rename("hudScale", "hud_scale");
}
@Migration(from = 2)
static void toVersion3(ConfigData data) {
if (!data.has("spawnRange")) {
data.set("spawnRange.minimum", 1)
.set("spawnRange.maximum", 12);
}
}
public static final class Display {
@Entry(comment = "Show contextual hints.")
public boolean showHints = true;
@Length(max = 32)
public List<String> hiddenHints = new ArrayList<>();
}
public enum Renderer {
DEFAULT,
COMPATIBILITY
}
}
// Custom type
public record IntRange(int minimum, int maximum) {
public static final Codec<IntRange> CODEC = RecordCodecBuilder.create(instance ->
instance.group(
Codec.INT.fieldOf("minimum").forGetter(IntRange::minimum),
Codec.INT.fieldOf("maximum").forGetter(IntRange::maximum)
).apply(instance, IntRange::new)
);
public static final StreamCodec<ByteBuf, IntRange> STREAM_CODEC =
StreamCodec.composite(
ByteBufCodecs.VAR_INT, IntRange::minimum,
ByteBufCodecs.VAR_INT, IntRange::maximum,
IntRange::new
);
}
// Custom config state cloner
public final class MyModConfigCloner implements StateCloner<MyModConfig> {
@Override
public MyModConfig copy(MyModConfig source) {
MyModConfig copy = new MyModConfig();
copy.hudScale = source.hudScale;
copy.renderer = source.renderer;
copy.database = source.database;
copy.profileName = source.profileName;
copy.spawnRange = source.spawnRange;
copy.display = copyDisplay(source.display);
copy.runtimeCache = source.runtimeCache == null
? new HashMap<>()
: new HashMap<>(source.runtimeCache);
return copy;
}
private static MyModConfig.Display copyDisplay(MyModConfig.Display source) {
if (source == null) {
return null;
}
MyModConfig.Display copy = new MyModConfig.Display();
copy.showHints = source.showHints;
copy.hiddenHints = source.hiddenHints == null
? null
: new ArrayList<>(source.hiddenHints);
return copy;
}
}
Register a custom Codec for file persistence and state copying, and a StreamCodec for synchronization.
public final class MyMod implements ModInitializer {
public static ConfigHolder<MyModConfig> config = LiteConfig.holder(MyModConfig.class, codecs -> codecs
.registerCodec(IntRange.class, IntRange.CODEC)
.registerStreamCodec(IntRange.class, IntRange.STREAM_CODEC))
.label("mymod")
.onUpdate(state -> System.out.println("HUD scale is now " + state.hudScale))
.onSave(state -> System.out.println("Saved MyMod config"))
.create();
@Override
public void onInitialize() {
// Fast shared read. Treat the returned object as read-only.
int currentScale = config.data().hudScale;
// Stable deep copy owned by this caller.
MyModConfig snapshot = config.copy();
snapshot.display.hiddenHints.add("crafting");
// Validated in-memory update.
UpdateResult result = config.update(state -> {
state.hudScale = 3;
state.display.hiddenHints = new ArrayList<>(
snapshot.display.hiddenHints
);
});
if (!result.accepted()) {
result.violations().forEach(violation ->
System.err.println(violation.id() + ": " + violation.message()));
}
// Update and save.
UpdateResult saved = config.updateAndSave(state ->
state.spawnRange = new IntRange(2, 24)
);
System.out.println("Saved: " + saved.accepted());
// Structural metadata for screens, commands, generated help, etc.
config.metadata().flatten().forEach(property ->
System.out.println(property.path() + " -> " + property.type().getSimpleName()));
}
}
The first create() loads config/mymod/mymoddir1/mymoddir2/mymodfile.json5, applies migrations, validates the result, and saves it. Files without configVersion start at version 1.
Only hud_scale, renderer, and spawnRange sync because they opt in with SyncMode.ENABLED.
Built-in values include primitives and wrappers, enums, arrays, typed List/Set/Map collections, UUID, BigInteger, BigDecimal, Duration, Instant, LocalDate, LocalTime, and LocalDateTime.
Project description from CurseForge.
Pick your setup
Lite Config by Minecraft version and loader
Choose the version and loader you play, then open the matching release.
26.3
2 loader builds26.2
2 loader builds26.1.2
2 loader builds26.1.1
2 loader builds26.1
2 loader builds1.21.11
2 loader builds1.21.10
2 loader builds1.21.9
2 loader builds1.21.8
2 loader builds1.21.7
2 loader builds1.21.6
2 loader builds1.21.5
2 loader buildsShowing the newest 12 of 17 game versions. Older files are in the list below.
Check the dependencies, then try the file in a copied instance before changing a world you care about.
Recent files
Lite Config versions and loaders
LiteConfig Fabric 1.3.0 for 1.21
liteconfig-fabric-1.3.0-1.21.jar
8 Nov 2026
LiteConfig NeoForge 1.3.0 for 1.21
liteconfig-neoforge-1.3.0-1.21.jar
8 Nov 2026
LiteConfig Fabric 1.3.0 for 1.21.11
liteconfig-fabric-1.3.0-1.21.11.jar
8 Nov 2026
LiteConfig NeoForge 1.3.0 for 1.21.11
liteconfig-neoforge-1.3.0-1.21.11.jar
8 Nov 2026
LiteConfig NeoForge 1.3.0 for 26.1
liteconfig-neoforge-1.3.0-26.1.jar
8 Nov 2026
LiteConfig Fabric 1.3.0 for 26.1
liteconfig-fabric-1.3.0-26.1.jar
8 Nov 2026
liteconfig-neoforge-1.2.0-1.21.11.jar
9 Sept 2026
liteconfig-neoforge-1.2.0-26.1.jar
9 Sept 2026
liteconfig-neoforge-1.2.0-1.21.jar
9 Sept 2026
liteconfig-fabric-1.2.0-26.1.jar
9 Sept 2026
liteconfig-fabric-1.2.0-1.21.11.jar
9 Sept 2026
liteconfig-fabric-1.2.0-1.21.jar
9 Sept 2026
Looking for an older file? The official CurseForge project page is in Resources.