Palworld macOS modding ecosystem
- Palworld Mod Manager — desktop app to install / enable / update mods (consumes this loader)
- PalworldMod — the mods themselves (Minimap, AutoHatch, …)
- UE4SS-Palworld-macOS (this repo) — the native arm64 loader runtime
A native macOS arm64 port of RE-UE4SS, targeted at macOS-native Palworld (App Store, Apple Silicon, UE5.1). It reuses the UE4SS "brain" (Unreal Engine reflection + Lua scripting) and rewrites the "hands" — dylib injection, arm64 inline hooking, and Mach-O symbol resolution — for Apple Silicon.
This is not WINE, Rosetta, or emulation: a native arm64 dylib is injected directly into the native game process.
This loader is the runtime consumed by the Palworld Mod Manager app, which downloads it from this repo's GitHub releases. See Releases below.
A working UE4SS loader for macOS-native Palworld (App Store, arm64, UE5.1). The full mod
pipeline runs on macOS: injection → bootstrap (6 engine anchors) → reactive hooking → UObject
listeners → Lua reflection → ProcessEvent / ProcessInternal / ExecuteInGameThread, plus
Blueprint mod loading (BPModLoaderMod) and macOS keybind input (RegisterKeyBind). A Lua mod can
hook and call game UFunctions to change real game state (demonstrated by an auto-hatch /
auto-receive mod).
This targets macOS-native Palworld specifically.
- Bootstrap is Palworld-specific. The engine anchors are resolved symbol-first with a Palworld-tuned AOB fallback, so it is built and validated for Palworld only; other UE5.1 macOS games are not supported as-is.
- Runtime member offsets: consumed members are mac-verified. Every offset the port actually reads was checked against a stock-UE5.1 arm64 fixture's DWARF. Remaining table entries are unexercised and handled reactively (disassemble the accessor on crash → add a setter). Any Palworld-specific fork-inserted fields are only resolved if and when they surface.
- GUI subsystem is disabled (built with
--ue4ssUI=None). - The engine-native UE console does not open on macOS. Its key-toggle path is not ported, so the
in-engine
~/F-key console (and console-only example mods) cannot be used. UE4SS keybinds (RegisterKeyBind) do work — though a few default keys (Ins, F-keys) are absent or intercepted by macOS. - Out of scope: game discovery, a product-grade launcher/injector, mod install/enable/update, and any mod manager UI. This repository only keeps experimental and minimal packaging scripts.
End users (running via the Palworld Mod Manager or the release's launch-palworld.command) need
only:
- macOS on Apple Silicon (arm64)
- Palworld installed
The shipped libUE4SS.dylib links only system libraries (CoreGraphics, CoreFoundation, libc++,
libSystem) — there is no homebrew/capstone runtime dependency. Nothing to install.
Building from source additionally requires:
- Xcode Command Line Tools
- xmake (e.g.
brew install xmake) - capstone (
brew install capstone) — used at build time only; not linked into the shipped dylib - The target game (e.g. Palworld) for runtime testing
# Unit tests — no game required
make test
# Full UE4SS dylib (Shipping, arm64, GUI disabled)
xmake f -P . -p macosx -a arm64 -m Game__Shipping__Mac --ue4ssUI=None -y
xmake build -P . -j4 UE4SS./tools/stage-ue4ss-runtime.sh # stage settings + mods into the sandbox container
./tools/launch-ue4ss.sh # inject via DYLD_INSERT_LIBRARIES and launch
./tools/tail-log.sh # stream the runtime logInjection requires launching through the script (Spotlight / double-click will not inject). UE4SS runtime data (logs, Mods, settings) lives in the game's sandbox container, not in this repo.
The minimal pre-zip package is generated under dist/UE4SS_mac/:
./tools/package-ue4ss-mac.sh --zipAfter the user receives that folder, running launch-palworld.command performs a basic preflight
(arm64 check, dylib/settings/mod files, Palworld sandbox container, dylib dependencies, ad-hoc
signing). If it passes, the script installs the settings into the sandbox container and the built-in
mods into the game bundle's Binaries/Win64/Mods (the bundle-migration model — chown-once, and
only escalates to sudo if that folder is not writable), then injects only libUE4SS.dylib into
the game process.
Package folder:
dist/UE4SS_mac/
launch-palworld.command
libUE4SS.dylib
version.txt
UE4SS/
UE4SS-settings.ini
Mods/
mods.txt
BPModLoaderMod/ (built-in: spawns BP mods from LogicMods)
shared/ (built-in: UEHelpers etc.)
Runtime layout the launcher creates — two destinations:
# Runtime data → sandbox container
~/Library/Containers/com.pocketpair.palworld.mac/Data/UE4SS/
UE4SS-settings.ini
# Built-in mods → game bundle
/Applications/Palworld.app/Contents/UE/Pal/Binaries/Win64/Mods/
mods.txt
BPModLoaderMod/
shared/
launch-palworld.command injects only the package's libUE4SS.dylib:
DYLD_INSERT_LIBRARIES="$PACKAGE_DIR/libUE4SS.dylib" \
/Applications/Palworld.app/Contents/MacOS/PalworldAfter the dylib is loaded inside the game process, UE4SS reads its settings from the sandbox
container ($HOME/UE4SS resolves there) and discovers mods from the game bundle's
Binaries/Win64/Mods. To ship a built-in mod in the package, place it under
dist/UE4SS_mac/UE4SS/Mods/<ModName>/; the launcher installs it into the bundle at launch.
The Palworld Mod Manager consumes this loader from GitHub releases. The release contract is fixed:
- Version source of truth: the
VERSIONfile at the repo root (semverX.Y.Z). - Each release is tagged
vX.Y.Zand carries a single asset namedUE4SS_mac.zipwhose payload containsUE4SS_mac/libUE4SS.dylib.
Cut a release with:
./tools/release.sh --dry-run # build + zip only, no publish
./tools/release.sh # tag vX.Y.Z + publish UE4SS_mac.zip to GitHubBump VERSION before publishing; release.sh refuses to clobber an existing tag unless
--replace is passed.
BPModLoaderMod(included) — the upstream, unmodified Blueprint mod loader. It also doubles as the Lua-runtime smoke signal:[Lua] Loading mod:lines in the log prove the Lua VM loads and runs inside the injected dylib (seetools/regression-check.sh --runtime).- AutoHatch (Palworld-specific demo) is kept in a separate mods repo, not here. For local
real-game testing, point the staging script at your local copy:
(Defaults to
PMM_AUTOHATCH_DIR=/path/to/AutoHatch ./tools/stage-ue4ss-runtime.sh
../04_AutoHatch; absent → skipped.)
For Lua API and mod authoring, see the bundled reference under docs/lua-api/. It documents the
UE4SS Lua API as of the vendored snapshot; the macOS port does not change the API surface, so it
applies as-is. See Limitations for mac-specific runtime exceptions (e.g. the in-engine console).
./tools/regression-check.sh # unit tests + on-binary symbol scan| Path | Contents |
|---|---|
src/darwin/ |
Mach-O memory access, module/segment parsing, AOB pattern scanning, logging |
src/hook/ |
arm64 relocator (B/BL/thunk resolution) and inline-hook primitives |
src/entry.cpp |
injected dylib entry point |
UE4SS/ |
upstream UE4SS core (reflection + Lua), built with the Darwin entry |
deps/first/ |
UEPseudo and patternsleuth submodules |
tools/ |
build/stage/launch/log scripts and AOB derivation helpers |
tests/ |
C++ unit tests (AOB, hooking, relocation, memory, symbol scan) |
MIT — a port of RE-UE4SS (MIT).
UEPseudo is a gated submodule (Epic EULA) and is not vendored here.