Assetize

MXH · Documentation

Run MXH over your Maximo export and act on what it finds.

Get the package, export your setup, run one command and read graded findings, each with its evidence, owner and closure test.

Get MXH · Open the sample assessment

BUILT NOW — shipped and working today.

Read your Maximo export. Compare it with the target release.

MXH reads the setup you export and compares it with versioned evidence for the release you are moving to. Each finding names the difference, its source, how sure the evidence is, who fixes it and how you prove it fixed.

  • 01 · Export: Your data dictionary, customisation code and screens, plus a short manifest. Structure only.
  • 02 · Run: One command on your own machine, against the exact release you are targeting.
  • 03 · Act: Graded findings with an owner and a closure test, then a rerun that shows what closed.

The assessment runs locally over your export. It compares definitions and code without executing your customisations. Developers also get a separate modelled local test harness.

Want to see the result first? Open the sample assessment, one full run for a sample company.

Install MXH and run it yourself.

Free: the tool and the metadata packs. You run it on your own machine, over your own export, and read the report yourself. No key and no sign-up.

  • Java 17 or newer on your PATH. Check with java -version.
  • MXH itself. Pick your system below, run its install command, then open it with mxh ui.
  • A folder for your export. The layout is under What to export.

Install · Windows

# PowerShell (Windows PowerShell 5.1 or PowerShell 7). No admin rights needed.
# The download is checked against its published SHA-256 before anything is installed.
irm https://assetize.com.au/mxh/install.ps1 | iex

# A particular version, or every version published. Older versions stay installed, so going back is the same command.
& ([scriptblock]::Create((irm https://assetize.com.au/mxh/install.ps1))) -Version 0.13.0
& ([scriptblock]::Create((irm https://assetize.com.au/mxh/install.ps1))) -List

Need Java 17? winget install Microsoft.OpenJDK.17. The installer adds mxh to your PATH, in this window and new ones.

Install · macOS

# The download is checked against its published SHA-256 before anything is installed.
curl -fsSL https://assetize.com.au/mxh/install.sh | sh

# A particular version, or every version published. Older versions stay installed, so going back is the same command.
curl -fsSL https://assetize.com.au/mxh/install.sh | sh -s -- --version 0.13.0
curl -fsSL https://assetize.com.au/mxh/install.sh | sh -s -- --list

Need Java 17? brew install --cask temurin@17.

Install · Linux

# The download is checked against its published SHA-256 before anything is installed.
curl -fsSL https://assetize.com.au/mxh/install.sh | sh

# A particular version, or every version published. Older versions stay installed, so going back is the same command.
curl -fsSL https://assetize.com.au/mxh/install.sh | sh -s -- --version 0.13.0
curl -fsSL https://assetize.com.au/mxh/install.sh | sh -s -- --list

Need Java 17? sudo apt install openjdk-17-jre on Debian and Ubuntu, sudo dnf install java-17-openjdk on Fedora and RHEL.

The installer puts each version in ~/.mxh/versions/, points ~/.mxh/mxh.jar at the one you chose and writes a launcher called mxh. Add --with-mcp for the MCP server for agents. On Windows the same layout sits under %USERPROFILE%\.mxh\ and the launcher is mxh.cmd; add -WithMcp there for the MCP server. A machine with no route to the site installs from a copy of the release folder with --base-url.

Check the install

# Check Java, the jar, every pack's signature, the licence and the --pdf browser
mxh doctor

# The build and pack versions, and offline help
mxh --version
mxh help assess

mxh doctor prints one line per check and ends with ready: and the command to run next. Its licence line reads free to use, no key needed. Every release carries the current metadata packs, so running the install command again updates them. The licence is below.

  1. Get MXH. One command installs it, free, with every metadata pack. mxh ui opens it in your browser.
  2. Export your Maximo. Your data dictionary, customisation code and screens, plus a manifest. Structure only, no business records.
  3. Run it. One command over one folder. MXH compares your export with IBM's own release for your target.
  4. Read the findings. Every difference has a severity, an evidence class, an owner and the test that closes it.
  5. Open the reports. Start with readiness.html, then the brief, the full report and the explorer. findings.xlsx and assessment.json feed your own tracking.
  6. Rerun after fixes. Compare the new run with the original. Closure follows the evidence checked; omitted inputs are never counted as fixes.

Get MXH. Stuck on a step? Email aniruddh@assetize.com.au.

The four commands of an upgrade.

Point mxh assess at your package folder. It reads the manifest, runs every check the inputs allow and writes the reports to the output folder.

Preflight, assess, rerun, close

# 1. Inventory your package before you assess (writes preflight.md and preflight.json)
mxh assess --from ./kestrel --output ./round-0 --preflight

# 2. Run the assessment
mxh assess --from ./kestrel --output ./round-1

# 3. Fix, then rerun and compare with the first run
mxh assess --from ./kestrel --output ./round-2 --baseline ./round-1

# 4. After the upgrade, check every finding closed
mxh verify-closure --baseline ./round-2 \
  --export ./after-upgrade/dd --code ./after-upgrade/src \
  --customer "Kestrel Energy" --out ./closure
  • --preflight lists what your package holds, so you can add a missing input before the real run. It writes preflight.md and preflight.json and assesses nothing.
  • --baseline compares this run with an earlier one. See Repeatable runs.
  • verify-closure reads a fresh export after the upgrade and marks every finding closed, not closed or not checked. See Post-upgrade proof.
  • mxh ui opens every command as a form in your browser, and shows the command line it builds. See In your browser.

Without a manifest

# The same run without a manifest: name each input with a flag
mxh assess --from 7.6.1.3 --to 9.2 \
  --export ./from-customer/dd --code ./from-customer/src --java-jars ./from-customer/lib \
  --out ./round-1

PDF and signing

# Print the HTML views to PDF as well (needs Chrome, Chromium or Edge)
mxh assess --from ./kestrel --output ./round-1 --pdf

# Sign the lock file with your own key
mxh assess --from ./kestrel --output ./round-1 --sign ./signing-key.pem

mxh help lists every command, offline. mxh help assess lists every flag.

Run it by clicking or by typing. You get the same command line either way.

mxh ui opens a page on your own machine with a form for every command. Each form shows the exact command it builds, so what you click once goes into a script or your pipeline.

  • 01 · Pick or type: Choose a command on the left, or type one in the bar at the top. The form fills in as you type, and the line updates as you fill in the form.
  • 02 · Run and watch: Output appears as the command works, with its real exit code. Stop ends a long run.
  • 03 · Open your report: The files a run wrote are listed. The readiness report opens in a tab or in a preview on the page.

Open it from your project folder

# From your project folder: every command as a form, with live output and your reports
cd ~/work/my-maximo-project
mxh ui

# On a server you reach over SSH: pick the port, then forward the same port to your laptop
mxh ui --port 8765 --no-open
  • Every flag is a field. The forms come from the text mxh help prints, so a new flag shows up the day it is added. Required fields come first, and Run waits for them.
  • Folder fields have Browse. It lists the folders on your machine, so you can point at your export without typing a path.
  • Keys stay out of the command line. A --apikey-env field takes the variable's name for the line and the value on its own. The value goes to that one run and is gone when it ends.
  • The start page checks your machine. It runs mxh doctor when the page opens and shows Java, the packs, the licence and the PDF browser.

The page runs on your machine and works with no network. It listens on 127.0.0.1 and asks for the token in the address mxh ui prints. mxh help ui lists the two flags.

Three ways to run it. Start with what you can export this week.

Each mode writes a full report. Start with the inputs you have and add the rest to a rerun.

ModeYou supplyYou get
SnapshotYour current release, the target and your add-ons. No export.Release-to-release findings from IBM's upgrade scripts, to size the work. Run it with --scripts-only.
Dictionary onlyA package whose manifest supplies dictionary alone.Every field-length, type, required-flag and removed-attribute difference against the target, on your own columns.
Full auditDictionary, customisation code, screens and the configuration inputs you include.Findings tied to your files and definitions, with severity, evidence and an owner for each.

Snapshot

# Release-to-release findings from IBM's upgrade scripts, before any export
mxh assess --from 7.6.1.3 --to 9.2 --scripts-only --solutions oilandgas --out ./snapshot

Add each add-on you run to --solutions, comma separated, for example --solutions oilandgas,utilities. The report reads the same way in every mode, and the manifest records what each run received.

Three parts of your system go in.

Everything is exported from your system. Nothing is installed on your Maximo.

  • Data setup: Your data dictionary: objects, attributes, relationships and domains. Add configuration and security definitions for a wider check.
  • Customisation code: Java source, compiled JARs and automation scripts, plus the launch points that fire each script.
  • Screens: Application Designer XML for classic screens and MAF (Maximo Application Framework) app.xml for role-based applications.

The report lists the inputs it assessed and the release evidence behind every finding, so you always know what a clean section covers.

What to export, and where each file goes.

Put everything in one folder with a manifest at the top. Take it from a lower environment that matches production customisations.

The package folder

kestrel/
  manifest.yaml
  export/              maxobject.csv  maxattribute.csv  maxrelationship.csv
                       synonymdomain.csv  alndomain.csv
  src/java/            your Java source
  src/scripts/         automation scripts (.py, .js)
  src/screens/         Application Designer XML, one file per application
  lib/                 compiled JARs
  launch-points/       scriptlaunchpoint.json  launchpointvars.json
  object-structures/   one OSLC JSON schema or OpenAPI file per object structure
  security/            maxgroup.json  applicationauth.json  securityrestrict.json  groupmembership.json
  configuration/       escalation.json, crontaskdef.json, wfprocess.json ... products.json,
                       reports/*.rptdesign, integrity-checker.log
  role-based-apps/     MAF app.xml, one per application
PartWhat it holdsManifest key
Data dictionaryFour CSV files with a header row: MAXOBJECT, MAXATTRIBUTE, MAXRELATIONSHIP and SYNONYMDOMAIN. Add ALNDOMAIN when you use ALN domains.dictionary
Customisation codeJava source and automation scripts. Compiled JARs get reference and signature checks.code, java-jars
ScreensApplication Designer presentation XML, one file per application.presentation
Role-based applicationsMAF app.xml, one per application. Include object-structure schemas for custom datasources.role-based-apps
Script bindingsThe launch-point and variable-binding rows: scriptlaunchpoint.json and launchpointvars.json.launch-points
IntegrationsExported OSLC object-structure schemas or OpenAPI definitions, one per structure.object-structures
ConfigurationJSON exports for escalations, cron tasks, actions, workflows, communication templates, domains, properties, integrations and KPIs; BIRT .rptdesign reports; products.json; the Integrity Checker log.configuration
SecurityMAXGROUP, APPLICATIONAUTH, SECURITYRESTRICT and group membership counts, as JSON.security

Structure, not records. The export is your schema and configuration. No work orders, assets or business rows. Security goes in as group membership counts. No user identities are needed.

Review configuration files for credentials and secrets before you include them. If what is deployed and what is in source control disagree, note it in the manifest.

Export recipes you can copy.

Read-only SELECTs, the same on Db2, Oracle and SQL Server. Or let MXH collect the package for you.

Print the SQL from MXH itself

# Print every export SELECT from the jar, or one part of it
mxh export-sql
mxh export-sql dictionary --out export-dictionary.sql
mxh export-sql configuration --out export-configuration.sql

mxh export-sql prints every SELECT below from the jar, in four parts: dictionary, security, launch-points and configuration. The columns are the ones mxh collect reads, checked against IBM's own dictionaries.

Data dictionary: one CSV per SELECT

-- Read-only SELECTs for Db2, Oracle and SQL Server. One CSV per result, with a header row.
-- Tip: add  WHERE objectname IN ('WORKORDER','ASSET',...)  to keep it small.

-- maxobject.csv
SELECT objectname, classname, persistent, entityname, description FROM maxobject;

-- maxattribute.csv
SELECT objectname, attributename, maxtype, length, scale, required, persistent, title, domainid FROM maxattribute;

-- maxrelationship.csv
SELECT parent, name, child, whereclause FROM maxrelationship;

-- synonymdomain.csv
SELECT domainid, maxvalue, value FROM synonymdomain;

-- alndomain.csv (add it when you use ALN domains)
SELECT domainid, value FROM alndomain;
  • A header row naming the columns. Case and spaces are ignored.
  • Comma separated, with standard quoting: a field holding a comma, quote or line break is wrapped in double quotes. WHERECLAUSE and DESCRIPTION often need it.
  • UTF-8. A byte-order mark is stripped and CRLF line endings are fine. On Windows, run chcp 65001 first.
  • A file with the wrong columns stops the run with a message naming the file, the header it found and the header it wanted.

Security: four JSON files

-- Written as JSON arrays of row objects into security/

-- maxgroup.json
SELECT groupname, description, authallsites, authallgls, independent FROM maxgroup;

-- applicationauth.json
SELECT groupname, app, optionname FROM applicationauth;

-- securityrestrict.json
SELECT groupname, objectname, attributename, conditionnum, app, restriction, type
  FROM securityrestrict;

-- groupmembership.json: counts of active users per group, no user ids
SELECT g.groupname, COUNT(*) AS usercount
  FROM groupuser g JOIN maxuser u ON u.userid = g.userid
 WHERE u.status = 'ACTIVE'
 GROUP BY g.groupname;

Or collect the whole package

# Build the package straight from your Maximo, read-only
mxh collect --out ./kestrel --release 7.6.1.3 --to 9.2 --solutions oilandgas \
  --customer "Kestrel Energy" --url https://maximo.example.com/maximo

mxh collect reads your system and writes the same folder layout and manifest. Point it at your Maximo URL with --url, your SMP folder with --smp, a Migration Manager package with --package, or a saved capture with --captured.

Screens: export each application from Application Designer and save the XML in src/screens/. Role-based applications: save each MAF app.xml in role-based-apps/. Launch points and configuration: export the rows of each table named in the folder layout as JSON.

One manifest says what the run is about.

manifest.yaml sits at the top of the package. It names your release, the target, your add-ons, the export date and each input.

manifest.yaml

# manifest.yaml, at the top of the package folder
customer: Kestrel Energy
estate:
  release: 7.6.1.3
  solutions: [oilandgas]
  exported: 2026-09-10
target:
  release: 9.2
supplied:
  dictionary: export
  code: [src/java, src/scripts]
  presentation: src/screens
not_supplied:
  security: Group grants are reviewed by our security team in a separate pass.
FieldWhat it says
customerThe name printed on every report. Required.
estate.releaseThe release you run today, for example 7.6.1.3. Required.
estate.solutionsYour installed add-ons, by package name, such as oilandgas.
estate.exportedThe export date, YYYY-MM-DD. Required.
target.releaseThe release you are moving to. Required, and later than your current release.
suppliedA folder for each input: dictionary, code, presentation, object-structures, launch-points, security, configuration, role-based-apps, java-jars. Supply a dictionary or code, or both.
not_suppliedAn input you are holding back, with the reason. The reason prints on the report.

MXH checks the manifest before it does any work. A key listed under both supplied and not_supplied, a target that is not later than your release, or a missing folder stops the run with a message that names the field.

Every finding carries four separate decisions.

Impact, strength of evidence, who fixes it and the test that proves it fixed are recorded separately.

  • 01 · Severity · How bad is it?: One of three grades: BLOCKING, REVIEW, ENVIRONMENT.
  • 02 · Evidence class · How sure is the evidence?: 6 evidence classes, A1 to C, keep a certain observation apart from a probable one.
  • 03 · Owner · Whose job is it?: The row names the role that fixes it.
  • 04 · Closure test · How do you know it is fixed?: A specific, checkable condition closes the item.
GradeWhat it means
BLOCKINGWill not compile, will not load, or throws on first use.
REVIEWA real difference whose consequence depends on what the code does with it.
ENVIRONMENTDiffers between the two systems; not a property of the release.

Beside the grades, every report states its coverage under NOT ASSESSED. Stated on every report, so a clean result's meaning is bounded.

Severity and evidence never collapse into one score. A serious finding on thinner evidence reads as exactly that, and a well-evidenced minor difference stays minor.

Read the evidence classes for what each one lets you say.

One finding, field by field.

From the sample assessment, 7.6.1.3 → 9.2. This is the shape of every row in findings.xlsx and assessment.json.

FieldValue
Messagepsdi.iface.jms.ErrorQueueNotfCronTask no longer exists in 9.1 and your code references it
GradeBLOCKING
Evidence classA2 · IBM's API at 9.1
WherePermitGate.java:8
OwnerCustomisation developer
Required actionReplace the reference. The type does not exist at the target, so the customisation will not compile; find the supported equivalent or remove the dependency.
Closure testThe customisation compiles against the target's businessobjects.jar with no unresolved import.

Every other finding in the run follows the same fields. Browse all of them in the sample.

The same inputs produce the same assessment.

Every input is fingerprinted in mxh.lock.json. Repeat a run over the same inputs and the output is byte-identical.

After remediation, rerun with --baseline pointing at the first run. Each finding lands in one of 7 outcomes. The earlier record stays visible, and an input omitted from the rerun is never counted as a fix.

  • Verified resolved: Gone from the baseline, and the same source or JAR was scanned again this run — the same evidence was checked and it is gone.
  • Not reassessed: Gone from the baseline, but the input that produced it was not part of this run: a file or JAR nobody supplied, or the customer's own data-dictionary export supplied to one of the two runs and not the other. Not a fix — supply the same input again to find out whether it still applies.
  • Invalidated by evidence correction: Gone from the baseline because mxh's own shipped evidence for the target release changed between the two runs, not because the customer's system did.
  • No longer observed: Gone from the baseline with no code-coverage signal to verify against — typically a dictionary-only finding. Read as "not seen this time", not as a confirmed fix.
  • Changed: In both runs, with a different grade, evidence or location this time. Read the new detail before you act on it.
  • Remaining: In both runs, identical. Still open work, exactly as the baseline described it.
  • Newly observed: In this run and absent from the baseline: new code, a new input or newer evidence for the target release.

Prove it closed, after the upgrade.

Once you have moved, mxh verify-closure reads a fresh export of your upgraded system and marks every finding closed, not closed or not checked, with the lines it read.

Closed means the finding was looked for again in the same kind of evidence it came from, and it is gone. Evidence you did not send the second time leaves that finding not checked, so a closure always rests on something read.

Two words to keep apart: a rerun (--baseline) compares two assessments before the move, and closure (verify-closure) checks the system after it.

Test customisations locally with a modelled harness.

Developers use MXH with JUnit to run selected custom code against version-aware, in-memory MBO (Maximo business object) models and generated fixtures. This is a separate workflow from the static upgrade assessment.

  1. Prepare a project. Get MXH, use Java 17 or newer, and run mxh init in your customisation repository.
  2. Choose the model and data. Pick the release profiles you need, such as mas-9.0, mas-9.1 or mas-9.2. Generate fixtures, and overlay your own dictionary with mxh import-dd when you test local extensions.
  3. Write focused tests. Use @MaximoTest for one profile and @MaximoMatrix for several. Exercise Java customisations, Jython scripts, headless classic-screen interactions or local OSLC contracts against the model.
  4. Keep the evidence. Keep the test results, generated fixtures, configuration and lock file in your build or CI pipeline.

Start a test project

# In your customisation repository
mxh init --id kestrel-wo --version 9.2

# Overlay your own dictionary on the model for local tests
mxh import-dd --version 9.2 --dir inputs/dd/9.2 --dest src/test/resources/mxh/metadata-project

Add the harness to your build

<!-- pom.xml: the harness as a test dependency. Every version stays available. -->
<repositories>
  <repository><id>assetize-mxh</id><url>https://assetize.com.au/mxh/maven</url></repository>
</repositories>

<dependency>
  <groupId>au.com.assetize.mxh</groupId><artifactId>mxh-mbo</artifactId>
  <version>0.13.0</version><scope>test</scope>
</dependency>

// Gradle
repositories { maven("https://assetize.com.au/mxh/maven") }
dependencies { testImplementation("au.com.assetize.mxh:mxh-mbo:0.13.0") }

mxh-ui (classic screens), mxh-script (automation scripts) and mxh-kernel come from the same repository at the same version. Every file has .sha1, .md5 and .sha256 beside it. Use your own businessobjects.jar at provided scope; the shipped mxh-psdi-shim is a compile-only stand-in.

  • Static comparison: Reads exported definitions and code references. Version-specific findings for developers, architects and upgrade leads.
  • Modelled local testing: Runs selected custom code against the harness model. Repeatable tests for developers and QA teams.
  • Customer-target evidence: Records what ran on your configured target system, with its inputs and results, for integration and acceptance decisions.

A local test result describes the selected model and fixtures. Each of the three keeps its own evidence record, and together they inform the go-live decision.

Compiled JARs get static checks too.

MXH reads class references and signatures from compiled customisations, so the comparison covers code you only have as a build.

A Java class carries its own index: the types it touches, its fields, its methods and their signatures. It is the same index the JVM reads to link a call. MXH reads your classes without running or decompiling them, and nothing is installed on your Maximo.

Reading a declared index gives the same answer every time, so two runs over the same JAR agree down to the byte.

The configuration IBM ships is compared, as well as the dictionary.

Reports, KPIs, cron tasks, escalations, workflows, security options, groups and restrictions, applications, properties, actions, templates, integrations, endpoints and document types. Shipped definitions are compared, and referenced differences become findings.

Your own configuration and security exports extend the check to your expressions, class references, integrations, grants and restrictions. An escalation whose condition names a column the target dropped shows up here, before its first run.

What fires an automation script is checked, as well as what it does.

The object and column a launch point fires on, and every variable bound to an attribute, are checked against the target like any other attribute.

A script whose code is unchanged is caught when the column its trigger binds to is gone or has changed shape.

One baseline from all the add-ons you run.

An assessment folds in every add-on you run, in a declared order, so it starts from the system you actually run.

Where two add-ons put the same column on the same object, the report says which definition applies and why. Where only install order decides it, the report names the query that reads the answer off your system.

A binding followed through a relationship path.

Screen fields and script variables are followed to the real object at any depth, and each finding is graded by which relationship graph answered each hop.

A path your own relationship rows answer is graded like any other binding. A hop answered by the shipped graph is labelled as such. A hop nothing answers is reported with the hop named.

Role-based MAF definitions are checked today.

Supply app.xml definitions to check datasource object structures, selected attributes, bindings, elements and properties against the release evidence.

These are static checks on the application definitions. Each finding names the registry it used. A match on the target release registry is class A3. A comparison against a nearby release registry is class C, modelled. Classic screens and headless classic-screen tests have their own checks.

50 cited behaviour rules model how Maximo acts.

The harness models 50 of Maximo's behaviour rules across 24 objects, including work order status transitions. Each rule cites its source and states its assumptions separately.

Coverage is measured against IBM's own class signatures at 9.2: 777 guard-shaped methods across 328 classes. A finding that rests on a rule is class C, modelled, and links to the rule's evidence.

Where the release knowledge comes from.

Every fact MXH compares against comes from material IBM publishes and from the shipped product itself: release documentation, the upgrade scripts that come with a release, and the release's own declared definitions.

Each finding cites the specific source it came from, so you can read it yourself. What the product carries is facts about those releases: names, types, lengths, signatures, and what a given upgrade script changes.

IBM's files, code and documentation text stay with IBM. MXH is an independent product.

The releases you move from, and the releases you move to.

MXH ships 3 target dictionaries and reads 3 moves from the classic levels IBM names as upgrade sources, plus 3 release moves between targets and 18 add-on packages.

Target releaseObjectsAttributes
9.01,73926,927
9.11,82028,165
9.21,86628,942

84,034 attributes counted across those 3 releases together, release by release.

Move fromTo 9.0To 9.1To 9.2
Maximo Asset Management 7.6.1.344 script-stated findings62 script-stated findings71 script-stated findings

The classic starting point here is Maximo Asset Management 7.6.1.3, and Control Desk 7.6.1.5 with Maximo Asset Management 7.6.1.3 for Maximo IT. A snapshot reads those moves from IBM's upgrade scripts, class A1. Add your own dictionary export and the same run becomes a full comparison on your own columns, at any level you run, MAS 8.x included. Confirm your source and target against IBM's upgrade checklist.

The 18 add-on packages are 13 industry solutions with tables of their own (Asset Configuration Manager, Aviation, Civil Infrastructure, Health, Health, Safety and Environment, Control Desk, Nuclear, Oil and Gas, Service Provider, Spatial, Strategize, Transportation and Utilities) and 5 integration add-ons that extend existing objects (Envizi, Oracle adapter, SAP adapter, TRIRIGA and Workday). Health, Safety and Environment and Oil and Gas ship one identical dictionary.

Use the interactive release and add-on explorers for the detail behind these totals.

Explore the 16 packaged sample files.

Every file below comes from one full run for Kestrel Energy, a sample company. Open any of them to see how one assessment serves executive decisions, technical remediation, evidence review, delivery tracking and automation.

  • Upgrade readiness — Open this first: the upgrade work grouped into must fix, rewire for containers, retest, clean up, and your data and fields, each with an owner, its evidence and when it is done. For: Everyone.
  • Executive brief — The decision-ready summary: the way forward, the work in scope and what it rests on. For: Executive sponsor.
  • Interactive explorer — From your whole system down to what blocks the upgrade, release by release, every number counted from the assessment. For: Everyone.
  • Technical report — Every finding with its evidence, owner, required action and closure condition. For: Technical lead.
  • Programme and delivery — Work packages with owner roles, sequencing and acceptance criteria, each linked back to its findings. For: Programme manager.
  • Architecture and technical leadership — Source, target and reach, the architecture decisions and the dependency register. For: Architect.
  • Development, data and testing — The verification playbook: each work package with its action and closure test. For: Developers, data and test teams.
  • Assurance and handover — One assessed result, one set of counts, and a trace from every decision to its evidence. For: Assurance and handover.
  • Evidence appendix — The evidence behind each finding. For: Reviewers.
  • Tracking spreadsheet — The findings in a workbook a delivery team can own and track. For: Delivery team.
  • Machine-readable findings — The assessment as structured data, for your own tooling. For: Developers.
  • Plain-text rendering — A stable text form for diffing one run against the next. For: Developers.
  • Readiness as data — The readiness work in readiness@1 form, for your tracker or pipeline. For: Developers.
  • Readiness as text — The readiness work as plain text, to paste into a change record. For: Programme manager.
  • Fingerprinted run record — The fingerprinted record of exactly what was checked. For: Assurance.
  • Data preflight queries (Db2) — Read-only SQL that lists the data records to review before the upgrade. For: Database administrator.

Open readiness.html first, with readiness.md and readiness.json beside it for your own tools. It groups the upgrade work into five lists: must fix before cutover, rewire for containers, retest after the upgrade, clean up before you move, and your data and fields. Each item has an owner, evidence and a completion condition.

preflight-db2.sql holds read-only Db2 checks for data that needs attention before the move, such as a column that gets shorter. MXH writes them and you run them. The sample's data triggers none, so its file is the header alone. It is separate from --preflight, which inventories your package before a run.

The same assessment answers a different question for each role.

Go to the page written for the decision you need to make.

RoleQuestionRead
Executive sponsorShould we commit?The executive case
Programme managerWhat is in scope?Programme and delivery
Maximo leadWhat changes for my users?Operations
Technical leadHow is this verified?How an assessment runs
DeveloperHow do I test my customisations?Developer testing
Security reviewerWhat leaves our network?For your security review
Business PartnerHow do I scope this before I have access?MXH for partners

Questions and fixes.

The messages people meet first, and what to do about each one.

You seeDo this
A FAIL line from mxh doctorDo what the line says, then run it again. It ends with the next command once every check passes.
mxh needs Java 17 or newer on PATHInstall Java 17 or newer and check java -version prints it.
UnsupportedClassVersionErrorAn older Java is first on your PATH. Put Java 17 or newer ahead of it.
mxh: command not foundAdd the launcher's folder to your PATH, or run java -jar mxh.jar directly.
mxh: no jar foundSet MXH_JAR to the full path of mxh.jar.
packs: evaluation, 0 day(s) leftThat line comes from an older MXH. Run the install command again; the packs are now free to use.
A CSV error naming two headersThe file has the wrong columns. Re-run the SELECT from the recipe above, with a header row.
Out of memory on a large exportSet MXH_JAVA_OPTS=-Xmx4g before the run.
--pdf writes no PDFInstall Chrome, Chromium or Edge, or point MXH_BROWSER at one.
  • Does anything leave my network? The run is local and your export stays with you. The security page has the detail and a checklist for your change board.
  • Which releases can I assess? Moves from 7.6.1.3 to 9.0, 9.1 and 9.2, and any level you run with your own dictionary export. See coverage.
  • Can I start without an export? Yes. A snapshot needs only your release, the target and your add-ons. See the three modes.
  • Can a partner run it for my client? Yes. The manifest takes an optional partner name and contact. See MXH for partners.
  • What do MBO, MAF, OSLC and BIRT mean? An MBO is a Maximo business object. MAF is the Maximo Application Framework behind role-based applications. OSLC is the REST interface Maximo integrations use. BIRT is the report engine behind .rptdesign files.

Free to use: the tool and the metadata packs.

The code is Apache-2.0. The metadata packs are free to use under the Assetize Metadata Pack Licence, in full below. Passing on an unmodified MXH release is fine; the one ask is not to republish the packs as a dataset.

Applies to: the Maximo metadata packs — mxh/metadata/**, mxh/packs/**, snapshots/assetize/** and any pack Assetize delivers inside mxh.jar or separately — hereafter "the Packs". It does not apply to the mxh source code, which is Apache-2.0 (see LICENSE).

Licensor: Assetize Pty Ltd, Melbourne, Australia.

1. What a Pack is

A Pack is a versioned, hashed set of derived facts about IBM Maximo releases: object → implementing class, attribute names, Maximo types, lengths, scales, required/persistent flags, domain values, and behaviour rules with citations to the published Assetize records they were derived from. Packs contain no IBM source code, no IBM binaries and no IBM documentation text.

2. Free use

You may use the Packs free of charge, for any purpose, on any number of machines and CI runners. That includes commercial work for your own organisation and for clients you run mxh for. No key or registration is needed. Every mxh release includes the current Packs, so updating mxh updates them.

3. Generated artefacts are yours

Everything you generate with the Packs — fixtures, stubs, MIF payloads, reports, lock files — is yours. You may commit it to your repositories, ship it, and keep using it, without further permission.

4. Passing mxh on, and what you may not do

You may pass on an unmodified mxh release — mxh.jar, mxh-mcp.jar, the release folder or the Maven artifacts, with the Packs inside them — for example on an internal mirror, through a Maven proxy, or to a client.

You may not:

  • Extract the Packs, in whole or in substantial part, and republish, resell or sublicense them as data — including as your own dataset, API, model training corpus or documentation site.
  • Remove or alter pack manifests, hashes, signatures or provenance fields.

5. No warranty, no IBM affiliation

The Packs are derived from published sources and are provided as is, without warranty of any kind. They are not certified by IBM, and Assetize is not liable for any loss arising from their use. Verify anything that matters against your own system's data dictionary — mxh import-dd exists for exactly that, and project metadata always wins over a Pack.

6. Termination

This licence ends for anyone who breaches clause 4. On termination you must stop using the Packs; artefacts already generated are unaffected.

7. Contact

licensing@assetize.com.au

Cut a release, publish it, and go back to an earlier one when you need to.

A release is one folder: the installer, two jars with their checksums, and the same build as a Maven repository. Build it from a committed state, publish it with one command and check the result against the build.

  • 01 · Build: tools/build-release.sh builds from the committed source and puts the commit's time in every jar, so the same commit gives the same bytes. It then installs from the folder it wrote and starts MXH, so the folder you publish has already run.
  • 02 · Publish: node scripts/publish-mxh-release.mjs build/release checks the folder adds up, uploads the version, then Maven's version lists, then the pointers last. It ends by downloading what it published and comparing it with the build.
  • 03 · Go back: --set-latest <version> points latest.json and the installer at an earlier version and changes nothing else. Pointers reach everyone within five minutes. A version's own files are cached for a year.

What a release folder holds

build/release/
  install.sh
  releases/
    latest.json   index.json
    v0.13.0/       mxh.jar  mxh-mcp.jar  SHA256SUMS  release.json
  maven/au/com/assetize/mxh/<artifact>/<version>/
                       the jar and pom, with .md5 .sha1 .sha256 beside each

Publish, check, go back

# Run from the assetize.com.au repository. First, see every object it would write
node scripts/publish-mxh-release.mjs build/release --dry-run

# Publish. Add --first-release only for the very first one
node scripts/publish-mxh-release.mjs build/release

# Compare the live site with the folder at any time
node scripts/publish-mxh-release.mjs build/release --verify-only

# Point the installer at an earlier version
node scripts/publish-mxh-release.mjs --set-latest <earlier version>
  • A published version stays as published. If the version is already out with different content, the publisher stops. A fix goes out as the next patch version.
  • An interrupted upload finishes with the same command. When the version, the commit and release.json match the published copy, it writes only the pointers, Maven's version lists and the installer.
  • One version per folder. Build into an empty build/release/. The publisher stops on a folder that holds an older version beside this one.
  • A backport leaves latest where it is. --no-latest publishes the version without moving latest.json.
  • A download checks by hand. With SHA256SUMS beside the jar, sha256sum -c SHA256SUMS prints OK for each file it finds.

A machine with no route to the site installs from a copy of the release folder with --base-url. See Get MXH and run it. The maintainers' copy of these steps, with the reason for each, is docs/releasing.md in the mxh repository.

Built from MXH integration package be0f912086adbe93 (mxh 2026.09).