Mendix package manager and workspace deduplicator with global caching and hard links.
Download each widget once, cache it globally, and share it across all your projects at zero extra disc cost. Then deduplicate the rest of the shared assets (libraries, theme resources) in one pass.
mxpak has two complementary mechanisms, both backed by the same content-addressable store at ~/.mxpak/store/{sha256}/:
mxp install— widget dependency manager. Downloads.mpkfiles from the Mendix Marketplace, stores them in the CAS by SHA-256 hash, and hard-links them into<project>/widgets/. Locked viamxpak.lockfor reproducibility.mxp scan— workspace deduplicator. Scans every project under a workspace, hashes shared files thatinstalldoesn't manage (Java libraries inuserlib//vendorlib/, Mendix standard theme assets inthemesource/), and replaces duplicates with hard links to a single CAS-stored copy.
If the cache and project are on different drives (where hard links don't work), mxpak falls back to a regular file copy automatically.
Prerequisite — Erlang/OTP 26+ must be on PATH (escript command available).
- macOS:
brew install erlang - Windows:
winget install Erlang.ErlangOTP - Linux:
sudo apt-get install erlang(or your distro's equivalent)
macOS / Linux
curl -fsSL https://github.com/GG-O-BP/mxpak/releases/latest/download/install.sh | shWindows (PowerShell)
iwr -useb https://github.com/GG-O-BP/mxpak/releases/latest/download/install.ps1 | iexBoth scripts place the mxp escript at ~/.mxpak/bin/ (macOS/Linux) or %USERPROFILE%\.mxpak\bin\ (Windows).
Windows — the installer adds the directory to your user PATH automatically, but the change only takes effect in new terminal windows. To use mxp immediately in the same session:
$env:PATH = "$env:USERPROFILE\.mxpak\bin;$env:PATH"
mxp --versionmacOS / Linux — add the directory to your shell rc file yourself:
export PATH="$HOME/.mxpak/bin:$PATH" # add to ~/.zshrc, ~/.bashrc, etc.
mxp --versionescript: ... command not found— Erlang/OTP is missing. Install via the prerequisite step above and re-run the installer.mxp: command not found(after install) — open a fresh terminal, or apply PATH in the current session as shown above.undefined function mxpak:main/0— outdated escript bundle. Re-run the installer to fetch the latest release.
git clone https://github.com/GG-O-BP/mxpak.git
cd mxpak
gleam run -m gleescript # produces ./mxpak — rename to mxp and place on PATHmxp <command> [options]
| Command | Description |
|---|---|
install [project_root] |
Resolve and install all widgets from config (lock file preferred) |
add <name> --version <v> |
Add a widget to config and install |
remove <name> |
Remove a widget from config |
update [name] |
Update widget(s) (clears lock, re-resolves) |
marketplace [project_root] |
Interactive TUI browser for the Mendix Marketplace |
outdated [project_root] |
List widgets with available updates |
list [project_root] |
List installed widgets |
info <name> |
Show widget details |
audit [project_root] |
Verify SHA-256 integrity of all installed .mpk files |
cache clean |
Clean the global cache |
scan [path] |
Deduplicate *.mpk, *.jar, and themesource/** across all projects under the workspace |
status [path] |
Show per-project deduplication stats and disc savings |
Add a [tools.mendraw] section to your project's TOML config:
[tools.mendraw]
mode = "mpk"
widgets_dir = "widgets"
[tools.mendraw.widgets.Badge]
version = "3.2.2"
id = 50325
[tools.mendraw.widgets."com.mendix.widget.web.Datagrid"]
version = "2.22.3"
id = 116540Running mxp install generates a lock file (mxpak.lock) that pins exact versions and SHA-256 hashes for reproducible builds.
mxp scan auto-detects what to scan based on where you run it:
# Case 1 — inside a single Mendix project (a `*.mpr` is in the directory):
cd ~/Mendix/TSVE4HMC-main
mxp scan # scans this project only
# its assets are absorbed into the global CAS at ~/.mxpak/store/
# future scans of any other project automatically dedup against them
# Case 2 — a directory whose immediate children are Mendix projects:
cd ~/Mendix # contains TSVE4HMC-main/, ChartTest/, Blank/, ...
mxp scan # scans every Mendix project (every immediate subdir with `*.mpr`)
mxp status # works the same way (single project or workspace)If neither case matches (no *.mpr here, none in immediate children), scan exits with a clear hint.
scan works with sensible defaults out of the box — no setup file required:
| Rule | Default value |
|---|---|
include |
["*.mpk", "*.jar"] — widgets and Java libraries (widgets/, userlib/, vendorlib/) |
include_dirs |
["themesource"] — Mendix standard theme modules (atlas_core, datawidgets, etc.); all extensions scanned under these directories |
exclude_dirs |
["deployment", "javascriptsource", "javasource", "modules", ".mendix-cache", ...] — build artefacts and project-unique code |
scan and install share the same CAS at ~/.mxpak/store/. Widgets installed via mxp install are already hard-linked into the cache, so scan over them is effectively a no-op. Widgets that Mendix Studio Pro placed directly are absorbed into the CAS on the first scan and deduplicated thereafter.
Drop a .mxpak-workspace.toml in your workspace root to override any of the above:
[scan]
include = ["*.mpk", "*.jar", "*.zip"]
include_dirs = ["themesource", "shared"]
exclude_dirs = [".git", "deployment"]Missing keys fall back to defaults.
mxp scan covers everything below in one pass:
| Target | Total | After dedup | Saved | Ratio |
|---|---|---|---|---|
widgets/*.mpk |
804 MB | 533 MB | 270 MB | 33.6% |
*.jar in userlib/vendorlib |
534 MB | 222 MB | 311 MB | 58.3% |
themesource/** |
57 MB | 15 MB | 42 MB | 74.0% |
| Combined | 1,395 MB | 770 MB | 623 MB | 44.7% |