Skip to content

Quickstart

GMalvestiti edited this page Aug 31, 2026 · 2 revisions

The builder creates either a mutable or read-only holder. Every holder exposes synchronous methods for calling-thread work and asynchronous methods backed by the shared config worker:

Builder call Behavior Best fit
create() Allows synchronous and asynchronous changes Regular runtime config
readOnly().create() Refuses loads and updates Config a mod reads but never changes

Declare the config class. Initialize persisted fields to their defaults and provide a public no-argument constructor:

@Config(name = "mymod") // format defaults to JSON5
public final class MyModConfig {
    public boolean showHints = true;
    public int hudScale = 2;
}

or for TOML:

@Config(name = "mymod", format = ConfigFormat.TOML)
public final class MyModConfig {
    public boolean showHints = true;
    public int hudScale = 2;
}

Create the holder once during mod initialization and keep it for the lifetime of the mod. create() resolves the file path, validates the model, loads any existing file (or writes the defaults if none exists), and validates the loaded state — the holder is ready to read immediately after it returns:

public final class MyMod implements ModInitializer {

    public static final ConfigHolder<MyModConfig> CONFIG = LiteConfig.holder(MyModConfig.class)
        .modId("mymod")
        .create();
}

Read through data(), mutate through update / updateAndSave:

if (MyMod.CONFIG.data().showHints) {
    // ...
}

MyMod.CONFIG.updateAndSave(config -> config.hudScale = 3);

That writes config/mymod.json5:

{
  "showHints": true,
  "hudScale": 3
}

Clone this wiki locally