Migrate Plugins Built for sfdx to sf

As of April 2023, the sfdx version of Salesforce CLI is deprecated and Salesforce no longer supports it. The latest and supported Salesforce CLI version is sf. However, many customers created their own plugins using the sfdx framework and libraries. If you're such a customer, read on.

You can install and use plugins originally built for sfdx in sf, although the general look-and-feel is different. We therefore recommend that you explicitly migrate your sfdx plugin to sf so its commands look and behave the same as other sf commands. You can also then take advantage of the many improvements we've made to the code that supports sf plugins.

Update @oclif and the @salesforce/core library to the latest versions.

  1. Update to v3 (or latest) of @oclif/core as described by this document.
  2. Update to v7 (or latest) of @salesforce/core as described this document. The root of the repository contains other MIGRATING_VX_VY.MD documents that detail every major change and upgrade tips.

These sections provide useful information for migrating your plugins from sfdx to sf.

Salesforce provides a set of eslint rules for Salesforce CLI plugins.

While migrating an sfdx plugin to sf, we recommend you use a set of additional rules that do most of the work for you. See the set up instructions for more details.

Some of these eslint rules automatically change some of your code while other rules provide suggestions where you can select which fix to apply.

Although v3+ of @salesforce/core works with your existing JSON message files, we recommend that you migrate them to Markdown. Message files contain the --help content and error messages.

  1. From the top-level directory of your plugin, run the dev convert messages command to convert an existing JSON file to a first-draft Markdown file to get you started. For example:

    In this case, the command generates the Markdown file messages/mycommand.md.

  2. Edit the generated Markdown file to make sure your messages look good. See the next section for information about reducing maintenance and Write Useful Messages for general information about writing messages.

  3. Run sf dev audit messages to find missing or unused messages, then update your code to add or remove references to the messages as needed.

  4. Delete the old JSON files after you're finished.

Messages in v3+ of @salesforce/core support dynamic references to the command and Salesforce CLI binary names. Specifically, the placeholder <%= config.bin %> refers to the binary name (sfdx or sf) and <%= command.id %> refers to the command itself.

If your plugin supports both sfdx and sf, use these placeholders in message files rather than hard coding the command and CLI executable name. As a result, you aren't required to rewrite the messages after you change your command structure or name.

Here's an example from the Markdown message file for the org delete sandbox command:

We encourage you to follow sf's styles in your command and flag names. See Design Guidelines for details. If you must maintain backward compatibility, you have some options.

If you rename a command, you can alias it back to its original name.

Similarly, if you rename a flag, you can alias it back to its previous name.

We provide some helpers for compatibility within @salesforce/sf-plugins-core. We've marked them as deprecated because you use these helpers only for migrating an existing sfdx plugin, not for new plugin development.

As described in this section, the eslint plugin handles most of the work of getting you to sfCommand. But there are some differences.

Some properties like this.logger don't automatically exist. You can create the property by importing Logger from sfdx-core. Other properties like requiresUsername don't do anything and are removed by the linter rules. You must add a flag for the org.

SfCommand has a private ux property, which means you can't pass it to helper functions. Instead of this code:

Use this code to construct a new Ux instance and pass it to your help:

SfdxCommand's requires|supports(devhub)username properties created a flag for both the username an apiversion flag. If your command must support an apiversion, or you want to keep it in place for compatibility, do this:

After you run yarn remove @salesforce/command you sometimes see that you were also using its test library, based on fancy-test.

sfdx-core v3+ includes better tools for mocking auths/orgs/projects/users/connections. See its docs.

This example uses TestSetup to mock an org and a connection and calls a command's run method.

To avoid breaking changes, we recommend that you leave existing tests which verify that you've correctly aliased all commands and flags.