Have a bit of an issue trying to develop a workflow to integrate SFDX....


  1. Base Package
  2. Extension Package

Base package needs extension package to be installed to operate functionally.

In SFDX development when creating a scratch org for the Base package we currently need to have one of the extension packages installed.


We cannot install the extension package into the Base scratch org because the extension package is dependent on the base package being present. Since the scratch org for Base has not packages, no extension can be installed.

Right now we are doing a process that includes unlocked packages and it is not ideal.


I am trying to make sure that there is not a better way to do this. Either I am missing something or this is a big hole in SFDX development.

So, what is are some of the better approaches to developing, within SFDX, a Base package (in a scratch org) that depends on an extension package.


3 Answers 3


If the base package determines which extension package must be installed, you can do a script using an algorithm like the following ( in groovy / node.js / ruby / python ... depending your preferences ) :

  • Install base package
  • Remotely execute base package code to return extension package id
  • Install extension package

Advanced algorithm :

// Install the base package
var basePackageId = '03c00000xxxx25'
var installBasePackgCommand = 'sfdx force:package:install --package '+basePackageId+' -u '+scratchOrgAlias+' -w 30' ;

// call custom code in scratch org to know which extension package to install
var apexExecCommand = 'sfdx force:apex:execute -f ~/myFileContainingApexCodeCallingBasePackageCodeDefiningWhichExtPackageToInstall.apex
 -u '+scratchOrgAlias ;
execLog = exec(apexExecCommand)

// Parse apex execution log to get the extension package id to install
var extPackageId = execLog.substringAfter('ExtPackageId=')

// Install extension package
var installExtPackgCommand = 'sfdx force:package:install --package '+extPackageId+' -u '+scratchOrgAlias+' -w 30' ;

If the need is to call an extension class from a base package class, you can use the following code

Define interface in base package

global interface MyInterface {
     void callMethod();

Define a class in extension package

global class MyClassInExtensionPackage Implements MyBasePackageNamespace.MyInterface{

    global void callMethod() {
         System.debug('I am here !');

Call extension class from base package class

Type extensionClass = Type.forName('MyClassInExtensionPackage');
if (extensionClass != null) {
    MyInterface extensionClassInstance = (MyInterface)extensionClass.newInstance();

Have you tried to use 2GMP? This should ideally cover your case.

You just defined them in sfdx-project.json

    "packageDirectories": [
            "path": "force-app",
            "default": true,
            "package": "Baseline",
            "versionName": "1.0.0",
            "versionNumber": "1.0.0.NEXT"
            "path": "extension",
            "package": "Extension",
            "versionName": "0.0.0",
            "versionNumber": "0.0.0.NEXT",
            "definitionFile": "config/project-scratch-def.json",
            "dependencies": [
                    "package": "Baseline",
                    "versionNumber": "1.0.0.LATEST"
            "default": false
    "namespace": "PackageNamespace",
    "sfdcLoginUrl": "https://login.salesforce.com",
    "sourceApiVersion": "53.0",
    "packageAliases": {
        "Baseline": "0HoBASEL1NE000oAAA",
        "Extension": "0HoEXTENSION000AAA"

Then just use sfdx force:source:push and both packages will be deployed to your scratch org

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .