Fabric config
Reference for mod configuration in Fabric Minecraft 1.20.1 — using Cloth Config API for GUI-based config screens, and plain TOML/JSON files with a custom serializer. Use this skill whenever the user asks about mod config, settings file, config screen, Cloth Config, ClothConfigScreen, AutoConfig, TOML config, JSON config, persistent mod settings, or config GUI. Triggers on: "mod config", "config file", "config screen", "Cloth Config", "ClothConfigScreen", "AutoConfig", "TOML", "settings screen", "config serializer", "persistent settings", or "mod options". Part of the fabric-mc-modding skill family.From its SKILL.md
npx -y skills add PSB1234/Fabric-Minecraft-Skill-1.20.1 --skill fabric-configAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
7.6 KB, ~1.7k tokens by cl100k_base, as published. Nobody here has run it
Fabric Config — 1.20.1 Reference
Two common approaches are covered here:
- Cloth Config + AutoConfig — GUI config screen with minimal boilerplate (recommended)
- Manual JSON/TOML — plain file-based config without a GUI dependency
Option A: Cloth Config + AutoConfig (Recommended)
1. Add dependency
build.gradle:
repositories {
maven { url "https://maven.shedaniel.me/" }
maven { url "https://maven.terraformersmc.com/releases/" }
}
dependencies {
// Cloth Config
modApi("me.shedaniel.cloth:cloth-config-fabric:11.1.136") {
exclude(group: "net.fabricmc.fabric-api")
}
// Optional: ModMenu integration (shows config button in mod list)
modImplementation "com.terraformersmc:modmenu:7.2.2"
}
gradle.properties — increment if you need newer versions:
cloth_config_version=11.1.136
modmenu_version=7.2.2
Include as JiJ (jar-in-jar) if you want to bundle it:
include("me.shedaniel.cloth:cloth-config-fabric:${project.cloth_config_version}")
2. Config class
@Config(name = "mymod") // generates mymod.json in .minecraft/config/
public class MyConfig implements ConfigData {
// These are the actual config values with defaults
public boolean enableFeature = true;
public int maxItems = 64;
public float damageMultiplier = 1.5f;
public String serverUrl = "example.com";
public List<String> allowedPlayers = new ArrayList<>();
// Bounds validation (Cloth Config respects these for sliders/fields)
@ConfigEntry.BoundedDiscrete(min = 1, max = 256)
public int tickRate = 20;
@ConfigEntry.ColorPicker
public int highlightColor = 0xFF00FF;
// Nested category
@ConfigEntry.Category("advanced")
public boolean debugMode = false;
}
3. Register and load
// In onInitialize() — do this before anything reads config values
public class MyMod implements ModInitializer {
public static MyConfig CONFIG;
@Override
public void onInitialize() {
AutoConfig.register(MyConfig.class, GsonConfigSerializer::new);
CONFIG = AutoConfig.getConfigHolder(MyConfig.class).getConfig();
// Now access config via MyMod.CONFIG.enableFeature etc.
}
}
4. ModMenu integration (optional, shows "Config" button)
Create src/main/java/com/example/mymod/ModMenuIntegration.java:
public class ModMenuIntegration implements ModMenuApi {
@Override
public ConfigScreenFactory<?> getModConfigScreenFactory() {
return parent -> AutoConfig.getConfigScreen(MyConfig.class, parent).get();
}
}
Register the entrypoint in fabric.mod.json:
{
"entrypoints": {
"modmenu": ["com.example.mymod.ModMenuIntegration"]
}
}
5. Saving config programmatically
// After modifying config values at runtime:
AutoConfig.getConfigHolder(MyConfig.class).save();
Option B: Manual JSON Config (No GUI)
Simple, zero-dependency approach using Gson:
Config class
public class ModConfig {
public boolean enableFeature = true;
public int maxItems = 64;
public float damageMultiplier = 1.5f;
public String serverUrl = "example.com";
}
Config manager
public class ConfigManager {
private static final Path CONFIG_PATH =
FabricLoader.getInstance().getConfigDir().resolve("mymod.json");
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
public static ModConfig config = new ModConfig(); // holds defaults
public static void load() {
if (Files.exists(CONFIG_PATH)) {
try (Reader reader = Files.newBufferedReader(CONFIG_PATH)) {
config = GSON.fromJson(reader, ModConfig.class);
if (config == null) config = new ModConfig();
} catch (IOException e) {
MyMod.LOGGER.error("Failed to load config", e);
config = new ModConfig();
}
} else {
save(); // write defaults on first run
}
}
public static void save() {
try {
Files.createDirectories(CONFIG_PATH.getParent());
try (Writer writer = Files.newBufferedWriter(CONFIG_PATH)) {
GSON.toJson(config, writer);
}
} catch (IOException e) {
MyMod.LOGGER.error("Failed to save config", e);
}
}
}
Call in onInitialize():
ConfigManager.load();
// Access: ConfigManager.config.enableFeature
Option C: Night Config (TOML files)
For TOML format with comments:
// build.gradle
dependencies {
implementation("com.electronwill.night-config:toml:3.6.7")
include("com.electronwill.night-config:toml:3.6.7")
include("com.electronwill.night-config:core:3.6.7")
}
public class TomlConfig {
private static final Path CONFIG_FILE =
FabricLoader.getInstance().getConfigDir().resolve("mymod.toml");
public static boolean enableFeature = true;
public static int maxItems = 64;
public static void load() {
CommentedFileConfig config = CommentedFileConfig.builder(CONFIG_FILE.toFile())
.sync()
.autosave()
.preserveInsertionOrder()
.build();
config.load();
// Read with defaults
enableFeature = config.getOrElse("general.enable_feature", true);
maxItems = config.getOrElse("general.max_items", 64);
// Write back (creates file with values on first run)
config.setComment("general.enable_feature", "Whether the feature is enabled");
config.set("general.enable_feature", enableFeature);
config.set("general.max_items", maxItems);
config.save();
}
}
Accessing Config Dir
Path configDir = FabricLoader.getInstance().getConfigDir();
// On client: .minecraft/config/
// On server: server-root/config/
Common Patterns
Read-only config (load once, never save at runtime)
- Load in
onInitialize(), use throughout.
Reloadable config (support /reload)
- Listen to
ServerLifecycleEvents.END_DATA_PACK_RELOADand callload()again.
Per-player config
- Store in NBT on the player entity or in a separate file per UUID.
Common Mistakes
- Cloth Config version mismatch — check https://modrinth.com/mod/cloth-config for the latest 1.20.1-compatible version.
CONFIGis null at startup —AutoConfig.register()must run beforegetConfig().- GSON deserializes null — always null-check or assign a new default instance if
fromJsonreturns null. - Config not persisting across runs — ensure
save()is called after any runtime changes.
Further Reading
- Cloth Config: https://github.com/shedaniel/ClothConfig
- AutoConfig: https://shedaniel.gitbook.io/cloth-config/auto-config
- ModMenu: https://github.com/TerraformersMC/ModMenu
Related Skills
fabric-mc-modding— project setupfabric-commands— exposing config values via commands
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.