Skip to content

04 Command Reference

Remy van Duijkeren edited this page Aug 22, 2026 · 3 revisions

Command Reference

Run commands from any directory inside your project; Flowline walks up to find .flowline. Cancel anytime with Ctrl+C (graceful) or Ctrl+Break (immediate, Windows). If cancelled mid-run, re-running is safe.


Global flags

Available on every command:

Flag Description
-h, --help Show help for the command. Works on every subcommand: flowline push --help, flowline deploy --help, etc.
-v, --verbose Show detailed command output
-f, --force <specifier> Approve a specific hazard by name; repeatable (--force x --force y). all approves every hazard a command gates. config approves a .flowline config overwrite. Each command's section lists the hazards it gates.
--no-cache Re-run all pre-flight checks instead of using cached results. Use it when the cache is stale, after creating a solution or switching PAC auth profiles.
-a, --auto-select-auth-profile Automatically switch PAC CLI's active auth profile to match the one Flowline resolved, without asking. The switch is not restored afterward. See 02-Authentication#keeping-pac-clis-active-profile-in-sync.

clone

Bootstraps an existing Dataverse solution into a new Git repo. Creates .flowline, unpacks the solution XML into Solution/src/, scaffolds the Plugins and WebResources projects, creates the solution file (*.slnx) and wires them up, writes AGENTS.md and CLAUDE.md, and generates the initial DATAVERSE_CONTEXT.md.

flowline clone ContosoSales --prod https://contoso.crm4.dynamics.com

Interactive mode: run clone with no [solution] and no environment configured, and it prompts: first a tenant-wide environment picker, then that environment's unmanaged solutions. Picking one confirms the .flowline role to save it under, defaulting to DEV. Pass a solution name and environment flags and clone runs without prompting.

Clone adopts a solution that already exists in Dataverse. To create one, use init.

Argument / Option Description
[solution] Solution to clone. Omit to pick one interactively
--prod <url> Production environment URL, saved to .flowline. Required on first run; omit once set.
--uat <url> UAT environment URL, saved to .flowline when provided. Typically set via flowline provision uat instead.
--test <url> Test environment URL, saved to .flowline when provided. Typically set via flowline provision test instead.
--dev <url> Development environment URL, saved to .flowline when provided. Typically set via flowline provision dev instead.
--managed Also clone the managed solution (saved to .flowline)

Every --prod/--uat/--test/--dev URL you pass is saved to .flowline, regardless of which environment the solution actually gets cloned from. So you can use clone to register any environment, not just the source. Re-run it later with just the flag for a new one (e.g. flowline clone ContosoSales --uat https://contoso-uat.crm4.dynamics.com) to add it without repeating the rest of the setup.

Clone source: the solution is unpacked from the first unmanaged match among the environments you've configured, checked in produattestdev order. Clone fails if none of them has an unmanaged copy.

What it scaffolds: Solution/ContosoSales.cdsproj plus Solution/src/, Plugins/ContosoSales.Plugins.csproj, and WebResources/ContosoSales.WebResources.csproj. Folders are the same in every Flowline repo; the project files are named after your solution, so the built assembly is ContosoSales.Plugins.dll.

Safe to re-run: anything already present (solution file, Plugins/WebResources projects, AGENTS.md, CLAUDE.md) is left alone. Remove the part you want to recreate and re-run clone. .flowline is re-saved with any new URLs merged in, and DATAVERSE_CONTEXT.md is regenerated from the current solution state.

Warning

Switching an already-cloned project to --managed re-syncs Solution/src/ from Dataverse, overwriting it. Commit local edits there first.


init

Creates a new publisher (or reuses an existing one) and an empty unmanaged solution in a DEV environment, then runs the same scaffold clone does: .flowline, Solution/<name>.cdsproj + Solution/src/, Plugins/WebResources projects, AGENTS.md/CLAUDE.md, and the initial DATAVERSE_CONTEXT.md. Use it for a greenfield solution; use clone for one that already exists.

flowline init ContosoSales --dev https://contoso-dev.crm4.dynamics.com --publisher-prefix cs
Argument / Option Description
[name] Solution unique name. [A-Za-z0-9_] only, starts with a letter or underscore, at most 65 characters, and not a C# keyword (it becomes the plugin namespace).
--dev <url> Target DEV environment. Omit for a tenant-wide picker listing the Sandbox and Developer environments in your tenant.
--display-name <text> Solution friendly name, at most 256 characters. Defaults to a humanized form of <name> (DWE_BaseDWE Base).
--publisher-prefix <prefix> Reuses the existing publisher whose customization prefix matches, or creates one. 2 to 8 alphanumeric characters, starts with a letter, and must not start with mscrm (reserved by Dataverse).
--publisher-name <text> Friendly name for a newly created publisher. Defaults to the prefix. Ignored when the prefix matches an existing publisher.

Omit [name], --dev, or --publisher-prefix in an interactive session and Flowline prompts for each in turn; with no TTY it fails naming the missing one. Long flag names only, no short aliases.

DEV-only. init runs against Sandbox and Developer environments only:

'Contoso Prod' (Production) isn't a Sandbox or Developer environment — create only runs against DEV-type environments.

Need a DEV environment first? Run flowline provision dev --prod <prod-url>, or create one in the Power Platform admin center, then re-run init.


push

Builds the solution and syncs plugin assemblies and web resources to DEV. Files under WebResources/dist/ are synced.

flowline push
Argument / Option Description
[solution] Solution to push. Required outside a Flowline project; optional in project mode, where a passed value is validated against the configured solution (error on mismatch)
-s, --scope <scope> Limit scope: all, webresources, plugins, or assemblyonly. Can be specified multiple times. webresources covers Form Event Handler registration too.
-p, --pluginFile <path> Prebuilt plugin assembly (.dll) or plugin package (.nupkg), for standalone use
-w, --webresources <path> Web resource folder, for standalone use
--dev <url> Dev environment URL, read from .flowline. Only needed to override or in standalone mode.
--no-delete Push without deleting Dataverse assets missing from source
--no-build Skip dotnet build and push the existing Release artifacts. Every plugin project must already have output in its bin/Release, and a plugin package must have been repacked rather than only recompiled, so push stops rather than deploy a stale .nupkg. Build first, or drop --no-build. No effect in standalone mode (--pluginFile/--webresources).
--no-publish Skip publishing web resources and Form Event Handlers after sync. Useful when pushing several solutions and publishing once at the end.
--dry-run Preview changes without touching Dataverse
-f, --force <specifier> Approves delete-orphans (delete an orphaned assembly/step, or the plugin package that owns it when the package owns nothing else; see What push deletes), recreate-assembly (delete-and-recreate an assembly whose identity changed), delete-form-handlers (remove an unrecognized Form Event Handler), config, or all. See Global flags

Plugin packaging: push supports both the classic .dll and NuGet plugin packages (.nupkg), auto-detected from the build output. Override via .flowline's PluginPackageMode key (Auto/Nupkg/Dll).

--scope assemblyonly: Updates only the assembly bytes, skipping step/Custom API registration. Useful for fast iteration when registrations haven't changed.

Full guide: 04-Push-Plugins-and-Custom-APIs · 05-Push-WebResources

Standalone push

push works outside a Flowline project, with no .flowline, Git repo, or project structure required:

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

Standalone rules:

  • --pluginFile must point to an already-built assembly (.dll) or plugin package (.nupkg).
  • --webresources points at the folder whose files should be synced.
  • Standalone mode stops anywhere inside a Flowline project, not only at its root: a .flowline governs every folder beneath it, so running from a subfolder is still project mode. Project mode and standalone mode cannot be mixed. Another folder in the same repository, outside any project, is fine.
  • The target solution must be unmanaged.
  • --force is validated here exactly as in project mode: an unrecognised specifier stops the run and lists the valid ones.

sync

Pulls the current solution state from DEV and unpacks it into the repo. Run this after making changes in the maker portal to capture them in source control.

Alias: flowline pull

Full guide: 06-Sync

flowline sync
Argument / Option Description
--dev <url> Dev environment URL, read from .flowline. Only needed to override.
--managed Export and unpack the managed solution in addition to unmanaged
--bump <component> Version component to increment: patch, minor, major, or none to skip bumping (default: patch)
--no-build Skip the dotnet build validation step after syncing
-f, --force <specifier> Approves dirty (overwrite uncommitted local Solution/src/ changes), config, or all. See Global flags

By default, Flowline syncs only the unmanaged solution. Pass --managed once to also export the managed package; the flag is saved to .flowline so all subsequent syncs include it automatically. Pass --managed false to revert.

Warning

You need --managed if you intend to deploy to other environments (test, UAT, prod) as a managed solution.


deploy

Packs the solution from the repo and imports it into the target environment.

Full guide: 07-Deploy

flowline deploy test
flowline deploy prod
flowline deploy https://contoso-uat.crm4.dynamics.com
Argument / Option Description
<target> Target environment: prod, uat, test, dev, or a URL
--path <zip> Import this pre-built solution zip instead of packing from source. Outside a Flowline project this also selects standalone mode
--skip-dtap-check Skip DTAP promotion checks (existence and version)
--skip-component-check Skip the missing-component gate that checks the target before importing
--skip-solution-check Skip the solution checker gate
--no-backup Skip the pre-deploy environment backup
--no-delete Report orphan components without deleting them
-f, --force <specifier> Approves drift (skip drift validation for local-only or plugin-size-mismatch changes), first-import (skip the first-import confirmation), or all. config is not one of deploy's values; see Global flags

By default, deploy imports the unmanaged solution. Managed/unmanaged mode is configured via clone --managed/sync --managed, not a deploy flag. deploy enforces promotion order (DTAP gate), confirms before a solution's first import to a target, checks the target for components the solution needs and it lacks, runs the solution checker, takes a pre-deploy backup, and cleans up orphaned components. See 07-Deploy for details on all of that.

When --path is omitted, repeated deploys of unchanged source reuse the last packed artifact instead of repacking (build once, promote through test/uat/prod); pass --path explicitly for CI pipelines that promote across separate jobs/runners. See 07-Deploy#artifacts for details. Pass --no-cache to bust this reuse cache and force a fresh pack even when the source commit hasn't changed.

After import, deploy also verifies that every plugin-bearing assembly in each imported plug-in package actually got registered in the target. See 07-Deploy#package-assembly-check. This check has its own exit code, 21 (AssemblyNotRegistered), separate from orphan cleanup's 18 (PartialSuccess); a check that couldn't inspect a package exits 19 (Inconclusive) instead of a false clean pass. No flag skips it.

Standalone deploy and drift

deploy and drift also run outside a Flowline project, against a solution zip packed elsewhere:

flowline deploy https://contoso-uat.crm4.dynamics.com --path ./ContosoSales_1_0_0_0.zip
flowline drift  https://contoso-uat.crm4.dynamics.com --path ./ContosoSales_1_0_0_0.zip

This is for the CI job that downloaded a build artifact and nothing else: it needs no .flowline, no Git repo and no checkout.

Standalone rules:

  • It activates when --path is set and no Flowline project is found. Inside a project, --path behaves exactly as it always has, and the same subtree rule as push applies: a .flowline governs every folder beneath it.
  • The solution unique name and managed flag come from solution.xml inside the zip, never from config. A zip whose manifest has no unique name is rejected before any Dataverse call.
  • Setup checks pac only. The Git, Git repo and .NET checks do not run, and neither does the DTAP gate, since there is no config to order the environments by.
  • Give the target as a full URL. A role keyword like prod has no config to resolve it against and is rejected.
  • Everything else behaves as in project mode: --no-delete, --dry-run, --force and the skip flags keep their meaning, and orphan cleanup deletes and reports exactly what it otherwise would. Orphan verdicts read as unresolved, since a downloaded artifact carries no history to resolve them against.

provision

Provisions a DEV, TEST, or UAT environment by copying an entire Dataverse environment from production via the Power Platform admin API (pac admin create + pac admin copy). This is a real environment copy, not just a solution clone. If the target doesn't exist yet, provision creates it first, then copies prod into it.

This is a long-running operation. Full Dataverse environment copies commonly take tens of minutes, and the underlying pac CLI enforces a 60-minute limit on the operation. Use it once when setting up a new environment, or again later to refresh an existing one back to a clean copy of prod.

Why it exists: Flowline treats PROD as the canonical baseline and Git as the delivery source. Dev, test, and UAT are meant to be short-lived workspaces provisioned from PROD, not permanent environments maintained by hand. provision is what makes that practical: one command instead of manually creating and refreshing environments in the admin center.

flowline provision dev --prod https://contoso.crm4.dynamics.com
flowline provision test --prod https://contoso.crm4.dynamics.com
flowline provision uat --prod https://contoso.crm4.dynamics.com
Argument / Option Description
[role] Target role: dev, test, or uat (default: dev)
--prod <url> Production environment URL to copy from, read from .flowline. Only needed to override.
--copy <type> Copy type for dev: minimal (no data, default) or full (with data). test and uat always copy with data, regardless of this flag.
--suffix <text> Target URL/display-name suffix (default: role name, e.g. Dev/Test/UAT)
--allow-overwrite Overwrite an existing target environment. Without it, an existing target is left untouched: provision warns and exits instead of copying.

The resulting environment URL is saved to .flowline, same as --dev/--test/--uat on clone.


generate

Generates early-bound C# entity types via pac modelbuilder build with opinionated defaults. Output lands in Plugins/Models/, with no separate assembly and no ILMerge. Running generate again fully replaces the folder.

Full guide: 09-Generate-Early-Bound-Types

flowline generate
flowline generate --namespace Contoso.Plugins.Models --extra-tables account,contact
Argument / Option Description
[solution] Solution to generate types for. Required outside a Flowline project; optional in project mode, where a passed value is validated against the configured solution (error on mismatch)
--namespace <ns> Model namespace, saved to .flowline for future runs
--extra-tables <tables> Comma-separated extra tables to include that are not in the solution
--dev <url> Dev environment URL, read from .flowline. Only needed to override or in standalone mode.
-o, --output <path> Output folder (required outside a Flowline project)
--generator {pac|xrmcontext3|xrmcontext|ebg} Generator to use. pac (default) uses pac modelbuilder build; xrmcontext3 uses Delegate.XrmContext v3 F# exe (Windows only, bridge); xrmcontext uses XrmContext v4 dotnet tool (cross-platform); ebg runs Early Bound Generator V2 in-process, with no PAC CLI call and no second sign-in. Saved to .flowline.

Standalone generate

Use outside a Flowline project by supplying -o, --dev, and the solution name:

flowline generate ContosoSales --dev https://contoso.crm4.dynamics.com --namespace Contoso.Plugins.Models -o ./src/Models

drift

A preview command: it shows what a deploy to the target would delete as orphans, without actually deploying. Compares committed source against a live environment and reports components that are present there but not declared in source, which is exactly what deploy's orphan cleanup would remove if you deployed now. Read-only, so it never deletes or modifies anything itself.

flowline drift prod
flowline drift dev
flowline drift test
flowline drift https://contoso-test.crm4.dynamics.com/
Argument / Option Description
<target> Environment to compare against: prod, uat, test, dev, or a URL
--path <zip> Compare this pre-built solution zip against the target instead of your checkout. Outside a Flowline project this also selects standalone mode

Run it against prod/test as a standalone drift check, or against dev before sync/deploy as a preview of what the next run would flag. It reuses the same comparison deploy's orphan cleanup runs internally, just pointed at whichever environment you name and always in report-only mode.

Every reported orphan carries a verdict read from your repository's history: removed from source (naming the commit, its author, and its subject), never in source, or unresolved when the lookup couldn't answer. See Where each orphan came from for which component types can answer today and where the verdict misleads.

Exit codes: 0 when the comparison ran and found nothing, 15 (Validation Failed) when drift is found, 19 (Inconclusive) when the comparison couldn't run at all (e.g. the solution has no components locally or in the target; investigate the printed reason before trusting the result), or the same connection/config codes deploy uses.

Current scope: this is the first, narrower half of drift detection. It only detects components present in the target but not declared in your committed source (created directly there, or added since your last sync), which is the orphan-deletion direction. It does not yet detect the opposite case, something your source declares that was deleted directly in the target. Extending drift to cover that direction too is a planned future improvement.


scaffold

Writes a project template into a folder. Aliased new.

flowline scaffold webresources
flowline new webresources
flowline scaffold webresources --output ./ContosoSales --name Scripts
Argument Description
<part> What to scaffold. Only webresources today.
Option Description
-o, --output <PATH> Scaffold into this folder instead of the current one. Created when missing.
--name <NAME> Name the project folder and its .csproj. Default: WebResources.

No Dataverse call, no authentication, no network. It only writes local files.

What it does

The command looks for a solution file (.sln or .slnx), and that one fact decides the rest.

Found: the project is named after it and added to it, the same result clone and init produce. Contoso.slnx gives you WebResources/Contoso.WebResources.csproj.

Not found: it writes WebResources/ under a generic WebResources.csproj, and warns that it isn't in any solution file. From there:

cd WebResources && npm install && npm run build
pac auth create --environment <url>          # if you haven't
flowline push <solution> --webresources ./WebResources/dist --dev <url>

Either way the run says which it was, so you know whether you got a project push can find or a folder it cannot.

Where things land

The project is written where you are standing. scaffold never moves files somewhere you didn't point it.

The solution file is searched for upward, stopping at the project root: the nearest folder holding a .flowline or a .git. Nothing above that is touched. Same rule as sln add.

The two are independent, so cd Plugins && flowline scaffold webresources writes Plugins/WebResources/ and adds Plugins/WebResources/Contoso.WebResources.csproj to the repo root's solution file.

--output and --name

--output is simply "the folder I'm standing in": the project is written there, and the solution-file search starts there:

flowline scaffold webresources --output ../ContosoSales

--name names the folder and the project file together, for a repo that wants something other than WebResources/:

flowline scaffold webresources --name Scripts     # Scripts/Scripts.csproj

Three names are refused: one ending in Test or Tests (Flowline reads that as a test project and would skip its web resources on every push), a path rather than a plain name (that's what --output is for), and a second WebResources project in a solution file that already records one (Flowline allows exactly one per project).

Use --name in a repo that already has a solution file, so the project is recorded there and found again later.

Re-running is safe: an existing WebResources project is reported and skipped, at exit 0. If template-named files are sitting there without a project claiming them, the run stops and names them rather than overwriting.


status

Shows DTAP status, environment info, Flowline version, .NET SDK, PAC CLI, and Git versions, plus authentication status.

flowline status

The output looks like this:

╭─╴╷  ╭─╮╷ ╷╷  ╷╭╮╷╭─╴
├╴ │  │ ││╷││  ││╰┤├╴
╵  ╰─╴╰─╯╰┴╯╰─╴╵╵ ╵╰─╴
Flowline CLI v0.7.1.0 (NT 10.0.26200.0, CLR:10.0.9, 64-bit)
.NET SDK version: 10.0.301
Power Platform CLI version: 2.8.1+ga4eb71c (.NET 10.0.9)
Git version: 2.54.0.windows.1

Configuration
  Dev: https://contoso-dev.crm4.dynamics.com/
    ✓ remy@contoso.com
  Test: https://contoso-test.crm4.dynamics.com/
    ✗ Not authenticated
  UAT: Not configured
  Prod: https://contoso.crm4.dynamics.com/
    ✓ remy@contoso.com

─────────────────────────────────────────────────────────────────────
  Solution        Dev          Repo             Test         Prod
─────────────────────────────────────────────────────────────────────
  ContosoSales    1.0.36  ──▶  1.0.37 ⚠ ●  ┈┈▶  ✗ auth  ┈┈▶  1.0.36 ↑
─────────────────────────────────────────────────────────────────────
— not deployed   ✗ auth failed   ↑ behind   ⚠ ahead   ● uncommitted

! an environment is ahead of an earlier stage — check the grid above.

The grid shows the project's solution, always exactly one row, with its version across your pipeline, left to right in promotion order (Dev → Repo → Test → UAT → Prod). The arrows show how each stage compares to the one before it: green means caught up, cyan means behind (normal, just not promoted yet), yellow means ahead (unexpected, usually something deployed out of band). A means not deployed there yet, red means the environment is configured but not authenticated, and flags uncommitted changes in the repo folder. Environments without a configured URL are skipped entirely.

The line below the grid sums it up: a warning if something's out of order, a nudge to promote if environments are just behind, or All environments in sync. when everything matches.


sln add

Adds a .cdsproj to the project's solution file. dotnet sln add refuses a .cdsproj, and exits 0 while doing it, so a script can't even tell it failed (dotnet/sdk#47638). Flowline writes the entry itself instead.

flowline sln add Solution/ContosoSales.cdsproj
Argument Description
<path> Path to the .cdsproj to add. A .csproj is refused; use dotnet sln add for those, which handles them fine.

clone already wires up the .cdsproj it creates, so you only need this for a project that didn't come from clone: a repo migrating off spkl, Daxif, or PACX, or one assembled by hand.

Runs standalone. No .flowline, no git repo, no PAC login needed, since it only edits a local file. That's deliberate: the repos that need it are usually the ones not yet set up for Flowline.

It finds the solution file by walking up from where you're standing, so running it from inside Solution/ works fine. The search stops at the project root, the nearest folder holding a .flowline or a .git. Same rule as scaffold.

Re-running is safe: a project already in the solution file is reported and skipped, not duplicated.

Clone this wiki locally