Writing Minecraft mods with Nix (Updated)
Surprisingly enough, my most popular blog post was about modding Minecraft on NixOS.
Recently, an acquaintance of mine, Wrees has asked me how I set up my dev environment for MC modding.
Apparently, he found out my blog post!
So I’ve decided to revisit this issue and provide an actually definitive guide on how to do MC mods with Nix.
Requirements
- Nix (with flakes support)
- IntelliJ (every other Java IDE sucks for Minecraft modding)
- Direnv (optional)
- A Minecraft mod project
Direnv is optional, however, recommended. It’s gonna be much easier to use direnv, you’re not gonna have to type
nix developevery time you open the project’s folder, additionally, there is an IntelliJ plugin for direnv support.
Flake
Your flake.nix should be the following:
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05";
flake-parts.url = "github:hercules-ci/flake-parts";
systems.url = "github:nix-systems/default";
};
outputs = inputs:
inputs.flake-parts.lib.mkFlake { inherit inputs; } {
systems = import inputs.systems;
perSystem = { config, self', pkgs, lib, system, ... }: let
java = pkgs.jetbrains.jdk-no-jcef;
nativeBuildInputs = with pkgs; [
java
git
];
buildInputs = with pkgs; [
libGL
glfw-wayland-minecraft # Not always needed, but in case it is, it's here.
flite # TTS
libpulseaudio # Required for audio
];
in {
devShells.default = pkgs.mkShell {
inherit nativeBuildInputs buildInputs;
env = {
LD_LIBRARY_PATH = lib.makeLibraryPath buildInputs;
JAVA_HOME = "${java.home}";
};
};
};
};
}
This flake is locked on Nix packages 25.05, where jetbrains.jdk-no-jcef is JetBrains’ JDK 21, which is commonly used for MC modding on versions 1.20 and above.
The reason why we’re using JetBrains’ JDK is because JBR supports DCEVM, which allows for hotswapping classes.
libGLis a required dependency, without it, the game won’t launch.fliteis used in Minecraft for TTS, you can remove it if you don’t need it.libpulseaudiois required for the game to play sounds, without it no sounds or music will play.
Direnv
Your .envrc file should be the following:
use flake
Then run direnv allow in your shell, to allow loading the environment automatically.
Setting up the IDE
First of all, we’re gonna install some plugins for InteliJ. You’re gonna need these plugins:
If you’re going the direnv route, you also going to need the following:
- Direnv Integration (if you’re going the direnv route)
After installing this, restart your IDE. Then go to Settings > Tools > Direnv Settings.
In the “DirenvPath” field put the path to your direnv binary:
/etc/profiles/per-user/<username>/bin/direnv(for HM direnv installations)/run/current-system/sw/bin/direnv(for configuration.nix direnv installations)
And turn on the appropriate options, e.g.:

Close your IDE. Open the project’s folder in your terminal, and run the IDE through the terminal while being in the project’s folder (make sure you’re in the correct environment, that is, you allowed direnv OR, if you’re going the no direnv route, ran nix develop).
Note: IntelliJ’s binary’s name is
idea-communityfor IntelliJ Community Edition andidea-ultimatefor IntelliJ Ultimate.
Do not worry, this procedure is needed to be done only once.
Now, open your project (if you haven’t already), then go to File > Project Structure, in the popup go to “Project”, and set the “SDK” to the JDK from the “Detected SDKs” dropdown. This is the JDK that we’ve installed through the flake.
Then, go to File > Settings > Build, Execution, Deployment > Build Tools > Gradle and set “Gradle JVM” to be “Project SDK”.
If you’re using direnv, make sure to exclude the .direnv folder by right-clicking on it, then clicking Mark Directory As > Excluded.
You can re-open the IDE normally one.
Running the game
Direnv
- Open the project.
- You should get a notification “Direnv environment detected”, suggesting you import it. Click the button.
- Run “Minecraft Client” gradle task.
No Direnv
- Open the project’s folder via terminal.
- Run
nix develop. - Open the IDE via terminal.
- Run “Minecraft Client” gradle task.
Success!
Update March 30th of 2026
Talking with Timtaran, they told be about another method of using a wrapper for IntelliJ.
This allows to mod Minecraft without even making a flake, hence, this approach is a bit too impure for my taste.
{ pkgs, ... }:
let
mc-dependencies = with pkgs; [
libpulseaudio
libGL
glfw3-minecraft
openal
flite
(lib.getLib stdenv.cc.cc)
];
in
pkgs.symlinkJoin {
name = "IntelliJ Minecraft Support";
paths = [
(pkgs.jetbrains.idea.override {
vmopts = ''
-Dnosplash=true
-Dawt.toolkit.name=WLToolkit
'';
})
];
buildInputs = [ pkgs.makeWrapper ];
postBuild = ''
wrapProgram $out/bin/idea \
--prefix LD_LIBRARY_PATH : ${pkgs.lib.makeLibraryPath mc-dependencies}
'';
}
(-Dawt.toolkit.name=WLToolkit is optional and turns on experimental Wayland support)
Then just call it as any other package and that’s about it.