Custom enchantments without mods: the data-driven enchantment format
Enchantments became datapack JSON, so a custom one needs no mod. Here is the file shape, the effect components that actually do something, and how to make it obtainable.
Enchantments used to be hardcoded. They are now datapack data, which means a genuinely custom enchantment — new name, new effect, new cost curve — is a JSON file.
Where it lives
data/<namespace>/enchantment/lightning_strike.json
Singular enchantment/, like every other datapack category since the rename.
The minimum file
{
"description": { "translate": "enchantment.my_pack.lightning_strike" },
"supported_items": "#minecraft:enchantable/sword",
"weight": 2,
"max_level": 3,
"min_cost": { "base": 10, "per_level_above_first": 10 },
"max_cost": { "base": 50, "per_level_above_first": 10 },
"anvil_cost": 4,
"slots": ["mainhand"]
}
That much gives a real enchantment that appears at the table and shows on the item. It does nothing yet — behaviour is separate.
weightis rarity at the enchanting table. Vanilla uses 10 for common, 1 for very
rare. It is relative, not a percentage.
slotsdecides where the enchantment is active:mainhand,offhand,armor,
head, and so on. Omit it and the enchantment never applies.
supported_itemstakes an item tag or a list.#minecraft:enchantable/*tags
already exist for the sensible groups.
Making it do something
effects attaches behaviour:
"effects": {
"minecraft:post_attack": [{
"effect": { "type": "minecraft:run_function", "function": "my_pack:strike" },
"requirements": { "condition": "minecraft:random_chance", "chance": 0.25 }
}]
}
run_function is the escape hatch — anything a function can do, the enchantment can do. The built-in effect types cover damage, knockback, durability, item drops and attributes without needing a function at all, and they are cheaper.
requirements takes any predicate, so gating on the target's type, the weather, or a random chance is one block of JSON.
Naming it
description is a text component, so a hardcoded name works:
"description": { "text": "Lightning Strike", "color": "gold" }
but a translate key plus a language file in a resource pack is what makes it read correctly for players in other languages — the same reason this site takes game terms from Mojang's own translations.
Making it obtainable
Three routes, and you usually want more than one:
- Enchanting table — automatic once
weightand the cost curve are set. - Loot tables —
enchant_randomlywith your enchantment listed, or
enchant_with_levels if it should compete on cost.
- Villager trades — an enchanted book with your enchantment in the trade's item.
Adding it to #minecraft:in_enchanting_table is what makes the table offer it at all; the tag is easy to forget and produces an enchantment that exists but never appears.
Build the enchantment JSON and its armor-trim counterpart, with the tags and slots set, in the Custom Enchantment & Trim Builder.