Resco Wiki
Auto Light Dark
Auto Light Dark

Woodford CLI

Woodford CLI is a command-line tool that allows you to manipulate app projects on remote Resco Cloud or Power Platform servers. It provides a flexible set of commands that help developers speed up the deployment of Woodford projects:

  • log in (device code or client credentials) and log out

  • list projects and roles

  • create, update and delete projects

  • import and export projects (since 19.2 also as distribution packages)

  • validate and publish projects

Find more details in the npmjs package readme document.

Prerequisites

Minimum version:

  • 15.0 (first supported release)

  • 19.1 for client ID and client secret authentication flow, update command, parent project property

  • 19.2 for distribution packages (-g, -w and -m export options)

Supported backends:

Software:

  • Node.js (current LTS) with npm

Installation

To install CLI globally, run the following command:

Bash
npm install -g @resconet/woodford-cli

To uninstall CLI, run the following command.

Bash
npm uninstall -g @resconet/woodford-cli

Available commands

Options:
       --help                Show help                                 [boolean]
       --version             Show version number                       [boolean]
  -u, --url                  Organization url                           [string]
  -l, --login                Login                                      [string]
  -p, --password             Password                                   [string]
  -c, --command              Command: [login | logout | list | export | import |
                             create | update | delete | publish | roles] project
                                                             [string] [required]
  -n, --name                 Project name                               [string]
  -f, --file                 Path to file                               [string]
  -v, --validate             Validate imported project [boolean] [default: true]
  -r, --properties           Command properties
                             - Create:
                             'priority;role1,role2,..;appid;version;parent'
                             - Update: 'priority;role1,role2,..;appid;version'
                                                                        [string]
  -d, --dynamicscrm          Dynamics CRM backend                      [boolean]
  -a, --clientid             Client ID                                  [string]
  -s, --clientsecret         Client Secret                              [string]
  -g, --distributionpackage  Export as distribution package            [boolean]
  -w, --allowderivation      Allow derivation                          [boolean]
  -m, --customversionid      Custom version ID                          [string]

Notes on options

  • -u – organization URL. Resco Cloud: https://<server>/<organization>; Power Platform: https://<name>.crm.dynamics.com.

  • -d – selects the Power Platform backend. The CLI selects it automatically when the URL ends with .dynamics.com; add -d for any other Power Platform URL. Without it, Resco Cloud is assumed.

  • -a and -s – client ID and client secret login (19.1 and later). Without them, -l starts the device code flow.

  • -v – applies to import and publish. Validation is on by default; use --no-validate to skip it.

  • -r – semicolon-separated parts, in this order:

  • priority – project priority (number, default 0)

  • role1,role2,... – comma-separated role names (default System Administrator). Use roles to list the available names.

  • appid – app ID

  • version – project version

  • parent – only for create (19.1 and later): name of the parent project; several parents can be separated by commas. Optional.

With update, parts you leave out fall back to their defaults (priority 0, role System Administrator), so pass every part you want to keep.

-g, -w and -m – see Distribution packages below.

Usage

Login (device code flow):

wf-cli -c login -u https://<server>.crm.dynamics.com -l user@example.com

Login (client credentials):

wf-cli -c login -u https://<server>.crm.dynamics.com -a <client_id> -s <client_secret>

Logout:

wf-cli -c logout

List projects:

wf-cli -c list

List roles:

wf-cli -c roles

Create project:

wf-cli -c create -n <project_name> -r "priority;role1,role2,...;appid;version;parent"
wf-cli -c create -n "Best Project" -r "1;System Administrator,Sales Person;My First App;v1.0"
wf-cli -c create -n "Derived Project" -r "1;System Administrator;My First App;v1.0;Best Project"

Update project:

wf-cli -c update -n <project_name> -r "priority;role1,role2,...;appid;version"
wf-cli -c update -n "Best Project" -r "2;System Administrator,Sales Person;My First App;v1.1"

Delete project (no confirmation is asked):

wf-cli -c delete -n <project_name>

Import project:

wf-cli -c import -n <project_name> -f project.woodford
wf-cli -c import -n <project_name> -f project.woodford --no-validate

Export project:

wf-cli -c export -n <project_name> -f project.woodford

Publish project:

wf-cli -c publish -n <project_name>
wf-cli -c publish -n <project_name> --no-validate

Distribution packages

Since 19.2, an app project can be exported as a read-only distribution package. When such a package is imported, it is created as a standard project that cannot be edited: Edit, Export, Clone and Git-related actions are disabled. See the v19.2 release notes and App projects for how this looks in App Configurator.

Export options:

  • -g (--distributionpackage) – export the project as a distribution package.

  • -w (--allowderivation) – allow derivation. If the package allows it, the Derive action stays available for the imported project.

  • -m (--customversionid) – custom version ID that identifies the package. It can be adjusted later in the project Properties dialog.

-w and -m only work together with -g.

Examples:

# distribution package
wf-cli -c export -n <project_name> -f project.woodford -g

# allow derivation
wf-cli -c export -n <project_name> -f project.woodford -g -w

# custom version ID
wf-cli -c export -n <project_name> -f project.woodford -g -m "v1.0"

# allow derivation and custom version ID
wf-cli -c export -n <project_name> -f project.woodford -g -w -m "v1.0"

If you use -w or -m without -g, the CLI prints Warning: -w (allowderivation) and -m (customversionid) options are only available when using -g (distributionpackage) and exports a standard project.

To import a distribution package, use the regular import command. The package properties are read from the file automatically.

Example: Migrate and publish a project with role assignment

The following PowerShell script demonstrates a full deployment workflow: authenticating with client credentials, selecting roles across all business units, conditionally creating a destination project, migrating configuration from a source project, and publishing.

PowerShell
$url = "https://<name>.crm4.dynamics.com"
$clientId = "<client id>"
$clientSecret = "<client secret>"
$srcProjectName = "<source project name>"
$dstProjectName = "<destination project name>"
$appId = "<app id>"
$priority = 100
$version = "<custom version>"
$roles = "Salesperson", "Field Service - Dispatcher", "Customer Service Representative"

# Login using client credentials
wf-cli -c login -u $url -a $clientId -s $clientSecret

# Select roles across all business units
# wf-cli returns roles in the format "RoleName(BusinessUnit)" — filter by known role names
$listRoles = wf-cli -c roles
$selectedRoles = $listRoles | Where-Object {
    foreach ($r in $roles) {
        if ($_ -match "^$r\(.*$") { return $true }
    }
    return $false
}
$projectRoles = $selectedRoles -join ","

# Export source project
wf-cli -c export -n $srcProjectName -f "$srcProjectName.woodford"

# Create destination project if it doesn't exist yet
$list = wf-cli -c list
if (-not ($list | Where-Object { $_ -match "^$dstProjectName$" })) {
    Write-Host "Project $dstProjectName not found. Creating..." -ForegroundColor Red
    wf-cli -c create -n $dstProjectName -r "$priority;$projectRoles;$appId;$version"
}

# Import configuration into destination project
wf-cli -c import -n $dstProjectName -f "$srcProjectName.woodford"

# Clean up exported file
Remove-Item "$srcProjectName.woodford"

# Publish destination project
wf-cli -c publish -n $dstProjectName

# Logout
wf-cli -c logout

Key points

  • The roles command returns entries in RoleName(BusinessUnit) format — the script matches by role name prefix to capture all business units automatically.

  • The create command is skipped if the destination project already exists, making the script safely re-runnable.

  • The -r (properties) parameter for create takes the format priority;role1,role2,...;appid;version;parent. The optional parent part is not used in this script.

Running in CI pipelines

Do not store the client secret in the script or in the repository. Keep it as a secret variable of your CI system and pass it to -s from the environment. The login state is saved in a .wf-cli file in the home directory of the user running the CLI; logout deletes it, so call it at the end of the job.

Bash example (WF_URL, WF_CLIENT_ID and WF_CLIENT_SECRET are secret variables; the destination project already exists):

Bash
#!/usr/bin/env bash
trap 'wf-cli -c logout' EXIT

wf-cli -c login -u "$WF_URL" -a "$WF_CLIENT_ID" -s "$WF_CLIENT_SECRET"
wf-cli -c export -n "$SRC_PROJECT" -f "$SRC_PROJECT.woodford"
wf-cli -c import -n "$DST_PROJECT" -f "$SRC_PROJECT.woodford"
wf-cli -c publish -n "$DST_PROJECT"
rm -f "$SRC_PROJECT.woodford"

Last updated: