xMatix
Sign in Request demo
xMatix
PRODUCTS
SalesField Sales & SFACRMRewardsClaimsInventoryProcurementWarehouse ManagementField ServiceServiceSupportTelephony & MessagingFinance & AccountingPayrollExpense ManagementCommercePortalsAnalytics & ReportingData StudioMobile AppSee all products →
PLATFORM
Platform overviewApp BuilderAutomationIntegrationsSecurity & GovernanceChange ManagementDevelopers
SENSE AI
Sense AI overviewSense AssistSense ControlSense VisionAI StudioTrust & governanceIn Claude & ChatGPTUse cases
SOLUTIONS
Auto DMSConsumer Goods DMSSales Force Automation (SFA) FMCG & DistributionManufacturing & Dealer NetworksAutomotive & DealershipsPharma & HealthcareConsumer DurablesAgri-InputsBuilding MaterialsService NetworksWarehousing & 3PLFinancial AccountingERP SoftwareIndia GST ComplianceUAE VAT & e-InvoicingSaudi ZATCA & VATAll solutions →
RESOURCES
Knowledge CenterDeveloper & CLIBlogGuidesWhat is xMatix?Company facts
COMPANY
AboutCareersPartnersEventsContactAuthorsLegal
Sign in Request demo
Home/Docs/Developer/Snapshots
REFERENCE · Last reviewed

Snapshots

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):

KindFolderExport runsImport runs, for each file
metadataxmatix/metadata/metadata pull --scope <scope>metadata push <file> for every *.json
scriptsxmatix/automation/scripts/scripts pullscripts push <file> for every *.csx
rulesxmatix/automation/rules/rules pullrules push <file> for every *.json
workflowsxmatix/automation/workflows/workflows pullworkflows push <file> for every *.json
dashboardsxmatix/analytics/dashboards/dashboards pulldashboards push <file> for every *.json
reportsxmatix/analytics/reports/reports pullreports 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 pull with no script name and without --all, and scripts pull refuses 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. Skip scripts and run xmatix scripts pull --all yourself.
  • Dashboards and reports don't round-trip. Their pull writes no files but still succeeds, and every push fails. 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 diff to 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 plan runs a full snapshot export internally, 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-kind push commands on those files instead.

How xMatix handles it

What export does

  1. It checks that you are inside a workspace, then runs metadata pull --scope <scope>, scripts pull, rules pull, workflows pull, dashboards pull and reports pull, in that order, leaving out the kinds in --skip.
  2. 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.
  3. 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.json for the default TenantOwned, tenant-full.json for TenantFull. The file is a full pack, its mode is always full, and it carries a fresh generatedAtUtc time. 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 --all yourself) — each script as a .csx file with its .meta.json, in a folder per entity. Scripts that have no current version are skipped. Every .meta.json gets a fresh lastPulledUtc time. 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

  1. 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.
  2. 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)".
  3. A push that fails is reported, and the import carries on with the next file and the next kind.
  4. 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:

KindEffect on the tenant
MetadataEvery 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
ScriptsSkipped 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
RulesUpdated 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
WorkflowsUpdated 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, reportsThe 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 login completed for the tenant in .xmatix/config.json. Check it with xmatix scripts list; xmatix whoami and xmatix doctor fail 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 diff shows 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 -I patterns hide hunks in which only the export or pull time changed (git 2.30 or later).
  • If the committed metadata file had its mode set to delta, the export sets it back to full. 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 metadata and push a delta copy yourself, which the procedure in Metadata seed-packs describes, or
  • set the file's mode to delta in 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 push shows the file and its size and asks Continue?. The default answer is no.
  • For each rule that already has actions on the tenant, rules push asks 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 pull and commit the file, so the next import updates that workflow instead of creating another copy.

Command options

CommandOptionEffect
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-runPrints the push commands without running them
CommandExit code
snapshot export0 when every pull succeeds, 1 when any pull fails. Without --skip scripts it is always 1
snapshot import0 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. --skip can 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 mode it 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.json above 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.

  1. On a clean checkout of the main branch, a developer runs xmatix snapshot export --skip scripts,dashboards,reports, then xmatix scripts pull --all. Both finish without failures.
  2. git status --short xmatix/ shows one new file, xmatix/automation/rules/Order/HoldHighValue.json. The git diff with the two -I patterns shows that CreditCheck.json now has a lower limit in its condition. The metadata file changed only in its export time, which the diff hides.
  3. They commit the new rule and the changed rule in a branch titled "Capture product changes to order rules" and merge it after review.
  4. Later the same week, they edit CreditCheck.json in the repository. After review, they run xmatix snapshot import --skip metadata,scripts,workflows,dashboards,reports --dry-run and see two would run: lines, one per rule file.
  5. They run the same import without --dry-run and confirm the replacement of each rule's actions. The run ends with Snapshot import complete.

Training

Practice exercise

In a sandbox workspace:

  1. Run xmatix snapshot export with 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).
  2. Run xmatix snapshot export --skip scripts,dashboards,reports and xmatix scripts pull --all, then commit the xmatix/ tree. Expected result: the export ends with Snapshot export complete.
  3. In the product, change the description of a test business rule. Export again with the same two commands and run the git diff from Step 2. Expected result: only that rule's file shows a change.
  4. Run xmatix snapshot import --skip metadata,scripts,workflows,dashboards,reports --dry-run. Expected result: one would run: xmatix rules push … line per rule file, and nothing changes on the tenant.

Quick reference

  • Export with --skip scripts,dashboards,reports, then run xmatix scripts pull --all.
  • migrate plan can'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-run an 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.manage capability, 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.json above the current folder decides the tenant. Keep one workspace per tenant.
  • Metadata scope. --scope on 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 mode in each metadata file decides whether its push prunes. Use delta for anything you import.
  • Kinds. Use --skip to leave out the kinds a repository doesn't own. In the current release, always skip scripts on export and dashboards,reports on both commands.
  • .gitignore. Add xmatix/.snapshot/, where migrate plan writes, and consider xmatix/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.