Modding Valheim on a Mac is mostly the same as on Windows, with three differences that will each cost you an afternoon if nobody tells you: Gatekeeper quarantines the files, Steam’s Play button bypasses BepInEx entirely, and on Apple Silicon the shipped launch script loads no plugins while reporting nothing.
Install BepInEx Link to heading
Download BepInEx_macos_universal_5.4.23.5.zip from the
BepInEx releases page and unzip it directly into the
game directory, next to Valheim.app:
~/Library/Application\ Support/Steam/steamapps/common/Valheim
You should end up with:
Valheim/
├── Valheim.app
├── BepInEx/
├── libdoorstop.dylib
├── run_bepinex.sh
├── changelog.txt
└── .doorstop_version
macOS quarantines anything it downloaded. Clear that first, or the dylib is blocked without telling you why:
cd ~/Library/Application\ Support/Steam/steamapps/common/Valheim
xattr -dr com.apple.quarantine libdoorstop.dylib BepInEx
chmod +x run_bepinex.sh
Then run the game once through the script:
./run_bepinex.sh ./Valheim.app
On an Intel Mac you now have BepInEx/LogOutput.log and you are done with this section. On Apple
Silicon you have BepInEx/config/BepInEx.cfg and no log at all. Keep reading.
The Apple Silicon line Link to heading
BepInEx 5 cannot patch code when the game runs as native arm64. It loads no plugins, writes no log, and does not report the failure. The workaround is to run the game translated instead.
Open run_bepinex.sh and find this block near the bottom — line 324 in 5.4.23.5:
if [ -n "${is_apple_silicon}" ]; then
export ARCHPREFERENCE="arm64,x86_64"
Reverse the two:
export ARCHPREFERENCE="x86_64,arm64"
Launch again and the log appears within ten seconds, with your plugins in it.
That preference order is the only lever. Wrapping the script in arch -x86_64 does nothing,
because the script re-exports ARCHPREFERENCE and re-execs through arch itself.
The upstream value is deliberate, and its comment explains the intent — stop an x86_64 parent process from silently downgrading a universal game binary. That reasoning is sound. It just does not account for BepInEx being unable to patch code once the game really is running as arm64. Why that happens, and the fix for it, are in running Valheim mods without Rosetta.
Surviving Steam updates Link to heading
A Steam update restores the stock run_bepinex.sh, and your mods go quiet again without saying
anything. Rather than remember the edit, wrap it. I keep this as launch-modded.sh in the game
directory:
#!/bin/sh
V="$HOME/Library/Application Support/Steam/steamapps/common/Valheim"
cd "$V" || exit 1
# A Steam update restores the stock run_bepinex.sh, and the wrong architecture
# then loads no plugins while saying nothing at all. Re-apply the one edit.
WANT='ARCHPREFERENCE="x86_64,arm64"'
if ! grep -q "$WANT" run_bepinex.sh; then
sed -i '' "s/export ARCHPREFERENCE=.*/export $WANT/" run_bepinex.sh
fi
if [ $# -gt 0 ]; then
exec ./run_bepinex.sh "$@"
fi
exec ./run_bepinex.sh ./Valheim.app
chmod +x launch-modded.sh
Configure Steam Link to heading
Steam’s Play button starts Valheim.app directly and loads no plugins at all. Point it at the
wrapper instead.
Right-click Valheim in your library, then Properties → General → Launch Options, and enter the
script path followed by %command%:
"/Users/you/Library/Application Support/Steam/steamapps/common/Valheim/launch-modded.sh" %command%
The quotes are required, because the path contains a space. Steam passes the inner executable path
as the argument, and run_bepinex.sh accepts either that or the .app, so launching from Steam and
launching from a terminal both work.
Going through Steam rather than running the script by hand is what keeps the overlay, playtime tracking and friend invites working.
Installing mods Link to heading
BepInEx loads any DLL it finds in BepInEx/plugins. There is no macOS mod manager worth the
trouble, so install by hand:
- Download the mod from Thunderstore.
- Unzip it. The DLL is usually at the top level or under a
plugins/directory. - Copy the DLL into
BepInEx/plugins/. - Clear the quarantine flag:
xattr -dr com.apple.quarantine BepInEx/plugins.
Some mods ship a folder of assets alongside the DLL. Copy the whole folder, keeping its structure.
Mods write their config on first launch, not at install time. Start the game once, quit, then edit
the .cfg file that appears in BepInEx/config/. A two-mod install ends up looking like this:
BepInEx/
├── plugins/
│ ├── ExampleMod.dll
│ └── AnotherMod.dll
├── config/
│ ├── BepInEx.cfg
│ ├── com.example.examplemod.cfg
│ └── com.example.anothermod.cfg
└── LogOutput.log
The config filenames come from each mod’s plugin GUID, not its filename, so they rarely match the DLL you copied in.
If you play on a server, mods that change game behaviour generally have to be installed on both sides at matching versions. Client-only mods — UI, map, quality of life — do not.
Checking it worked Link to heading
head -5 "$HOME/Library/Application Support/Steam/steamapps/common/Valheim/BepInEx/LogOutput.log"
[Message: BepInEx] BepInEx 5.4.23.5 - Valheim (2026-09-18 7:24:32 AM)
[Info : BepInEx] Detected Unity version: v6000.0.75f1
[Message: BepInEx] Preloader started
[Info : BepInEx] Patching [UnityEngine.CoreModule] with [BepInEx.Chainloader]
[Message: BepInEx] Preloader finished
Then look for a Loading [<your mod>] line further down.
If that file does not exist at all, the architecture edit did not take. Check that Steam is
launching the wrapper and not the app, and look in
Valheim.app/Contents/MacOS/preloader_*.log — on Apple Silicon that is where the real error goes.
Feedback Link to heading
This is the setup I actually run, on an M4 Pro. If something here does not match what you see — particularly on an Intel Mac, which I no longer have to test against — tell me and I will correct it.