xmatix snapshot runs the per-kind pull or push commands one after another, so a single command copies a tenant's configuration into your workspace (snapshot export) or sends the workspace's files back to the tenant (snapshot import). Export is how a repository gets its first copy of a tenant and how it catches up with changes made in the product. Import is the engine under migrate apply, which is the last step of a reviewed change.
xmatix snapshot export --skip scripts,dashboards,reports # metadata, rules, workflows
xmatix scripts pull --all # scripts, run separately
xmatix snapshot export --scope TenantFull --skip scripts,dashboards,reports
xmatix snapshot import --skip dashboards,reports --dry-run # preview only
xmatix snapshot import --skip metadata,dashboards,reports # push automation files
Overview
Both commands work on the workspace's canonical folders (see Workspace layout):
| Kind | Folder | Export runs | Import runs, for each file |
|---|---|---|---|
metadata | xmatix/metadata/ | metadata pull --scope <scope> | metadata push <file> for every *.json |
scripts | xmatix/automation/scripts/ | scripts pull | scripts push <file> for every *.csx |
rules | xmatix/automation/rules/ | rules pull | rules push <file> for every *.json |
workflows | xmatix/automation/workflows/ | workflows pull | workflows push <file> for every *.json |
dashboards | xmatix/analytics/dashboards/ | dashboards pull | dashboards push <file> for every *.json |
reports | xmatix/analytics/reports/ | reports pull | reports push <file> for every *.json |
Each command runs in its own process, exactly as if you had typed it, and prints its own output. Neither snapshot command adds options of its own to those commands: export passes only --scope to the metadata pull, and import passes only the file path.
In the current release, three kinds don't work through a snapshot:
- Scripts never export. Export runs
scripts pullwith no script name and without--all, andscripts pullrefuses that with "Specify a script name or pass --all." So the scripts step fails on every run, your script files are not refreshed, and the export ends with a failure and exit code 1. Skipscriptsand runxmatix scripts pull --allyourself. - Dashboards and reports don't round-trip. Their
pullwrites no files but still succeeds, and everypushfails. See Dashboards and reports in the CLI.
When to use it
- First copy of a tenant. Export into a new workspace and commit the result.
- Catching up with the product. Export into a clean checkout and review
git diffto see what someone changed in the product since the last export. - Comparing the repository with the tenant. Use an export into a clean checkout.
migrate planruns a fullsnapshot exportinternally, so in the current release it stops with "Server snapshot export failed; aborting plan." every time. - Pushing reviewed files. Import, or
migrate apply, pushes every file of the kinds you don't skip. To push only a few files, run the per-kindpushcommands on those files instead.
How xMatix handles it
What export does
- It checks that you are inside a workspace, then runs
metadata pull --scope <scope>,scripts pull,rules pull,workflows pull,dashboards pullandreports pull, in that order, leaving out the kinds in--skip. - Before each command it prints
→and the command's name. A command that ends with a non-zero exit code is reported as "✗ <command> exited <code>", and the export moves on to the next kind. - It ends with Snapshot export complete. and exit code 0, or Snapshot export finished with N failure(s). and exit code 1.
What each pull writes:
- Metadata — one seed-pack file. Its name depends on the scope:
tenant-owned.jsonfor the defaultTenantOwned,tenant-full.jsonforTenantFull. The file is a full pack, itsmodeis alwaysfull, and it carries a freshgeneratedAtUtctime. See Metadata seed-packs. - Rules — one file per rule under a folder per entity. Rules on entities the CLI can't see go to
_unknown/and can't be pushed back. See Business rules in the CLI. - Workflows — one file per workflow, named after the workflow (or its definition id when it has no name).
- Scripts (when you run
scripts pull --allyourself) — each script as a.csxfile with its.meta.json, in a folder per entity. Scripts that have no current version are skipped. Every.meta.jsongets a freshlastPulledUtctime. See Scripts.
Export overwrites files that already exist and never deletes any. A rule, workflow or script that was deleted or renamed in the product leaves its old file behind. Delete such files yourself in the same commit.
What import does
- It checks that you are inside a workspace, then pushes the folders in this order, so that metadata exists before the automation that uses it: metadata, scripts, rules, workflows, dashboards, reports.
- For each folder it prints
→, the folder and the number of files, then pushes each file in alphabetical order of path, including files in subfolders. A folder that doesn't exist is reported as "(missing, skipped)", and a folder with no matching files as "(no … files, skipped)". - A push that fails is reported, and the import carries on with the next file and the next kind.
- It ends with Snapshot import complete. and exit code 0, or Snapshot import finished with N failure(s). and exit code 1. When no folder had any file to push, it prints Nothing to push (no source files found). and exits 0.
With --dry-run, import prints a would run: line with the push command for every file and contacts nothing. It always exits 0.
What each push does with its file:
| Kind | Effect on the tenant |
|---|---|
| Metadata | Every row in the file is created or updated. A full-mode file also deletes every row an earlier seed-pack delivered that the file doesn't contain. metadata push asks Continue? before each file |
| Scripts | Skipped when the file matches the version recorded in its .meta.json. Otherwise a new version is saved and compiled, but not made active. Refused when the .meta.json is missing, and when the script was changed in the product after the last pull |
| Rules | Updated by entity and rule name, or created. The file's actions replace the rule's actions, after a confirmation when the rule already has actions |
| Workflows | Updated when the file's definition id exists on the tenant, otherwise created as a new workflow. The published state in the file is kept |
| Dashboards, reports | The push fails in the current release |
Import never deletes a script, rule, workflow, dashboard or report on the tenant. Only a full-mode metadata file deletes anything.
Prerequisites
- The CLI installed and a workspace created with
xmatix init. xmatix logincompleted for the tenant in.xmatix/config.json. Check it withxmatix scripts list;xmatix whoamiandxmatix doctorfail in the current release (see CLI authentication).- The access each kind needs (see Permissions).
- For a comparison, a clean git working tree: commit or stash your own changes first, so that
git diffshows only what the export changed.
Procedure
Step 1 — Export the tenant
From anywhere inside the workspace, run:
xmatix snapshot export --skip scripts,dashboards,reports
xmatix scripts pull --all
The export prints a line per kind and ends with Snapshot export complete. The script pull prints Pulled with the path and version for each script, then Done. with the counts. Add --scope <scope> to the export only if your repository is kept in a scope other than TenantOwned.
If a step fails, the export says which one. Fix the cause (see Common problems) and run the export again; it simply overwrites the files.
Step 2 — Review the changes
git status --short xmatix/
git diff -I '"generatedAtUtc"' -I '"lastPulledUtc"' -- xmatix/
- New files (
??) are artifacts that were created in the product, or that the export placed somewhere new, such as a rule under_unknown/. - Changed files show what was changed in the product. The two
-Ipatterns hide hunks in which only the export or pull time changed (git 2.30 or later). - If the committed metadata file had its
modeset todelta, the export sets it back tofull. Expect that line to change. - Nothing shows an artifact that was deleted in the product, because export never deletes files. Check the tenant for anything you expect to be gone.
Commit what you want to keep. Don't commit _unknown/ rule folders, and read the metadata file for anything that shouldn't go into a repository before you commit it.
Step 3 — Prepare the metadata for an import
Skip this step if you leave metadata out of the import.
The exported metadata file is a full pack, and pushing it removes standard metadata that it doesn't contain. Before an import, either:
- import with
--skip metadataand push a delta copy yourself, which the procedure in Metadata seed-packs describes, or - set the file's
modetodeltain the working copy:jq '.mode = "delta"' xmatix/metadata/tenant-owned.json > tenant-owned.delta.json, then move the delta file over the original.
Keep only one metadata file in xmatix/metadata/. Import pushes every *.json in that folder, so a leftover tenant-full.json beside tenant-owned.json is pushed too.
Step 4 — Preview the import
xmatix snapshot import --skip dashboards,reports --dry-run
Check that every would run: line points into the workspace you expect and that no folder you meant to push is reported as skipped.
Step 5 — Import
Run the import in a terminal, so that you can answer the confirmations:
xmatix snapshot import --skip dashboards,reports
- For each metadata file,
metadata pushshows the file and its size and asks Continue?. The default answer is no. - For each rule that already has actions on the tenant,
rules pushasks before replacing them. - The run ends with Snapshot import complete., or Snapshot import finished with N failure(s). and exit code 1. Scroll up to find the files that failed.
Step 6 — Finish the scripts and workflows
- Pushed scripts are saved as new versions but are not active. Activate them in the product, or push each changed script again with
xmatix scripts push <file> --activate. - If a workflow was created rather than updated, run
xmatix workflows pulland commit the file, so the next import updates that workflow instead of creating another copy.
Command options
| Command | Option | Effect |
|---|---|---|
snapshot export | --scope <scope> | Metadata scope passed to metadata pull: TenantOwned (default) or TenantFull. The scope decides the metadata file's name |
snapshot export | --skip <kinds> | Comma-separated kinds to leave out: metadata, scripts, rules, workflows, dashboards, reports. Not case-sensitive |
snapshot import | --skip <kinds> | The same list, for the import |
snapshot import | --dry-run | Prints the push commands without running them |
| Command | Exit code |
|---|---|
snapshot export | 0 when every pull succeeds, 1 when any pull fails. Without --skip scripts it is always 1 |
snapshot import | 0 when every push succeeds or there is nothing to push, 1 when any push fails. Always 0 with --dry-run |
Business rules
- Export and import run their commands in a fixed order.
--skipcan leave kinds out but can't change the order. - A failure in one kind or one file never stops the rest. The exit code reports the whole run.
- Export writes the metadata file as a full pack every time. Import sends each metadata file with the
modeit contains. - Export never deletes local files, and import never deletes scripts, rules, workflows, dashboards or reports on the tenant.
- Import pushes every file of every kind it runs, whether or not the file changed. Unchanged scripts are skipped; rules and workflows are written again, and a rule's actions are deleted and recreated.
- Scripts are matched by the script id in their
.meta.json, rules by entity name and rule name, and workflows by definition id. That makes scripts, and workflows that are matched by id, specific to the tenant they were pulled from. - Both commands act on the tenant in the nearest
.xmatix/config.jsonabove the current folder.
Example
A team keeps its tenant's automation in a repository and wants to bring in changes an administrator made in the product.
- On a clean checkout of the main branch, a developer runs
xmatix snapshot export --skip scripts,dashboards,reports, thenxmatix scripts pull --all. Both finish without failures. git status --short xmatix/shows one new file,xmatix/automation/rules/Order/HoldHighValue.json. Thegit diffwith the two-Ipatterns shows thatCreditCheck.jsonnow has a lower limit in its condition. The metadata file changed only in its export time, which the diff hides.- They commit the new rule and the changed rule in a branch titled "Capture product changes to order rules" and merge it after review.
- Later the same week, they edit
CreditCheck.jsonin the repository. After review, they runxmatix snapshot import --skip metadata,scripts,workflows,dashboards,reports --dry-runand see twowould run:lines, one per rule file. - They run the same import without
--dry-runand confirm the replacement of each rule's actions. The run ends with Snapshot import complete.
Training
Practice exercise
In a sandbox workspace:
- Run
xmatix snapshot exportwith no options. Expected result: the scripts step reports "Specify a script name or pass --all." and the export ends with Snapshot export finished with 1 failure(s). (more if another step also fails). - Run
xmatix snapshot export --skip scripts,dashboards,reportsandxmatix scripts pull --all, then commit thexmatix/tree. Expected result: the export ends with Snapshot export complete. - In the product, change the description of a test business rule. Export again with the same two commands and run the
git difffrom Step 2. Expected result: only that rule's file shows a change. - Run
xmatix snapshot import --skip metadata,scripts,workflows,dashboards,reports --dry-run. Expected result: onewould run: xmatix rules push …line per rule file, and nothing changes on the tenant.
Quick reference
- Export with
--skip scripts,dashboards,reports, then runxmatix scripts pull --all. migrate plancan't run in the current release; compare by exporting into a clean checkout.- The exported metadata file is a full pack. Push only a delta copy, or skip metadata.
- Keep one metadata file in
xmatix/metadata/. - Always
--dry-runan import first, and run the real import in a terminal. - Import pushes every file, continues after failures and exits 1 if any failed.
- Pushed scripts are not active until you activate them.
- Neither command ever deletes files or artifacts, except a full-mode metadata push.
Permissions
The CLI acts with the permissions of the account that signed in with xmatix login, and the server records that account as the author of every change.
- The metadata step of export and import needs the
setup.metadata.packages.managecapability, the same one that opens Setup → Packages. Without it, the metadata pull or push fails with a 403 and the snapshot reports a failure. - Scripts, rules and workflows need the same access their own screens need in the product.
See the security model for how capabilities are granted.
Configuration
- Target tenant. The nearest
.xmatix/config.jsonabove the current folder decides the tenant. Keep one workspace per tenant. - Metadata scope.
--scopeon export decides which metadata is exported and the file's name. Keep the scope your repository already uses (see Which rows each scope includes). - Metadata mode. The
modein each metadata file decides whether its push prunes. Usedeltafor anything you import. - Kinds. Use
--skipto leave out the kinds a repository doesn't own. In the current release, always skipscriptson export anddashboards,reportson both commands. .gitignore. Addxmatix/.snapshot/, wheremigrate planwrites, and considerxmatix/automation/rules/_unknown/.
Common problems
The export ends with "Snapshot export finished with 1 failure(s)."
Look for the ✗ line. If it is "✗ scripts pull exited 1" after "Specify a script name or pass --all.", that is the scripts step, which fails on every export in the current release. Add scripts to --skip and run xmatix scripts pull --all separately. For any other kind, the lines above the ✗ show that command's own error.
"No xMatix workspace found. Run xmatix init in your repository root first."
The command was run outside a workspace. Change to a folder inside the workspace that holds .xmatix/.
The metadata step fails with a 403
The signed-in account lacks the setup.metadata.packages.manage capability. Grant it, or skip metadata.
The import stops at "Continue?" or fails at the metadata or rules step in a pipeline
metadata push, and rules push for a rule that already has actions, ask for confirmation, and import doesn't pass --yes. Nobody can answer in a pipeline, so those pushes fail. Skip those kinds and push them yourself with --yes, as in CI recipes.
Standard entities, fields or layouts disappeared after an import
A full-mode metadata file was imported. It deletes metadata that an earlier seed-pack delivered and that the file doesn't contain. Always import a delta copy or skip metadata. See Standard entities, fields or layouts disappeared after a push.
Every rule under _unknown/ fails to push
Those rules belong to entities the CLI couldn't see during the pull, so their files name an entity called _unknown. Delete the folder, or keep it out of the workspace. See My pull created an _unknown folder.
Every dashboard and report file fails, or the analytics folders stay empty
Dashboards and reports don't round-trip in the current release. Add dashboards,reports to --skip on both commands.
My pushed script changes don't take effect
Import saves a new version of each changed script without making it active. Activate it in the product, or push it with --activate.
"Server has a newer current version than your local copy." during import
Someone changed the script in the product after your last pull. Pull it with xmatix scripts pull <name>, merge the changes, and import again.
Each import creates another copy of a workflow
The file's definition id doesn't exist on this tenant, so each push creates a new workflow and the file keeps the old id. Run xmatix workflows pull after the first import and commit the file. Delete the extra copies in the product.
A file I deleted locally is still on the tenant
Import never deletes artifacts. Delete it in the product.
Common questions
How often should a team export?
At every deliberate change, plus on a schedule. The deliberate exports keep the repository authoritative. A scheduled one, nightly for example, catches changes someone made in the product without exporting them, and shows them as a reviewable diff while the author still remembers making them. The CI recipes page has a scheduled version.
Is import idempotent?
Not entirely. Importing the same tree twice leaves rules and existing workflows with the same content, and unchanged scripts are skipped. But a changed script gets another new version on every import until it is activated, because the .meta.json keeps pointing at the old active version. A workflow whose definition id isn't on the tenant is created again on every import. A full-mode metadata file prunes each time. Use a delta metadata file, activate scripts and re-pull new workflows, and a rerun after a partial failure is safe.
Why does migrate plan always fail?
migrate plan exports the tenant into a temporary workspace with snapshot export --scope <scope>, and it can't pass --skip. The export's scripts step always fails, so the plan stops with "Server snapshot export failed; aborting plan." To compare the repository with the tenant, export into a clean checkout and review git status and git diff, as in Steps 1 and 2.
Why did my import half-succeed?
Import deliberately carries on past failures and reports them at the end with exit code 1. Common causes are the metadata or rules confirmation in a pipeline, analytics files, rules under _unknown/, scripts whose new version fails to compile, and a --skip metadata import on a tenant that doesn't yet have the entities the rules refer to. Fix the named files and import again.
Can I use a snapshot to copy one tenant to another?
Only partly. Metadata and rules can move between tenants, with the limits described in Can I promote from one tenant to another? Scripts can't, because each .meta.json holds the source tenant's script id. Workflows are created as new copies. Keep a separate exported workspace for each tenant.
