Upgrading a Mendix version without Studio Pro
SkillWeb & browsingLets your agent upgrade a Mendix project to a newer version from the command line, without opening Studio Pro.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Upgrading a Mendix version without Studio Pro skill
About this capability
Move a project to a newer Mendix version headlessly, with no Studio Pro. Use when raising a project's Mendix version, when a build complains the project version does not match MxBuild, or before adopting a newer runtime. Covers the one check that decides whether a converter must run, and the two gre
What this skill tells your AI
The instructions your AI receives, as published by mendixlabs/mxcli in .claude/skills/mendix/upgrade-mendix-version/SKILL.md and read by ahel’s review.
Why this needs a skill
Both ways of getting it wrong look like success:
| what you do | what you see | what is true |
|---|---|---|
mxbuild --loose-version-check | BUILD SUCCEEDED | the project is still on the old version |
UPDATE _MetaData SET _ProductVersion | the project reports the new version, and mxcli agrees | every unit is read against the wrong schema |
Neither prints a warning. The first is not hypothetical — it is what happened to the project that reported this, and it took going back to look at the version column to notice that a successful build had upgraded nothing.
The check that decides everything
A .mpr is SQLite. The version lives in one table, _MetaData, with columns
_FormatVersion, _ProductVersion, _BuildVersion and _SchemaHash.
Use Python rather than the sqlite3 CLI: python3 ships with a sqlite3
module, while the CLI is frequently absent (it is not in the mxcli devcontainer).
mprhash() { python3 -c "import sqlite3,sys
print(*sqlite3.connect(sys.argv[1]).execute(
'SELECT _ProductVersion,_SchemaHash FROM _MetaData').fetchone(), sep=' ')" "$1"; }
mprhash app.mpr
11.13.0 {SHA256}5Fk35jOyzj+cWnJe9ZkGWQjMEzsge3nIzS2zxH9jp6M=
For the version alone, mxcli says it on connect — no SQL needed:
Connected to: /path/App.mpr (Mendix 11.14.0)
One UPDATE would make the project claim the new version. Whether that is an
upgrade or a corruption is decided by the fourth column:
- Create a blank project at the target version (or use a project you already
have there) and read its
_SchemaHash. - Compare it with the project's.
- Same → the model schema did not change. The version is a label.
- Different → the schema changed, so units stored against the old one would be read against the new. A converter must run.
_SchemaHash is a property of the Mendix version, not of the project —
which is what makes this usable. Measured across two unrelated projects and two
machines: a 517-unit application and a blank app, both at 11.13.0, carry
byte-identical hashes, and the same holds at 11.14.0. So a reference value can be
recorded and reused rather than rebuilt each time.
11.13.0 {SHA256}5Fk35jOyzj+cWnJe9ZkGWQjMEzsge3nIzS2zxH9jp6M=
11.14.0 {SHA256}o9B9S8lorV9RD5gY9B6j1bJp4ALW87u4newnreIbRAg=
Two values are not a rule. Treat the table as a cache to check against, and re-derive the target version's hash from a blank project the first time you go to a version that is not listed — one command, and it is the only thing that actually answers the question.
Doing it
mx convert is the converter. It sits beside mxbuild in the toolset, and
mxcli does not wrap it.
# 1. Cache the target toolchain.
mxcli setup mxbuild --version 11.14.0 # ~/.mxcli/mxbuild/11.14.0/modeler/
# 2. Get the reference hash for the target version, if you do not have it.
mx create-project --app-name Ref --output-dir /short/path
mprhash /short/path/Ref.mpr
# 3. Convert a COPY first, never the project.
cp -a MyApp /short/MyApp-probe
mx convert --in-place /short/MyApp-probe
# 4. Verify the copy before touching anything real.
mprhash /short/MyApp-probe/App.mpr # must equal the reference from step 2
mx check /short/MyApp-probe/App.mpr
# 5. Only now, the real project.
mx convert --in-place MyApp
Converting a copy first, confirming its hash matches the reference, and only then touching the real project is what makes this safe rather than lucky. Step 4 is the whole point: it is the difference between "the conversion ran" and "the conversion produced what the target version expects".
Verifying MPR v2 survived
mx convert preserves MPR v2 — which is not a given. Its siblings
mx update-widgets and mx rename-design-properties collapse a v2 project into
a single-file v1 .mpr and delete mprcontents/ as a side effect, one-way. That
is the whole reason mxcli fix widgets exists.
Check the storage format, not the unit count. Measured on an 11.13 → 11.14
conversion: .mxunit files went 391 → 386 while v2 was perfectly intact. A
conversion may legitimately drop or merge units, so an unchanged count is a
coincidence, not the invariant. What actually distinguishes preserved from
collapsed:
[ -d MyApp/mprcontents ] && echo "v2 intact" # a collapse deletes this
stat -c%s MyApp/App.mpr # v2: tens of KB. v1: tens of MB
On the measured run: mprcontents/ present, .mpr 73,728 bytes.
Traps
mx convert takes the app DIRECTORY, not the .mpr. Pointing it at the file
fails with a message that reads like the project is missing:
Conversion failed: The app directory '/path/App.mpr' does not exist.
--loose-version-check suppresses the check, it does not run a converter.
Verified: after invoking mxbuild with the flag, _ProductVersion and
_SchemaHash are untouched. A green build proves nothing about the version.
A runtime version and its tooling move together. The upgrade may break the tools around it, and the failure need not mention a version at all. On 11.13 → 11.14 it surfaced as:
Error: bundling web client: no rollup.config.mjs in .../deployment/web
(run a serve Deploy build first)
— because 11.14's MxBuild bundles the web client itself, so the separate rollup
step has nothing left to configure. Deleting deployment/ and rebuilding does
not help; a newer mxcli is what fixes it. When something breaks right after an
upgrade and names no version, suspect the toolchain before the model.
mx create-project needs a short output path. It fails with
System.IO.PathTooLongException under a deeply nested directory, during package
extraction — the message names a path length, not the real constraint.
What generalises, and what does not
Most version-pair specifics will be wrong next time. The web-client bundling change is 11.13 → 11.14 and will not recur; the two hashes above are facts about two releases, not a pattern.
What generalises is the decision procedure — _SchemaHash decides label vs
convert — plus the three traps: convert takes a directory, --loose-version-check
upgrades nothing, and the tooling moves with the runtime. Check the specifics
against your own versions rather than trusting them.
After the upgrade
Re-run whatever the project relies on that is not covered by mx check, because
a clean check is not evidence the app still works. On the reporting project the
thing worth being anxious about was a non-standard database connection type not
in Mendix's own picker; it survived, and a full sync cycle proved it. Pick your
own equivalent — the integration nobody would notice breaking — and exercise it.
Related
run-local— booting the app after an upgrade; the toolchain mismatch above surfaces there first.debug-bson— if the converted model behaves oddly, and for whymx convert's bare error count is not evidence about a model.
Signals
- GitHub stars
- 122
- Forks
- 49
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
upgrade-mendix-version- Source
- github.com/mendixlabs/mxcli