Releases: mendixlabs/mxcli
v0.13.0
[0.13.0] - 2026-06-20
Headline: the roundtrip codec engine is now the default. Reads and writes route through the new modelsdk codec engine — a Go-native, roundtrip-safe metamodel codec spanning 53 domains — replacing the legacy sdk/mpr write path. Legacy remains available as an explicit --engine legacy (or MXCLI_ENGINE=legacy) fallback for the few constructs the codec can't yet reproduce (e.g. SOAP), and refuses an op rather than dropping data where it can't. This release also lands an experimental MCP/PED backend for authoring against a running Studio Pro.
A big thank-you to engalar. The roundtrip codec engine and the expression type-checker that anchor this release are built on his contributions — his
modelsdkcodec work (the 53-domain, roundtrip-safe metamodel implementation) andexprcheckport were cherry-picked and adapted here. Much of what makes v0.13.0 possible is his. Thank you!
Added
-
Experimental MCP/PED backend (
mxcli mcp) — author Mendix models against a running Studio Pro over the Model Edit Protocol (PED/MCP) transport, instead of writing the.mpron disk.mxcli mcp capabilitiesreports what the connected Studio Pro version supports (a version-keyed capability registry), and CREATE/ALTER ops are gated on that model — unsupported constructs are refused with an actionable message rather than silently dropped. Covers entity create/update with NOT NULL / UNIQUE validation rules, ALTER ENTITY ADD ATTRIBUTE, ALTER STYLING design properties, page authoring (typed params, edit-button actions, design properties), folder placement, and business-event/workflow reads. Honoured in bothexecand the interactive REPL (--mcp). Verified against Studio Pro 11.11. -
Graph community detection & centrality (
refresh catalog communities) — a pure-Go (no CGO, no deps) graph engine over the refs graph: Leiden community detection, Tarjan cycles, topological layering, PageRank, and betweenness.refresh catalog communities [resolution n]computes them (in the full-refresh transaction) into new catalog tables/views —communities+community_summary,graph_cycles,graph_layers,graph_centrality,graph_integration_surface(cross-community edges → OData/REST/event mechanisms),graph_module_dependencies— and adds PageRank/betweenness columns tograph_god_nodes. Surfaced viaSHOW COMMUNITIES/SHOW COMMUNITY [MEMBERS] OF Module.Asset, and exposed to Starlark lint rules (community_of,layer_of,cycles,module_dependencies,centrality,god_nodes,integration_surface,refs_from) so teams validate their own architecture guidelines. The native Leiden matches theleidenalgreference exactly (105 communities on Evora). Targets two refactoring journeys: spaghetti → layered/modular (cycles + layer sequence numbers) and monolith → multi-app (community cut → integration-contract list). -
mxcli graph-report— architecture map from the dependency graph — renders six analyses over newCATALOG.graph_*views: god nodes (degree centrality), cross-module coupling ("surprise edges"), module cohesion (intra/inter ratio), dead documents (no inbound edge), the reference-kind distribution, and entity hotspots (used by the most flows). Framework/marketplace modules are excluded by default (--include-frameworkto keep them);--top N,--format markdown|json,-o file. Each section is a thinSELECTover agraph_*view, so it's reproducible directly (select * from CATALOG.graph_god_nodes). Built on the now-substantially-completerefsgraph; requiresrefresh catalog full(the command runs it). Also madeCATALOG.<name>query translation generic (regex strip) so new catalog views work without a per-name allowlist. -
Marketplace download & install — the content API now returns a per-version
downloadUrl, so the previously-parked install path is unblocked.mxcli marketplace download <id> [--version X] [-o file]fetches a content version's.mpk(two-step: MxToken-authed303onmarketplace.mendix.com→ public CDN, no token sent to the CDN).mxcli marketplace install <id> -p app.mpris type-aware: widgets are copied intowidgets/, new modules are imported viamx module-import, other types are downloaded with import instructions. Module updates are intentionally reported-not-applied — re-importing an existing module would discard local edits and change persistent-entity IDs (data loss); that path is left to Studio Pro pending an ID-preserving merge -
Marketplace search caching — the first
mxcli marketplace searchfetches the full catalog listing once and caches it under~/.mxcli/marketplace-catalog-<profile>.json(24h TTL, mode 0600); subsequent searches (any keyword) are served from the cache instantly.--refreshbypasses the cache and re-fetches. An interactive progress line ("Searching marketplace… N items scanned") shows during a fresh scan -
describeauto-detects the document type — the type is now optional for a qualified name:mxcli describe MyModule.Customerresolves the type itself (entity, microflow, page, snippet, enumeration, constant, java action, nanoflow, workflow, association incl. cross-module, …). Resolution prefers the catalog cache (O(1) lookup, no overhead vs. the explicit form) and falls back to a live project scan when the catalog is absent. An ambiguous name (e.g. an entity and a microflow sharing a name) is reported with its candidates. The explicitdescribe <type> <name>form is unchanged, and is still required for the forms that have no single qualified name (module, settings, navigation, module role) -
Bare
describe Module.Nameworks as MDL, not just as a CLI flag — the auto-detect form is now part of the MDL grammar, so it parses and runs everywhere MDL does: the REPL,execscripts,check, and the LSP (previouslydescribe Sales.Orderin the REPL was a parse error and onlymxcli describe Sales.Orderworked). The bare form resolves the type from the project's catalogobjectsindex at execution time (built on demand, fresh — no staleness concern); all typeddescribe <type> …forms still take precedence, and an ambiguous or unknown name returns an actionable error -
Pop-up page geometry —
CREATE PAGEandALTER PAGEcan now set a pop-up page'swidth,height, andresizablein the page header (#661).DESCRIBE PAGEround-trips them. -
Compound (nested) design properties — design properties on pages and snippets that nest (a group containing sub-properties) are now written and round-tripped by
DESCRIBE PAGE/DESCRIBE STYLING, on both the codec engine and over MCP (#668) -
Quoted identifiers in member lists and attribute refs — names that collide with MDL reserved words can now be quoted in member lists and attribute references (#675), extending the reserved-word-quoting support to more positions (
DESCRIBEemitters now quote reserved-word names in the remaining strict-identifier spots, #619)
Changed
-
The codec engine (
modelsdk) is the default;sdk/mpris the explicit fallback — all reads and writes now route through the roundtrip codec engine by default. The legacy path is reachable via--engine legacyorMXCLI_ENGINE=legacyfor the constructs the codec can't yet reproduce (notably SOAP); where the codec path can't reproduce a construct it refuses the op rather than dropping data. This is the culmination of the Issue 7 parity effort that brought every document type — domain models, microflows, pages, workflows, security, REST/OData, agent-editor docs, settings, and more — tomx checkparity on the codec path. -
Catalog
objectsindex includes associations — the unifiedobjectsview now unions theassociationstable (ObjectType = ASSOCIATION), so it is a complete index for the cataloged document types and consumers no longer need a separate associations query. Catalog schema bumped to v3; cached.mxcli/catalog.dbfiles rebuild automatically on the nextrefresh catalog. -
Catalog indexes image collections, JavaScript actions, and data transformers — these document types had no catalog table at all; they are now built (via the raw-unit surface, so no
CatalogReader/backend change) into their own tables and unioned intoobjects(IMAGE_COLLECTION,JAVASCRIPT_ACTION,DATA_TRANSFORMER).describeauto-detect resolves image collections and data transformers by bare name. Catalog schema bumped to v4. -
Catalog indexes agent-editor documents — agents, AI models, knowledge bases, and consumed MCP services (one shared
CustomBlobDocuments$CustomBlobDocumentBSON wrapper, distinguished byCustomDocumentType) are now cataloged into their own tables and unioned intoobjects(AGENT,AI_MODEL,KNOWLEDGE_BASE,CONSUMED_MCP_SERVICE). The document name turned out to be a top-level wrapper field (not buried in the inner JSON blob), so this reads through the raw-unit surface with noCatalogReader/backend change, anddescribeauto-detect resolves all four by bare name. Catalog schema bumped to v5; this completes theobjectsindex for the document types tracked in #658. (Verified againsttest3-app: 8 agent-editor docs across all four types.)
Fixed
- Page authoring fidelity — several page constructs that were silently dropped or mis-stored are fixed:
DYNAMICTEXTAttribute bindings are no longer dropped (#650);ALTER PAGEcan set conditionalVisible/Editableexpressions without tripping CE0117 (#627); a ComboBox datasource property that was silently dropped is now caught at check time (#643); a quotedwhere '<xpath>'constraint is no longer mis-stored as CE0161 (#642); and galleryDesktopColumns+classare honoured on pluggable widgets. checkcatches more page errors — forward widget→page references (#674) and invalid static widget values (#672, #673) are now flagged at check time instead of surfacing later in Studi...
v0.12.0
What's Changed
- fix #583: parse StringAttributeType.Length across BSON numeric widths by @ako in #584
- fix: CREATE ODATA CLIENT strips uppercase MICROFLOW keyword prefix (#573) by @ako in #586
- fix #585: parse remaining numeric BSON fields across all numeric widths by @ako in #587
- fix: ALTER STYLING writes design properties on pages and snippets (#631) by @peterjumpnl in #632
- deps: bump github.com/mattn/go-runewidth from 0.0.23 to 0.0.24 by @dependabot[bot] in #611
- deps: bump modernc.org/sqlite from 1.50.1 to 1.51.0 by @dependabot[bot] in #612
- deps: bump github.com/alecthomas/chroma/v2 from 2.24.1 to 2.26.1 by @dependabot[bot] in #613
Full Changelog: v0.11.0...v0.12.0
v0.11.0
What's Changed
- deps: bump modernc.org/sqlite from 1.50.0 to 1.50.1 by @dependabot[bot] in #562
Full Changelog: v0.10.0...v0.11.0
v0.10.0
What's Changed
- deps: bump github.com/fsnotify/fsnotify from 1.10.0 to 1.10.1 by @dependabot[bot] in #537
- deps: bump golang.org/x/term from 0.42.0 to 0.43.0 by @dependabot[bot] in #536
- ci: bump actions/cache from 4 to 5 by @dependabot[bot] in #535
Full Changelog: v0.9.0...v0.10.0
v0.9.0
What's Changed
- fix: skip System.* references in
mxcli check --referencesby @hjotha in #523 - fix: classify reverse-Reference traversal through entity inheritance by @hjotha in #522
- feat: support inheritance split and cast statements by @hjotha in #365
- Pull by @ako in #531
- fix: roundtrip REST mapping cardinality via
as list ofsyntax by @hjotha in #519 - fix: emit "empty" keyword for typed Java action arguments by @hjotha in #521
- fix: prevent catalog crash on duplicate business event channels by @dhruvbehl in #533
New Contributors
- @dhruvbehl made their first contribution in #533
Full Changelog: v0.8.0...v0.9.0
v0.8.0
What's Changed
- Misc by @ako in #247
- fix: handle missing TaskPage key in workflow activity mutation by @retran in #243
- Add test enablers: MockPageMutator, MockWorkflowMutator, registry completeness by @retran in #244
- test: add visitor tests for 20 untested source files by @retran in #245
- fix: make workflow mutator property lookup case-insensitive; fix REST… by @ako in #248
- feat: Support local file metadata for OData clients by @dionesiusap in #210
- feat: add mxcli catalog search and show commands by @dionesiusap in #218
- feat: support full user targeting on workflow USER TASK (fixes #169) by @ako in #251
- feat: self-describing syntax feature registry for LLM-friendly help discovery by @ako in #252
- test: add mock tests for 8 executor handler files by @retran in #253
- test: expand mock tests for 28 executor handler files by @retran in #254
- test(linter): add unit tests for all 14 untested linter rules by @retran in #255
- test(catalog): add unit tests for builder pure helper functions by @retran in #256
- fix: preserve MPR v1 contents hash and UnitID across DROP+CREATE by @hjotha in #258
- Misc by @ako in #269
- fix: accept qualified function calls in expression parser by @hjotha in #259
- fix: normalise built-in Mendix function case in expression roundtrip by @hjotha in #260
- fix: gate Mx 9 microflow roundtrip keys by project version by @hjotha in #261
- fix: treat terminal nested IF as returning in flow builder by @hjotha in #262
- fix: preserve decision/loop captions across nested control flow by @hjotha in #263
- fix: preserve rule-based decision subtype across microflow roundtrips by @hjotha in #265
- fix: preserve rule split describer output and free annotations by @hjotha in #266
- fix: correct microflow body syntax in bug-test 258 by @hjotha in #270
- fix: DESCRIBE PAGE recurses into ScrollContainer / TabControl children by @hjotha in #271
- Misc by @ako in #278
- fix: support log node expressions and harden microflow describe roundtrip by @hjotha in #264
- fix: stabilize MDL roundtrip and integration test harness by @hjotha in #267
- refactor: remove ExecContext.executor back-pointer by @retran in #274
- feat: @anchor annotation for microflow sequence flow endpoints by @hjotha in #276
- refactor: extract CatalogDB interface for WASM portability by @retran in #277
- deps: bump github.com/jackc/pgx/v5 from 5.9.1 to 5.9.2 by @dependabot[bot] in #284
- feat: import consumed REST client from OpenAPI 3.0 spec by @ako in #286
- fix: create OpenApiTest module before use in openapi-import doctype test by @ako in #288
- fix: preserve change-member name when entity type is unknown (#282) by @hjotha in #283
- fix: traverse through unpaired ExclusiveMerge in describe (#281) by @hjotha in #285
- refactor: quick-win cleanup — panic stubs, SaveToFile, dead code, error handling, syncWriter by @retran in #287
- refactor: introduce LintReader interface, decouple linter from sdk/mpr by @retran in #289
- refactor: add type-safe BSON helpers in writer_security by @retran in #297
- deps: bump modernc.org/sqlite from 1.48.2 to 1.49.1 by @dependabot[bot] in #300
- fix: drop empty else branch from describer output by @hjotha in #305
- fix: preserve commit error handling through describe/exec/describe by @hjotha in #309
- fix: honor branch anchor destination on split-to-merge flows by @hjotha in #311
- fix: skip reference checks for excluded microflows by @hjotha in #313
- feat(executor): allow MXCLI_EXEC_TIMEOUT to override the per-statement timeout by @hjotha in #315
- refactor: extract microflow anchor selection helpers by @hjotha in #325
- feat: support microflow download file statement by @hjotha in #333
- fix: write valid show-page parameter mappings by @hjotha in #338
- fix: refresh empty change-object actions by @hjotha in #340
- fix: preserve microflow-call BSON field order by @hjotha in #342
- fix: preserve compact reverse-association retrieves by @hjotha in #356
- fix: emit ResultHandlingHttpResponse for REST 'returns response' by @hjotha in #378
- fix: write REST HttpResponse result variable type by @hjotha in #376
- fix: write valid change-action item storage lists by @hjotha in #374
- fix: emit list retrieve for owner-both reverse references by @hjotha in #381
- fix: preserve void EndEvent returns in describe by @hjotha in #371
- fix: infer java action result variable types by @hjotha in #357
- fix: register import mapping result variable types by @hjotha in #360
- fix: preserve object-valued owner-both reverse retrieves by @hjotha in #384
- fix: preserve manual while-true loop roundtrips by @hjotha in #354
- feat: full nanoflow support — CREATE, DROP, SHOW, DESCRIBE, DIFF, MERMAID, security, and agentic skill by @retran in #301
- fix(writer): drop synthetic trailing newline from EndEvent ReturnValue by @hjotha in #317
- feat: support free microflow annotations by @hjotha in #319
- fix: do not emit annotations before unsupported-action comments by @hjotha in #307
- fix: suppress default anchor fragments in describe by @hjotha in #321
- fix: preserve multiline source expression whitespace by @hjotha in #323
- fix: pair microflow splits with nearest merge by @hjotha in #327
- fix: preserve nested loop body flow traversal by @hjotha in #329
- feat: preserve change object refresh modifier by @hjotha in #363
- feat: support legacy microflow call web service statement by @hjotha in #334
- fix: preserve attribute-based list operations by @hjotha in #344
- fix: preserve incoming anchors for inheritance splits by @hjotha in #454
- fix: emit loop captions during microflow describe by @hjotha in #444
- test: cover empty EndEvent return serialization by @hjotha in #446
- feat: support enum split microflow statements by @hjotha in #364
- fix: preserve mapping result range cardinality by @hjotha in #372
- feat: support empty Java action arguments by @hjotha in #336
- fix: preserve no-merge branch continuations by @hjotha in #355
- deps: bump github.com/microsoft/go-mssqldb from 1.9.8 to 1.10.0 by @dependabot[bot] in #485
- deps: bump go.uber.org/zap from 1.27.1 to 1.28.0 by @dependabot[bot] in #484
- deps: bump github.com/fsnotify/fsnotify from 1.9.0 to 1.10.0 by @dependabot[bot] in #483
- deps: bump github.com/alecthomas/chroma/v2 from 2.23.1 to 2.24.1 by @dependabot[bot] in #482
- deps: bump modernc.org/sqlite from 1.49.1 to 1.50.0 by @dependabot[bot] in #481
- fix: preserve annotations attached inside loop bodies by @hjotha in #331
- fix: stabilize integration CI baseline by @hjotha in #412
- fix: reject duplicate microflow output variables by @hjotha in #337
- fix: p...
v0.7.0
What's Changed
- fix: resolve page context tree for ALTER PAGE and check --references by @engalar in #158
- fix: docker cache detection on Windows and reload schema warning by @engalar in #160
- feat: workflow microflow actions and COMPLETE_TASK page action by @engalar in #159
- feat: generate .gitignore for Mendix projects during init by @engalar in #163
- fix: run mx update-widgets before mx check to prevent false CE0463 by @engalar in #164
- fix: association navigation expression missing target entity and extra spaces by @engalar in #165
- fix: augment nested ObjectType properties from .mpk to prevent CE0463 by @engalar in #166
- feat: add data container context hints to DESCRIBE PAGE by @engalar in #168
- fix: strip REST path slashes and validate microflow param entity refs by @engalar in #170
- deps: bump github.com/mattn/go-runewidth from 0.0.22 to 0.0.23 by @dependabot[bot] in #187
- deps: bump modernc.org/sqlite from 1.48.1 to 1.48.2 by @dependabot[bot] in #188
- fix: emit correct enum value format for XPath vs expression contexts by @engalar in #167
- fix: remove broken GRANT/REVOKE EXECUTE ON WORKFLOW by @engalar in #173
- fix: improve data container context hints and LSP completion by @engalar in #184
- fix: add 168 missing lexer tokens to keyword rule by @engalar in #186
- fix: support @Module.Const syntax in expressions by @engalar in #179
- fix: prefer Studio Pro over CDN downloads on Windows by @engalar in #195
- fix: microflow layout issues (ConnectionIndex, redundant Merge, DESCRIBE roundtrip) by @engalar in #204
- fix: skip Attribute fallback for custom-content datagrid columns by @ako in #208
- docs: add mxcli-dev contributor command namespace and /mxcli-dev:review by @yscraft in #220
- fix: route path/query params correctly and suppress BodyVariable for JSON bodies in SEND REST REQUEST by @yscraft in #215
- docs: add fix-issue skill with TDD protocol and symptom→layer table by @yscraft in #216
- feat: add typed error system for executor by @retran in #222
- feat: dispatch registry, backend interfaces, and MockBackend by @retran in #224
- docs: add fork PR flow diagram to CONTRIBUTING.md by @yscraft in #223
- ci: bump softprops/action-gh-release from 2 to 3 by @dependabot[bot] in #226
- ci: bump actions/upload-pages-artifact from 4 to 5 by @dependabot[bot] in #227
- refactor: migrate executor handlers to free functions with ExecContext by @retran in #225
- Context & catalog isolation — ExecContext gains Backend, handlers decoupled from mpr by @retran in #229
- deps: bump github.com/spf13/pflag from 1.0.9 to 1.0.10 by @dependabot[bot] in #228
- feat: add comprehensive mock-based handler tests (189 tests) by @retran in #232
- refactor: extract shared types and utility functions to mdl/types by @retran in #235
- refactor: define mutation backend interfaces by @retran in #236
- refactor: implement mutation backends and migrate handlers by @retran in #237
- refactor: decouple executor from storage layer by @retran in #238
- refactor: code quality — deterministic output, doc comments, naming by @retran in #239
New Contributors
Full Changelog: v0.6.0...v0.7.0
v0.6.0
What's Changed
- feat: ALTER WORKFLOW command with full activity manipulation by @engalar in #107
- fix: align BSON properties with Mendix schema for mx diff compatibility by @engalar in #109
- feat: add virtual System module for complete module listing by @engalar in #110
- fix(security): validate demo user password against project policy by @engalar in #140
- refactor: split 5 large files into smaller modules by @engalar in #141
Full Changelog: v0.5.0...v0.6.0
v0.5.0
What's Changed
- fix: int32→int64 for BSON property values by @engalar in #71
- fix: CREATE OR REPLACE PAGE reuses existing UUID by @engalar in #72
- feat: diag --check-units + grammar fixes by @engalar in #67
- feat: SHOW/DESCRIBE/CREATE/DROP JSON STRUCTURE by @peterjumpnl in #80
- docs: MDL i18n design proposal by @engalar in #87
- ci: bump actions/deploy-pages from 4 to 5 by @dependabot[bot] in #92
- ci: bump actions/checkout from 4 to 6 by @dependabot[bot] in #93
- ci: bump actions/upload-pages-artifact from 3 to 4 by @dependabot[bot] in #94
- deps: bump github.com/mattn/go-runewidth from 0.0.21 to 0.0.22 by @dependabot[bot] in #95
- deps: bump @vscode/vsce from 2.32.0 to 3.7.1 in /vscode-mdl by @dependabot[bot] in #96
- deps: bump modernc.org/sqlite from 1.48.0 to 1.48.1 by @dependabot[bot] in #97
- deps: bump typescript from 5.9.3 to 6.0.2 in /vscode-mdl by @dependabot[bot] in #99
- deps: Bump esbuild from 0.27.7 to 0.28.0 in /vscode-mdl by @dependabot[bot] in #98
- fix: remove invalid ParentConnection/ChildConnection from CrossAssociation BSON (#50) by @engalar in #105
- docs: workflow improvements design proposal by @engalar in #88
- feat: pluggable widget engine v2 by @engalar in #68
- feat: WidgetDemo baseline by @engalar in #69
New Contributors
- @peterjumpnl made their first contribution in #80
Full Changelog: v0.4.0...v0.5.0
v0.4.0
What's Changed
- Fix batch of reported issues (#18, #19, #23, #25, #26, #27, #28) by @engalar in #35
- feat(tui): add agent channel for external automation by @engalar in #38
- docs: add comprehensive theme & styling skill by @engalar in #40
- fix(catalog): recurse into loop bodies when extracting references by @engalar in #45
- feat: add custom pluggable widget AIGC skill by @engalar in #42
- feat(init): add OpenCode tool support by @retran in #47
- feat: pluggable widget engine with data-driven definitions by @engalar in #28
- fix: address PR #28 review follow-ups by @ako in #48
- docs: add mxbuild setup & mx tool skill by @engalar in #43
- deps: bump modernc.org/sqlite from 1.42.2 to 1.48.0 by @dependabot[bot] in #57
- deps: bump go.mongodb.org/mongo-driver from 1.17.6 to 1.17.9 by @dependabot[bot] in #60
- deps: bump github.com/spf13/cobra from 1.8.0 to 1.10.2 by @dependabot[bot] in #62
- deps: bump github.com/mattn/go-runewidth from 0.0.19 to 0.0.21 by @dependabot[bot] in #61
- deps: bump go.uber.org/zap from 1.21.0 to 1.27.1 by @dependabot[bot] in #59
- deps: bump github.com/jackc/pgx/v5 from 5.8.0 to 5.9.1 by @dependabot[bot] in #58
New Contributors
- @retran made their first contribution in #47
- @ako made their first contribution in #48
- @dependabot[bot] made their first contribution in #57
Full Changelog: v0.3.0...v0.4.0