How to make your own Horizon mod

Follow the official make-a-mod path: pick content or native, set up the tools, build Playtime in the game, run the checks and publish to the Horizon registry.

By: MC Horizon editors · Published · Updated

To make a Horizon mod, first pick the kind. A content mod (.hmod) adds blocks, items, recipes and textures from data files, and you build it with the cargo horizon-mod tool. A native mod (.hnmod) is Rust code that hooks into the game: a HUD, keys, commands, new behaviour. You write it against Horizon’s hook points, check it with native.py from the registry repository, build a game with it through the launcher, then submit it at playhorizon.dev/mods/submit for review.

Everything below follows the official docs. Where the docs show code, we quote the small pieces that matter; we don’t invent APIs.

Pick the kind

Content mod Native mod
What it adds Blocks, items, recipes, loot tables, tags, models, textures, names, structures HUD elements, keys, commands, settings, new behaviour
File .hmod .hnmod
Code None Rust, compiled into the game
Players get it by The game reading it at start The launcher compiling a game with it
Safety Can’t run anything Not sandboxed

Rule of thumb from the docs: if you add a thing (a block, an item, a structure), make a content mod. If the mod has to do something, make a native mod. They can ship side by side, with the native part holding behaviour and the content part holding the blocks.

Write bundlenative.py checknative-buildTest in gamepackage .hnmodminisign (optional)Submit manifest + .rs filescargo check on Horizonlauncher compiles gameOptions › Modssame files, same hashsign each versiona person reads it all
The native mod path from the official guide. Content mods skip the compile steps and use cargo horizon-mod build and check.

Path A: a content mod in an afternoon

Install the tool (it needs Rust from rustup.rs and builds from source in a few minutes), then scaffold a mod:

cargo install --git https://github.com/horizon-rust/horizon cargo-horizon-mod
cargo horizon-mod new my-blocks --template content

The template gives you one working block, Glowing Amethyst: an amethyst block that gives light, with its block state, model, item model, name, loot table, a recipe and the pickaxe tag. Copy and rename its files to add your own.

The pieces you’ll touch:

  • horizon-mod.toml, the manifest: id, name, version, description, authors, api = "0.2", side = "both", capabilities = ["registries"]. Unknown keys are refused, so typos fail loudly.
  • Blocks in data/<id>/horizon/block/<name>.json. Each copies a vanilla template (minecraft:iron_block, minecraft:oak_door…) and overrides properties such as hardness, light (0–15), sounds or map colour.
  • Items in data/<id>/horizon/item/<name>.json, also from a template, with optional max_stack_size and rarity.
  • Everything else uses vanilla 26.3’s own data pack and resource pack formats: recipes, loot tables, tags, block states, models, textures, lang/en_us.json.

While you work, run the game with the folder as a dev mod: in the launcher’s Settings, put --dev-mod "/path/to/your-mod" in Game arguments and press Play. When it’s ready, cargo horizon-mod build packs target/horizon-mod/<id>.hmod, and cargo horizon-mod check on that file reads it the way the registry does. One limit to plan around: content mods work in single player today; playing them together on a server is planned.

Path B: a native mod

Tools

  • Rust (stable toolchain) and Git.
  • Python 3.11 or later and rsync. On Windows, use WSL for the checks.
  • A clone of the registry repository: git clone https://github.com/horizon-rust/horizon-mods. Its native/tools/native.py applies your bundle to Horizon’s source, checks it, builds it and packages the .hnmod.
  • A current launcher, prepared at least once. Launcher 0.2.37 or later also builds mods written with the newer typed API.

How it works

A native mod is a bundle for horizon-mixins: a manifest, horizon-mixin.toml, plus a few .rs files. Before the game compiles, horizon-mixins pastes your code into Horizon’s source and calls it from the hook points the manifest names. Horizon exposes more than 350 hook points and 100 helpers; the first eleven cover most beginner mods, among them native_tick, native_frame, native_hud, native_key, native_command and native_mods (your row in Options → Mods). Hook points keep their names and parameters between releases and are only ever added to, so a mod using only them keeps building on later Nightlies.

The worked example: Playtime

The docs build Playtime, which counts how long you’ve played, shows it in the top-right corner, answers /playtime and /playtime reset, and has a settings page with one button. It hooks six points. Its own logic lives in runtime.rs as plain Rust you can unit-test without the game, for example the formatter:

/// `1h 05m` from a number of ticks (20 a second).
pub fn format(ticks: u64) -> String {
    let minutes = ticks / 20 / 60;
    format!("{}h {:02}m", minutes / 60, minutes % 60)
}

Each hook then gets a small helper file (tick.rs, hud.rs, command.rs…) that starts by checking game.native_on(m::ID), so the mod does nothing while switched off, and calls helpers like native_text, native_fill and native_set_setting. The full listing, including the [[injection]] entries of the manifest, is on the Hook points and helpers page. If you’d rather start from real code, Horizon’s own mods sit in horizon-mods’ native/ folder; the docs call fps-overlay, the source of the FPS Counter mod, the smallest.

Check, build, play

cd horizon-mods
python3 native/tools/native.py check /path/to/playtime
horizon-launcher native-build /path/to/playtime/mixins/playtime --trust-native-code

check downloads Horizon’s source at the commit your compatibility.json names, applies the bundle and runs cargo check. The first run takes several minutes, later ones seconds to a minute. native-build compiles a game for the instance picked in the launcher; the first build downloads Rust and takes 20 to 30 minutes. Tip from the docs: horizon-launcher settings native-profile dev makes rebuilds about six times faster while the game runs up to about twice as slow. Switch back to performance to play.

The typed API

Nightlies since 3 November 2026 also offer a typed API: one crate implementing the Hooks trait, with a typed event per hook (the docs’ example halves damage to pigs). It’s newer, and native.py doesn’t handle it yet, so the docs advise mixin helpers for a mod you want in the registry today.

Test it

  • cargo test for your own logic.
  • native.py check … --horizon latest against the newest Nightly, every time one comes out.
  • In game: your row in Options → Mods, the switch off (the mod must do nothing), every command with good and bad arguments, single player and a server, F1 and F3, quit and restart.
  • A panic in your code stops the game, so use Option and Result as the helpers do.

Content mods: place, mine and craft each thing, read logs/latest.log. For both kinds, finish with cargo horizon-mod check <file>, which runs the registry’s own checks.

Publish it

  1. Bump version in the manifest; published files never change.
  2. Put the source in a public repository under an SPDX licence such as MIT or Apache-2.0. Reviewers read it.
  3. For native mods, native.py package writes native/target/<id>-<version>.hnmod. The same files always give the same file, so anyone can rebuild and compare.
  4. Optionally sign with minisign. Once a project has a public key, every later version must be signed with it.
  5. Submit at playhorizon.dev/mods/submit with a GitHub sign-in. That opens a pull request in horizon-mods; a reviewer reads it, and for a native mod reads every line.

After the merge the file becomes a registry release within minutes and appears in the launcher and in our mod catalog. Players then install it as described in how to install mods, behind a warning that names your mod, because native code isn’t sandboxed. Why that review matters is covered in Is Horizon safe?

Sources

FAQ

Do I need to know Java modding to make a Horizon mod?

No. The official guide says no Minecraft modding experience is needed. Content mods use the same JSON formats as vanilla data packs and resource packs; native mods are Rust.

Can I port my Fabric mod to Horizon?

Not by recompiling it. Its data and assets can become a content mod, and its behaviour has to be rewritten in Rust as a native mod on Horizon's hook points.

Which is more stable to build on?

Content mods (api 0.2) are at the preview level. Native mods are marked experimental, though hook points are only ever added, never renamed, so a mod that uses only hook points keeps building on later Nightlies.

Comments

Comments load when you scroll down to them.