I'm going to do a Q&A-style entry here since I had to spend some time figuring this out, and I couldn't find any good articles about it via search.

Bulk-upserting Custom Metadata Type records is a common admin/developer task, but we have not had good tools for this historically. The legacy Custom Metadata Loader tool has been deprecated in favor of new Salesforce CLI commands.

So now I'm a Salesforce Developer in 2021 who wants to use the CLI to pull down a CSV of my existing data, update the CSV, then upsert those records back into my org. Maybe I don't have a lot of experience writing shell scripts. How should I go about this?

1 Answer 1


Here are some basic bash scripts to make this task simpler. I have created a folder called bash in my scripts folder, and added the following new files in my SFDX project:

    |    deployCustomMetadata.sh
    |    retrieveCustomMetadata.sh

Step 1: Retrieve the Custom Metadata Type records as a CSV

Here is an example bash script for retrieving Custom Metadata Type records in CSV format. This will create a new folder called data at the top of your SFDX project directory structure, unless you change the DIR variable. Replace the QUERY with your own SOQL logic.



# Script to retrieve custom metadata records
# Prerequisites: Must be run within an SFDX project with Salesforce CLI 
#   installed and authenticated to an org
# Call example: . scripts/bash/retrieveCustomMetadata.sh

    DeveloperName, \
    Country__r.DeveloperName, \
    State_Code__c, \
    Population__c \
  FROM State__mdt \
  WHERE Country__r.DeveloperName = '${COUNTRY}'"
# Update DIR if you want to put the CSV file somewhere else
# FILENAME is the name the CSV file will have when it's saved

# Create the directory to store the CSV data, if it doesn't exist
mkdir -p ${DIR}

# Query State__mdt data
echo "Executing query: ${QUERY}"
sfdx force:data:soql:query -q "${QUERY}" -r csv > ${FILEPATH}

Step 2: Update the CSV

You can now update field values and/or add new rows, using the CSV editing tool of your choice.

Step 3: Deploy the updated CSV data

This script transforms and deploys the CSV data to your org. It deals with the quirks of Custom Metadata relationship fields, in case you have any. Be sure to update the FILEPATH and METADATA_TYPE variables according to your own scenario.



# Script to deploy custom metadata records
# Prerequisites: Must be run within an SFDX project with Salesforce CLI 
#   installed and authenticated to an org
# Inputs: file path for the CSV you want to import
# Call example: . scripts/bash/deployCustomMetadata.sh

# Create the XMLs for the custom metadata records in the SFDX project
echo "Retrieving custom metadata definition from Salesforce"
sfdx force:source:retrieve -m "CustomObject:${METADATA_TYPE}__mdt"

echo "Updating CSV headers to work with force:cmdt:record:insert"
# Replace "__r.DeveloperName" with "__c" in the header row. We use the parent 
# CMDT's DeveloperName as the foreign key on deployment -- not its ID.
sed -i -e "1 s/__r.DeveloperName/__c/" ${FILEPATH}

echo "Converting CSV data to XML for deployment"
sfdx force:cmdt:record:insert \
    --filepath ${FILEPATH} \
    --typename ${METADATA_TYPE} \
    --namecolumn "DeveloperName"

echo "Transforming custom metadata records for deployment"
for FILE in force-app/main/default/customMetadata/${METADATA_TYPE}*; do
    # force:cmdt:record:insert creates lookup fields with xsi:type="xsd:undefined"
    # Need to make it xsi:type="xsd:string" so it won't fail on deployment
    sed -i -e "s/xsd:undefined/xsd:string/g" $FILE

echo "Deploying new custom metadata records"
sfdx force:source:deploy -p force-app/main/default/customMetadata

Notes on this last script:

  • The final line deploys all Custom Metadata you have defined in your SFDX project. If there is a lot more there than you want to deploy, you'll want to customize the filepath to make it more selective.

You must log in to answer this question.

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