Skip to content

16 Migration from PACX

RemyDuijkeren edited this page Jul 17, 2026 · 2 revisions

Migration from PACX (Greg.Xrm.Command)

PACX is a broad Dataverse CLI — think XrmToolBox for the terminal. It covers component-level management (tables, columns, views, relationships, workflows, ribbons) well beyond what Flowline does.

This guide covers only the commands where the two tools overlap: plugin push, web resource push, auth, and project setup. PACX commands with no Flowline equivalent (table management, views, relationships, data export, etc.) are out of scope — continue using PACX for those.


What maps to what

PACX command Flowline equivalent
pacx auth create / pacx auth select pac auth create / pac auth select
pacx plugin push --path MyPlugin.dll flowline push --scope plugins
pacx plugin step register ... (per step, manual) Automatic from [Step] attributes
pacx plugin step enable / disable No equivalent
pacx webresources push flowline push --scope webresources
pacx webresources push --no-action flowline push --dry-run
pacx webresources init flowline clone / flowline init
pacx publish all Built into flowline push
pacx project init (.pacxproj) .flowline config file

Two-phase migration strategy

Running everything in one pass is possible, but splitting the migration into two phases reduces risk — only one thing changes at a time, so problems are easier to diagnose.

Phase 1 — Standalone (no project restructuring required)

Replace PACX for plugin registration, web resource sync, and type generation using Flowline's standalone mode. No .flowline config, no folder restructuring — Flowline reads your existing build output directly. Run these from a folder that does not contain a .flowline file.

# Plugins only
flowline push MySolution --pluginFile ./bin/Release/MyPlugins.dll --dev https://your-org.crm4.dynamics.com

# Web resources only
flowline push MySolution --webresources ./WebResources/dist --dev https://your-org.crm4.dynamics.com

# Both at once
flowline push MySolution --pluginFile ./bin/Release/MyPlugins.dll --webresources ./WebResources/dist --dev https://your-org.crm4.dynamics.com

# Type generation
flowline generate MySolution --namespace MyNamespace --output ./Models --dev https://your-org.crm4.dynamics.com

Always verify with --dry-run first to confirm Flowline's plan matches what PACX was registering. Once phase 1 is stable, PACX is no longer needed for day-to-day plugin and web resource pushes (continue using PACX for table management and other non-overlapping operations).

Phase 2 — Project structure (when you're ready)

Run flowline init to create the .flowline config and adopt the Flowline folder convention (Plugins/, WebResources/ at the project root). From this point, flowline push reads from the project rather than requiring explicit flags.

The steps below cover Phase 2 in detail. See also Standalone push (without a Flowline project) in Step 2 if you want to stay in standalone mode longer.


Step 1 — Switch to PAC CLI auth

PACX manages its own auth profiles with AES-256 encrypted connection strings. Flowline delegates entirely to PAC CLI — no credentials in its own config files.

# PACX — opens browser, stores encrypted connection string
pacx auth create --name prod --url https://contoso.crm4.dynamics.com
pacx auth select --index 1

# Flowline — same browser OAuth, handled by PAC CLI
pac auth create --environment https://contoso.crm4.dynamics.com

If you already use PAC CLI for pac solution import or other operations, you likely have an auth profile set up. Run flowline status to confirm Flowline can reach the environment.

For CI/CD, both tools support service principals:

# PACX (ClientSecret in connection string)
pacx auth create --name ci --url "AuthType=ClientSecret;Url=...;ClientId=...;ClientSecret=..."

# Flowline — via PAC CLI
pac auth create --kind ServicePrincipal --applicationId $CLIENT_ID --clientSecret $CLIENT_SECRET --tenant $TENANT_ID

Step 2 — Replace plugin push

Assembly push

# PACX — push DLL, then register each step manually
pacx plugin push --path ./bin/Release/MyPlugins.dll --solution MySolution
pacx plugin step register --class "MyPlugin.AccountPreUpdatePlugin" --message Update --table account --stage PreOperation --filteringAttributes "name,creditlimit"
pacx plugin step register --class "MyPlugin.AccountPostCreatePlugin" --message Create --table account --stage PostOperation

# Flowline — push DLL and auto-register all steps from attributes
flowline push --scope plugins

The key difference: automatic vs manual step registration

PACX pushes the assembly and plugin types, but requires a separate plugin step register call for every step. Flowline reads [Step], [Filter], [PreImage], and [PostImage] attributes from the compiled assembly and registers everything in one pass.

Add Flowline.Attributes to your Plugins project:

<PackageReference Include="Flowline.Attributes" Version="1.0.0" PrivateAssets="all" />

Then decorate your plugin classes:

// Before: no attributes, steps registered manually via pacx plugin step register

// After: Flowline reads these and registers in Dataverse automatically
[Step("account")]
[Filter("name", "creditlimit")]
[PreImage("name", "creditlimit")]
public class AccountPreUpdatePlugin : IPlugin
{
    public void Execute(IServiceProvider sp) { ... }
}

The class name encodes stage and message — AccountPreUpdatePlugin maps to PreOperation + Update on account. See 04-Push-Plugins-and-Custom-APIs for the full naming reference and all supported attributes including [CustomApi], [Input], and [Output].

Standalone push (without a Flowline project)

If you are not ready to adopt the full Flowline project structure, flowline push works standalone — no .flowline config required:

flowline push MySolution --pluginFile ./bin/Release/MyPlugins.dll --dev https://contoso-dev.crm4.dynamics.com

This is equivalent to pacx plugin push with the addition of automatic step registration.


Step 3 — Replace web resource push

# PACX
pacx webresources push --solution MySolution

# Flowline
flowline push --scope webresources

Both tools use content-based change detection and targeted publish of only changed resources.

Key differences

PACX Flowline
Orphan cleanup Additive only — files removed locally stay in Dataverse Deletes orphans by default; --no-delete to suppress
Dry-run --no-action --dry-run
Single-file push --path scripts/myfile.js No equivalent — full dist/ folder only
External references .wr.pacx file with ExternalReferences Handled automatically — see below
Folder scaffolding pacx webresources init flowline clone / flowline init

Folder convention

PACX expects a {publisherprefix}_/ folder at the root of your web resource project and uses that path directly as the Dataverse unique name. Flowline syncs WebResources/dist/ and by default prefixes the Dataverse name with {prefix}_{solutionname}/.

However, if a file path inside dist/ already starts with {publisherprefix}_/, Flowline skips the auto-prefix and uses the path as-is. This means PACX's naming is fully reproducible in Flowline:

PACX:     new_/scripts/utils.js               →  new_/scripts/utils.js
Flowline: WebResources/dist/new_/scripts/utils.js  →  new_/scripts/utils.js  (no auto-prefix)
Flowline: WebResources/dist/scripts/utils.js       →  new_mysolution/scripts/utils.js  (auto-prefixed)

To keep existing Dataverse names unchanged during migration, mirror the PACX folder structure inside dist/: move files from new_/scripts/utils.js to WebResources/dist/new_/scripts/utils.js. Run flowline push --dry-run to confirm the names match before going live.

External references (.wr.pacx)

PACX's .wr.pacx file solves two distinct problems:

  1. Dataverse side — prevents creating duplicate web resource records when the same file is shared across multiple solutions.
  2. Local side — lets a solution project reference a file that lives in a different project folder without copying it.

Dataverse side: handled automatically. When a file in dist/ resolves to a Dataverse unique name that already exists — because another solution pushed it — Flowline recognises it and adds it to the current solution's components rather than creating a duplicate. No config file, no --reference flag needed.

Local side: build tool concern. PACX's external reference keeps one copy of a shared file on disk and lets multiple solution projects point at it. In Flowline, dist/ is a build output folder — your bundler populates it before flowline push runs. Use Rollup, Vite, or esbuild to copy or bundle the shared source into each solution's dist/:

// rollup.config.js — copy shared utils into this solution's dist/
import copy from 'rollup-plugin-copy';

export default {
  plugins: [
    copy({
      targets: [
        { src: '../../shared/utils.js', dest: 'dist/new_/scripts' }
      ]
    })
  ]
};

One authoritative source file, each solution's dist/ gets its copy at build time. No Flowline config needed.

See 08-WebResources-Project for a full guide to the TypeScript setup, Rollup build pipeline, and folder structure.


Step 4 — Replace project setup

PACX uses .pacxproj to store per-project auth profile and default solution:

{
  "Version": "1.0",
  "AuthProfileName": "prod",
  "SolutionName": "MyCustomSolution"
}

Flowline uses .flowline to store environment URLs and solution config. Initialize it with:

# Existing solution
flowline clone MySolution --prod https://contoso.crm4.dynamics.com --dev https://contoso-dev.crm4.dynamics.com

# New solution
flowline init MySolution --prod https://contoso.crm4.dynamics.com

This creates .flowline, the solution folder structure, a Plugins project, and a WebResources project in one step.


What PACX does that Flowline doesn't

These commands have no Flowline equivalent — keep using PACX for them:

PACX command What it does
pacx plugin step enable / disable Toggle a step on/off without unregistering
pacx webresources applyIcons Auto-assign SVG icons to custom tables
pacx workflow activate / deactivate Enable/disable Power Automate flows
pacx table, pacx column, pacx rel Schema management
pacx view, pacx forms UI component management
pacx solution component Solution component management
pacx script Generate PowerShell metadata scripts

PACX and Flowline complement each other well — PACX for interactive component management, Flowline for the push inner loop and deploy pipeline.

Clone this wiki locally